From 108eafbb1982632334a460be28064da7b6c21afd Mon Sep 17 00:00:00 2001 From: Julian Bauer Date: Thu, 6 Apr 2023 11:18:16 +0200 Subject: [PATCH] Initial release --- .gitignore | 24 + .mvn/wrapper/MavenWrapperDownloader.java | 118 + .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 58727 bytes .mvn/wrapper/maven-wrapper.properties | 18 + .npmrc | 6 + .prettierrc.js | 4 + LICENSE | 4 +- README.md | 7 + frontend/index.html | 23 + .../themes/iamreportingmodule/indicator.css | 42 + .../themes/iamreportingmodule/main-layout.css | 57 + frontend/themes/iamreportingmodule/styles.css | 2 + frontend/themes/iamreportingmodule/theme.json | 3 + mvnw | 316 + mvnw.cmd | 190 + package-lock.json | 12290 ++++++++++++++++ package.json | 366 + pom.xml | 305 + .../iamreportingmodule/Application.java | 30 + .../core/exception/DatabaseException.java | 18 + .../core/exception/DeleteEntityException.java | 18 + .../core/exception/FileException.java | 18 + .../core/exception/FormulaException.java | 18 + .../exception/JobSchedulingException.java | 18 + .../core/exception/SaveEntityException.java | 18 + .../core/scheduling/CalculateJob.java | 87 + .../core/scheduling/MeasureJob.java | 188 + .../service/CustomUserDetailsService.java | 52 + .../core/service/DataSourceService.java | 194 + .../core/service/GroupService.java | 196 + .../core/service/InformationNeedService.java | 113 + .../core/service/JobSchedulingService.java | 282 + .../core/service/MeasurableService.java | 378 + .../core/service/UserService.java | 61 + .../iamreportingmodule/core/util/CsvUtil.java | 228 + .../core/util/DatabaseUtil.java | 133 + .../core/util/FormulaUtil.java | 281 + .../converter/StringToFormulaConverter.java | 112 + .../converter/StringToFrequencyConverter.java | 114 + .../data/converter/StringToPortConverter.java | 106 + .../data/entity/AbstractEntity.java | 73 + .../data/entity/Audience.java | 64 + .../data/entity/CsvAggregationMethod.java | 16 + .../data/entity/CustomUserDetails.java | 114 + .../data/entity/DataSource.java | 117 + .../data/entity/DataSourceType.java | 13 + .../data/entity/DatabaseDataSource.java | 158 + .../iamreportingmodule/data/entity/Dbms.java | 13 + .../data/entity/FileDataSource.java | 91 + .../data/entity/FileType.java | 13 + .../data/entity/Formula.java | 107 + .../data/entity/Frequency.java | 91 + .../iamreportingmodule/data/entity/Group.java | 56 + .../data/entity/InformationNeed.java | 93 + .../data/entity/ManualDataSource.java | 48 + .../data/entity/Measurable.java | 292 + .../data/entity/Measurement.java | 61 + .../data/entity/Metric.java | 69 + .../data/entity/Result.java | 103 + .../iamreportingmodule/data/entity/Scale.java | 14 + .../data/entity/Stakeholder.java | 64 + .../iamreportingmodule/data/entity/Unit.java | 12 + .../iamreportingmodule/data/entity/User.java | 177 + .../data/generator/DataGenerator.java | 500 + .../data/repository/AudienceRepository.java | 25 + .../DatabaseDataSourceRepository.java | 14 + .../repository/FileDataSourceRepository.java | 14 + .../data/repository/GroupRepository.java | 15 + .../repository/InformationNeedRepository.java | 14 + .../ManualDataSourceRepository.java | 14 + .../repository/MeasurementRepository.java | 24 + .../data/repository/MetricRepository.java | 36 + .../data/repository/ResultRepository.java | 33 + .../repository/StakeholderRepository.java | 14 + .../data/repository/UserRepository.java | 23 + .../data/validator/FormulaValidator.java | 63 + .../validator/MeasurableLabelValidator.java | 84 + .../web/component/appnav/AppNav.java | 147 + .../web/component/appnav/AppNavItem.java | 316 + .../web/component/dashboard/Indicator.java | 158 + .../notification/CustomNotification.java | 131 + .../notification/ErrorNotification.java | 45 + .../notification/SuccessNotification.java | 45 + .../web/form/DatabaseDataSourceForm.java | 311 + .../web/form/FileDataSourceForm.java | 352 + .../web/form/GroupForm.java | 222 + .../web/form/InformationNeedForm.java | 202 + .../web/form/ManualDataSourceForm.java | 208 + .../web/form/MeasurementForm.java | 636 + .../web/form/MetricForm.java | 331 + .../web/security/SecurityConfig.java | 48 + .../web/security/SecurityService.java | 47 + .../web/view/AddAudienceView.java | 92 + .../web/view/AddDatabaseDataSourceView.java | 91 + .../web/view/AddFileDataSourceView.java | 86 + .../web/view/AddInformationNeedView.java | 86 + .../web/view/AddManualDataSourceView.java | 86 + .../web/view/AddMeasurementView.java | 94 + .../web/view/AddMetricView.java | 94 + .../web/view/AddStakeholderView.java | 92 + .../web/view/AudiencesView.java | 131 + .../web/view/DashboardView.java | 234 + .../web/view/DataSourcesView.java | 196 + .../web/view/EditAudienceView.java | 145 + .../web/view/EditDatabaseDataSourceView.java | 145 + .../web/view/EditFileDataSourceView.java | 142 + .../web/view/EditInformationNeedView.java | 142 + .../web/view/EditManualDataSourceView.java | 142 + .../web/view/EditMeasurementView.java | 225 + .../web/view/EditMetricView.java | 225 + .../web/view/EditStakeholderView.java | 145 + .../web/view/InformationNeedsView.java | 128 + .../web/view/LoginView.java | 57 + .../web/view/LogoutView.java | 23 + .../web/view/MainLayout.java | 155 + .../web/view/MeasurementsView.java | 134 + .../web/view/MetricsView.java | 132 + .../web/view/ResultsView.java | 146 + .../web/view/StakeholdersView.java | 131 + .../META-INF/resources/icons/icon.png | Bin 0 -> 2424 bytes .../META-INF/resources/images/empty-plant.png | Bin 0 -> 70951 bytes src/main/resources/application-it.properties | 11 + .../resources/application-local.properties | 12 + .../application-production.properties | 11 + src/main/resources/application.properties | 22 + src/main/resources/banner.txt | 6 + src/main/resources/quartz/schema.sql | 199 + .../core/util/DatabaseUtilTest.java | 75 + .../core/util/FormulaUtilTest.java | 255 + tsconfig.json | 39 + types.d.ts | 5 + vite.config.ts | 9 + 132 files changed, 26510 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 .mvn/wrapper/MavenWrapperDownloader.java create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 .npmrc create mode 100644 .prettierrc.js create mode 100644 README.md create mode 100644 frontend/index.html create mode 100644 frontend/themes/iamreportingmodule/indicator.css create mode 100644 frontend/themes/iamreportingmodule/main-layout.css create mode 100644 frontend/themes/iamreportingmodule/styles.css create mode 100644 frontend/themes/iamreportingmodule/theme.json create mode 100644 mvnw create mode 100644 mvnw.cmd create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 pom.xml create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/Application.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/exception/DatabaseException.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/exception/DeleteEntityException.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/exception/FileException.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/exception/FormulaException.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/exception/JobSchedulingException.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/exception/SaveEntityException.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/scheduling/CalculateJob.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/scheduling/MeasureJob.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/service/CustomUserDetailsService.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/service/DataSourceService.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/service/GroupService.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/service/InformationNeedService.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/service/JobSchedulingService.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/service/MeasurableService.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/service/UserService.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/util/CsvUtil.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/util/DatabaseUtil.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/core/util/FormulaUtil.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToFormulaConverter.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToFrequencyConverter.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToPortConverter.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/AbstractEntity.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Audience.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/CsvAggregationMethod.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/CustomUserDetails.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DataSource.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DataSourceType.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DatabaseDataSource.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Dbms.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/FileDataSource.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/FileType.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Formula.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Frequency.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Group.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/InformationNeed.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/ManualDataSource.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Measurable.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Measurement.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Metric.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Result.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Scale.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Stakeholder.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Unit.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/entity/User.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/generator/DataGenerator.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/AudienceRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/DatabaseDataSourceRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/FileDataSourceRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/GroupRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/InformationNeedRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/ManualDataSourceRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/MeasurementRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/MetricRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/ResultRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/StakeholderRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/repository/UserRepository.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/validator/FormulaValidator.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/data/validator/MeasurableLabelValidator.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/component/appnav/AppNav.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/component/appnav/AppNavItem.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/component/dashboard/Indicator.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/CustomNotification.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/ErrorNotification.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/SuccessNotification.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/form/DatabaseDataSourceForm.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/form/FileDataSourceForm.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/form/GroupForm.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/form/InformationNeedForm.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/form/ManualDataSourceForm.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/form/MeasurementForm.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/form/MetricForm.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/security/SecurityConfig.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/security/SecurityService.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddAudienceView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddDatabaseDataSourceView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddFileDataSourceView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddInformationNeedView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddManualDataSourceView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddMeasurementView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddMetricView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddStakeholderView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/AudiencesView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/DashboardView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/DataSourcesView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditAudienceView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditDatabaseDataSourceView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditFileDataSourceView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditInformationNeedView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditManualDataSourceView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditMeasurementView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditMetricView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditStakeholderView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/InformationNeedsView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/LoginView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/LogoutView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/MainLayout.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/MeasurementsView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/MetricsView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/ResultsView.java create mode 100644 src/main/java/de/uniregensburg/iamreportingmodule/web/view/StakeholdersView.java create mode 100644 src/main/resources/META-INF/resources/icons/icon.png create mode 100644 src/main/resources/META-INF/resources/images/empty-plant.png create mode 100644 src/main/resources/application-it.properties create mode 100644 src/main/resources/application-local.properties create mode 100644 src/main/resources/application-production.properties create mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/banner.txt create mode 100644 src/main/resources/quartz/schema.sql create mode 100644 src/test/java/de/uniregensburg/iamreportingmodule/core/util/DatabaseUtilTest.java create mode 100644 src/test/java/de/uniregensburg/iamreportingmodule/core/util/FormulaUtilTest.java create mode 100644 tsconfig.json create mode 100644 types.d.ts create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6eff08f --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +/target/ +.idea/ +.vscode/ +.settings +.project +.classpath + +*.iml +.DS_Store + +# The following files are generated/updated by vaadin-maven-plugin +node_modules/ +frontend/generated/ +pnpmfile.js +vite.generated.ts + +# Browser drivers for local integration tests +drivers/ +# Error screenshots generated by TestBench for failed integration tests +error-screenshots/ +webpack.generated.js + +# Logging +*.log* \ No newline at end of file diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..8895dd4 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.io.*; +import java.net.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is + * provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl + * property to use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download + * url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a + // custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..c1dd12f17644411d6e840bd5a10c6ecda0175f18 GIT binary patch literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cc33341 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..34e3360 --- /dev/null +++ b/.npmrc @@ -0,0 +1,6 @@ +# +# NOTICE: this is an auto-generated file +# +# This file sets the default parameters for manual `pnpm install`. +# +shamefully-hoist=true diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..783d42f --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,4 @@ +module.exports = { + singleQuote: true, + printWidth: 120, +}; diff --git a/LICENSE b/LICENSE index 4487d4e..46045bb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Julian Bauer +Copyright (c) 2022-2023 Julian Bauer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..496baae --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# IAM Reporting Module + +Tool for periodically collecting IAM measurements from various sources, periodically calculating IAM metrics based on a +formula and displaying the metrics in reports for various IAM goals. + +The tool was developed as part of the master thesis: +Design and implementation of an identity and access management reporting module based on metrics. diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..a5cdd40 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + +
+ + diff --git a/frontend/themes/iamreportingmodule/indicator.css b/frontend/themes/iamreportingmodule/indicator.css new file mode 100644 index 0000000..13c7f75 --- /dev/null +++ b/frontend/themes/iamreportingmodule/indicator.css @@ -0,0 +1,42 @@ +.indicator { + border-radius: var(--lumo-border-radius-l); + box-shadow: var(--lumo-box-shadow-xs); + cursor: var(--lumo-clickable-cursor); + padding: var(--lumo-space-m); + transition: box-shadow 0.3s ease-in-out; + position: relative; + text-align: center; +} + +.indicator:hover { + box-shadow: var(--lumo-box-shadow-m); +} + +.indicator-link { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.indicator-link:hover { + text-decoration: none; +} + +.indicator-title { + font-size: var(--lumo-font-size-l); + color: var(--lumo-header-text-color); + font-weight: bold; +} + +.indicator-value { + font-size: var(--lumo-font-size-xxxl); + color: var(--lumo-body-text-color); + font-weight: bold; +} + +.indicator-unit { + font-size: var(--lumo-font-size-s); + color: var(--lumo-tertiary-text-color); +} \ No newline at end of file diff --git a/frontend/themes/iamreportingmodule/main-layout.css b/frontend/themes/iamreportingmodule/main-layout.css new file mode 100644 index 0000000..307ecff --- /dev/null +++ b/frontend/themes/iamreportingmodule/main-layout.css @@ -0,0 +1,57 @@ +vaadin-app-layout[primary-section="navbar"]::part(navbar)::before { + background: var(--lumo-base-color) linear-gradient(var(--lumo-contrast-5pct), var(--lumo-contrast-5pct)); +} + +vaadin-app-layout[primary-section="drawer"]::part(navbar)::before { + background: var(--lumo-base-color); +} + +vaadin-app-layout[primary-section="drawer"]::part(navbar) { + box-shadow: 0 1px 0 0 var(--lumo-contrast-10pct); +} + +vaadin-app-layout[primary-section="drawer"]:not([overlay])::part(drawer) { + background: var(--lumo-shade-5pct); + border: 0; + box-shadow: 1px 0 0 0 var(--lumo-contrast-10pct), 1px 0 0 0 var(--lumo-base-color); + z-index: 1; +} + +vaadin-drawer-toggle[slot="navbar"] { + color: var(--lumo-secondary-text-color); +} + +::part(navbar) { + min-height: var(--lumo-size-xl); +} + +::part(drawer) { + display: flex; + flex-direction: column; +} + +vaadin-scroller[slot="drawer"] { + flex: 1; + padding: var(--lumo-space-s); +} + +vaadin-scroller[slot="drawer"][overflow~="top"] { + border-top: 1px solid var(--lumo-contrast-10pct); +} + +vaadin-scroller[slot="drawer"][overflow~="bottom"] { + border-bottom: 1px solid var(--lumo-contrast-10pct); +} + +[slot="drawer"]:is(header, footer) { + display: flex; + align-items: center; + gap: var(--lumo-space-s); + padding: var(--lumo-space-s) var(--lumo-space-m); + min-height: var(--lumo-size-xl); + box-sizing: border-box; +} + +[slot="drawer"]:is(header, footer):is(:empty) { + display: none; +} diff --git a/frontend/themes/iamreportingmodule/styles.css b/frontend/themes/iamreportingmodule/styles.css new file mode 100644 index 0000000..5c4eab2 --- /dev/null +++ b/frontend/themes/iamreportingmodule/styles.css @@ -0,0 +1,2 @@ +@import url('./main-layout.css'); +@import url('line-awesome/dist/line-awesome/css/line-awesome.min.css'); \ No newline at end of file diff --git a/frontend/themes/iamreportingmodule/theme.json b/frontend/themes/iamreportingmodule/theme.json new file mode 100644 index 0000000..0f7a81f --- /dev/null +++ b/frontend/themes/iamreportingmodule/theme.json @@ -0,0 +1,3 @@ +{ + "lumoImports" : [ "typography", "color", "spacing", "badge", "utility" ] +} \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..5643201 --- /dev/null +++ b/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..ae01454 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,190 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + @setlocal EnableDelayedExpansion + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '!WRAPPER_JAR!')"^ + "}" + @endlocal + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6131325 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12290 @@ +{ + "name": "no-name", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "no-name", + "license": "UNLICENSED", + "dependencies": { + "@polymer/iron-icon": "3.0.1", + "@polymer/iron-iconset-svg": "3.0.1", + "@polymer/iron-list": "3.1.0", + "@polymer/iron-meta": "3.0.1", + "@polymer/iron-resizable-behavior": "3.0.1", + "@polymer/polymer": "3.5.1", + "@vaadin-component-factory/vcf-nav": "1.0.6", + "@vaadin/accordion": "23.3.8", + "@vaadin/app-layout": "23.3.8", + "@vaadin/avatar": "23.3.8", + "@vaadin/avatar-group": "23.3.8", + "@vaadin/bundles": "23.3.8", + "@vaadin/button": "23.3.8", + "@vaadin/checkbox": "23.3.8", + "@vaadin/checkbox-group": "23.3.8", + "@vaadin/combo-box": "23.3.8", + "@vaadin/common-frontend": "0.0.17", + "@vaadin/component-base": "23.3.8", + "@vaadin/confirm-dialog": "23.3.8", + "@vaadin/context-menu": "23.3.8", + "@vaadin/custom-field": "23.3.8", + "@vaadin/date-picker": "23.3.8", + "@vaadin/date-time-picker": "23.3.8", + "@vaadin/details": "23.3.8", + "@vaadin/dialog": "23.3.8", + "@vaadin/email-field": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/field-highlighter": "23.3.8", + "@vaadin/form-layout": "23.3.8", + "@vaadin/grid": "23.3.8", + "@vaadin/horizontal-layout": "23.3.8", + "@vaadin/icon": "23.3.8", + "@vaadin/icons": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/integer-field": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/list-box": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/login": "23.3.8", + "@vaadin/menu-bar": "23.3.8", + "@vaadin/message-input": "23.3.8", + "@vaadin/message-list": "23.3.8", + "@vaadin/multi-select-combo-box": "23.3.8", + "@vaadin/notification": "23.3.8", + "@vaadin/number-field": "23.3.8", + "@vaadin/password-field": "23.3.8", + "@vaadin/polymer-legacy-adapter": "23.3.8", + "@vaadin/progress-bar": "23.3.8", + "@vaadin/radio-group": "23.3.8", + "@vaadin/router": "1.7.4", + "@vaadin/scroller": "23.3.8", + "@vaadin/select": "23.3.8", + "@vaadin/split-layout": "23.3.8", + "@vaadin/tabs": "23.3.8", + "@vaadin/tabsheet": "23.3.8", + "@vaadin/text-area": "23.3.8", + "@vaadin/text-field": "23.3.8", + "@vaadin/time-picker": "23.3.8", + "@vaadin/tooltip": "23.3.8", + "@vaadin/upload": "23.3.8", + "@vaadin/vaadin-accordion": "23.3.8", + "@vaadin/vaadin-app-layout": "23.3.8", + "@vaadin/vaadin-avatar": "23.3.8", + "@vaadin/vaadin-button": "23.3.8", + "@vaadin/vaadin-checkbox": "23.3.8", + "@vaadin/vaadin-combo-box": "23.3.8", + "@vaadin/vaadin-confirm-dialog": "23.3.8", + "@vaadin/vaadin-context-menu": "23.3.8", + "@vaadin/vaadin-custom-field": "23.3.8", + "@vaadin/vaadin-date-picker": "23.3.8", + "@vaadin/vaadin-date-time-picker": "23.3.8", + "@vaadin/vaadin-details": "23.3.8", + "@vaadin/vaadin-development-mode-detector": "2.0.6", + "@vaadin/vaadin-dialog": "23.3.8", + "@vaadin/vaadin-form-layout": "23.3.8", + "@vaadin/vaadin-grid": "23.3.8", + "@vaadin/vaadin-icon": "23.3.8", + "@vaadin/vaadin-icons": "23.3.8", + "@vaadin/vaadin-item": "23.3.8", + "@vaadin/vaadin-list-box": "23.3.8", + "@vaadin/vaadin-list-mixin": "23.3.8", + "@vaadin/vaadin-login": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-menu-bar": "23.3.8", + "@vaadin/vaadin-messages": "23.3.8", + "@vaadin/vaadin-notification": "23.3.8", + "@vaadin/vaadin-ordered-layout": "23.3.8", + "@vaadin/vaadin-overlay": "23.3.8", + "@vaadin/vaadin-progress-bar": "23.3.8", + "@vaadin/vaadin-radio-button": "23.3.8", + "@vaadin/vaadin-select": "23.3.8", + "@vaadin/vaadin-split-layout": "23.3.8", + "@vaadin/vaadin-tabs": "23.3.8", + "@vaadin/vaadin-template-renderer": "23.3.8", + "@vaadin/vaadin-text-field": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8", + "@vaadin/vaadin-time-picker": "23.3.8", + "@vaadin/vaadin-upload": "23.3.8", + "@vaadin/vaadin-usage-statistics": "2.1.2", + "@vaadin/vaadin-virtual-list": "23.3.8", + "@vaadin/vertical-layout": "23.3.8", + "@vaadin/virtual-list": "23.3.8", + "construct-style-sheets-polyfill": "3.1.0", + "date-fns": "2.29.3", + "line-awesome": "1.3.0", + "lit": "2.6.1" + }, + "devDependencies": { + "@rollup/plugin-replace": "3.1.0", + "@rollup/pluginutils": "4.1.0", + "async": "3.2.2", + "glob": "7.2.3", + "mkdirp": "1.0.4", + "rollup-plugin-brotli": "3.1.0", + "strip-css-comments": "5.0.0", + "transform-ast": "2.4.4", + "typescript": "4.9.3", + "vite": "3.2.5", + "vite-plugin-checker": "0.5.4", + "workbox-build": "6.5.4", + "workbox-core": "6.5.4", + "workbox-precaching": "6.5.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", + "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", + "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.5", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.5", + "@babel/types": "^7.18.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/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==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/generator/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "dev": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", + "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/browserslist": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.0.tgz", + "integrity": "sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001358", + "electron-to-chromium": "^1.4.164", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.0.tgz", + "integrity": "sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-member-expression-to-functions": "^7.17.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz", + "integrity": "sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/regexpu-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "dev": true + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", + "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", + "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.0", + "@babel/types": "^7.18.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", + "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.2.tgz", + "integrity": "sha512-XzAIyxx+vFnrOxiQrToSUOzUOn0e1J2Li40ntddek1Y69AXUTXoDJ40/D5RdjFu7s7qHiaeoTiempZcbuVXh2Q==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-member-expression-to-functions": "^7.17.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", + "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", + "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", + "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", + "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.17.12", + "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.17.12.tgz", + "integrity": "sha512-xCJQXl4EeQ3J9C4yOmpTrtVGmzpm2iSzyxbkZHw7UCnZBftHpF/hpII80uWVyVrc40ytIClHjgWGTG1g/yB+aw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.17.12.tgz", + "integrity": "sha512-/vt0hpIw0x4b6BLKUkwlvEoiGZYYLNZ96CzyHYPbtG2jZGz6LBe7/V+drYrc/d+ovrF9NBi0pmtvmNb/FsWtRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.17.12.tgz", + "integrity": "sha512-RWVvqD1ooLKP6IqWTA5GyFVX2isGEgC5iFxKzfYOIy/QEFdxYyCybBDtIGjipHpb9bDWHzcqGqFakf+mVmBTdQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz", + "integrity": "sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.0.tgz", + "integrity": "sha512-t+8LsRMMDE74c6sV7KShIw13sqbqd58tlqNrsWoWBTIMw7SVQ0cZ905wLNS/FBCy/3PyooRHLFFlfrUNyyz5lA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.17.12.tgz", + "integrity": "sha512-j7Ye5EWdwoXOpRmo5QmRyHPsDIe6+u70ZYZrd7uz+ebPYFKfRcLcNu3Ro0vOlJ5zuv8rU7xa+GttNiRzX56snQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.17.12.tgz", + "integrity": "sha512-rKJ+rKBoXwLnIn7n6o6fulViHMrOThz99ybH+hKHcOZbnN14VuMnH9fo2eHE69C8pO4uX1Q7t2HYYIDmv8VYkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.17.12.tgz", + "integrity": "sha512-EqFo2s1Z5yy+JeJu7SFfbIUtToJTVlC61/C7WLKDntSw4Sz6JNAIfL7zQ74VvirxpjB5kz/kIx0gCcb+5OEo2Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.17.12.tgz", + "integrity": "sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.0.tgz", + "integrity": "sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.17.12.tgz", + "integrity": "sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.17.12.tgz", + "integrity": "sha512-SllXoxo19HmxhDWm3luPz+cPhtoTSKLJE9PXshsfrOzBqs60QP0r8OaJItrPhAj0d7mZMnNF0Y1UUggCDgMz1A==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.17.12.tgz", + "integrity": "sha512-/6BtVi57CJfrtDNKfK5b66ydK2J5pXUKBKSPD2G1whamMuEnZWgoOIfO8Vf9F/DoD4izBLD/Au4NMQfruzzykg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.17.12.tgz", + "integrity": "sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.17.12.tgz", + "integrity": "sha512-n/loy2zkq9ZEM8tEOwON9wTQSTNDTDEz6NujPtJGLU7qObzT1N4c4YZZf8E6ATB2AjNQg/Ib2AIpO03EZaCehw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz", + "integrity": "sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.17.12.tgz", + "integrity": "sha512-J8dbrWIOO3orDzir57NRsjg4uxucvhby0L/KZuGsWDj0g7twWK3g7JhJhOrXtuXiw8MeiSdJ3E0OW9H8LYEzLQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-remap-async-to-generator": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.4.tgz", + "integrity": "sha512-+Hq10ye+jlvLEogSOtq4mKvtk7qwcUQ1f0Mrueai866C82f844Yom2cttfJdMdqRLTxWpsbfbkIkOIfovyUQXw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.4.tgz", + "integrity": "sha512-e42NSG2mlKWgxKUAD9EJJSkZxR67+wZqzNxLSpc51T8tRU5SLFHsPmgYR5yr7sdgX4u+iHA1C5VafJ6AyImV3A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-replace-supers": "^7.18.2", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.17.12.tgz", + "integrity": "sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.0.tgz", + "integrity": "sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.17.12.tgz", + "integrity": "sha512-EA5eYFUG6xeerdabina/xIoB95jJ17mAkR8ivx6ZSu9frKShBjpOGZPn511MTDTkiCO+zXnzNczvUM69YSf3Zw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.18.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.1.tgz", + "integrity": "sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.17.12.tgz", + "integrity": "sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.0.tgz", + "integrity": "sha512-h8FjOlYmdZwl7Xm2Ug4iX2j7Qy63NANI+NQVWQzv6r25fqgg7k2dZl03p95kvqNclglHs4FZ+isv4p1uXMA+QA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.2.tgz", + "integrity": "sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-simple-access": "^7.18.2", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.5.tgz", + "integrity": "sha512-SEewrhPpcqMF1V7DhnEbhVJLrC+nnYfe1E0piZMZXBpxi9WvZqWGwpsk7JYP7wPWeqaBh4gyKlBhHJu3uz5g4Q==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.0.tgz", + "integrity": "sha512-d/zZ8I3BWli1tmROLxXLc9A6YXvGK8egMxHp+E/rRwMh1Kip0AP77VwZae3snEJ33iiWwvNv2+UIIhfalqhzZA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.12.tgz", + "integrity": "sha512-vWoWFM5CKaTeHrdUJ/3SIOTRV+MBVGybOC9mhJkaprGNt5demMymDW24yC74avb915/mIRe3TgNb/d8idvnCRA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.5.tgz", + "integrity": "sha512-TuRL5uGW4KXU6OsRj+mLp9BM7pO8e7SGNTEokQRRxHFkXYMFiy2jlKSZPFtI/mKORDzciH+hneskcSOp0gU8hg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.17.12.tgz", + "integrity": "sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.0.tgz", + "integrity": "sha512-C8YdRw9uzx25HSIzwA7EM7YP0FhCe5wNvJbZzjVNHHPGVcDJ3Aie+qGYYdS1oVQgn+B3eAIJbWFLrJ4Jipv7nw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "regenerator-transform": "^0.15.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator/node_modules/regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.17.12.tgz", + "integrity": "sha512-1KYqwbJV3Co03NIi14uEHW8P50Md6KqFgt0FfpHdK6oyAHQVTosgPuPSiWud1HX0oYJ1hGRRlk0fP87jFpqXZA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.17.12.tgz", + "integrity": "sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.2.tgz", + "integrity": "sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.17.12.tgz", + "integrity": "sha512-Q8y+Jp7ZdtSPXCThB6zjQ74N3lj0f6TDh1Hnf5B+sYlzQ8i5Pjp8gW0My79iekSpT4WnI06blqP6DT0OmaXXmw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.2.tgz", + "integrity": "sha512-PfpdxotV6afmXMU47S08F9ZKIm2bJIQ0YbAAtDfIENX7G1NUAXigLREh69CWDjtgUy7dYn7bsMzkgdtAlmS68Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.17.12", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.17.12", + "@babel/plugin-proposal-async-generator-functions": "^7.17.12", + "@babel/plugin-proposal-class-properties": "^7.17.12", + "@babel/plugin-proposal-class-static-block": "^7.18.0", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.17.12", + "@babel/plugin-proposal-json-strings": "^7.17.12", + "@babel/plugin-proposal-logical-assignment-operators": "^7.17.12", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.17.12", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.18.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.17.12", + "@babel/plugin-proposal-private-methods": "^7.17.12", + "@babel/plugin-proposal-private-property-in-object": "^7.17.12", + "@babel/plugin-proposal-unicode-property-regex": "^7.17.12", + "@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.17.12", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.17.12", + "@babel/plugin-transform-async-to-generator": "^7.17.12", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.17.12", + "@babel/plugin-transform-classes": "^7.17.12", + "@babel/plugin-transform-computed-properties": "^7.17.12", + "@babel/plugin-transform-destructuring": "^7.18.0", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.17.12", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.18.1", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.17.12", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.18.0", + "@babel/plugin-transform-modules-commonjs": "^7.18.2", + "@babel/plugin-transform-modules-systemjs": "^7.18.0", + "@babel/plugin-transform-modules-umd": "^7.18.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.12", + "@babel/plugin-transform-new-target": "^7.17.12", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.17.12", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.18.0", + "@babel/plugin-transform-reserved-words": "^7.17.12", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.17.12", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.18.2", + "@babel/plugin-transform-typeof-symbol": "^7.17.12", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.2", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz", + "integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true + }, + "node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", + "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.18.5", + "@babel/types": "^7.18.4", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", + "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types/node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", + "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/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==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.0.0.tgz", + "integrity": "sha512-ic93MBXfApIFTrup4a70M/+ddD8xdt2zxxj9sRwHQzhS9ag/syqkD8JPdTXsc1gUy2K8TTirhlCqyTEM/sifNw==" + }, + "node_modules/@lit/reactive-element": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.1.tgz", + "integrity": "sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@open-wc/dedupe-mixin": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@open-wc/dedupe-mixin/-/dedupe-mixin-1.3.1.tgz", + "integrity": "sha512-ukowSvzpZQDUH0Y3znJTsY88HkiGk3Khc0WGpIPhap1xlerieYi27QBg6wx/nTurpWfU6XXXsx9ocxDYCdtw0Q==" + }, + "node_modules/@polymer/iron-a11y-keys-behavior": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-a11y-keys-behavior/-/iron-a11y-keys-behavior-3.0.1.tgz", + "integrity": "sha512-lnrjKq3ysbBPT/74l0Fj0U9H9C35Tpw2C/tpJ8a+5g8Y3YJs1WSZYnEl1yOkw6sEyaxOq/1DkzH0+60gGu5/PQ==", + "dependencies": { + "@polymer/polymer": "^3.0.0" + } + }, + "node_modules/@polymer/iron-flex-layout": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-flex-layout/-/iron-flex-layout-3.0.1.tgz", + "integrity": "sha512-7gB869czArF+HZcPTVSgvA7tXYFze9EKckvM95NB7SqYF+NnsQyhoXgKnpFwGyo95lUjUW9TFDLUwDXnCYFtkw==", + "dependencies": { + "@polymer/polymer": "^3.0.0" + } + }, + "node_modules/@polymer/iron-icon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-icon/-/iron-icon-3.0.1.tgz", + "integrity": "sha512-QLPwirk+UPZNaLnMew9VludXA4CWUCenRewgEcGYwdzVgDPCDbXxy6vRJjmweZobMQv/oVLppT2JZtJFnPxX6g==", + "dependencies": { + "@polymer/iron-flex-layout": "^3.0.0-pre.26", + "@polymer/iron-meta": "^3.0.0-pre.26", + "@polymer/polymer": "^3.0.0" + } + }, + "node_modules/@polymer/iron-iconset-svg": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-iconset-svg/-/iron-iconset-svg-3.0.1.tgz", + "integrity": "sha512-XNwURbNHRw6u2fJe05O5fMYye6GSgDlDqCO+q6K1zAnKIrpgZwf2vTkBd5uCcZwsN0FyCB3mvNZx4jkh85dRDw==", + "dependencies": { + "@polymer/iron-meta": "^3.0.0-pre.26", + "@polymer/polymer": "^3.0.0" + } + }, + "node_modules/@polymer/iron-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@polymer/iron-list/-/iron-list-3.1.0.tgz", + "integrity": "sha512-Eiv6xd3h3oPmn8SXFntXVfC3ZnegH+KHAxiKLKcOASFSRY3mHnr2AdcnExUJ9ItoCMA5UzKaM/0U22eWzGERtA==", + "dependencies": { + "@polymer/iron-a11y-keys-behavior": "^3.0.0-pre.26", + "@polymer/iron-resizable-behavior": "^3.0.0-pre.26", + "@polymer/iron-scroll-target-behavior": "^3.0.0-pre.26", + "@polymer/polymer": "^3.0.0" + } + }, + "node_modules/@polymer/iron-meta": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-meta/-/iron-meta-3.0.1.tgz", + "integrity": "sha512-pWguPugiLYmWFV9UWxLWzZ6gm4wBwQdDy4VULKwdHCqR7OP7u98h+XDdGZsSlDPv6qoryV/e3tGHlTIT0mbzJA==", + "dependencies": { + "@polymer/polymer": "^3.0.0" + } + }, + "node_modules/@polymer/iron-resizable-behavior": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-resizable-behavior/-/iron-resizable-behavior-3.0.1.tgz", + "integrity": "sha512-FyHxRxFspVoRaeZSWpT3y0C9awomb4tXXolIJcZ7RvXhMP632V5lez+ch5G5SwK0LpnAPkg35eB0LPMFv+YMMQ==", + "dependencies": { + "@polymer/polymer": "^3.0.0" + } + }, + "node_modules/@polymer/iron-scroll-target-behavior": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-scroll-target-behavior/-/iron-scroll-target-behavior-3.0.1.tgz", + "integrity": "sha512-xg1WanG25BIkQE8rhuReqY9zx1K5M7F+YAIYpswEp5eyDIaZ1Y3vUmVeQ3KG+hiSugzI1M752azXN7kvyhOBcQ==", + "dependencies": { + "@polymer/polymer": "^3.0.0" + } + }, + "node_modules/@polymer/polymer": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.5.1.tgz", + "integrity": "sha512-JlAHuy+1qIC6hL1ojEUfIVD58fzTpJAoCxFwV5yr0mYTXV1H8bz5zy0+rC963Cgr9iNXQ4T9ncSjC2fkF9BQfw==", + "dependencies": { + "@webcomponents/shadycss": "^1.9.1" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-babel/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-babel/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-node-resolve/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-node-resolve/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/@rollup/plugin-replace": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.1.0.tgz", + "integrity": "sha512-pA3XRUrSKybVYqmH5TqWNZpGxF+VV+1GrYchKgCNIj2vsSOX7CVm2RCtx8p2nrC7xvkziYyK+lSi74T93MU3YA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/@rollup/pluginutils": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz", + "integrity": "sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dev": true, + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", + "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==", + "dev": true + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" + }, + "node_modules/@vaadin-component-factory/vcf-nav": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@vaadin-component-factory/vcf-nav/-/vcf-nav-1.0.6.tgz", + "integrity": "sha512-TKgNqpbO6QtXEDCCXeF2LT59l1jshDEwS+ErFR1axuiol+8ihAbvckO62WtfqhlKd67dwipjNDGic/D4GAyBhg==", + "dependencies": { + "@vaadin/vaadin-lumo-styles": "^v23.0.0", + "lit": "^v2.0.0" + } + }, + "node_modules/@vaadin/accordion": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/accordion/-/accordion-23.3.8.tgz", + "integrity": "sha512-/XJ3hZdKbsovaCMwIHpOWWeZmHz+L6LE5Nr+0good8d9joiCGkmLPwxqRweepjCO82Hlmjrn5SUwcsD0vwnNTQ==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/details": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/app-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/app-layout/-/app-layout-23.3.8.tgz", + "integrity": "sha512-SHpvSOjf3wvjuufmvkpwPitSumgZDZculQikjjg7X+NqBsJsdz1duUYBbHABlYSK4J9qC1kopabq54/8w5Uk+A==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/avatar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/avatar/-/avatar-23.3.8.tgz", + "integrity": "sha512-ky4FS4/va3cB2cHecsSh+muGpCCtDqHJmszDqPF/zDOp+dm1ENVHoc+zW41b7t29cL+8L+ifZcYmRhJsEbcj+g==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/item": "~23.3.8", + "@vaadin/list-box": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/tooltip": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/avatar-group": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/avatar-group/-/avatar-group-23.3.8.tgz", + "integrity": "sha512-v7VS6PBnTKWeDIQGD+r0AKgdpe/vUbYZNIOXL34DthysBeG8/xYrXXKZ41hmla5IKSuPX8p2nyU3yjEeWjKrCw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/avatar": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/item": "~23.3.8", + "@vaadin/list-box": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/bundles": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/bundles/-/bundles-23.3.8.tgz", + "integrity": "sha512-WZTnlztUYrVWq8gWXjoimYGaghOZGVOmHKLHh5Ac1HnQroae/qyoaAyw7kO1vJqZW+tyOrlwnt4W9fN7NZd9eQ==", + "peerDependencies": { + "@polymer/iron-flex-layout": "3.0.1", + "@polymer/iron-icon": "3.0.1", + "@polymer/iron-iconset-svg": "3.0.1", + "@polymer/iron-media-query": "3.0.1", + "@polymer/iron-meta": "3.0.1", + "@polymer/polymer": "3.5.1", + "@vaadin/accordion": "23.3.8", + "@vaadin/app-layout": "23.3.8", + "@vaadin/avatar": "23.3.8", + "@vaadin/avatar-group": "23.3.8", + "@vaadin/board": "23.3.8", + "@vaadin/button": "23.3.8", + "@vaadin/charts": "23.3.8", + "@vaadin/checkbox": "23.3.8", + "@vaadin/checkbox-group": "23.3.8", + "@vaadin/combo-box": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/confirm-dialog": "23.3.8", + "@vaadin/context-menu": "23.3.8", + "@vaadin/cookie-consent": "23.3.8", + "@vaadin/crud": "23.3.8", + "@vaadin/custom-field": "23.3.8", + "@vaadin/date-picker": "23.3.8", + "@vaadin/date-time-picker": "23.3.8", + "@vaadin/details": "23.3.8", + "@vaadin/dialog": "23.3.8", + "@vaadin/email-field": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/field-highlighter": "23.3.8", + "@vaadin/form-layout": "23.3.8", + "@vaadin/grid": "23.3.8", + "@vaadin/grid-pro": "23.3.8", + "@vaadin/horizontal-layout": "23.3.8", + "@vaadin/icon": "23.3.8", + "@vaadin/icons": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/integer-field": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/list-box": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/login": "23.3.8", + "@vaadin/map": "23.3.8", + "@vaadin/menu-bar": "23.3.8", + "@vaadin/message-input": "23.3.8", + "@vaadin/message-list": "23.3.8", + "@vaadin/multi-select-combo-box": "23.3.8", + "@vaadin/notification": "23.3.8", + "@vaadin/number-field": "23.3.8", + "@vaadin/overlay": "23.3.8", + "@vaadin/password-field": "23.3.8", + "@vaadin/polymer-legacy-adapter": "23.3.8", + "@vaadin/progress-bar": "23.3.8", + "@vaadin/radio-group": "23.3.8", + "@vaadin/rich-text-editor": "23.3.8", + "@vaadin/scroller": "23.3.8", + "@vaadin/select": "23.3.8", + "@vaadin/split-layout": "23.3.8", + "@vaadin/tabs": "23.3.8", + "@vaadin/tabsheet": "23.3.8", + "@vaadin/text-area": "23.3.8", + "@vaadin/text-field": "23.3.8", + "@vaadin/time-picker": "23.3.8", + "@vaadin/tooltip": "23.3.8", + "@vaadin/upload": "23.3.8", + "@vaadin/vaadin-development-mode-detector": "2.0.5", + "@vaadin/vaadin-list-mixin": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8", + "@vaadin/vaadin-usage-statistics": "2.1.2", + "@vaadin/vertical-layout": "23.3.8", + "@vaadin/virtual-list": "23.3.8", + "cookieconsent": "3.1.1", + "highcharts": "9.2.2", + "lit": "2.6.1", + "ol": "6.13.0", + "quickselect": "2.0.0", + "rbush": "3.0.1" + }, + "peerDependenciesMeta": { + "@polymer/iron-flex-layout": { + "optional": true + }, + "@polymer/iron-icon": { + "optional": true + }, + "@polymer/iron-iconset-svg": { + "optional": true + }, + "@polymer/iron-media-query": { + "optional": true + }, + "@polymer/iron-meta": { + "optional": true + }, + "@polymer/polymer": { + "optional": true + }, + "@vaadin/accordion": { + "optional": true + }, + "@vaadin/app-layout": { + "optional": true + }, + "@vaadin/avatar": { + "optional": true + }, + "@vaadin/avatar-group": { + "optional": true + }, + "@vaadin/board": { + "optional": true + }, + "@vaadin/button": { + "optional": true + }, + "@vaadin/charts": { + "optional": true + }, + "@vaadin/checkbox": { + "optional": true + }, + "@vaadin/checkbox-group": { + "optional": true + }, + "@vaadin/combo-box": { + "optional": true + }, + "@vaadin/component-base": { + "optional": true + }, + "@vaadin/confirm-dialog": { + "optional": true + }, + "@vaadin/context-menu": { + "optional": true + }, + "@vaadin/cookie-consent": { + "optional": true + }, + "@vaadin/crud": { + "optional": true + }, + "@vaadin/custom-field": { + "optional": true + }, + "@vaadin/date-picker": { + "optional": true + }, + "@vaadin/date-time-picker": { + "optional": true + }, + "@vaadin/details": { + "optional": true + }, + "@vaadin/dialog": { + "optional": true + }, + "@vaadin/email-field": { + "optional": true + }, + "@vaadin/field-base": { + "optional": true + }, + "@vaadin/field-highlighter": { + "optional": true + }, + "@vaadin/form-layout": { + "optional": true + }, + "@vaadin/grid": { + "optional": true + }, + "@vaadin/grid-pro": { + "optional": true + }, + "@vaadin/horizontal-layout": { + "optional": true + }, + "@vaadin/icon": { + "optional": true + }, + "@vaadin/icons": { + "optional": true + }, + "@vaadin/input-container": { + "optional": true + }, + "@vaadin/integer-field": { + "optional": true + }, + "@vaadin/item": { + "optional": true + }, + "@vaadin/list-box": { + "optional": true + }, + "@vaadin/lit-renderer": { + "optional": true + }, + "@vaadin/login": { + "optional": true + }, + "@vaadin/map": { + "optional": true + }, + "@vaadin/menu-bar": { + "optional": true + }, + "@vaadin/message-input": { + "optional": true + }, + "@vaadin/message-list": { + "optional": true + }, + "@vaadin/multi-select-combo-box": { + "optional": true + }, + "@vaadin/notification": { + "optional": true + }, + "@vaadin/number-field": { + "optional": true + }, + "@vaadin/overlay": { + "optional": true + }, + "@vaadin/password-field": { + "optional": true + }, + "@vaadin/polymer-legacy-adapter": { + "optional": true + }, + "@vaadin/progress-bar": { + "optional": true + }, + "@vaadin/radio-group": { + "optional": true + }, + "@vaadin/rich-text-editor": { + "optional": true + }, + "@vaadin/scroller": { + "optional": true + }, + "@vaadin/select": { + "optional": true + }, + "@vaadin/split-layout": { + "optional": true + }, + "@vaadin/tabs": { + "optional": true + }, + "@vaadin/tabsheet": { + "optional": true + }, + "@vaadin/text-area": { + "optional": true + }, + "@vaadin/text-field": { + "optional": true + }, + "@vaadin/time-picker": { + "optional": true + }, + "@vaadin/tooltip": { + "optional": true + }, + "@vaadin/upload": { + "optional": true + }, + "@vaadin/vaadin-development-mode-detector": { + "optional": true + }, + "@vaadin/vaadin-list-mixin": { + "optional": true + }, + "@vaadin/vaadin-lumo-styles": { + "optional": true + }, + "@vaadin/vaadin-themable-mixin": { + "optional": true + }, + "@vaadin/vaadin-usage-statistics": { + "optional": true + }, + "@vaadin/vertical-layout": { + "optional": true + }, + "@vaadin/virtual-list": { + "optional": true + }, + "cookieconsent": { + "optional": true + }, + "highcharts": { + "optional": true + }, + "lit": { + "optional": true + }, + "ol": { + "optional": true + }, + "quickselect": { + "optional": true + }, + "rbush": { + "optional": true + } + } + }, + "node_modules/@vaadin/button": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/button/-/button-23.3.8.tgz", + "integrity": "sha512-22Fx70y6hPDgVQhDyYz/0YxpLm8CKnFErHvW/k59iVLNwT4IwRZYUjqudgwIowEySsJb/2634ivH4LtqDmuj0g==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/checkbox": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/checkbox/-/checkbox-23.3.8.tgz", + "integrity": "sha512-YNIb/D0Kx+tMaD+DDP0KzsUF/qSq88zPyvM3qN0J6fTsz2cpwO0lO0o4HKUgefU+HiqAKrLzVqr9GWUS7mJQhw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/checkbox-group": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/checkbox-group/-/checkbox-group-23.3.8.tgz", + "integrity": "sha512-6WLEuARNj/lYgFf0saj4udX7m6ZAPp2l7nhqDoWV37h37aDFATkWgY/su//yEU2WSxtBcmqedWhNzolnRurWnQ==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/checkbox": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/combo-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/combo-box/-/combo-box-23.3.8.tgz", + "integrity": "sha512-ZJVk/mhXzu3AC0KyM6QGnlet1c4d5xyQ7J418CASAUmdccj2xwELiWo3ppHcKfpwqeF1qSzid0aco4TWsDEoTw==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/input-container": "~23.3.8", + "@vaadin/item": "~23.3.8", + "@vaadin/lit-renderer": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/common-frontend": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@vaadin/common-frontend/-/common-frontend-0.0.17.tgz", + "integrity": "sha512-M4tg10cYgdDqQAXfGfXpQ90eHm+xL6ynAFEDgtc2IxXVWXKYU8jGK08SM5yOcZ4wDk0ETyHMtQlKUPDNkz6Qfw==", + "dependencies": { + "tslib": "^2.3.1" + }, + "peerDependencies": { + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/component-base": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/component-base/-/component-base-23.3.8.tgz", + "integrity": "sha512-N0ewZPUbV8Nt5Nup45NK3dvsAzzlaSyeL89CNad1UNP9jIdnXwcYVNBrupaXKT4aNmo1+RGc7+hC3Ve6wdxTOg==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/vaadin-development-mode-detector": "^2.0.0", + "@vaadin/vaadin-usage-statistics": "^2.1.0", + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/confirm-dialog": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/confirm-dialog/-/confirm-dialog-23.3.8.tgz", + "integrity": "sha512-fK3mo5fj1DQGt1Re/EflULUVmeyqy5+jLZ/jJqjQFwYSIfjR7/UJfirM7a9i5f/Xt4Mrx6sETlWfMuJE30Wu/Q==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/dialog": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/context-menu": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/context-menu/-/context-menu-23.3.8.tgz", + "integrity": "sha512-nyBu0Cz3zvgi9lnL+IM44VuZ6pj5Fd6mQvGfqmpXaUVycM3ZrR7XDmjBUZqI6v89ULNvmRHZyqZRvcsULyDYXg==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/item": "~23.3.8", + "@vaadin/list-box": "~23.3.8", + "@vaadin/lit-renderer": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/custom-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/custom-field/-/custom-field-23.3.8.tgz", + "integrity": "sha512-JXz3nc3dSzY8gds3HFKA9LQUkWBHvZVFn47yDevKQdjwY48/loMyTJoiRuTZ5vHQZk0599HcacCFLj4yRbNVeg==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/date-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/date-picker/-/date-picker-23.3.8.tgz", + "integrity": "sha512-UY8nrLVC6RMV7cKhWDHP9nUu0fC2YG5Mb9SL4622d8wE0nJox9oPh61e/Qa1rj1bUL7hxl/AqgCS+9pbX5O3eQ==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.2.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/input-container": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/date-time-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/date-time-picker/-/date-time-picker-23.3.8.tgz", + "integrity": "sha512-GOW6RElVYJbZMIQQGaF4rLu7Sy1XuW7HH0Lz6X9S86xAJjjq1r8egzrLaFVIBfPFyOe+zbUHJvpkBNrvuG0Atw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/custom-field": "~23.3.8", + "@vaadin/date-picker": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/time-picker": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/details": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/details/-/details-23.3.8.tgz", + "integrity": "sha512-3qZ12xJjsRMrFNzzk1sbGnl1TRmEiXmgQSr2M0A8EC6/rZIAb9MynIm4HttrV16Qbug7JP3O9/USd2QM7zC4Sg==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/dialog": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/dialog/-/dialog-23.3.8.tgz", + "integrity": "sha512-JWqijQz4I7s6RXACNW5ttkbTZe9kr3FqRw943S/eJitBCr6bNnB/ct183gcTKE2u49Gdvl8Igto95lVy8sPkLg==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/lit-renderer": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/email-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/email-field/-/email-field-23.3.8.tgz", + "integrity": "sha512-TvRvEm1Xn3PY3AVdujGsFibpbPworYeOzv/1RssUHvhXPROstjAAYzTaGbAbUtVlK7fF1dt1egUeae7pi5WOEg==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/text-field": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/field-base": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/field-base/-/field-base-23.3.8.tgz", + "integrity": "sha512-Ixb5b/X6kjmY5zt9/0796JSDL0HoL00YBwFpoLv8zrGNI9eIkRJzvaJYYYRD8z/qKFZKJesn741LH2tGtZ05qg==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/field-highlighter": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/field-highlighter/-/field-highlighter-23.3.8.tgz", + "integrity": "sha512-7L63B69AzRwqTLKbN3XuA427XbJng/mAWtjOU+8utzM4UJZzz7Vo6mPKqM2LGa1qL65eqlTFF0CveDdIW3UxfA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8", + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/form-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/form-layout/-/form-layout-23.3.8.tgz", + "integrity": "sha512-V5WHswXN+KfuBpX4DwCFs4jBxRItllpk8Ki6VFZNVmQQh3060bRYSLf5jEgO8ddR+XkIsy4f8RuBh9mpfEDbiQ==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/grid": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/grid/-/grid-23.3.8.tgz", + "integrity": "sha512-o1TuHsl9u5eSe5IrqUKkVdv8Tm43cvY8Cfs/WOViBOjAT8VXck1ctUDGdQZMYEuIKZocYWEnNA0+9KSbBeocbQ==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/checkbox": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/lit-renderer": "~23.3.8", + "@vaadin/text-field": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/horizontal-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/horizontal-layout/-/horizontal-layout-23.3.8.tgz", + "integrity": "sha512-mnDMEUXhrvozFJofl/PGbjFlFMHxC5v/Nwk/ndla1EuizxTJkNf/DdXCJfwqrMALXOYkdXO2GV++MBs5PxkXxg==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/icon": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/icon/-/icon-23.3.8.tgz", + "integrity": "sha512-PT6nWZYY5sIuUBpPKlpwz/n/QdSEKszSEhDqdDGB+OS19Dhn+o4Ackw0QtmeEcnuX2brl8z+Ln10WaWasz4/vA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8", + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/icons": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/icons/-/icons-23.3.8.tgz", + "integrity": "sha512-jR4tQyOT3mJffZVDgDEdcfMapw+UWvbTefjIoNJeqgXLwEJ18Iku9D0W2nEGp+7tpmkNPW2rQZsmg8KTPi6GQQ==", + "dependencies": { + "@polymer/iron-icon": "^3.0.0", + "@polymer/iron-iconset-svg": "^3.0.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/icon": "~23.3.8" + } + }, + "node_modules/@vaadin/input-container": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/input-container/-/input-container-23.3.8.tgz", + "integrity": "sha512-soMGphDbEeH9WgjTDRZih80wGcABL+rsUGsftKYs/L6nK39ZHCFoIWd/X5bQNU6kvIuFtQZwgf6Grix8KwrSfw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/integer-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/integer-field/-/integer-field-23.3.8.tgz", + "integrity": "sha512-ElQcZgOAGCtwkMgiTLC2cvKDC3FVu99078pqBMVyrpXqb8jktpKM1c5WOok1+nvfE5kC6taw3jVcwI05Nf6uEg==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/number-field": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8" + } + }, + "node_modules/@vaadin/item": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/item/-/item-23.3.8.tgz", + "integrity": "sha512-nqMc6OXiesQHbEeewiOPL4LOmzNaQyiRMrgHsMSlbtur1F5wQCiKsiVqWYPS+/adhtcS8TPn+9ppliyH5AhVag==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/list-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/list-box/-/list-box-23.3.8.tgz", + "integrity": "sha512-sEPkoxPQcqSSM0UCEEAmchUMC5pjbMX3WNzeo3YV+c5+H/EGR9hFeYJPYhmS5fmcw1Z1qsKjsSDL7LzVzSGwjQ==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/item": "~23.3.8", + "@vaadin/vaadin-list-mixin": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/lit-renderer": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/lit-renderer/-/lit-renderer-23.3.8.tgz", + "integrity": "sha512-3RIDgz7oym2iXG0jVMEsjKmVkpaIPm8maQCwhJcp6ANQmDg1lgQtoubvMTJYAVCs6luosQM2Uk45E4BLzGpBqw==", + "dependencies": { + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/login": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/login/-/login-23.3.8.tgz", + "integrity": "sha512-M42NGONCSrtdkiVrB5C5mdtyETXG4e+ZpAjnLVx0anFdChu8WTug4FV6gqOgqrPf4sOsF3tOsruP6hiwr3BcTw==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/password-field": "~23.3.8", + "@vaadin/text-field": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/menu-bar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/menu-bar/-/menu-bar-23.3.8.tgz", + "integrity": "sha512-i4jfGST4tIbEyvcuoO8EQGoLDMjzmT/UbtJB2nTebzqUiY1z0Og69+AaY7eQQS7sOTmtC4wjSW+4difDhYVRxQ==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/context-menu": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/message-input": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/message-input/-/message-input-23.3.8.tgz", + "integrity": "sha512-y9sgt9gbHrtyNO0kddR2WdjG/AcQPIFVI0jysAfvKoIKBcUwFAE35sZyh7Ef1EOKZy1691XpqTVhXY+83qsz8A==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/text-area": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/message-list": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/message-list/-/message-list-23.3.8.tgz", + "integrity": "sha512-+dpe2ww0cg99Ir5NFDAUzHfIN3jyA+WF89grbWlDaVnBZonEijdrJUgCGKFubl1qu5ZHiXHE4vKPGMGmopGV0g==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/avatar": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/multi-select-combo-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/multi-select-combo-box/-/multi-select-combo-box-23.3.8.tgz", + "integrity": "sha512-isPK52yYjTfzHq7LZjhEH0r6cVr2E7weKSK3HTEtN3DrkrjLHuW1dkbM7IBVOeYHEejknpIe6hsuykLX+kf9Tw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/combo-box": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/input-container": "~23.3.8", + "@vaadin/lit-renderer": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/notification": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/notification/-/notification-23.3.8.tgz", + "integrity": "sha512-3uZzeDy1lbHbO7a8XYFwgBJrR2IrYKvJFs+KGag26RZRf8saLDMjqZNoM1NgdJy4I+Jtx5W2SzQx2TA6hfg52w==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/lit-renderer": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8", + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/number-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/number-field/-/number-field-23.3.8.tgz", + "integrity": "sha512-0K+hVjTS8OJV7GDe6Nbr9dOBkDl/bO2GR2/L2vlTaTcgLXl9UXIyzqa0+ZxLLjpe4yAHFU8niDdN6MmlWjY+0Q==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/input-container": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/overlay": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/overlay/-/overlay-23.3.8.tgz", + "integrity": "sha512-sngdoFTrcEvz0nE3T0nK9CR2aO8AU6xySHugP1LADxwjwAYGAWeSljzf8yk5520bBIOz+7M0NbFSk7qqJhpK2Q==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/password-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/password-field/-/password-field-23.3.8.tgz", + "integrity": "sha512-jNVdhFMUi12wnfHLzG23VuWLcWFMatZ0fRjpOxknGQqm0PI58XV5XUIJDbayPFhhFPy50ne1riO5X9Lo0xkAxg==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/text-field": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/polymer-legacy-adapter": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/polymer-legacy-adapter/-/polymer-legacy-adapter-23.3.8.tgz", + "integrity": "sha512-joAmp1nHTKSfmJfqXAxnAebFiyOXiZv4F07d5Aks38HFIZHrMUpynGYvCqaGTeIdiG2xgKXHs0wl5vJg85e5vw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/vaadin-themable-mixin": "~23.3.8", + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/progress-bar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/progress-bar/-/progress-bar-23.3.8.tgz", + "integrity": "sha512-BNx3aOjSrVsZuZ3RMMMynPXQfnjmCM+vt2l7OoeqB0xNRswEU+DPHeAbYYms1oAkPY0y/BeTI8vijGk+1rNgGg==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/radio-group": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/radio-group/-/radio-group-23.3.8.tgz", + "integrity": "sha512-T4/SWFUHK8G+9Y/hfM28uvp083pDuxGgepTBh7f2Eh52cN/d4ehhsmEsrvzkaZdx2ZsKEJUPzmi+tIGB2qq8hA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/router": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@vaadin/router/-/router-1.7.4.tgz", + "integrity": "sha512-B4JVtzFVUMlsjuJHNXEMfNZrM4QDrdeOMc6EEigiHYxwF82py6yDdP6SWP0aPoP3f6aQHt51tLWdXSpkKpWf7A==", + "dependencies": { + "@vaadin/vaadin-usage-statistics": "^2.1.0", + "path-to-regexp": "2.4.0" + } + }, + "node_modules/@vaadin/scroller": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/scroller/-/scroller-23.3.8.tgz", + "integrity": "sha512-HuzjgZNTTKfy56RODNC2nseJF5PP6AcqasndU1ivAzAFzf4MQmNyRImcmAcz3LeXJz7QCmhyaMhxKh6jXzLSSA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/select": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/select/-/select-23.3.8.tgz", + "integrity": "sha512-5D0/QzUE+gSRyd0kbQEi/wxjYU34dMtnrarJWSzJogpHQwsmJTLPKwjVV4qp9mq1AQzlE5Emdv0bD6/btt2EfA==", + "dependencies": { + "@polymer/polymer": "^3.2.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/input-container": "~23.3.8", + "@vaadin/item": "~23.3.8", + "@vaadin/list-box": "~23.3.8", + "@vaadin/lit-renderer": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-list-mixin": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/split-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/split-layout/-/split-layout-23.3.8.tgz", + "integrity": "sha512-uSMtdyfglrqHE/9lrubYGXELHdGd2pzAcSc5aLXhRidV2Qg+IOGb7evq2y3sXD+UAn2Vy1nXpZmR0uB7Dn+rHA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/tabs": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/tabs/-/tabs-23.3.8.tgz", + "integrity": "sha512-kKakZ0mdO6G9K7CN/IhUD/3BbqCHBAxTHmreltw12hhoJ6ue48rqhdNPlLW+XU2a7dzcOvwn5xYGnWDpSe5hsg==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/item": "~23.3.8", + "@vaadin/vaadin-list-mixin": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/tabsheet": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/tabsheet/-/tabsheet-23.3.8.tgz", + "integrity": "sha512-x4423gjZEmibh2h0s0/2Xs/poohW+JRpGPxpK06sfzEFUc+kAIuTBFtEdk2Z8IKAs6hSCCLf0rEWDykqvk+Auw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/scroller": "~23.3.8", + "@vaadin/tabs": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/text-area": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/text-area/-/text-area-23.3.8.tgz", + "integrity": "sha512-p4NUNPtCaGFanbbSy6rdjtJuMgk0slSUhDtw4i8C/OkunpBxlYD98VTajLdWCovUXmL8cUAk4Tfs4pe6d405WA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/input-container": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/text-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/text-field/-/text-field-23.3.8.tgz", + "integrity": "sha512-rASUOn7pnSRZWX+td7QSBMThbPEp9iWDNkZEunhuOObGQybnSI+7v8dJUmxZDqsA7uHU6HcyVW+sfD8l0RF/cw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/input-container": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/time-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/time-picker/-/time-picker-23.3.8.tgz", + "integrity": "sha512-95V2FLm1z2IcCYY1clUY9SNjEu/1mKQOl7fkBNJcjqEx2TxvUAduR3h4aU0VDamnAfSwgGI7PWSUjWjKfsmjOQ==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/combo-box": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/field-base": "~23.3.8", + "@vaadin/input-container": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/tooltip": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/tooltip/-/tooltip-23.3.8.tgz", + "integrity": "sha512-a1+pjrr4Xv/sh065wP3eLvWM8L5gs/29cWO3y1SbN3EC5xr+XtsAvn7qBTDWSlPypUNKKgwBxZjEDflJ64tgaw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/upload": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/upload/-/upload-23.3.8.tgz", + "integrity": "sha512-93J+IDXMKw0XTa7lZPIEF5ZQ9AvVSyxj6emTgDiMEYIuUTwPZT7Oe7iJo8pvFO/dWpQSs6ZBqcUcz3cjgXF7xA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/button": "~23.3.8", + "@vaadin/component-base": "~23.3.8", + "@vaadin/progress-bar": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-accordion": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-accordion/-/vaadin-accordion-23.3.8.tgz", + "integrity": "sha512-TpXTA204MG5sPXWbqLsCa/aeMYRVEO2HRCFksHBpT5gtxEFZ7uy7PGc2FXD3V3/PR8OgZta8ubNcEbYzZbH6Fg==", + "dependencies": { + "@vaadin/accordion": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-app-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-app-layout/-/vaadin-app-layout-23.3.8.tgz", + "integrity": "sha512-J07LoDRx/8pyWvaobLikvEW0BIwYyskwgVLep1p2s4XbN9fwqqLNKBRzeYfWlkJMF+pv6RPsJuLsYvLY70vHGg==", + "dependencies": { + "@vaadin/app-layout": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-avatar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-avatar/-/vaadin-avatar-23.3.8.tgz", + "integrity": "sha512-iEduoqSKO09MmK6XD231L9WIBIiY1IgzZZxQtt96OIXGjFgRek9+v2jCPCPride9GIo47kxJCh6TcS2lRGG2vA==", + "dependencies": { + "@vaadin/avatar": "~23.3.8", + "@vaadin/avatar-group": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-button": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-button/-/vaadin-button-23.3.8.tgz", + "integrity": "sha512-f3RlJgdwsg7XuCIJTjhkK07yLqC/Ta/45Z3kSixRkNZeNFBTz1/HHN3OfB2vnDnhvQ6zPVqYQHeLrwh8+gQetA==", + "dependencies": { + "@vaadin/button": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-checkbox": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-checkbox/-/vaadin-checkbox-23.3.8.tgz", + "integrity": "sha512-Z4rCKBCVcKOp/58njpEEyvH5Gq13PRmrrOiFyeLOO2K3c6s3xM0E5tYycBGwaW6d25Y1Z38Olo5qN0pZa03arA==", + "dependencies": { + "@vaadin/checkbox": "~23.3.8", + "@vaadin/checkbox-group": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-combo-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-combo-box/-/vaadin-combo-box-23.3.8.tgz", + "integrity": "sha512-Ob9PW60B7svycRQcvnLET8OcySM+c+3ec7yG4lEDliOsJHcxqQwPRyKVIWKOLzheCdPWHY/zi4OsQYeXPXBvaQ==", + "dependencies": { + "@vaadin/combo-box": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-confirm-dialog": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-confirm-dialog/-/vaadin-confirm-dialog-23.3.8.tgz", + "integrity": "sha512-/gIr7QT4MemjTAITar9yDAgTTL9CwPJsFw5FPDnDnmWf3dCazgrHrL0GaLK89D0e/+RR1NTe4Be0YzvUXoltug==", + "dependencies": { + "@vaadin/confirm-dialog": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-context-menu": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-context-menu/-/vaadin-context-menu-23.3.8.tgz", + "integrity": "sha512-CL0mzcA16rsDaNrSKg9alQ3hLuDjgkALVmhzfktq9WAfg4rPvh2BdY13djKb8NUx0Br5qcaoavTOhEt1mibcMQ==", + "dependencies": { + "@vaadin/context-menu": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-custom-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-custom-field/-/vaadin-custom-field-23.3.8.tgz", + "integrity": "sha512-ejvZ+W7gQZDLTmLh/cSUlSc+QQogLZa4s4uUvcxR+syznHUPg8ZQLcjYuJGzfo2nrZo/JDyI0Xkk+uRVQCg3Og==", + "dependencies": { + "@vaadin/custom-field": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-date-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-date-picker/-/vaadin-date-picker-23.3.8.tgz", + "integrity": "sha512-vKirMDoPozHgJ4k7t2n2djy41LYvfCYvDiad681kYughOt4T+R0uMFLws+WxghUoTZa2RCyKLYqp/mYzRO260w==", + "dependencies": { + "@vaadin/date-picker": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-date-time-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-date-time-picker/-/vaadin-date-time-picker-23.3.8.tgz", + "integrity": "sha512-mouw6PNgVAXvUVMIWqApRQ0z9uEUrtsGAEvsAPzc2btvruCjq/AVnihHd93bpDKd6hAWETqK977CER15jFysaA==", + "dependencies": { + "@vaadin/date-time-picker": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-details": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-details/-/vaadin-details-23.3.8.tgz", + "integrity": "sha512-+7gKrHL8+q08CcaR1Dsl6aJbKY0Ac59xn/s2grVSNBmHJkHPP1VK/g4ly9bckiBjy1QjHDp3J2Ws1qY+q2FMwg==", + "dependencies": { + "@vaadin/details": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-development-mode-detector": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-development-mode-detector/-/vaadin-development-mode-detector-2.0.6.tgz", + "integrity": "sha512-N6a5nLT/ytEUlpPo+nvdCKIGoyNjPsj3rzPGvGYK8x9Ceg76OTe1xI/GtN71mRW9e2HUScR0kCNOkl1Z63YDjw==" + }, + "node_modules/@vaadin/vaadin-dialog": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-dialog/-/vaadin-dialog-23.3.8.tgz", + "integrity": "sha512-M/KFCeuG5u0iq/JMtoL2Q/2OI+CxO3D5g891caW1kqveZOwif5jJY1WtUjnZDOFRpv8mlvazBsVIFte3QttrsA==", + "dependencies": { + "@vaadin/dialog": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-form-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-form-layout/-/vaadin-form-layout-23.3.8.tgz", + "integrity": "sha512-ZNi9qspjH2fsqzGRR49fGbjeQIdwirAwZQvGyahF+g4RW/9emNcrmx29+SXwyP6cYzh2FzcYwmFC06Y8mnOIvg==", + "dependencies": { + "@vaadin/form-layout": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-grid": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-grid/-/vaadin-grid-23.3.8.tgz", + "integrity": "sha512-Jk2wLJqh5/MF+sNRleaZxDJj8D66wgXEMpo9Gi48IAHFCIljgR3fRw6IylnBOQ3r0ChGSftmRIAW/SRN8eMkMA==", + "dependencies": { + "@vaadin/grid": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-icon": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-icon/-/vaadin-icon-23.3.8.tgz", + "integrity": "sha512-kbVC1TO88jau7przMx2s0z+jUnXI7Xc1i6aVyuonEYe/fWal7OT8JwsGSdXxQt0gHylKn46lIBg2lNlLbi62KA==", + "dependencies": { + "@vaadin/icon": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-icons": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-icons/-/vaadin-icons-23.3.8.tgz", + "integrity": "sha512-NoJxorZ4cKrujJqIARyfOaI0AYQEqF/D6i0X7VgloD1EJEUoWD/vkarEMdIChw7ikSTzN/jreeA1RfkRffFLaQ==", + "dependencies": { + "@vaadin/icons": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-item": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-item/-/vaadin-item-23.3.8.tgz", + "integrity": "sha512-F7uDZ9EO7Wz0Mw0gRo0kpxzVS9WmU1JEMppBrxfKzByyldolGO8XoTPKjwwxMeriN7V7jBv3dnSfc4hHfFcJfg==", + "dependencies": { + "@vaadin/item": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-list-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-list-box/-/vaadin-list-box-23.3.8.tgz", + "integrity": "sha512-NkKCI4FAqW59xYTdXYPKRxRiYYNJZk6/fqcclWRObtJUHc5EAF3MtzgaCH+p9FHIjsAsJkJmxKBP3fW5KcSmiw==", + "dependencies": { + "@vaadin/list-box": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-list-mixin": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-list-mixin/-/vaadin-list-mixin-23.3.8.tgz", + "integrity": "sha512-rUNf7ntDNOfbX7oH59rFCnVX+zjsoifctcNWTI2kZ/G/MGmETWsQnKqlBOGpLYsw7CCzG6nYDxbRL/PESME6Cw==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-login": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-login/-/vaadin-login-23.3.8.tgz", + "integrity": "sha512-HrWs9+jqm5Rg+Qhca5MgsH6QdbzYyadPBJrr96MBHR584dOYHtftpW/RuRa4l0gOwRL8Gmv7YildaqxjbZgtYg==", + "dependencies": { + "@vaadin/login": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-lumo-styles": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-lumo-styles/-/vaadin-lumo-styles-23.3.8.tgz", + "integrity": "sha512-N6nfNCF/H3Vg1gemJZCeMXpWHV7TvUdqbFjKkFIipeI/VXuRXo1icAjGMQUbhs2DZnb89xsP+krRtn5lcfbeow==", + "dependencies": { + "@polymer/iron-icon": "^3.0.0", + "@polymer/iron-iconset-svg": "^3.0.0", + "@polymer/polymer": "^3.0.0", + "@vaadin/icon": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-material-styles": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-material-styles/-/vaadin-material-styles-23.3.8.tgz", + "integrity": "sha512-mIEngTejkEyDcgIvovIkXBEgVrH4Qx0JMSwGirjp97LRUAXTe5Lz2tzfTHRjLCccDkSdQaQNt4f9jCwhj6HcKA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-menu-bar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-menu-bar/-/vaadin-menu-bar-23.3.8.tgz", + "integrity": "sha512-7ghRXR2bus3d5cap/iAZ5DA2RLjH7d5jg/CC3d0IvfSdUF+VALWDsB0ui36ZKNLprGHrt5iEQyY5bGSIjpMwMg==", + "dependencies": { + "@vaadin/menu-bar": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-messages": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-messages/-/vaadin-messages-23.3.8.tgz", + "integrity": "sha512-O8Pic1UV9Myh7hHCE+Oar3Fo9H3XiTZcmxgRPwsX9MFM7KPoaQ2vYfAQfclxnqSCz7B+EgCI+Yqv42YpRXQavA==", + "dependencies": { + "@vaadin/message-input": "~23.3.8", + "@vaadin/message-list": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-notification": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-notification/-/vaadin-notification-23.3.8.tgz", + "integrity": "sha512-dwqCeSwa7Y+Z7W2H2HRaYekRWiWkJIee2d0SjtVDAMZd/EnGz7uSQ+tUKoGdGi/Xvo/5YNlN9qX7cfA0OWa8lA==", + "dependencies": { + "@vaadin/notification": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-ordered-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-ordered-layout/-/vaadin-ordered-layout-23.3.8.tgz", + "integrity": "sha512-oaL4fjVN6A0Bei56vmWWAB6TUWKGZZ+qNrH24R87FYpSG85SGkoH+B1mkv0RtmfyRxxH/jZNlnKbBVRbrtn+ag==", + "dependencies": { + "@vaadin/horizontal-layout": "~23.3.8", + "@vaadin/scroller": "~23.3.8", + "@vaadin/vertical-layout": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-overlay": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-overlay/-/vaadin-overlay-23.3.8.tgz", + "integrity": "sha512-alRKsG5YFcD0VduOR78pcQuqOI66FiY19pRuYB+tDPIX9RTfZOYc0wS51jNdCIIJXYog6vYU7owBwGYI2ezvBw==", + "dependencies": { + "@vaadin/overlay": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-progress-bar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-progress-bar/-/vaadin-progress-bar-23.3.8.tgz", + "integrity": "sha512-XS49afqNmc2SJwzCdTWHhNOIjycnyL/ojo5uO0XgAMWZV7y2pBINHxSxVv+tQJk/zPtgRcEyf05nP/HSysBJWg==", + "dependencies": { + "@vaadin/progress-bar": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-radio-button": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-radio-button/-/vaadin-radio-button-23.3.8.tgz", + "integrity": "sha512-LJ6aKo1ge1oj4xN7lQDmOoTYOMor94PFRZWuxRJOQV6dlELKaAU+R4EaYCwDy1Ip2Sqs3CevrK+oBm4vLoMDLQ==", + "dependencies": { + "@vaadin/radio-group": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-select": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-select/-/vaadin-select-23.3.8.tgz", + "integrity": "sha512-tKl6l+JcqpbJjq629EatvS5XFw7LI+kg/zQNMPTmH/1y88EciOZOPBc6vlSPKxB4D+8hIXetdOi49+iXeAt+Hw==", + "dependencies": { + "@vaadin/select": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-split-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-split-layout/-/vaadin-split-layout-23.3.8.tgz", + "integrity": "sha512-2qc3UwdaaHeGXFNbcWB4eCcb3ygZ+R3fP3q+NcOOV3qI6tk2rvLoekdnsxjXCp3ObtHx/YngfpOtn+Xl2B4BHg==", + "dependencies": { + "@vaadin/split-layout": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-tabs": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-tabs/-/vaadin-tabs-23.3.8.tgz", + "integrity": "sha512-FXzWtfzyp3m//MTk8qDfD9oQd7GgSAD976zs/3EIzHl2RpqO9UbKj3Y/mANoWQgFFcZidUlIfUfzrp86kfx2lw==", + "dependencies": { + "@vaadin/tabs": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-template-renderer": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-template-renderer/-/vaadin-template-renderer-23.3.8.tgz", + "integrity": "sha512-CzF9QwaFzlXYh6lgOA3LN/+hSk4w+SIav+gb4VDzv1jsB7hDOOmQOx7TpsWY3C5RfLk+12cwnUWkuE+FNHkxnQ==", + "dependencies": { + "@vaadin/polymer-legacy-adapter": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-text-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-text-field/-/vaadin-text-field-23.3.8.tgz", + "integrity": "sha512-MTrdLe055dE5FAh3vYEcqIMkPThAdJnx+Azu9WfZINB4iIXBqa5iFCLfdAJB/VEE+TvflSORH5km0bMXmmVAKw==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/email-field": "~23.3.8", + "@vaadin/integer-field": "~23.3.8", + "@vaadin/number-field": "~23.3.8", + "@vaadin/password-field": "~23.3.8", + "@vaadin/text-area": "~23.3.8", + "@vaadin/text-field": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-themable-mixin": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-themable-mixin/-/vaadin-themable-mixin-23.3.8.tgz", + "integrity": "sha512-ePzyNzxY7QqSO2hUSv0l1mjm58QhPTmD1DznKECNMIOFeOjZlw1eMVxtwTrahlvwtErLmCYIU3xRwjqB9R4Zig==", + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "lit": "^2.0.0" + } + }, + "node_modules/@vaadin/vaadin-time-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-time-picker/-/vaadin-time-picker-23.3.8.tgz", + "integrity": "sha512-EheRMIZylIes7xk6tbVJ8LDNDY0ae0WObEWg47255+GnN2rYVrxObeZyLLGSqoHdhQueaKNdaYt2sk0mzDfbig==", + "dependencies": { + "@vaadin/time-picker": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-upload": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-upload/-/vaadin-upload-23.3.8.tgz", + "integrity": "sha512-o2Oh59t9QoBW9IH9IzxpLozfH3EwID8UpZmr4VCeYxwTycLLQmvZ9cTWBoBQYIXrpa+HaTKWX+XTNFUCIHw6TQ==", + "dependencies": { + "@vaadin/upload": "~23.3.8" + } + }, + "node_modules/@vaadin/vaadin-usage-statistics": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-usage-statistics/-/vaadin-usage-statistics-2.1.2.tgz", + "integrity": "sha512-xKs1PvRfTXsG0eWWcImLXWjv7D+f1vfoIvovppv6pZ5QX8xgcxWUdNgERlOOdGt3CTuxQXukTBW3+Qfva+OXSg==", + "hasInstallScript": true, + "dependencies": { + "@vaadin/vaadin-development-mode-detector": "^2.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@vaadin/vaadin-virtual-list": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-virtual-list/-/vaadin-virtual-list-23.3.8.tgz", + "integrity": "sha512-Eir2bq9qGzVJ/QZZRnukW1vusM7IEQZmXEaN0Mtc4hAXu6hzbzZHhnGzsq+ouEDIFQIGP6iXz4rywB1+PUmJgw==", + "dependencies": { + "@vaadin/virtual-list": "~23.3.8" + } + }, + "node_modules/@vaadin/vertical-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vertical-layout/-/vertical-layout-23.3.8.tgz", + "integrity": "sha512-iIAmBA4c3ncXj85Ps/XY2fSeOWo0NAXSHvJZ5aLRrlxxTJx0D3fDOKzoyes9333FSzozHCF9E4fgAx3jgrgx6Q==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@vaadin/virtual-list": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/virtual-list/-/virtual-list-23.3.8.tgz", + "integrity": "sha512-u81uYO9ElknvhotZL/sqgmbjONZ0t1w1YhCCGLpDuKCftt2KK9txmO2jmarFwj4fO3ogY4OaGvWDkU3FetPiPA==", + "dependencies": { + "@polymer/polymer": "^3.0.0", + "@vaadin/component-base": "~23.3.8", + "@vaadin/lit-renderer": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "~23.3.8", + "@vaadin/vaadin-material-styles": "~23.3.8", + "@vaadin/vaadin-themable-mixin": "~23.3.8" + } + }, + "node_modules/@webcomponents/shadycss": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.11.0.tgz", + "integrity": "sha512-L5O/+UPum8erOleNjKq6k58GVl3fNsEQdSOyh0EUhNmi7tHUyRuCJy1uqJiWydWcLARE5IPsMoPYMZmUGrz1JA==" + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/async": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001359", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001359.tgz", + "integrity": "sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/construct-style-sheets-polyfill": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.1.0.tgz", + "integrity": "sha512-HBLKP0chz8BAY6rBdzda11c3wAZeCZ+kIG4weVC2NM3AXzxx09nhe8t0SQNdloAvg5GLuHwq/0SPOOSPvtCcKw==" + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/core-js-compat": { + "version": "3.23.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.3.tgz", + "integrity": "sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.0", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/browserslist": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.0.tgz", + "integrity": "sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001358", + "electron-to-chromium": "^1.4.164", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-js-compat/node_modules/update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, + "node_modules/date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.170", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.170.tgz", + "integrity": "sha512-rZ8PZLhK4ORPjFqLp9aqC4/S1j4qWFsPPz13xmWdrbBkU/LlxMcok+f+6f8YnQ57MiZwKtOaW15biZZsY5Igvw==", + "dev": true + }, + "node_modules/es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", + "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/line-awesome": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/line-awesome/-/line-awesome-1.3.0.tgz", + "integrity": "sha512-Y0YHksL37ixDsHz+ihCwOtF5jwJgCDxQ3q+zOVgaSW8VugHGTsZZXMacPYZB1/JULBi6BAuTCTek+4ZY/UIwcw==" + }, + "node_modules/lit": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.6.1.tgz", + "integrity": "sha512-DT87LD64f8acR7uVp7kZfhLRrHkfC/N4BVzAtnw9Yg8087mbBJ//qedwdwX0kzDbxgPccWRW6mFwGbRQIxy0pw==", + "dependencies": { + "@lit/reactive-element": "^1.6.0", + "lit-element": "^3.2.0", + "lit-html": "^2.6.0" + } + }, + "node_modules/lit-element": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.2.tgz", + "integrity": "sha512-6ZgxBR9KNroqKb6+htkyBwD90XGRiqKDHVrW/Eh0EZ+l+iC+u+v+w3/BA5NGi4nizAVHGYvQBHUDuSmLjPp7NQ==", + "dependencies": { + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.2.0" + } + }, + "node_modules/lit-html": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.6.1.tgz", + "integrity": "sha512-Z3iw+E+3KKFn9t2YKNjsXNEu/LRLI98mtH/C6lnFg7kvaqPIzPn124Yd4eT/43lyqrejpc5Wb6BHq3fdv4S8Rw==", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/merge-source-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", + "integrity": "sha512-PGSmS0kfnTnMJCzJ16BLLCEe6oeYCamKFFdQKshi4BmM6FUwipjVOcBFGxqtQtirtAG4iZvHlqST9CpZKqlRjA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mutexify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mutexify/-/mutexify-1.4.0.tgz", + "integrity": "sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg==", + "dev": true, + "dependencies": { + "queue-tick": "^1.0.0" + } + }, + "node_modules/nanobench": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nanobench/-/nanobench-2.1.1.tgz", + "integrity": "sha512-z+Vv7zElcjN+OpzAxAquUayFLGK3JI/ubCl0Oh64YQqsTGG09CGqieJVQw4ui8huDnnAgrvTv93qi5UaOoNj8A==", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^0.1.2", + "chalk": "^1.1.3", + "mutexify": "^1.1.0", + "pretty-hrtime": "^1.0.2" + }, + "bin": { + "nanobench": "run.js", + "nanobench-compare": "compare.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz", + "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/queue-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.0.tgz", + "integrity": "sha512-ULWhjjE8BmiICGn3G8+1L9wFpERNxkf8ysxkAer4+TFdRefDaXOCV5m92aMB9FtBVmn/8sETXLXY6BfW7hyaWQ==", + "dev": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-brotli": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-brotli/-/rollup-plugin-brotli-3.1.0.tgz", + "integrity": "sha512-vXRPVd9B1x+aaXeBdmLKNNsai9AH3o0Qikf4u0m1icKqgi3qVA4UhOfwGaPYoAHML1GLMUnR//PDhiMHXN/M6g==", + "dev": true, + "engines": { + "node": ">=11.7.0" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/strip-css-comments": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-css-comments/-/strip-css-comments-5.0.0.tgz", + "integrity": "sha512-943vUh0ZxvxO6eK+TzY2F4nVN7a+ZdRK4KIdwHaGMvMrXTrAsJBRudOR3Zi0bLTuVSbF0CQXis4uw04uCabWkg==", + "dev": true, + "dependencies": { + "is-regexp": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-css-comments/node_modules/is-regexp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz", + "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/tiny-invariant": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", + "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/transform-ast": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/transform-ast/-/transform-ast-2.4.4.tgz", + "integrity": "sha512-AxjeZAcIOUO2lev2GDe3/xZ1Q0cVGjIMk5IsriTy8zbWlsEnjeB025AhkhBJHoy997mXpLd4R+kRbvnnQVuQHQ==", + "dev": true, + "dependencies": { + "acorn-node": "^1.3.0", + "convert-source-map": "^1.5.1", + "dash-ast": "^1.0.0", + "is-buffer": "^2.0.0", + "magic-string": "^0.23.2", + "merge-source-map": "1.0.4", + "nanobench": "^2.1.1" + } + }, + "node_modules/transform-ast/node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/transform-ast/node_modules/magic-string": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.23.2.tgz", + "integrity": "sha512-oIUZaAxbcxYIp4AyLafV6OVKoB3YouZs0UTCJ8mOKBHNyJgGDaMJ4TgA+VylJh6fx7EQCC52XkbURxxG9IoJXA==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.1" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", + "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.15.9", + "postcss": "^8.4.18", + "resolve": "^1.22.1", + "rollup": "^2.79.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-checker": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.5.4.tgz", + "integrity": "sha512-T6y+OHXqwOjGrCErbhzg5x79NQZV46cgLwYTxuMQnDzAfA6skh2i8PIHcKks8ZlxopzbkvMb5vwc2DpNXiHJdg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "ansi-escapes": "^4.3.0", + "chalk": "^4.1.1", + "chokidar": "^3.5.1", + "commander": "^8.0.0", + "fast-glob": "^3.2.7", + "lodash.debounce": "^4.0.8", + "lodash.pick": "^4.4.0", + "npm-run-path": "^4.0.1", + "strip-ansi": "^6.0.0", + "tiny-invariant": "^1.1.0", + "vscode-languageclient": "^7.0.0", + "vscode-languageserver": "^7.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-uri": "^3.0.2" + }, + "engines": { + "node": ">=14.16" + }, + "peerDependencies": { + "eslint": ">=7", + "meow": "^9.0.0", + "optionator": "^0.9.1", + "stylelint": ">=13", + "typescript": "*", + "vite": ">=2.0.0", + "vls": "*", + "vti": "*", + "vue-tsc": "*" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "meow": { + "optional": true + }, + "optionator": { + "optional": true + }, + "stylelint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vls": { + "optional": true + }, + "vti": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/vite-plugin-checker/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/vite-plugin-checker/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/vite-plugin-checker/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/vite-plugin-checker/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/vite-plugin-checker/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/vite-plugin-checker/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/vite-plugin-checker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/vite-plugin-checker/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/vite-plugin-checker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", + "dev": true, + "engines": { + "node": ">=8.0.0 || >=10.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", + "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4", + "semver": "^7.3.4", + "vscode-languageserver-protocol": "3.16.0" + }, + "engines": { + "vscode": "^1.52.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", + "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", + "dev": true, + "dependencies": { + "vscode-languageserver-protocol": "3.16.0" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "dev": true, + "dependencies": { + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz", + "integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==", + "dev": true + }, + "node_modules/vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==", + "dev": true + }, + "node_modules/vscode-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.3.tgz", + "integrity": "sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==", + "dev": true + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "dev": true, + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "dev": true, + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.5.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.4.tgz", + "integrity": "sha512-Ic2d8ZT6HJiSikGVQvSklaFyw1OUv4g8sDOxa0PXSlbmN/3gL5IO1WYY9DOwTDqOFmjWoqG1yaaKnPDqYCE9KA==", + "dev": true, + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/workbox-build/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/workbox-build/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==", + "dev": true + }, + "node_modules/workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "dev": true, + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "dev": true, + "dependencies": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "dev": true, + "dependencies": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "node_modules/workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==", + "dev": true + }, + "node_modules/workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "dev": true, + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "target/flow-frontend": { + "name": "@vaadin/flow-frontend", + "version": "1.0.0", + "extraneous": true, + "license": "UNLICENSED" + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/compat-data": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", + "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", + "dev": true + }, + "@babel/core": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", + "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.5", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.5", + "@babel/types": "^7.18.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "requires": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@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==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", + "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "dependencies": { + "browserslist": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.0.tgz", + "integrity": "sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001358", + "electron-to-chromium": "^1.4.164", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.0.tgz", + "integrity": "sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-member-expression-to-functions": "^7.17.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz", + "integrity": "sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + }, + "regexpu-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "dev": true, + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + } + }, + "regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "dev": true + }, + "regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "dev": true + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", + "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", + "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.0", + "@babel/types": "^7.18.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", + "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + } + }, + "@babel/helper-replace-supers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.2.tgz", + "integrity": "sha512-XzAIyxx+vFnrOxiQrToSUOzUOn0e1J2Li40ntddek1Y69AXUTXoDJ40/D5RdjFu7s7qHiaeoTiempZcbuVXh2Q==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-member-expression-to-functions": "^7.17.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", + "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "dev": true, + "requires": { + "@babel/types": "^7.18.2" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + } + }, + "@babel/helpers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", + "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + } + }, + "@babel/highlight": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", + "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", + "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", + "dev": true + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.17.12", + "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.17.12.tgz", + "integrity": "sha512-xCJQXl4EeQ3J9C4yOmpTrtVGmzpm2iSzyxbkZHw7UCnZBftHpF/hpII80uWVyVrc40ytIClHjgWGTG1g/yB+aw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.17.12.tgz", + "integrity": "sha512-/vt0hpIw0x4b6BLKUkwlvEoiGZYYLNZ96CzyHYPbtG2jZGz6LBe7/V+drYrc/d+ovrF9NBi0pmtvmNb/FsWtRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.17.12" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.17.12.tgz", + "integrity": "sha512-RWVvqD1ooLKP6IqWTA5GyFVX2isGEgC5iFxKzfYOIy/QEFdxYyCybBDtIGjipHpb9bDWHzcqGqFakf+mVmBTdQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz", + "integrity": "sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.0.tgz", + "integrity": "sha512-t+8LsRMMDE74c6sV7KShIw13sqbqd58tlqNrsWoWBTIMw7SVQ0cZ905wLNS/FBCy/3PyooRHLFFlfrUNyyz5lA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.17.12.tgz", + "integrity": "sha512-j7Ye5EWdwoXOpRmo5QmRyHPsDIe6+u70ZYZrd7uz+ebPYFKfRcLcNu3Ro0vOlJ5zuv8rU7xa+GttNiRzX56snQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.17.12.tgz", + "integrity": "sha512-rKJ+rKBoXwLnIn7n6o6fulViHMrOThz99ybH+hKHcOZbnN14VuMnH9fo2eHE69C8pO4uX1Q7t2HYYIDmv8VYkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.17.12.tgz", + "integrity": "sha512-EqFo2s1Z5yy+JeJu7SFfbIUtToJTVlC61/C7WLKDntSw4Sz6JNAIfL7zQ74VvirxpjB5kz/kIx0gCcb+5OEo2Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.17.12.tgz", + "integrity": "sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.0.tgz", + "integrity": "sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.17.12" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.17.12.tgz", + "integrity": "sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.17.12.tgz", + "integrity": "sha512-SllXoxo19HmxhDWm3luPz+cPhtoTSKLJE9PXshsfrOzBqs60QP0r8OaJItrPhAj0d7mZMnNF0Y1UUggCDgMz1A==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.17.12.tgz", + "integrity": "sha512-/6BtVi57CJfrtDNKfK5b66ydK2J5pXUKBKSPD2G1whamMuEnZWgoOIfO8Vf9F/DoD4izBLD/Au4NMQfruzzykg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.17.12.tgz", + "integrity": "sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.17.12.tgz", + "integrity": "sha512-n/loy2zkq9ZEM8tEOwON9wTQSTNDTDEz6NujPtJGLU7qObzT1N4c4YZZf8E6ATB2AjNQg/Ib2AIpO03EZaCehw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz", + "integrity": "sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.17.12.tgz", + "integrity": "sha512-J8dbrWIOO3orDzir57NRsjg4uxucvhby0L/KZuGsWDj0g7twWK3g7JhJhOrXtuXiw8MeiSdJ3E0OW9H8LYEzLQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-remap-async-to-generator": "^7.16.8" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.4.tgz", + "integrity": "sha512-+Hq10ye+jlvLEogSOtq4mKvtk7qwcUQ1f0Mrueai866C82f844Yom2cttfJdMdqRLTxWpsbfbkIkOIfovyUQXw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.4.tgz", + "integrity": "sha512-e42NSG2mlKWgxKUAD9EJJSkZxR67+wZqzNxLSpc51T8tRU5SLFHsPmgYR5yr7sdgX4u+iHA1C5VafJ6AyImV3A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-replace-supers": "^7.18.2", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.17.12.tgz", + "integrity": "sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.0.tgz", + "integrity": "sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.17.12.tgz", + "integrity": "sha512-EA5eYFUG6xeerdabina/xIoB95jJ17mAkR8ivx6ZSu9frKShBjpOGZPn511MTDTkiCO+zXnzNczvUM69YSf3Zw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.18.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.1.tgz", + "integrity": "sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.17.12.tgz", + "integrity": "sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.0.tgz", + "integrity": "sha512-h8FjOlYmdZwl7Xm2Ug4iX2j7Qy63NANI+NQVWQzv6r25fqgg7k2dZl03p95kvqNclglHs4FZ+isv4p1uXMA+QA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.2.tgz", + "integrity": "sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-simple-access": "^7.18.2", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.5.tgz", + "integrity": "sha512-SEewrhPpcqMF1V7DhnEbhVJLrC+nnYfe1E0piZMZXBpxi9WvZqWGwpsk7JYP7wPWeqaBh4gyKlBhHJu3uz5g4Q==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.0.tgz", + "integrity": "sha512-d/zZ8I3BWli1tmROLxXLc9A6YXvGK8egMxHp+E/rRwMh1Kip0AP77VwZae3snEJ33iiWwvNv2+UIIhfalqhzZA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.12.tgz", + "integrity": "sha512-vWoWFM5CKaTeHrdUJ/3SIOTRV+MBVGybOC9mhJkaprGNt5demMymDW24yC74avb915/mIRe3TgNb/d8idvnCRA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.5.tgz", + "integrity": "sha512-TuRL5uGW4KXU6OsRj+mLp9BM7pO8e7SGNTEokQRRxHFkXYMFiy2jlKSZPFtI/mKORDzciH+hneskcSOp0gU8hg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.17.12.tgz", + "integrity": "sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.0.tgz", + "integrity": "sha512-C8YdRw9uzx25HSIzwA7EM7YP0FhCe5wNvJbZzjVNHHPGVcDJ3Aie+qGYYdS1oVQgn+B3eAIJbWFLrJ4Jipv7nw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "regenerator-transform": "^0.15.0" + }, + "dependencies": { + "regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + } + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.17.12.tgz", + "integrity": "sha512-1KYqwbJV3Co03NIi14uEHW8P50Md6KqFgt0FfpHdK6oyAHQVTosgPuPSiWud1HX0oYJ1hGRRlk0fP87jFpqXZA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.17.12.tgz", + "integrity": "sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.2.tgz", + "integrity": "sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.17.12.tgz", + "integrity": "sha512-Q8y+Jp7ZdtSPXCThB6zjQ74N3lj0f6TDh1Hnf5B+sYlzQ8i5Pjp8gW0My79iekSpT4WnI06blqP6DT0OmaXXmw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/preset-env": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.2.tgz", + "integrity": "sha512-PfpdxotV6afmXMU47S08F9ZKIm2bJIQ0YbAAtDfIENX7G1NUAXigLREh69CWDjtgUy7dYn7bsMzkgdtAlmS68Q==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.17.12", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.17.12", + "@babel/plugin-proposal-async-generator-functions": "^7.17.12", + "@babel/plugin-proposal-class-properties": "^7.17.12", + "@babel/plugin-proposal-class-static-block": "^7.18.0", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.17.12", + "@babel/plugin-proposal-json-strings": "^7.17.12", + "@babel/plugin-proposal-logical-assignment-operators": "^7.17.12", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.17.12", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.18.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.17.12", + "@babel/plugin-proposal-private-methods": "^7.17.12", + "@babel/plugin-proposal-private-property-in-object": "^7.17.12", + "@babel/plugin-proposal-unicode-property-regex": "^7.17.12", + "@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.17.12", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.17.12", + "@babel/plugin-transform-async-to-generator": "^7.17.12", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.17.12", + "@babel/plugin-transform-classes": "^7.17.12", + "@babel/plugin-transform-computed-properties": "^7.17.12", + "@babel/plugin-transform-destructuring": "^7.18.0", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.17.12", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.18.1", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.17.12", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.18.0", + "@babel/plugin-transform-modules-commonjs": "^7.18.2", + "@babel/plugin-transform-modules-systemjs": "^7.18.0", + "@babel/plugin-transform-modules-umd": "^7.18.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.12", + "@babel/plugin-transform-new-target": "^7.17.12", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.17.12", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.18.0", + "@babel/plugin-transform-reserved-words": "^7.17.12", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.17.12", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.18.2", + "@babel/plugin-transform-typeof-symbol": "^7.17.12", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.2", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz", + "integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true + } + } + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", + "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.18.5", + "@babel/types": "^7.18.4", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", + "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + } + } + }, + "@esbuild/android-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "dev": true, + "optional": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", + "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "dev": true + }, + "@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==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@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==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@lit-labs/ssr-dom-shim": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.0.0.tgz", + "integrity": "sha512-ic93MBXfApIFTrup4a70M/+ddD8xdt2zxxj9sRwHQzhS9ag/syqkD8JPdTXsc1gUy2K8TTirhlCqyTEM/sifNw==" + }, + "@lit/reactive-element": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.1.tgz", + "integrity": "sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==", + "requires": { + "@lit-labs/ssr-dom-shim": "^1.0.0" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@open-wc/dedupe-mixin": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@open-wc/dedupe-mixin/-/dedupe-mixin-1.3.1.tgz", + "integrity": "sha512-ukowSvzpZQDUH0Y3znJTsY88HkiGk3Khc0WGpIPhap1xlerieYi27QBg6wx/nTurpWfU6XXXsx9ocxDYCdtw0Q==" + }, + "@polymer/iron-a11y-keys-behavior": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-a11y-keys-behavior/-/iron-a11y-keys-behavior-3.0.1.tgz", + "integrity": "sha512-lnrjKq3ysbBPT/74l0Fj0U9H9C35Tpw2C/tpJ8a+5g8Y3YJs1WSZYnEl1yOkw6sEyaxOq/1DkzH0+60gGu5/PQ==", + "requires": { + "@polymer/polymer": "3.5.1" + } + }, + "@polymer/iron-flex-layout": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-flex-layout/-/iron-flex-layout-3.0.1.tgz", + "integrity": "sha512-7gB869czArF+HZcPTVSgvA7tXYFze9EKckvM95NB7SqYF+NnsQyhoXgKnpFwGyo95lUjUW9TFDLUwDXnCYFtkw==", + "requires": { + "@polymer/polymer": "3.5.1" + } + }, + "@polymer/iron-icon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-icon/-/iron-icon-3.0.1.tgz", + "integrity": "sha512-QLPwirk+UPZNaLnMew9VludXA4CWUCenRewgEcGYwdzVgDPCDbXxy6vRJjmweZobMQv/oVLppT2JZtJFnPxX6g==", + "requires": { + "@polymer/iron-flex-layout": "^3.0.0-pre.26", + "@polymer/iron-meta": "3.0.1", + "@polymer/polymer": "3.5.1" + } + }, + "@polymer/iron-iconset-svg": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-iconset-svg/-/iron-iconset-svg-3.0.1.tgz", + "integrity": "sha512-XNwURbNHRw6u2fJe05O5fMYye6GSgDlDqCO+q6K1zAnKIrpgZwf2vTkBd5uCcZwsN0FyCB3mvNZx4jkh85dRDw==", + "requires": { + "@polymer/iron-meta": "3.0.1", + "@polymer/polymer": "3.5.1" + } + }, + "@polymer/iron-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@polymer/iron-list/-/iron-list-3.1.0.tgz", + "integrity": "sha512-Eiv6xd3h3oPmn8SXFntXVfC3ZnegH+KHAxiKLKcOASFSRY3mHnr2AdcnExUJ9ItoCMA5UzKaM/0U22eWzGERtA==", + "requires": { + "@polymer/iron-a11y-keys-behavior": "^3.0.0-pre.26", + "@polymer/iron-resizable-behavior": "3.0.1", + "@polymer/iron-scroll-target-behavior": "^3.0.0-pre.26", + "@polymer/polymer": "3.5.1" + } + }, + "@polymer/iron-meta": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-meta/-/iron-meta-3.0.1.tgz", + "integrity": "sha512-pWguPugiLYmWFV9UWxLWzZ6gm4wBwQdDy4VULKwdHCqR7OP7u98h+XDdGZsSlDPv6qoryV/e3tGHlTIT0mbzJA==", + "requires": { + "@polymer/polymer": "3.5.1" + } + }, + "@polymer/iron-resizable-behavior": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-resizable-behavior/-/iron-resizable-behavior-3.0.1.tgz", + "integrity": "sha512-FyHxRxFspVoRaeZSWpT3y0C9awomb4tXXolIJcZ7RvXhMP632V5lez+ch5G5SwK0LpnAPkg35eB0LPMFv+YMMQ==", + "requires": { + "@polymer/polymer": "3.5.1" + } + }, + "@polymer/iron-scroll-target-behavior": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@polymer/iron-scroll-target-behavior/-/iron-scroll-target-behavior-3.0.1.tgz", + "integrity": "sha512-xg1WanG25BIkQE8rhuReqY9zx1K5M7F+YAIYpswEp5eyDIaZ1Y3vUmVeQ3KG+hiSugzI1M752azXN7kvyhOBcQ==", + "requires": { + "@polymer/polymer": "3.5.1" + } + }, + "@polymer/polymer": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.5.1.tgz", + "integrity": "sha512-JlAHuy+1qIC6hL1ojEUfIVD58fzTpJAoCxFwV5yr0mYTXV1H8bz5zy0+rC963Cgr9iNXQ4T9ncSjC2fkF9BQfw==", + "requires": { + "@webcomponents/shadycss": "^1.9.1" + } + }, + "@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + } + } + }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + } + } + }, + "@rollup/plugin-replace": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.1.0.tgz", + "integrity": "sha512-pA3XRUrSKybVYqmH5TqWNZpGxF+VV+1GrYchKgCNIj2vsSOX7CVm2RCtx8p2nrC7xvkziYyK+lSi74T93MU3YA==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + } + } + }, + "@rollup/pluginutils": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz", + "integrity": "sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==", + "dev": true, + "requires": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + } + }, + "@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dev": true, + "requires": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", + "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==", + "dev": true + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" + }, + "@vaadin-component-factory/vcf-nav": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@vaadin-component-factory/vcf-nav/-/vcf-nav-1.0.6.tgz", + "integrity": "sha512-TKgNqpbO6QtXEDCCXeF2LT59l1jshDEwS+ErFR1axuiol+8ihAbvckO62WtfqhlKd67dwipjNDGic/D4GAyBhg==", + "requires": { + "@vaadin/vaadin-lumo-styles": "23.3.8", + "lit": "2.6.1" + } + }, + "@vaadin/accordion": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/accordion/-/accordion-23.3.8.tgz", + "integrity": "sha512-/XJ3hZdKbsovaCMwIHpOWWeZmHz+L6LE5Nr+0good8d9joiCGkmLPwxqRweepjCO82Hlmjrn5SUwcsD0vwnNTQ==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/details": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/app-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/app-layout/-/app-layout-23.3.8.tgz", + "integrity": "sha512-SHpvSOjf3wvjuufmvkpwPitSumgZDZculQikjjg7X+NqBsJsdz1duUYBbHABlYSK4J9qC1kopabq54/8w5Uk+A==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/avatar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/avatar/-/avatar-23.3.8.tgz", + "integrity": "sha512-ky4FS4/va3cB2cHecsSh+muGpCCtDqHJmszDqPF/zDOp+dm1ENVHoc+zW41b7t29cL+8L+ifZcYmRhJsEbcj+g==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/list-box": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/tooltip": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/avatar-group": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/avatar-group/-/avatar-group-23.3.8.tgz", + "integrity": "sha512-v7VS6PBnTKWeDIQGD+r0AKgdpe/vUbYZNIOXL34DthysBeG8/xYrXXKZ41hmla5IKSuPX8p2nyU3yjEeWjKrCw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/avatar": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/list-box": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/bundles": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/bundles/-/bundles-23.3.8.tgz", + "integrity": "sha512-WZTnlztUYrVWq8gWXjoimYGaghOZGVOmHKLHh5Ac1HnQroae/qyoaAyw7kO1vJqZW+tyOrlwnt4W9fN7NZd9eQ==", + "requires": {} + }, + "@vaadin/button": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/button/-/button-23.3.8.tgz", + "integrity": "sha512-22Fx70y6hPDgVQhDyYz/0YxpLm8CKnFErHvW/k59iVLNwT4IwRZYUjqudgwIowEySsJb/2634ivH4LtqDmuj0g==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/checkbox": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/checkbox/-/checkbox-23.3.8.tgz", + "integrity": "sha512-YNIb/D0Kx+tMaD+DDP0KzsUF/qSq88zPyvM3qN0J6fTsz2cpwO0lO0o4HKUgefU+HiqAKrLzVqr9GWUS7mJQhw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/checkbox-group": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/checkbox-group/-/checkbox-group-23.3.8.tgz", + "integrity": "sha512-6WLEuARNj/lYgFf0saj4udX7m6ZAPp2l7nhqDoWV37h37aDFATkWgY/su//yEU2WSxtBcmqedWhNzolnRurWnQ==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/checkbox": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/combo-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/combo-box/-/combo-box-23.3.8.tgz", + "integrity": "sha512-ZJVk/mhXzu3AC0KyM6QGnlet1c4d5xyQ7J418CASAUmdccj2xwELiWo3ppHcKfpwqeF1qSzid0aco4TWsDEoTw==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/common-frontend": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@vaadin/common-frontend/-/common-frontend-0.0.17.tgz", + "integrity": "sha512-M4tg10cYgdDqQAXfGfXpQ90eHm+xL6ynAFEDgtc2IxXVWXKYU8jGK08SM5yOcZ4wDk0ETyHMtQlKUPDNkz6Qfw==", + "requires": { + "tslib": "^2.3.1" + } + }, + "@vaadin/component-base": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/component-base/-/component-base-23.3.8.tgz", + "integrity": "sha512-N0ewZPUbV8Nt5Nup45NK3dvsAzzlaSyeL89CNad1UNP9jIdnXwcYVNBrupaXKT4aNmo1+RGc7+hC3Ve6wdxTOg==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/vaadin-development-mode-detector": "2.0.6", + "@vaadin/vaadin-usage-statistics": "2.1.2", + "lit": "2.6.1" + } + }, + "@vaadin/confirm-dialog": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/confirm-dialog/-/confirm-dialog-23.3.8.tgz", + "integrity": "sha512-fK3mo5fj1DQGt1Re/EflULUVmeyqy5+jLZ/jJqjQFwYSIfjR7/UJfirM7a9i5f/Xt4Mrx6sETlWfMuJE30Wu/Q==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/dialog": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/context-menu": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/context-menu/-/context-menu-23.3.8.tgz", + "integrity": "sha512-nyBu0Cz3zvgi9lnL+IM44VuZ6pj5Fd6mQvGfqmpXaUVycM3ZrR7XDmjBUZqI6v89ULNvmRHZyqZRvcsULyDYXg==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/list-box": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/custom-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/custom-field/-/custom-field-23.3.8.tgz", + "integrity": "sha512-JXz3nc3dSzY8gds3HFKA9LQUkWBHvZVFn47yDevKQdjwY48/loMyTJoiRuTZ5vHQZk0599HcacCFLj4yRbNVeg==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/date-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/date-picker/-/date-picker-23.3.8.tgz", + "integrity": "sha512-UY8nrLVC6RMV7cKhWDHP9nUu0fC2YG5Mb9SL4622d8wE0nJox9oPh61e/Qa1rj1bUL7hxl/AqgCS+9pbX5O3eQ==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/date-time-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/date-time-picker/-/date-time-picker-23.3.8.tgz", + "integrity": "sha512-GOW6RElVYJbZMIQQGaF4rLu7Sy1XuW7HH0Lz6X9S86xAJjjq1r8egzrLaFVIBfPFyOe+zbUHJvpkBNrvuG0Atw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/custom-field": "23.3.8", + "@vaadin/date-picker": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/time-picker": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/details": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/details/-/details-23.3.8.tgz", + "integrity": "sha512-3qZ12xJjsRMrFNzzk1sbGnl1TRmEiXmgQSr2M0A8EC6/rZIAb9MynIm4HttrV16Qbug7JP3O9/USd2QM7zC4Sg==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/dialog": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/dialog/-/dialog-23.3.8.tgz", + "integrity": "sha512-JWqijQz4I7s6RXACNW5ttkbTZe9kr3FqRw943S/eJitBCr6bNnB/ct183gcTKE2u49Gdvl8Igto95lVy8sPkLg==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/email-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/email-field/-/email-field-23.3.8.tgz", + "integrity": "sha512-TvRvEm1Xn3PY3AVdujGsFibpbPworYeOzv/1RssUHvhXPROstjAAYzTaGbAbUtVlK7fF1dt1egUeae7pi5WOEg==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/text-field": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/field-base": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/field-base/-/field-base-23.3.8.tgz", + "integrity": "sha512-Ixb5b/X6kjmY5zt9/0796JSDL0HoL00YBwFpoLv8zrGNI9eIkRJzvaJYYYRD8z/qKFZKJesn741LH2tGtZ05qg==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "lit": "2.6.1" + } + }, + "@vaadin/field-highlighter": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/field-highlighter/-/field-highlighter-23.3.8.tgz", + "integrity": "sha512-7L63B69AzRwqTLKbN3XuA427XbJng/mAWtjOU+8utzM4UJZzz7Vo6mPKqM2LGa1qL65eqlTFF0CveDdIW3UxfA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8", + "lit": "2.6.1" + } + }, + "@vaadin/form-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/form-layout/-/form-layout-23.3.8.tgz", + "integrity": "sha512-V5WHswXN+KfuBpX4DwCFs4jBxRItllpk8Ki6VFZNVmQQh3060bRYSLf5jEgO8ddR+XkIsy4f8RuBh9mpfEDbiQ==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/grid": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/grid/-/grid-23.3.8.tgz", + "integrity": "sha512-o1TuHsl9u5eSe5IrqUKkVdv8Tm43cvY8Cfs/WOViBOjAT8VXck1ctUDGdQZMYEuIKZocYWEnNA0+9KSbBeocbQ==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/checkbox": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/text-field": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/horizontal-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/horizontal-layout/-/horizontal-layout-23.3.8.tgz", + "integrity": "sha512-mnDMEUXhrvozFJofl/PGbjFlFMHxC5v/Nwk/ndla1EuizxTJkNf/DdXCJfwqrMALXOYkdXO2GV++MBs5PxkXxg==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/icon": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/icon/-/icon-23.3.8.tgz", + "integrity": "sha512-PT6nWZYY5sIuUBpPKlpwz/n/QdSEKszSEhDqdDGB+OS19Dhn+o4Ackw0QtmeEcnuX2brl8z+Ln10WaWasz4/vA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8", + "lit": "2.6.1" + } + }, + "@vaadin/icons": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/icons/-/icons-23.3.8.tgz", + "integrity": "sha512-jR4tQyOT3mJffZVDgDEdcfMapw+UWvbTefjIoNJeqgXLwEJ18Iku9D0W2nEGp+7tpmkNPW2rQZsmg8KTPi6GQQ==", + "requires": { + "@polymer/iron-icon": "3.0.1", + "@polymer/iron-iconset-svg": "3.0.1", + "@polymer/polymer": "3.5.1", + "@vaadin/icon": "23.3.8" + } + }, + "@vaadin/input-container": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/input-container/-/input-container-23.3.8.tgz", + "integrity": "sha512-soMGphDbEeH9WgjTDRZih80wGcABL+rsUGsftKYs/L6nK39ZHCFoIWd/X5bQNU6kvIuFtQZwgf6Grix8KwrSfw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/integer-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/integer-field/-/integer-field-23.3.8.tgz", + "integrity": "sha512-ElQcZgOAGCtwkMgiTLC2cvKDC3FVu99078pqBMVyrpXqb8jktpKM1c5WOok1+nvfE5kC6taw3jVcwI05Nf6uEg==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/number-field": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8" + } + }, + "@vaadin/item": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/item/-/item-23.3.8.tgz", + "integrity": "sha512-nqMc6OXiesQHbEeewiOPL4LOmzNaQyiRMrgHsMSlbtur1F5wQCiKsiVqWYPS+/adhtcS8TPn+9ppliyH5AhVag==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/list-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/list-box/-/list-box-23.3.8.tgz", + "integrity": "sha512-sEPkoxPQcqSSM0UCEEAmchUMC5pjbMX3WNzeo3YV+c5+H/EGR9hFeYJPYhmS5fmcw1Z1qsKjsSDL7LzVzSGwjQ==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/vaadin-list-mixin": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/lit-renderer": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/lit-renderer/-/lit-renderer-23.3.8.tgz", + "integrity": "sha512-3RIDgz7oym2iXG0jVMEsjKmVkpaIPm8maQCwhJcp6ANQmDg1lgQtoubvMTJYAVCs6luosQM2Uk45E4BLzGpBqw==", + "requires": { + "lit": "2.6.1" + } + }, + "@vaadin/login": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/login/-/login-23.3.8.tgz", + "integrity": "sha512-M42NGONCSrtdkiVrB5C5mdtyETXG4e+ZpAjnLVx0anFdChu8WTug4FV6gqOgqrPf4sOsF3tOsruP6hiwr3BcTw==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/password-field": "23.3.8", + "@vaadin/text-field": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/menu-bar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/menu-bar/-/menu-bar-23.3.8.tgz", + "integrity": "sha512-i4jfGST4tIbEyvcuoO8EQGoLDMjzmT/UbtJB2nTebzqUiY1z0Og69+AaY7eQQS7sOTmtC4wjSW+4difDhYVRxQ==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/context-menu": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/message-input": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/message-input/-/message-input-23.3.8.tgz", + "integrity": "sha512-y9sgt9gbHrtyNO0kddR2WdjG/AcQPIFVI0jysAfvKoIKBcUwFAE35sZyh7Ef1EOKZy1691XpqTVhXY+83qsz8A==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/text-area": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/message-list": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/message-list/-/message-list-23.3.8.tgz", + "integrity": "sha512-+dpe2ww0cg99Ir5NFDAUzHfIN3jyA+WF89grbWlDaVnBZonEijdrJUgCGKFubl1qu5ZHiXHE4vKPGMGmopGV0g==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/avatar": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/multi-select-combo-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/multi-select-combo-box/-/multi-select-combo-box-23.3.8.tgz", + "integrity": "sha512-isPK52yYjTfzHq7LZjhEH0r6cVr2E7weKSK3HTEtN3DrkrjLHuW1dkbM7IBVOeYHEejknpIe6hsuykLX+kf9Tw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/combo-box": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/notification": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/notification/-/notification-23.3.8.tgz", + "integrity": "sha512-3uZzeDy1lbHbO7a8XYFwgBJrR2IrYKvJFs+KGag26RZRf8saLDMjqZNoM1NgdJy4I+Jtx5W2SzQx2TA6hfg52w==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8", + "lit": "2.6.1" + } + }, + "@vaadin/number-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/number-field/-/number-field-23.3.8.tgz", + "integrity": "sha512-0K+hVjTS8OJV7GDe6Nbr9dOBkDl/bO2GR2/L2vlTaTcgLXl9UXIyzqa0+ZxLLjpe4yAHFU8niDdN6MmlWjY+0Q==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/overlay": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/overlay/-/overlay-23.3.8.tgz", + "integrity": "sha512-sngdoFTrcEvz0nE3T0nK9CR2aO8AU6xySHugP1LADxwjwAYGAWeSljzf8yk5520bBIOz+7M0NbFSk7qqJhpK2Q==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/password-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/password-field/-/password-field-23.3.8.tgz", + "integrity": "sha512-jNVdhFMUi12wnfHLzG23VuWLcWFMatZ0fRjpOxknGQqm0PI58XV5XUIJDbayPFhhFPy50ne1riO5X9Lo0xkAxg==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/text-field": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/polymer-legacy-adapter": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/polymer-legacy-adapter/-/polymer-legacy-adapter-23.3.8.tgz", + "integrity": "sha512-joAmp1nHTKSfmJfqXAxnAebFiyOXiZv4F07d5Aks38HFIZHrMUpynGYvCqaGTeIdiG2xgKXHs0wl5vJg85e5vw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/vaadin-themable-mixin": "23.3.8", + "lit": "2.6.1" + } + }, + "@vaadin/progress-bar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/progress-bar/-/progress-bar-23.3.8.tgz", + "integrity": "sha512-BNx3aOjSrVsZuZ3RMMMynPXQfnjmCM+vt2l7OoeqB0xNRswEU+DPHeAbYYms1oAkPY0y/BeTI8vijGk+1rNgGg==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/radio-group": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/radio-group/-/radio-group-23.3.8.tgz", + "integrity": "sha512-T4/SWFUHK8G+9Y/hfM28uvp083pDuxGgepTBh7f2Eh52cN/d4ehhsmEsrvzkaZdx2ZsKEJUPzmi+tIGB2qq8hA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/router": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@vaadin/router/-/router-1.7.4.tgz", + "integrity": "sha512-B4JVtzFVUMlsjuJHNXEMfNZrM4QDrdeOMc6EEigiHYxwF82py6yDdP6SWP0aPoP3f6aQHt51tLWdXSpkKpWf7A==", + "requires": { + "@vaadin/vaadin-usage-statistics": "2.1.2", + "path-to-regexp": "2.4.0" + } + }, + "@vaadin/scroller": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/scroller/-/scroller-23.3.8.tgz", + "integrity": "sha512-HuzjgZNTTKfy56RODNC2nseJF5PP6AcqasndU1ivAzAFzf4MQmNyRImcmAcz3LeXJz7QCmhyaMhxKh6jXzLSSA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/select": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/select/-/select-23.3.8.tgz", + "integrity": "sha512-5D0/QzUE+gSRyd0kbQEi/wxjYU34dMtnrarJWSzJogpHQwsmJTLPKwjVV4qp9mq1AQzlE5Emdv0bD6/btt2EfA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/list-box": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-list-mixin": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/split-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/split-layout/-/split-layout-23.3.8.tgz", + "integrity": "sha512-uSMtdyfglrqHE/9lrubYGXELHdGd2pzAcSc5aLXhRidV2Qg+IOGb7evq2y3sXD+UAn2Vy1nXpZmR0uB7Dn+rHA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/tabs": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/tabs/-/tabs-23.3.8.tgz", + "integrity": "sha512-kKakZ0mdO6G9K7CN/IhUD/3BbqCHBAxTHmreltw12hhoJ6ue48rqhdNPlLW+XU2a7dzcOvwn5xYGnWDpSe5hsg==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/vaadin-list-mixin": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/tabsheet": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/tabsheet/-/tabsheet-23.3.8.tgz", + "integrity": "sha512-x4423gjZEmibh2h0s0/2Xs/poohW+JRpGPxpK06sfzEFUc+kAIuTBFtEdk2Z8IKAs6hSCCLf0rEWDykqvk+Auw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/scroller": "23.3.8", + "@vaadin/tabs": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/text-area": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/text-area/-/text-area-23.3.8.tgz", + "integrity": "sha512-p4NUNPtCaGFanbbSy6rdjtJuMgk0slSUhDtw4i8C/OkunpBxlYD98VTajLdWCovUXmL8cUAk4Tfs4pe6d405WA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/text-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/text-field/-/text-field-23.3.8.tgz", + "integrity": "sha512-rASUOn7pnSRZWX+td7QSBMThbPEp9iWDNkZEunhuOObGQybnSI+7v8dJUmxZDqsA7uHU6HcyVW+sfD8l0RF/cw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/time-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/time-picker/-/time-picker-23.3.8.tgz", + "integrity": "sha512-95V2FLm1z2IcCYY1clUY9SNjEu/1mKQOl7fkBNJcjqEx2TxvUAduR3h4aU0VDamnAfSwgGI7PWSUjWjKfsmjOQ==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/combo-box": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/tooltip": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/tooltip/-/tooltip-23.3.8.tgz", + "integrity": "sha512-a1+pjrr4Xv/sh065wP3eLvWM8L5gs/29cWO3y1SbN3EC5xr+XtsAvn7qBTDWSlPypUNKKgwBxZjEDflJ64tgaw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/overlay": "~23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/upload": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/upload/-/upload-23.3.8.tgz", + "integrity": "sha512-93J+IDXMKw0XTa7lZPIEF5ZQ9AvVSyxj6emTgDiMEYIuUTwPZT7Oe7iJo8pvFO/dWpQSs6ZBqcUcz3cjgXF7xA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/button": "23.3.8", + "@vaadin/component-base": "23.3.8", + "@vaadin/progress-bar": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/vaadin-accordion": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-accordion/-/vaadin-accordion-23.3.8.tgz", + "integrity": "sha512-TpXTA204MG5sPXWbqLsCa/aeMYRVEO2HRCFksHBpT5gtxEFZ7uy7PGc2FXD3V3/PR8OgZta8ubNcEbYzZbH6Fg==", + "requires": { + "@vaadin/accordion": "23.3.8" + } + }, + "@vaadin/vaadin-app-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-app-layout/-/vaadin-app-layout-23.3.8.tgz", + "integrity": "sha512-J07LoDRx/8pyWvaobLikvEW0BIwYyskwgVLep1p2s4XbN9fwqqLNKBRzeYfWlkJMF+pv6RPsJuLsYvLY70vHGg==", + "requires": { + "@vaadin/app-layout": "23.3.8" + } + }, + "@vaadin/vaadin-avatar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-avatar/-/vaadin-avatar-23.3.8.tgz", + "integrity": "sha512-iEduoqSKO09MmK6XD231L9WIBIiY1IgzZZxQtt96OIXGjFgRek9+v2jCPCPride9GIo47kxJCh6TcS2lRGG2vA==", + "requires": { + "@vaadin/avatar": "23.3.8", + "@vaadin/avatar-group": "23.3.8" + } + }, + "@vaadin/vaadin-button": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-button/-/vaadin-button-23.3.8.tgz", + "integrity": "sha512-f3RlJgdwsg7XuCIJTjhkK07yLqC/Ta/45Z3kSixRkNZeNFBTz1/HHN3OfB2vnDnhvQ6zPVqYQHeLrwh8+gQetA==", + "requires": { + "@vaadin/button": "23.3.8" + } + }, + "@vaadin/vaadin-checkbox": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-checkbox/-/vaadin-checkbox-23.3.8.tgz", + "integrity": "sha512-Z4rCKBCVcKOp/58njpEEyvH5Gq13PRmrrOiFyeLOO2K3c6s3xM0E5tYycBGwaW6d25Y1Z38Olo5qN0pZa03arA==", + "requires": { + "@vaadin/checkbox": "23.3.8", + "@vaadin/checkbox-group": "23.3.8" + } + }, + "@vaadin/vaadin-combo-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-combo-box/-/vaadin-combo-box-23.3.8.tgz", + "integrity": "sha512-Ob9PW60B7svycRQcvnLET8OcySM+c+3ec7yG4lEDliOsJHcxqQwPRyKVIWKOLzheCdPWHY/zi4OsQYeXPXBvaQ==", + "requires": { + "@vaadin/combo-box": "23.3.8" + } + }, + "@vaadin/vaadin-confirm-dialog": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-confirm-dialog/-/vaadin-confirm-dialog-23.3.8.tgz", + "integrity": "sha512-/gIr7QT4MemjTAITar9yDAgTTL9CwPJsFw5FPDnDnmWf3dCazgrHrL0GaLK89D0e/+RR1NTe4Be0YzvUXoltug==", + "requires": { + "@vaadin/confirm-dialog": "23.3.8" + } + }, + "@vaadin/vaadin-context-menu": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-context-menu/-/vaadin-context-menu-23.3.8.tgz", + "integrity": "sha512-CL0mzcA16rsDaNrSKg9alQ3hLuDjgkALVmhzfktq9WAfg4rPvh2BdY13djKb8NUx0Br5qcaoavTOhEt1mibcMQ==", + "requires": { + "@vaadin/context-menu": "23.3.8" + } + }, + "@vaadin/vaadin-custom-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-custom-field/-/vaadin-custom-field-23.3.8.tgz", + "integrity": "sha512-ejvZ+W7gQZDLTmLh/cSUlSc+QQogLZa4s4uUvcxR+syznHUPg8ZQLcjYuJGzfo2nrZo/JDyI0Xkk+uRVQCg3Og==", + "requires": { + "@vaadin/custom-field": "23.3.8" + } + }, + "@vaadin/vaadin-date-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-date-picker/-/vaadin-date-picker-23.3.8.tgz", + "integrity": "sha512-vKirMDoPozHgJ4k7t2n2djy41LYvfCYvDiad681kYughOt4T+R0uMFLws+WxghUoTZa2RCyKLYqp/mYzRO260w==", + "requires": { + "@vaadin/date-picker": "23.3.8" + } + }, + "@vaadin/vaadin-date-time-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-date-time-picker/-/vaadin-date-time-picker-23.3.8.tgz", + "integrity": "sha512-mouw6PNgVAXvUVMIWqApRQ0z9uEUrtsGAEvsAPzc2btvruCjq/AVnihHd93bpDKd6hAWETqK977CER15jFysaA==", + "requires": { + "@vaadin/date-time-picker": "23.3.8" + } + }, + "@vaadin/vaadin-details": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-details/-/vaadin-details-23.3.8.tgz", + "integrity": "sha512-+7gKrHL8+q08CcaR1Dsl6aJbKY0Ac59xn/s2grVSNBmHJkHPP1VK/g4ly9bckiBjy1QjHDp3J2Ws1qY+q2FMwg==", + "requires": { + "@vaadin/details": "23.3.8" + } + }, + "@vaadin/vaadin-development-mode-detector": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-development-mode-detector/-/vaadin-development-mode-detector-2.0.6.tgz", + "integrity": "sha512-N6a5nLT/ytEUlpPo+nvdCKIGoyNjPsj3rzPGvGYK8x9Ceg76OTe1xI/GtN71mRW9e2HUScR0kCNOkl1Z63YDjw==" + }, + "@vaadin/vaadin-dialog": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-dialog/-/vaadin-dialog-23.3.8.tgz", + "integrity": "sha512-M/KFCeuG5u0iq/JMtoL2Q/2OI+CxO3D5g891caW1kqveZOwif5jJY1WtUjnZDOFRpv8mlvazBsVIFte3QttrsA==", + "requires": { + "@vaadin/dialog": "23.3.8" + } + }, + "@vaadin/vaadin-form-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-form-layout/-/vaadin-form-layout-23.3.8.tgz", + "integrity": "sha512-ZNi9qspjH2fsqzGRR49fGbjeQIdwirAwZQvGyahF+g4RW/9emNcrmx29+SXwyP6cYzh2FzcYwmFC06Y8mnOIvg==", + "requires": { + "@vaadin/form-layout": "23.3.8" + } + }, + "@vaadin/vaadin-grid": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-grid/-/vaadin-grid-23.3.8.tgz", + "integrity": "sha512-Jk2wLJqh5/MF+sNRleaZxDJj8D66wgXEMpo9Gi48IAHFCIljgR3fRw6IylnBOQ3r0ChGSftmRIAW/SRN8eMkMA==", + "requires": { + "@vaadin/grid": "23.3.8" + } + }, + "@vaadin/vaadin-icon": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-icon/-/vaadin-icon-23.3.8.tgz", + "integrity": "sha512-kbVC1TO88jau7przMx2s0z+jUnXI7Xc1i6aVyuonEYe/fWal7OT8JwsGSdXxQt0gHylKn46lIBg2lNlLbi62KA==", + "requires": { + "@vaadin/icon": "23.3.8" + } + }, + "@vaadin/vaadin-icons": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-icons/-/vaadin-icons-23.3.8.tgz", + "integrity": "sha512-NoJxorZ4cKrujJqIARyfOaI0AYQEqF/D6i0X7VgloD1EJEUoWD/vkarEMdIChw7ikSTzN/jreeA1RfkRffFLaQ==", + "requires": { + "@vaadin/icons": "23.3.8" + } + }, + "@vaadin/vaadin-item": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-item/-/vaadin-item-23.3.8.tgz", + "integrity": "sha512-F7uDZ9EO7Wz0Mw0gRo0kpxzVS9WmU1JEMppBrxfKzByyldolGO8XoTPKjwwxMeriN7V7jBv3dnSfc4hHfFcJfg==", + "requires": { + "@vaadin/item": "23.3.8" + } + }, + "@vaadin/vaadin-list-box": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-list-box/-/vaadin-list-box-23.3.8.tgz", + "integrity": "sha512-NkKCI4FAqW59xYTdXYPKRxRiYYNJZk6/fqcclWRObtJUHc5EAF3MtzgaCH+p9FHIjsAsJkJmxKBP3fW5KcSmiw==", + "requires": { + "@vaadin/list-box": "23.3.8" + } + }, + "@vaadin/vaadin-list-mixin": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-list-mixin/-/vaadin-list-mixin-23.3.8.tgz", + "integrity": "sha512-rUNf7ntDNOfbX7oH59rFCnVX+zjsoifctcNWTI2kZ/G/MGmETWsQnKqlBOGpLYsw7CCzG6nYDxbRL/PESME6Cw==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8" + } + }, + "@vaadin/vaadin-login": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-login/-/vaadin-login-23.3.8.tgz", + "integrity": "sha512-HrWs9+jqm5Rg+Qhca5MgsH6QdbzYyadPBJrr96MBHR584dOYHtftpW/RuRa4l0gOwRL8Gmv7YildaqxjbZgtYg==", + "requires": { + "@vaadin/login": "23.3.8" + } + }, + "@vaadin/vaadin-lumo-styles": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-lumo-styles/-/vaadin-lumo-styles-23.3.8.tgz", + "integrity": "sha512-N6nfNCF/H3Vg1gemJZCeMXpWHV7TvUdqbFjKkFIipeI/VXuRXo1icAjGMQUbhs2DZnb89xsP+krRtn5lcfbeow==", + "requires": { + "@polymer/iron-icon": "3.0.1", + "@polymer/iron-iconset-svg": "3.0.1", + "@polymer/polymer": "3.5.1", + "@vaadin/icon": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/vaadin-material-styles": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-material-styles/-/vaadin-material-styles-23.3.8.tgz", + "integrity": "sha512-mIEngTejkEyDcgIvovIkXBEgVrH4Qx0JMSwGirjp97LRUAXTe5Lz2tzfTHRjLCccDkSdQaQNt4f9jCwhj6HcKA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/vaadin-menu-bar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-menu-bar/-/vaadin-menu-bar-23.3.8.tgz", + "integrity": "sha512-7ghRXR2bus3d5cap/iAZ5DA2RLjH7d5jg/CC3d0IvfSdUF+VALWDsB0ui36ZKNLprGHrt5iEQyY5bGSIjpMwMg==", + "requires": { + "@vaadin/menu-bar": "23.3.8" + } + }, + "@vaadin/vaadin-messages": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-messages/-/vaadin-messages-23.3.8.tgz", + "integrity": "sha512-O8Pic1UV9Myh7hHCE+Oar3Fo9H3XiTZcmxgRPwsX9MFM7KPoaQ2vYfAQfclxnqSCz7B+EgCI+Yqv42YpRXQavA==", + "requires": { + "@vaadin/message-input": "23.3.8", + "@vaadin/message-list": "23.3.8" + } + }, + "@vaadin/vaadin-notification": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-notification/-/vaadin-notification-23.3.8.tgz", + "integrity": "sha512-dwqCeSwa7Y+Z7W2H2HRaYekRWiWkJIee2d0SjtVDAMZd/EnGz7uSQ+tUKoGdGi/Xvo/5YNlN9qX7cfA0OWa8lA==", + "requires": { + "@vaadin/notification": "23.3.8" + } + }, + "@vaadin/vaadin-ordered-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-ordered-layout/-/vaadin-ordered-layout-23.3.8.tgz", + "integrity": "sha512-oaL4fjVN6A0Bei56vmWWAB6TUWKGZZ+qNrH24R87FYpSG85SGkoH+B1mkv0RtmfyRxxH/jZNlnKbBVRbrtn+ag==", + "requires": { + "@vaadin/horizontal-layout": "23.3.8", + "@vaadin/scroller": "23.3.8", + "@vaadin/vertical-layout": "23.3.8" + } + }, + "@vaadin/vaadin-overlay": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-overlay/-/vaadin-overlay-23.3.8.tgz", + "integrity": "sha512-alRKsG5YFcD0VduOR78pcQuqOI66FiY19pRuYB+tDPIX9RTfZOYc0wS51jNdCIIJXYog6vYU7owBwGYI2ezvBw==", + "requires": { + "@vaadin/overlay": "~23.3.8" + } + }, + "@vaadin/vaadin-progress-bar": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-progress-bar/-/vaadin-progress-bar-23.3.8.tgz", + "integrity": "sha512-XS49afqNmc2SJwzCdTWHhNOIjycnyL/ojo5uO0XgAMWZV7y2pBINHxSxVv+tQJk/zPtgRcEyf05nP/HSysBJWg==", + "requires": { + "@vaadin/progress-bar": "23.3.8" + } + }, + "@vaadin/vaadin-radio-button": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-radio-button/-/vaadin-radio-button-23.3.8.tgz", + "integrity": "sha512-LJ6aKo1ge1oj4xN7lQDmOoTYOMor94PFRZWuxRJOQV6dlELKaAU+R4EaYCwDy1Ip2Sqs3CevrK+oBm4vLoMDLQ==", + "requires": { + "@vaadin/radio-group": "23.3.8" + } + }, + "@vaadin/vaadin-select": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-select/-/vaadin-select-23.3.8.tgz", + "integrity": "sha512-tKl6l+JcqpbJjq629EatvS5XFw7LI+kg/zQNMPTmH/1y88EciOZOPBc6vlSPKxB4D+8hIXetdOi49+iXeAt+Hw==", + "requires": { + "@vaadin/select": "23.3.8" + } + }, + "@vaadin/vaadin-split-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-split-layout/-/vaadin-split-layout-23.3.8.tgz", + "integrity": "sha512-2qc3UwdaaHeGXFNbcWB4eCcb3ygZ+R3fP3q+NcOOV3qI6tk2rvLoekdnsxjXCp3ObtHx/YngfpOtn+Xl2B4BHg==", + "requires": { + "@vaadin/split-layout": "23.3.8" + } + }, + "@vaadin/vaadin-tabs": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-tabs/-/vaadin-tabs-23.3.8.tgz", + "integrity": "sha512-FXzWtfzyp3m//MTk8qDfD9oQd7GgSAD976zs/3EIzHl2RpqO9UbKj3Y/mANoWQgFFcZidUlIfUfzrp86kfx2lw==", + "requires": { + "@vaadin/tabs": "23.3.8" + } + }, + "@vaadin/vaadin-template-renderer": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-template-renderer/-/vaadin-template-renderer-23.3.8.tgz", + "integrity": "sha512-CzF9QwaFzlXYh6lgOA3LN/+hSk4w+SIav+gb4VDzv1jsB7hDOOmQOx7TpsWY3C5RfLk+12cwnUWkuE+FNHkxnQ==", + "requires": { + "@vaadin/polymer-legacy-adapter": "23.3.8" + } + }, + "@vaadin/vaadin-text-field": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-text-field/-/vaadin-text-field-23.3.8.tgz", + "integrity": "sha512-MTrdLe055dE5FAh3vYEcqIMkPThAdJnx+Azu9WfZINB4iIXBqa5iFCLfdAJB/VEE+TvflSORH5km0bMXmmVAKw==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/email-field": "23.3.8", + "@vaadin/integer-field": "23.3.8", + "@vaadin/number-field": "23.3.8", + "@vaadin/password-field": "23.3.8", + "@vaadin/text-area": "23.3.8", + "@vaadin/text-field": "23.3.8" + } + }, + "@vaadin/vaadin-themable-mixin": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-themable-mixin/-/vaadin-themable-mixin-23.3.8.tgz", + "integrity": "sha512-ePzyNzxY7QqSO2hUSv0l1mjm58QhPTmD1DznKECNMIOFeOjZlw1eMVxtwTrahlvwtErLmCYIU3xRwjqB9R4Zig==", + "requires": { + "@open-wc/dedupe-mixin": "^1.3.0", + "lit": "2.6.1" + } + }, + "@vaadin/vaadin-time-picker": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-time-picker/-/vaadin-time-picker-23.3.8.tgz", + "integrity": "sha512-EheRMIZylIes7xk6tbVJ8LDNDY0ae0WObEWg47255+GnN2rYVrxObeZyLLGSqoHdhQueaKNdaYt2sk0mzDfbig==", + "requires": { + "@vaadin/time-picker": "23.3.8" + } + }, + "@vaadin/vaadin-upload": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-upload/-/vaadin-upload-23.3.8.tgz", + "integrity": "sha512-o2Oh59t9QoBW9IH9IzxpLozfH3EwID8UpZmr4VCeYxwTycLLQmvZ9cTWBoBQYIXrpa+HaTKWX+XTNFUCIHw6TQ==", + "requires": { + "@vaadin/upload": "23.3.8" + } + }, + "@vaadin/vaadin-usage-statistics": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-usage-statistics/-/vaadin-usage-statistics-2.1.2.tgz", + "integrity": "sha512-xKs1PvRfTXsG0eWWcImLXWjv7D+f1vfoIvovppv6pZ5QX8xgcxWUdNgERlOOdGt3CTuxQXukTBW3+Qfva+OXSg==", + "requires": { + "@vaadin/vaadin-development-mode-detector": "2.0.6" + } + }, + "@vaadin/vaadin-virtual-list": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-virtual-list/-/vaadin-virtual-list-23.3.8.tgz", + "integrity": "sha512-Eir2bq9qGzVJ/QZZRnukW1vusM7IEQZmXEaN0Mtc4hAXu6hzbzZHhnGzsq+ouEDIFQIGP6iXz4rywB1+PUmJgw==", + "requires": { + "@vaadin/virtual-list": "23.3.8" + } + }, + "@vaadin/vertical-layout": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/vertical-layout/-/vertical-layout-23.3.8.tgz", + "integrity": "sha512-iIAmBA4c3ncXj85Ps/XY2fSeOWo0NAXSHvJZ5aLRrlxxTJx0D3fDOKzoyes9333FSzozHCF9E4fgAx3jgrgx6Q==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@vaadin/virtual-list": { + "version": "23.3.8", + "resolved": "https://registry.npmjs.org/@vaadin/virtual-list/-/virtual-list-23.3.8.tgz", + "integrity": "sha512-u81uYO9ElknvhotZL/sqgmbjONZ0t1w1YhCCGLpDuKCftt2KK9txmO2jmarFwj4fO3ogY4OaGvWDkU3FetPiPA==", + "requires": { + "@polymer/polymer": "3.5.1", + "@vaadin/component-base": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8" + } + }, + "@webcomponents/shadycss": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.11.0.tgz", + "integrity": "sha512-L5O/+UPum8erOleNjKq6k58GVl3fNsEQdSOyh0EUhNmi7tHUyRuCJy1uqJiWydWcLARE5IPsMoPYMZmUGrz1JA==" + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "async": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==", + "dev": true + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "caniuse-lite": { + "version": "1.0.30001359", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001359.tgz", + "integrity": "sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "construct-style-sheets-polyfill": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.1.0.tgz", + "integrity": "sha512-HBLKP0chz8BAY6rBdzda11c3wAZeCZ+kIG4weVC2NM3AXzxx09nhe8t0SQNdloAvg5GLuHwq/0SPOOSPvtCcKw==" + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-js-compat": { + "version": "3.23.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.3.tgz", + "integrity": "sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw==", + "dev": true, + "requires": { + "browserslist": "^4.21.0", + "semver": "7.0.0" + }, + "dependencies": { + "browserslist": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.0.tgz", + "integrity": "sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001358", + "electron-to-chromium": "^1.4.164", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.0" + } + }, + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + } + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, + "dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, + "date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, + "electron-to-chromium": { + "version": "1.4.170", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.170.tgz", + "integrity": "sha512-rZ8PZLhK4ORPjFqLp9aqC4/S1j4qWFsPPz13xmWdrbBkU/LlxMcok+f+6f8YnQ57MiZwKtOaW15biZZsY5Igvw==", + "dev": true + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonpointer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", + "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "line-awesome": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/line-awesome/-/line-awesome-1.3.0.tgz", + "integrity": "sha512-Y0YHksL37ixDsHz+ihCwOtF5jwJgCDxQ3q+zOVgaSW8VugHGTsZZXMacPYZB1/JULBi6BAuTCTek+4ZY/UIwcw==" + }, + "lit": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.6.1.tgz", + "integrity": "sha512-DT87LD64f8acR7uVp7kZfhLRrHkfC/N4BVzAtnw9Yg8087mbBJ//qedwdwX0kzDbxgPccWRW6mFwGbRQIxy0pw==", + "requires": { + "@lit/reactive-element": "^1.6.0", + "lit-element": "^3.2.0", + "lit-html": "^2.6.0" + } + }, + "lit-element": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.2.tgz", + "integrity": "sha512-6ZgxBR9KNroqKb6+htkyBwD90XGRiqKDHVrW/Eh0EZ+l+iC+u+v+w3/BA5NGi4nizAVHGYvQBHUDuSmLjPp7NQ==", + "requires": { + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.2.0" + } + }, + "lit-html": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.6.1.tgz", + "integrity": "sha512-Z3iw+E+3KKFn9t2YKNjsXNEu/LRLI98mtH/C6lnFg7kvaqPIzPn124Yd4eT/43lyqrejpc5Wb6BHq3fdv4S8Rw==", + "requires": { + "@types/trusted-types": "^2.0.2" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "merge-source-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", + "integrity": "sha512-PGSmS0kfnTnMJCzJ16BLLCEe6oeYCamKFFdQKshi4BmM6FUwipjVOcBFGxqtQtirtAG4iZvHlqST9CpZKqlRjA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "mutexify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mutexify/-/mutexify-1.4.0.tgz", + "integrity": "sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg==", + "dev": true, + "requires": { + "queue-tick": "^1.0.0" + } + }, + "nanobench": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nanobench/-/nanobench-2.1.1.tgz", + "integrity": "sha512-z+Vv7zElcjN+OpzAxAquUayFLGK3JI/ubCl0Oh64YQqsTGG09CGqieJVQw4ui8huDnnAgrvTv93qi5UaOoNj8A==", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2", + "chalk": "^1.1.3", + "mutexify": "^1.1.0", + "pretty-hrtime": "^1.0.2" + } + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-to-regexp": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz", + "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "queue-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.0.tgz", + "integrity": "sha512-ULWhjjE8BmiICGn3G8+1L9wFpERNxkf8ysxkAer4+TFdRefDaXOCV5m92aMB9FtBVmn/8sETXLXY6BfW7hyaWQ==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-brotli": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-brotli/-/rollup-plugin-brotli-3.1.0.tgz", + "integrity": "sha512-vXRPVd9B1x+aaXeBdmLKNNsai9AH3o0Qikf4u0m1icKqgi3qVA4UhOfwGaPYoAHML1GLMUnR//PDhiMHXN/M6g==", + "dev": true + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true + }, + "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==", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true + }, + "strip-css-comments": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-css-comments/-/strip-css-comments-5.0.0.tgz", + "integrity": "sha512-943vUh0ZxvxO6eK+TzY2F4nVN7a+ZdRK4KIdwHaGMvMrXTrAsJBRudOR3Zi0bLTuVSbF0CQXis4uw04uCabWkg==", + "dev": true, + "requires": { + "is-regexp": "^3.0.0" + }, + "dependencies": { + "is-regexp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz", + "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==", + "dev": true + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true + }, + "tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dev": true, + "requires": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + } + }, + "terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "tiny-invariant": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", + "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "transform-ast": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/transform-ast/-/transform-ast-2.4.4.tgz", + "integrity": "sha512-AxjeZAcIOUO2lev2GDe3/xZ1Q0cVGjIMk5IsriTy8zbWlsEnjeB025AhkhBJHoy997mXpLd4R+kRbvnnQVuQHQ==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "convert-source-map": "^1.5.1", + "dash-ast": "^1.0.0", + "is-buffer": "^2.0.0", + "magic-string": "^0.23.2", + "merge-source-map": "1.0.4", + "nanobench": "^2.1.1" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true + }, + "magic-string": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.23.2.tgz", + "integrity": "sha512-oIUZaAxbcxYIp4AyLafV6OVKoB3YouZs0UTCJ8mOKBHNyJgGDaMJ4TgA+VylJh6fx7EQCC52XkbURxxG9IoJXA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.1" + } + } + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true + }, + "typescript": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "dev": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "vite": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", + "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==", + "dev": true, + "requires": { + "esbuild": "^0.15.9", + "fsevents": "~2.3.2", + "postcss": "^8.4.18", + "resolve": "^1.22.1", + "rollup": "^2.79.1" + } + }, + "vite-plugin-checker": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.5.4.tgz", + "integrity": "sha512-T6y+OHXqwOjGrCErbhzg5x79NQZV46cgLwYTxuMQnDzAfA6skh2i8PIHcKks8ZlxopzbkvMb5vwc2DpNXiHJdg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "ansi-escapes": "^4.3.0", + "chalk": "^4.1.1", + "chokidar": "^3.5.1", + "commander": "^8.0.0", + "fast-glob": "^3.2.7", + "lodash.debounce": "^4.0.8", + "lodash.pick": "^4.4.0", + "npm-run-path": "^4.0.1", + "strip-ansi": "^6.0.0", + "tiny-invariant": "^1.1.0", + "vscode-languageclient": "^7.0.0", + "vscode-languageserver": "^7.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-uri": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", + "dev": true + }, + "vscode-languageclient": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", + "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", + "dev": true, + "requires": { + "minimatch": "^3.0.4", + "semver": "^7.3.4", + "vscode-languageserver-protocol": "3.16.0" + } + }, + "vscode-languageserver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", + "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", + "dev": true, + "requires": { + "vscode-languageserver-protocol": "3.16.0" + } + }, + "vscode-languageserver-protocol": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "dev": true, + "requires": { + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz", + "integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==", + "dev": true + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==", + "dev": true + }, + "vscode-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.3.tgz", + "integrity": "sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==", + "dev": true + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "dev": true, + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "dev": true, + "requires": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.5.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "dependencies": { + "@apideck/better-ajv-errors": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.4.tgz", + "integrity": "sha512-Ic2d8ZT6HJiSikGVQvSklaFyw1OUv4g8sDOxa0PXSlbmN/3gL5IO1WYY9DOwTDqOFmjWoqG1yaaKnPDqYCE9KA==", + "dev": true, + "requires": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + } + }, + "@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "requires": { + "whatwg-url": "^7.0.0" + } + } + } + }, + "workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==", + "dev": true + }, + "workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "dev": true, + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "dev": true, + "requires": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "dev": true, + "requires": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==", + "dev": true + }, + "workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "dev": true, + "requires": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..bd18922 --- /dev/null +++ b/package.json @@ -0,0 +1,366 @@ +{ + "name": "no-name", + "license": "UNLICENSED", + "dependencies": { + "@polymer/iron-icon": "3.0.1", + "@polymer/iron-iconset-svg": "3.0.1", + "@polymer/iron-list": "3.1.0", + "@polymer/iron-meta": "3.0.1", + "@polymer/iron-resizable-behavior": "3.0.1", + "@polymer/polymer": "3.5.1", + "@vaadin-component-factory/vcf-nav": "1.0.6", + "@vaadin/accordion": "23.3.8", + "@vaadin/app-layout": "23.3.8", + "@vaadin/avatar": "23.3.8", + "@vaadin/avatar-group": "23.3.8", + "@vaadin/bundles": "23.3.8", + "@vaadin/button": "23.3.8", + "@vaadin/checkbox": "23.3.8", + "@vaadin/checkbox-group": "23.3.8", + "@vaadin/combo-box": "23.3.8", + "@vaadin/common-frontend": "0.0.17", + "@vaadin/component-base": "23.3.8", + "@vaadin/confirm-dialog": "23.3.8", + "@vaadin/context-menu": "23.3.8", + "@vaadin/custom-field": "23.3.8", + "@vaadin/date-picker": "23.3.8", + "@vaadin/date-time-picker": "23.3.8", + "@vaadin/details": "23.3.8", + "@vaadin/dialog": "23.3.8", + "@vaadin/email-field": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/field-highlighter": "23.3.8", + "@vaadin/form-layout": "23.3.8", + "@vaadin/grid": "23.3.8", + "@vaadin/horizontal-layout": "23.3.8", + "@vaadin/icon": "23.3.8", + "@vaadin/icons": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/integer-field": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/list-box": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/login": "23.3.8", + "@vaadin/menu-bar": "23.3.8", + "@vaadin/message-input": "23.3.8", + "@vaadin/message-list": "23.3.8", + "@vaadin/multi-select-combo-box": "23.3.8", + "@vaadin/notification": "23.3.8", + "@vaadin/number-field": "23.3.8", + "@vaadin/password-field": "23.3.8", + "@vaadin/polymer-legacy-adapter": "23.3.8", + "@vaadin/progress-bar": "23.3.8", + "@vaadin/radio-group": "23.3.8", + "@vaadin/router": "1.7.4", + "@vaadin/scroller": "23.3.8", + "@vaadin/select": "23.3.8", + "@vaadin/split-layout": "23.3.8", + "@vaadin/tabs": "23.3.8", + "@vaadin/tabsheet": "23.3.8", + "@vaadin/text-area": "23.3.8", + "@vaadin/text-field": "23.3.8", + "@vaadin/time-picker": "23.3.8", + "@vaadin/tooltip": "23.3.8", + "@vaadin/upload": "23.3.8", + "@vaadin/vaadin-accordion": "23.3.8", + "@vaadin/vaadin-app-layout": "23.3.8", + "@vaadin/vaadin-avatar": "23.3.8", + "@vaadin/vaadin-button": "23.3.8", + "@vaadin/vaadin-checkbox": "23.3.8", + "@vaadin/vaadin-combo-box": "23.3.8", + "@vaadin/vaadin-confirm-dialog": "23.3.8", + "@vaadin/vaadin-context-menu": "23.3.8", + "@vaadin/vaadin-custom-field": "23.3.8", + "@vaadin/vaadin-date-picker": "23.3.8", + "@vaadin/vaadin-date-time-picker": "23.3.8", + "@vaadin/vaadin-details": "23.3.8", + "@vaadin/vaadin-development-mode-detector": "2.0.6", + "@vaadin/vaadin-dialog": "23.3.8", + "@vaadin/vaadin-form-layout": "23.3.8", + "@vaadin/vaadin-grid": "23.3.8", + "@vaadin/vaadin-icon": "23.3.8", + "@vaadin/vaadin-icons": "23.3.8", + "@vaadin/vaadin-item": "23.3.8", + "@vaadin/vaadin-list-box": "23.3.8", + "@vaadin/vaadin-list-mixin": "23.3.8", + "@vaadin/vaadin-login": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-menu-bar": "23.3.8", + "@vaadin/vaadin-messages": "23.3.8", + "@vaadin/vaadin-notification": "23.3.8", + "@vaadin/vaadin-ordered-layout": "23.3.8", + "@vaadin/vaadin-overlay": "23.3.8", + "@vaadin/vaadin-progress-bar": "23.3.8", + "@vaadin/vaadin-radio-button": "23.3.8", + "@vaadin/vaadin-select": "23.3.8", + "@vaadin/vaadin-split-layout": "23.3.8", + "@vaadin/vaadin-tabs": "23.3.8", + "@vaadin/vaadin-template-renderer": "23.3.8", + "@vaadin/vaadin-text-field": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8", + "@vaadin/vaadin-time-picker": "23.3.8", + "@vaadin/vaadin-upload": "23.3.8", + "@vaadin/vaadin-usage-statistics": "2.1.2", + "@vaadin/vaadin-virtual-list": "23.3.8", + "@vaadin/vertical-layout": "23.3.8", + "@vaadin/virtual-list": "23.3.8", + "construct-style-sheets-polyfill": "3.1.0", + "date-fns": "2.29.3", + "line-awesome": "1.3.0", + "lit": "2.6.1" + }, + "devDependencies": { + "@rollup/plugin-replace": "3.1.0", + "@rollup/pluginutils": "4.1.0", + "async": "3.2.2", + "glob": "7.2.3", + "mkdirp": "1.0.4", + "rollup-plugin-brotli": "3.1.0", + "strip-css-comments": "5.0.0", + "transform-ast": "2.4.4", + "typescript": "4.9.3", + "vite": "3.2.5", + "vite-plugin-checker": "0.5.4", + "workbox-build": "6.5.4", + "workbox-core": "6.5.4", + "workbox-precaching": "6.5.4" + }, + "overrides": { + "@vaadin/bundles": "$@vaadin/bundles", + "@vaadin/accordion": "$@vaadin/accordion", + "@vaadin/app-layout": "$@vaadin/app-layout", + "@vaadin/avatar": "$@vaadin/avatar", + "@vaadin/avatar-group": "$@vaadin/avatar-group", + "@vaadin/button": "$@vaadin/button", + "@vaadin/checkbox": "$@vaadin/checkbox", + "@vaadin/checkbox-group": "$@vaadin/checkbox-group", + "@vaadin/combo-box": "$@vaadin/combo-box", + "@vaadin/component-base": "$@vaadin/component-base", + "@vaadin/context-menu": "$@vaadin/context-menu", + "@vaadin/custom-field": "$@vaadin/custom-field", + "@vaadin/date-picker": "$@vaadin/date-picker", + "@vaadin/date-time-picker": "$@vaadin/date-time-picker", + "@vaadin/details": "$@vaadin/details", + "@vaadin/dialog": "$@vaadin/dialog", + "@vaadin/email-field": "$@vaadin/email-field", + "@vaadin/field-base": "$@vaadin/field-base", + "@vaadin/field-highlighter": "$@vaadin/field-highlighter", + "@vaadin/form-layout": "$@vaadin/form-layout", + "@vaadin/grid": "$@vaadin/grid", + "@vaadin/horizontal-layout": "$@vaadin/horizontal-layout", + "@vaadin/icon": "$@vaadin/icon", + "@vaadin/icons": "$@vaadin/icons", + "@vaadin/input-container": "$@vaadin/input-container", + "@vaadin/integer-field": "$@vaadin/integer-field", + "@polymer/iron-icon": "$@polymer/iron-icon", + "@polymer/iron-iconset-svg": "$@polymer/iron-iconset-svg", + "@polymer/iron-list": "$@polymer/iron-list", + "@polymer/iron-meta": "$@polymer/iron-meta", + "@polymer/iron-resizable-behavior": "$@polymer/iron-resizable-behavior", + "@vaadin/item": "$@vaadin/item", + "@vaadin/list-box": "$@vaadin/list-box", + "@vaadin/lit-renderer": "$@vaadin/lit-renderer", + "@vaadin/login": "$@vaadin/login", + "@vaadin/menu-bar": "$@vaadin/menu-bar", + "@vaadin/message-input": "$@vaadin/message-input", + "@vaadin/message-list": "$@vaadin/message-list", + "@vaadin/notification": "$@vaadin/notification", + "@vaadin/number-field": "$@vaadin/number-field", + "@vaadin/password-field": "$@vaadin/password-field", + "@vaadin/polymer-legacy-adapter": "$@vaadin/polymer-legacy-adapter", + "@vaadin/progress-bar": "$@vaadin/progress-bar", + "@vaadin/radio-group": "$@vaadin/radio-group", + "@vaadin/scroller": "$@vaadin/scroller", + "@vaadin/select": "$@vaadin/select", + "@vaadin/split-layout": "$@vaadin/split-layout", + "@vaadin/tabs": "$@vaadin/tabs", + "@vaadin/text-area": "$@vaadin/text-area", + "@vaadin/text-field": "$@vaadin/text-field", + "@vaadin/time-picker": "$@vaadin/time-picker", + "@vaadin/upload": "$@vaadin/upload", + "@vaadin/vaadin-accordion": "$@vaadin/vaadin-accordion", + "@vaadin/vaadin-app-layout": "$@vaadin/vaadin-app-layout", + "@vaadin/vaadin-avatar": "$@vaadin/vaadin-avatar", + "@vaadin/vaadin-button": "$@vaadin/vaadin-button", + "@vaadin/vaadin-checkbox": "$@vaadin/vaadin-checkbox", + "@vaadin/vaadin-combo-box": "$@vaadin/vaadin-combo-box", + "@vaadin/vaadin-context-menu": "$@vaadin/vaadin-context-menu", + "@vaadin/vaadin-custom-field": "$@vaadin/vaadin-custom-field", + "@vaadin/vaadin-date-picker": "$@vaadin/vaadin-date-picker", + "@vaadin/vaadin-date-time-picker": "$@vaadin/vaadin-date-time-picker", + "@vaadin/vaadin-details": "$@vaadin/vaadin-details", + "@vaadin/vaadin-development-mode-detector": "$@vaadin/vaadin-development-mode-detector", + "@vaadin/vaadin-dialog": "$@vaadin/vaadin-dialog", + "@vaadin/vaadin-form-layout": "$@vaadin/vaadin-form-layout", + "@vaadin/vaadin-grid": "$@vaadin/vaadin-grid", + "@vaadin/vaadin-icon": "$@vaadin/vaadin-icon", + "@vaadin/vaadin-icons": "$@vaadin/vaadin-icons", + "@vaadin/vaadin-item": "$@vaadin/vaadin-item", + "@vaadin/vaadin-list-box": "$@vaadin/vaadin-list-box", + "@vaadin/vaadin-list-mixin": "$@vaadin/vaadin-list-mixin", + "@vaadin/vaadin-login": "$@vaadin/vaadin-login", + "@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles", + "@vaadin/vaadin-material-styles": "$@vaadin/vaadin-material-styles", + "@vaadin/vaadin-menu-bar": "$@vaadin/vaadin-menu-bar", + "@vaadin/vaadin-messages": "$@vaadin/vaadin-messages", + "@vaadin/vaadin-notification": "$@vaadin/vaadin-notification", + "@vaadin/vaadin-ordered-layout": "$@vaadin/vaadin-ordered-layout", + "@vaadin/vaadin-overlay": "$@vaadin/vaadin-overlay", + "@vaadin/vaadin-progress-bar": "$@vaadin/vaadin-progress-bar", + "@vaadin/vaadin-radio-button": "$@vaadin/vaadin-radio-button", + "@vaadin/router": "$@vaadin/router", + "@vaadin/vaadin-select": "$@vaadin/vaadin-select", + "@vaadin/vaadin-split-layout": "$@vaadin/vaadin-split-layout", + "@vaadin/vaadin-tabs": "$@vaadin/vaadin-tabs", + "@vaadin/vaadin-template-renderer": "$@vaadin/vaadin-template-renderer", + "@vaadin/vaadin-text-field": "$@vaadin/vaadin-text-field", + "@vaadin/vaadin-themable-mixin": "$@vaadin/vaadin-themable-mixin", + "@vaadin/vaadin-time-picker": "$@vaadin/vaadin-time-picker", + "@vaadin/vaadin-upload": "$@vaadin/vaadin-upload", + "@vaadin/vaadin-usage-statistics": "$@vaadin/vaadin-usage-statistics", + "@vaadin/vaadin-virtual-list": "$@vaadin/vaadin-virtual-list", + "@vaadin/vertical-layout": "$@vaadin/vertical-layout", + "@vaadin/virtual-list": "$@vaadin/virtual-list", + "@vaadin/confirm-dialog": "$@vaadin/confirm-dialog", + "@vaadin/vaadin-confirm-dialog": "$@vaadin/vaadin-confirm-dialog", + "@vaadin/common-frontend": "$@vaadin/common-frontend", + "construct-style-sheets-polyfill": "$construct-style-sheets-polyfill", + "lit": "$lit", + "@polymer/polymer": "$@polymer/polymer", + "date-fns": "$date-fns", + "@vaadin/multi-select-combo-box": "$@vaadin/multi-select-combo-box", + "@vaadin/tabsheet": "$@vaadin/tabsheet", + "@vaadin/tooltip": "$@vaadin/tooltip", + "@vaadin-component-factory/vcf-nav": "$@vaadin-component-factory/vcf-nav", + "line-awesome": "$line-awesome" + }, + "vaadin": { + "dependencies": { + "@polymer/iron-icon": "3.0.1", + "@polymer/iron-iconset-svg": "3.0.1", + "@polymer/iron-list": "3.1.0", + "@polymer/iron-meta": "3.0.1", + "@polymer/iron-resizable-behavior": "3.0.1", + "@polymer/polymer": "3.5.1", + "@vaadin-component-factory/vcf-nav": "1.0.6", + "@vaadin/accordion": "23.3.8", + "@vaadin/app-layout": "23.3.8", + "@vaadin/avatar": "23.3.8", + "@vaadin/avatar-group": "23.3.8", + "@vaadin/bundles": "23.3.8", + "@vaadin/button": "23.3.8", + "@vaadin/checkbox": "23.3.8", + "@vaadin/checkbox-group": "23.3.8", + "@vaadin/combo-box": "23.3.8", + "@vaadin/common-frontend": "0.0.17", + "@vaadin/component-base": "23.3.8", + "@vaadin/confirm-dialog": "23.3.8", + "@vaadin/context-menu": "23.3.8", + "@vaadin/custom-field": "23.3.8", + "@vaadin/date-picker": "23.3.8", + "@vaadin/date-time-picker": "23.3.8", + "@vaadin/details": "23.3.8", + "@vaadin/dialog": "23.3.8", + "@vaadin/email-field": "23.3.8", + "@vaadin/field-base": "23.3.8", + "@vaadin/field-highlighter": "23.3.8", + "@vaadin/form-layout": "23.3.8", + "@vaadin/grid": "23.3.8", + "@vaadin/horizontal-layout": "23.3.8", + "@vaadin/icon": "23.3.8", + "@vaadin/icons": "23.3.8", + "@vaadin/input-container": "23.3.8", + "@vaadin/integer-field": "23.3.8", + "@vaadin/item": "23.3.8", + "@vaadin/list-box": "23.3.8", + "@vaadin/lit-renderer": "23.3.8", + "@vaadin/login": "23.3.8", + "@vaadin/menu-bar": "23.3.8", + "@vaadin/message-input": "23.3.8", + "@vaadin/message-list": "23.3.8", + "@vaadin/multi-select-combo-box": "23.3.8", + "@vaadin/notification": "23.3.8", + "@vaadin/number-field": "23.3.8", + "@vaadin/password-field": "23.3.8", + "@vaadin/polymer-legacy-adapter": "23.3.8", + "@vaadin/progress-bar": "23.3.8", + "@vaadin/radio-group": "23.3.8", + "@vaadin/router": "1.7.4", + "@vaadin/scroller": "23.3.8", + "@vaadin/select": "23.3.8", + "@vaadin/split-layout": "23.3.8", + "@vaadin/tabs": "23.3.8", + "@vaadin/tabsheet": "23.3.8", + "@vaadin/text-area": "23.3.8", + "@vaadin/text-field": "23.3.8", + "@vaadin/time-picker": "23.3.8", + "@vaadin/tooltip": "23.3.8", + "@vaadin/upload": "23.3.8", + "@vaadin/vaadin-accordion": "23.3.8", + "@vaadin/vaadin-app-layout": "23.3.8", + "@vaadin/vaadin-avatar": "23.3.8", + "@vaadin/vaadin-button": "23.3.8", + "@vaadin/vaadin-checkbox": "23.3.8", + "@vaadin/vaadin-combo-box": "23.3.8", + "@vaadin/vaadin-confirm-dialog": "23.3.8", + "@vaadin/vaadin-context-menu": "23.3.8", + "@vaadin/vaadin-custom-field": "23.3.8", + "@vaadin/vaadin-date-picker": "23.3.8", + "@vaadin/vaadin-date-time-picker": "23.3.8", + "@vaadin/vaadin-details": "23.3.8", + "@vaadin/vaadin-development-mode-detector": "2.0.6", + "@vaadin/vaadin-dialog": "23.3.8", + "@vaadin/vaadin-form-layout": "23.3.8", + "@vaadin/vaadin-grid": "23.3.8", + "@vaadin/vaadin-icon": "23.3.8", + "@vaadin/vaadin-icons": "23.3.8", + "@vaadin/vaadin-item": "23.3.8", + "@vaadin/vaadin-list-box": "23.3.8", + "@vaadin/vaadin-list-mixin": "23.3.8", + "@vaadin/vaadin-login": "23.3.8", + "@vaadin/vaadin-lumo-styles": "23.3.8", + "@vaadin/vaadin-material-styles": "23.3.8", + "@vaadin/vaadin-menu-bar": "23.3.8", + "@vaadin/vaadin-messages": "23.3.8", + "@vaadin/vaadin-notification": "23.3.8", + "@vaadin/vaadin-ordered-layout": "23.3.8", + "@vaadin/vaadin-overlay": "23.3.8", + "@vaadin/vaadin-progress-bar": "23.3.8", + "@vaadin/vaadin-radio-button": "23.3.8", + "@vaadin/vaadin-select": "23.3.8", + "@vaadin/vaadin-split-layout": "23.3.8", + "@vaadin/vaadin-tabs": "23.3.8", + "@vaadin/vaadin-template-renderer": "23.3.8", + "@vaadin/vaadin-text-field": "23.3.8", + "@vaadin/vaadin-themable-mixin": "23.3.8", + "@vaadin/vaadin-time-picker": "23.3.8", + "@vaadin/vaadin-upload": "23.3.8", + "@vaadin/vaadin-usage-statistics": "2.1.2", + "@vaadin/vaadin-virtual-list": "23.3.8", + "@vaadin/vertical-layout": "23.3.8", + "@vaadin/virtual-list": "23.3.8", + "construct-style-sheets-polyfill": "3.1.0", + "date-fns": "2.29.3", + "line-awesome": "1.3.0", + "lit": "2.6.1" + }, + "devDependencies": { + "@rollup/plugin-replace": "3.1.0", + "@rollup/pluginutils": "4.1.0", + "async": "3.2.2", + "glob": "7.2.3", + "mkdirp": "1.0.4", + "rollup-plugin-brotli": "3.1.0", + "strip-css-comments": "5.0.0", + "transform-ast": "2.4.4", + "typescript": "4.9.3", + "vite": "3.2.5", + "vite-plugin-checker": "0.5.4", + "workbox-build": "6.5.4", + "workbox-core": "6.5.4", + "workbox-precaching": "6.5.4" + }, + "hash": "5bf27a4d5c8b9c9178e292921678bdd7fa23bb9d7abc37cdfa21ebf90fbfc943" + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..6bd85a5 --- /dev/null +++ b/pom.xml @@ -0,0 +1,305 @@ + + + 4.0.0 + de.uniregensburg.iamreportingmodule + iamreportingmodule + iamreportingmodule + 1.0-SNAPSHOT + jar + + + 17 + 23.3.8 + + 4.8.1 + 5.3.2 + 2.1.214 + 42.6.0 + 3.0.3 + 1.2.2 + + + + org.springframework.boot + spring-boot-starter-parent + 2.7.9 + + + + + + + + central + https://repo.maven.apache.org/maven2 + + false + + + + vaadin-prereleases + + https://maven.vaadin.com/vaadin-prereleases/ + + + + + Vaadin Directory + https://maven.vaadin.com/vaadin-addons + + false + + + + + + + + central + https://repo.maven.apache.org/maven2 + + false + + + + vaadin-prereleases + + https://maven.vaadin.com/vaadin-prereleases/ + + + + + + + + com.vaadin + vaadin-bom + ${vaadin.version} + pom + import + + + + + + + com.vaadin + + vaadin-core + + + com.vaadin + vaadin-spring-boot-starter + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-devtools + true + + + org.springframework.boot + spring-boot-starter-test + test + + + com.vaadin + vaadin-testbench + test + + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + io.github.bonigarcia + webdrivermanager + ${webdrivermanager.version} + test + + + + org.postgresql + postgresql + ${postgres.version} + + + com.h2database + h2 + ${h2.version} + runtime + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.boot + spring-boot-starter-quartz + + + + com.ezylang + EvalEx + ${evalex.version} + + + + org.vaadin.addons.tatu + lumogridlayout + ${lumogridlayout.version} + + + + + + spring-boot:run + + + src/main/resources + true + + + + + org.springframework.boot + spring-boot-maven-plugin + + + -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5683 + 500 + 240 + + + + + + com.vaadin + vaadin-maven-plugin + ${vaadin.version} + + + + prepare-frontend + + + + + + + + + + local + + true + + + local + + + + + production + + production + + + + + com.vaadin + vaadin-maven-plugin + ${vaadin.version} + + + + build-frontend + + compile + + + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + it + + it + + + + + org.springframework.boot + spring-boot-maven-plugin + + + start-spring-boot + pre-integration-test + + start + + + + stop-spring-boot + post-integration-test + + stop + + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + + false + true + + + + + + + + diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/Application.java b/src/main/java/de/uniregensburg/iamreportingmodule/Application.java new file mode 100644 index 0000000..506852b --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/Application.java @@ -0,0 +1,30 @@ +package de.uniregensburg.iamreportingmodule; + +import com.vaadin.flow.component.dependency.NpmPackage; +import com.vaadin.flow.component.page.AppShellConfigurator; +import com.vaadin.flow.theme.Theme; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * The entry point of the Spring Boot application. + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/Application.java + * + * @author Julian Bauer + */ +@SpringBootApplication +@Theme(value = "iamreportingmodule") +@NpmPackage(value = "line-awesome", version = "1.3.0") +@NpmPackage(value = "@vaadin-component-factory/vcf-nav", version = "1.0.6") +public class Application implements AppShellConfigurator { + + /** + * Starts spring application + * @param args + */ + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/DatabaseException.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/DatabaseException.java new file mode 100644 index 0000000..c5731a6 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/DatabaseException.java @@ -0,0 +1,18 @@ +package de.uniregensburg.iamreportingmodule.core.exception; + +/** + * Exception for database tasks + * + * @author Julian Bauer + */ +public class DatabaseException extends Exception { + + /** + * + * @param message + */ + public DatabaseException(String message) { + super(message); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/DeleteEntityException.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/DeleteEntityException.java new file mode 100644 index 0000000..88ebeea --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/DeleteEntityException.java @@ -0,0 +1,18 @@ +package de.uniregensburg.iamreportingmodule.core.exception; + +/** + * Exception for deleting entities + * + * @author Julian Bauer + */ +public class DeleteEntityException extends Exception { + + /** + * + * @param message + */ + public DeleteEntityException(String message) { + super(message); + } + +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/FileException.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/FileException.java new file mode 100644 index 0000000..3bbe261 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/FileException.java @@ -0,0 +1,18 @@ +package de.uniregensburg.iamreportingmodule.core.exception; + +/** + * Exception for file handling + * + * @author Julian Bauer + */ +public class FileException extends Exception { + + /** + * + * @param message + */ + public FileException(String message) { + super(message); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/FormulaException.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/FormulaException.java new file mode 100644 index 0000000..a6d3d5e --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/FormulaException.java @@ -0,0 +1,18 @@ +package de.uniregensburg.iamreportingmodule.core.exception; + +/** + * Exception for formula evaluation + * + * @author Julian Bauer + */ +public class FormulaException extends Exception { + + /** + * + * @param message + */ + public FormulaException(String message) { + super(message); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/JobSchedulingException.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/JobSchedulingException.java new file mode 100644 index 0000000..4870eae --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/JobSchedulingException.java @@ -0,0 +1,18 @@ +package de.uniregensburg.iamreportingmodule.core.exception; + +/** + * Exception for scheduling jobs + * + * @author Julian Bauer + */ +public class JobSchedulingException extends Exception { + + /** + * + * @param message + */ + public JobSchedulingException(String message) { + super(message); + } + +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/SaveEntityException.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/SaveEntityException.java new file mode 100644 index 0000000..82307e1 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/exception/SaveEntityException.java @@ -0,0 +1,18 @@ +package de.uniregensburg.iamreportingmodule.core.exception; + +/** + * Exception for saving entities + * + * @author Julian Bauer + */ +public class SaveEntityException extends Exception { + + /** + * + * @param message + */ + public SaveEntityException(String message) { + super(message); + } + +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/scheduling/CalculateJob.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/scheduling/CalculateJob.java new file mode 100644 index 0000000..b95a5a7 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/scheduling/CalculateJob.java @@ -0,0 +1,87 @@ +package de.uniregensburg.iamreportingmodule.core.scheduling; + +import de.uniregensburg.iamreportingmodule.core.exception.FormulaException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.util.FormulaUtil; +import de.uniregensburg.iamreportingmodule.data.entity.Formula; +import de.uniregensburg.iamreportingmodule.data.entity.Metric; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.stereotype.Component; + +import java.util.UUID; + +/** + * Quartz job definition for calculating metrics + * + * @author Julian Bauer + */ +@Component +public class CalculateJob extends QuartzJobBean { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final MeasurableService service; + private final FormulaUtil util; + + /** + * + * @param service + */ + CalculateJob(MeasurableService service) { + this.service = service; + this.util = new FormulaUtil(service); + } + + /** + * Overrides job execution definition + * + * @param context add id of metric (String metricId) to JobDataMap + * @throws JobExecutionException + */ + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + logger.info("Starting job execution"); + // get id of metric + JobDataMap jobDataMap = context.getMergedJobDataMap(); + String metricId = jobDataMap.getString("metricId"); + if (metricId.isBlank()) { + logger.info("No metric id provided"); + throw new JobExecutionException("No metric id provided"); + } + // get metric + Metric metric = service.findMetricById(UUID.fromString(metricId)); + if (metric == null) { + logger.info("Metric is null"); + throw new JobExecutionException("Metric is null"); + } + logger.info("Metric: " + metric.getName()); + + // get formula + logger.info("Checking formula"); + Formula formula = metric.getFormula(); + if (formula == null) { + logger.info("Formula is null"); + throw new JobExecutionException("Formula is null"); + } + if (formula.getFormula().isBlank()) { + logger.info("Formula is blank"); + throw new JobExecutionException("Formula is blank"); + } + logger.info("Formula: " + formula.getFormula()); + + // calculate + try { + Result result = util.calculate(formula.getFormula()); + result.setMeasurable(metric); + // save result + service.saveResult(result); + } catch (FormulaException e) { + logger.info("Failed to calculate metric " + metric.getName() + ": " + e.getMessage()); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/scheduling/MeasureJob.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/scheduling/MeasureJob.java new file mode 100644 index 0000000..d2a89d3 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/scheduling/MeasureJob.java @@ -0,0 +1,188 @@ +package de.uniregensburg.iamreportingmodule.core.scheduling; + +import de.uniregensburg.iamreportingmodule.core.exception.DatabaseException; +import de.uniregensburg.iamreportingmodule.core.exception.FileException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.util.CsvUtil; +import de.uniregensburg.iamreportingmodule.core.util.DatabaseUtil; +import de.uniregensburg.iamreportingmodule.data.entity.*; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.Map; +import java.util.UUID; + +/** + * Quartz job definition for determining measurements + * + * @author Julian Bauer + */ +@Component +public class MeasureJob implements Job { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final MeasurableService service; + + /** + * + * @param service + */ + public MeasureJob(MeasurableService service) { + this.service = service; + } + + /** + * Overrides job execution definition + * + * @param context add id of measurement (String measurementId) to JobDataMap + * @throws JobExecutionException + */ + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + logger.info("Starting job execution"); + // get id of measurement + JobDataMap jobDataMap = context.getMergedJobDataMap(); + String measurementId = jobDataMap.getString("measurementId"); + if (measurementId.isBlank()) { + logger.info("No measurement id provided"); + throw new JobExecutionException("No measurement id provided"); + } + // get measurement + Measurement measurement = service.findMeasurementById(UUID.fromString(measurementId)); + if (measurement == null) { + logger.info("Measurement is null"); + throw new JobExecutionException("Measurement is null"); + } + logger.info("Measurement: " + measurement.getName()); + + // get datasource + logger.info("Getting datasource"); + DataSource dataSource = measurement.getDataSource(); + if (dataSource == null) { + logger.info("Datasource is null"); + throw new JobExecutionException("Datasource is null"); + } + logger.info("Datasource: " + dataSource.getName()); + + // get datasource type + logger.info("Getting datasource type"); + DataSourceType type = dataSource.getType(); + if (type == null) { + logger.info("Datasource type is null"); + throw new JobExecutionException("Datasource type is null"); + } + + // measure depending on datasource type + Result result; + if (DataSourceType.MANUAL.equals(type)) { + logger.info("Manual datasource"); + ManualDataSource manualDataSource = (ManualDataSource) dataSource; + result = measureManualDataSource(manualDataSource); + } else if (DataSourceType.DATABASE.equals(type)) { + logger.info("Database datasource"); + DatabaseDataSource databaseDataSource = (DatabaseDataSource) dataSource; + result = measureDatabaseDataSource(databaseDataSource, measurement); + } else if (DataSourceType.FILE.equals(type)) { + logger.info("File datasource"); + FileDataSource fileDataSource = (FileDataSource) dataSource; + FileType fileType = fileDataSource.getFileType(); + if (FileType.CSV.equals(fileType)) { + result = measureCsvFileDataSource(fileDataSource, measurement); + } else { + throw new JobExecutionException("Unknown file type: " + fileType); + } + } else { + throw new JobExecutionException("Unknown datasource type: " + type); + } + + // save result + result.setMeasurable(measurement); + service.saveResult(result); + } + + /** + * Determines measurement in database using sql query + * + * @param databaseDataSource + * @param measurement + * @return + * @throws JobExecutionException + */ + private Result measureDatabaseDataSource(DatabaseDataSource databaseDataSource, Measurement measurement) throws JobExecutionException { + // get sql query + logger.info("Checking query"); + Map attributes = measurement.getAttributes(); + String query = attributes.get("sqlQuery"); + if (query == null) { + logger.info("Query is null"); + throw new JobExecutionException("Query is null"); + } + if (query.isBlank()) { + logger.info("Query is blank"); + throw new JobExecutionException("Query is blank"); + } + logger.info("Query: " + query); + + // execute sql query + logger.info("Measuring database datasource"); + DatabaseUtil databaseUtil = new DatabaseUtil(databaseDataSource); + try { + Result result = databaseUtil.measure(query); + logger.info("Query successful: " + result.getValue()); + return result; + } catch (DatabaseException e) { + logger.info("Query failed: " + e.getMessage()); + throw new JobExecutionException("Query failed: " + e.getMessage()); + } + } + + /** + * Determines measurement in manual datasource + * + * @param manualDataSource + * @return + * @throws JobExecutionException + */ + private Result measureManualDataSource(ManualDataSource manualDataSource) throws JobExecutionException { + // get value + logger.info("Measuring manual datasource"); + BigDecimal value = manualDataSource.getValue(); + if (value == null) { + logger.info("Measured value is null"); + throw new JobExecutionException("Measured value is null"); + } + logger.info("Measuring successful: " + value); + return new Result(value); + } + + /** + * Determines measurement in csv file + * + * @param fileDataSource + * @param measurement + * @return + * @throws JobExecutionException + */ + private Result measureCsvFileDataSource(FileDataSource fileDataSource, Measurement measurement) throws JobExecutionException { + logger.info("Measuring file datasource"); + // get attributes and csv util + Map attributes = measurement.getAttributes(); + logger.info("Measuring file datasource"); + CsvUtil util = new CsvUtil(fileDataSource); + // get value using csv util and attributes + try { + Result result = util.measure(attributes); + logger.info("Measurement successful: " + result.getValue()); + return result; + } catch (FileException e) { + logger.info("Measurement failed: " + e.getMessage()); + throw new JobExecutionException("Measurement failed: " + e.getMessage()); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/service/CustomUserDetailsService.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/CustomUserDetailsService.java new file mode 100644 index 0000000..44d42e2 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/CustomUserDetailsService.java @@ -0,0 +1,52 @@ +package de.uniregensburg.iamreportingmodule.core.service; + +import de.uniregensburg.iamreportingmodule.data.entity.CustomUserDetails; +import de.uniregensburg.iamreportingmodule.data.entity.User; +import de.uniregensburg.iamreportingmodule.data.repository.UserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +/** + * Service for returning information of user for spring security + * + * @author Julian Bauer + */ +@Service +public class CustomUserDetailsService implements UserDetailsService { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final UserRepository userRepository; + + /** + * + * @param userRepository + */ + public CustomUserDetailsService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + /** + * Overrides method to get user details by username + * + * @param username + * @return + * @throws UsernameNotFoundException + */ + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + logger.info("Loading user by username " + username); + // get user + User user = userRepository.findByUsername(username); + if (user == null) { + logger.info("User null"); + throw new UsernameNotFoundException(username); + } + logger.info("Returning user"); + // return user details + return new CustomUserDetails(user); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/service/DataSourceService.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/DataSourceService.java new file mode 100644 index 0000000..fa22227 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/DataSourceService.java @@ -0,0 +1,194 @@ +package de.uniregensburg.iamreportingmodule.core.service; + +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.data.entity.*; +import de.uniregensburg.iamreportingmodule.data.repository.DatabaseDataSourceRepository; +import de.uniregensburg.iamreportingmodule.data.repository.FileDataSourceRepository; +import de.uniregensburg.iamreportingmodule.data.repository.ManualDataSourceRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Service for persisting datasources + * + * @author Julian Bauer + */ +@Service +public class DataSourceService { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final ManualDataSourceRepository manualDataSourceRepository; + private final DatabaseDataSourceRepository databaseDataSourceRepository; + private final FileDataSourceRepository fileDataSourceRepository; + + /** + * + * @param manualDataSourceRepository + * @param databaseDataSourceRepository + * @param fileDataSourceRepository + */ + public DataSourceService(ManualDataSourceRepository manualDataSourceRepository, DatabaseDataSourceRepository databaseDataSourceRepository, FileDataSourceRepository fileDataSourceRepository) { + this.manualDataSourceRepository = manualDataSourceRepository; + this.databaseDataSourceRepository = databaseDataSourceRepository; + this.fileDataSourceRepository = fileDataSourceRepository; + } + + /** + * Returns all datasources + * + * @return + */ + public List findAllDataSources() { + logger.info("Returning all datasources"); + // get datasources of all three types + List dataSources = new ArrayList<>(); + dataSources.addAll(manualDataSourceRepository.findAll()); + dataSources.addAll(databaseDataSourceRepository.findAll()); + dataSources.addAll(fileDataSourceRepository.findAll()); + // return all datasources sorted by name + return dataSources.stream().sorted(Comparator.comparing(DataSource::getName)).collect(Collectors.toList()); + } + + /** + * Saves a datasource + * + * @param dataSource + * @throws SaveEntityException + */ + public void saveDataSource(DataSource dataSource) throws SaveEntityException { + logger.info("Saving datasource"); + // check datasource + if (dataSource == null) { + logger.info("Datasource is null"); + throw new SaveEntityException("No datasource provided"); + } + // save datasource depending on type + DataSourceType type = dataSource.getType(); + try { + if (type.equals(DataSourceType.MANUAL)) { + ManualDataSource manualDataSource = (ManualDataSource) dataSource; + manualDataSourceRepository.save(manualDataSource); + } else if (type.equals(DataSourceType.DATABASE)) { + DatabaseDataSource databaseDataSource = (DatabaseDataSource) dataSource; + databaseDataSourceRepository.save(databaseDataSource); + } else if (type.equals(DataSourceType.FILE)) { + FileDataSource fileDataSource = (FileDataSource) dataSource; + fileDataSourceRepository.save(fileDataSource); + } else { + logger.info("Saving datasource type " + type + " not implemented yet"); + throw new SaveEntityException("Saving datasource type " + type + " not implemented yet"); + } + logger.info("Datasource saved"); + } catch (Exception e) { + logger.info("Error while saving datasource: " + e.getMessage()); + throw new SaveEntityException("Error while saving datasource"); + } + } + + /** + * Deletes a datasource + * + * @param dataSource + * @throws DeleteEntityException + */ + public void deleteDataSource(DataSource dataSource) throws DeleteEntityException { + logger.info("Deleting datasource"); + // check datasource + if (dataSource == null) { + logger.info("Datasource is null"); + return; + } + // delete datasource depending on type + DataSourceType type = dataSource.getType(); + try { + if (type.equals(DataSourceType.MANUAL)) { + ManualDataSource manualDataSource = (ManualDataSource) dataSource; + manualDataSourceRepository.delete(manualDataSource); + } else if (type.equals(DataSourceType.DATABASE)) { + DatabaseDataSource databaseDataSource = (DatabaseDataSource) dataSource; + databaseDataSourceRepository.delete(databaseDataSource); + } else if (type.equals(DataSourceType.FILE)) { + FileDataSource fileDataSource = (FileDataSource) dataSource; + fileDataSourceRepository.delete(fileDataSource); + } else { + logger.info("Deleting datasource type " + type + " not implemented yet"); + throw new SaveEntityException("Deleting datasource type " + type + " not implemented yet"); + } + logger.info("Datasource deleted"); + } catch (Exception ex) { + logger.info("Cannot delete datasource: " + ex.getMessage()); + throw new DeleteEntityException("Datasource is probably used in one or more measurements"); + } + } + + /** + * Returns manual datasource by id + * + * @param id + * @return + */ + public ManualDataSource findManualDataSourceById(UUID id) { + logger.info("Searching manual datasource with id " + id); + // get datasource + Optional dataSource = manualDataSourceRepository.findById(id); + + // check if datasource exists + if (dataSource.isEmpty()) { + logger.info("Manual datasource not found"); + return null; + } + + logger.info("Manual datasource found"); + // return datasource + return dataSource.get(); + } + + /** + * Returns database datasource by id + * + * @param id + * @return + */ + public DatabaseDataSource findDatabaseDataSourceById(UUID id) { + logger.info("Searching database datasource with id " + id); + // get datasource + Optional dataSource = databaseDataSourceRepository.findById(id); + + // check if datasource exists + if (dataSource.isEmpty()) { + logger.info("Database datasource not found"); + return null; + } + + logger.info("Database datasource found"); + // return datasource + return dataSource.get(); + } + + /** + * Returns file datasource by id + * + * @param id + * @return + */ + public FileDataSource findFileDataSourceById(UUID id) { + logger.info("Searching file datasource with id " + id); + // get datasource + Optional dataSource = fileDataSourceRepository.findById(id); + + // check if datasource exists + if (dataSource.isEmpty()) { + logger.info("File datasource not found"); + return null; + } + + logger.info("File datasource found"); + // return datasource + return dataSource.get(); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/service/GroupService.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/GroupService.java new file mode 100644 index 0000000..b4fbaff --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/GroupService.java @@ -0,0 +1,196 @@ +package de.uniregensburg.iamreportingmodule.core.service; + +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.data.entity.Audience; +import de.uniregensburg.iamreportingmodule.data.entity.Group; +import de.uniregensburg.iamreportingmodule.data.entity.Stakeholder; +import de.uniregensburg.iamreportingmodule.data.entity.User; +import de.uniregensburg.iamreportingmodule.data.repository.AudienceRepository; +import de.uniregensburg.iamreportingmodule.data.repository.GroupRepository; +import de.uniregensburg.iamreportingmodule.data.repository.StakeholderRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +/** + * Service for persisting groups (audiences and stakeholders) + * + * @author Julian Bauer + */ +@Service +public class GroupService { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final AudienceRepository audienceRepository; + private final StakeholderRepository stakeholderRepository; + private final GroupRepository groupRepository; + + /** + * + * @param audienceRepository + * @param stakeholderRepository + * @param groupRepository + */ + public GroupService(AudienceRepository audienceRepository, StakeholderRepository stakeholderRepository, GroupRepository groupRepository) { + this.audienceRepository = audienceRepository; + this.stakeholderRepository = stakeholderRepository; + this.groupRepository = groupRepository; + } + + /** + * Returns all audiences + * + * @return + */ + public List findAllAudiences() { + logger.info("Returning all audiences"); + // get and return all + return audienceRepository.findAll(); + } + + /** + * Returns all stakeholders + * + * @return + */ + public List findAllStakeholders() { + logger.info("Returning all stakeholders"); + // return all + return stakeholderRepository.findAll(); + } + + /** + * Saves a group + * + * @param group + * @throws SaveEntityException + */ + public void saveGroup(Group group) throws SaveEntityException { + logger.info("Saving group"); + // check group + if (group == null) { + logger.info("Group is null"); + throw new SaveEntityException("Group is null"); + } + // save group + try { + groupRepository.save(group); + logger.info("Group saved"); + } catch (Exception e) { + logger.info("Error while saving group: " + e.getMessage()); + throw new SaveEntityException("Error while saving group"); + } + } + + /** + * Deletes a group + * + * @param group + * @throws DeleteEntityException + */ + public void deleteGroup(Group group) throws DeleteEntityException { + logger.info("Deleting group"); + // check group + if (group == null) { + logger.info("Group is null"); + return; + } + // delete group + try { + groupRepository.delete(group); + logger.info("Group deleted"); + } catch (Exception ex) { + logger.info("Cannot delete group: " + ex.getMessage()); + throw new DeleteEntityException("Group is probably used in one or more measurables"); + } + } + + /** + * Returns a group by id + * + * @param id + * @return + */ + public Group findGroupById(UUID id) { + logger.info("Searching group with id " + id); + // search group by id + Optional group = groupRepository.findById(id); + + // check group + if (group.isEmpty()) { + logger.info("Group not found"); + return null; + } + + logger.info("Group found"); + // return group + return group.get(); + } + + /** + * Returns an audience by id + * + * @param id + * @return + */ + public Audience findAudienceById(UUID id) { + logger.info("Searching audience with id " + id); + // search group + Group group = findGroupById(id); + if (group == null) { + logger.info("Group is null"); + return null; + } + // check if group is an audience + if (group.getClass().equals(Audience.class)) { + // return audience + return (Audience) group; + } else { + logger.info("Group is not an audience"); + return null; + } + } + + /** + * Returns a stakeholder by id + * + * @param id + * @return + */ + public Stakeholder findStakeholderById(UUID id) { + logger.info("Searching stakeholder with id " + id); + // search group + Group group = findGroupById(id); + if (group == null) { + logger.info("Group is null"); + return null; + } + // check if group is a stakeholder + if (group.getClass().equals(Stakeholder.class)) { + // return stakeholder + return (Stakeholder) group; + } else { + logger.info("Group is not a stakeholder"); + return null; + } + } + + /** + * Returns all audiences containing specific member + * + * @param member + * @return + */ + public List findAudiencesByMember(User member) { + logger.info("Searching audiences with member " + member.getUsername()); + // search and return all audiences containing specific member + return audienceRepository.findAllByMembersIn(Set.of(member)); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/service/InformationNeedService.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/InformationNeedService.java new file mode 100644 index 0000000..cbe0446 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/InformationNeedService.java @@ -0,0 +1,113 @@ +package de.uniregensburg.iamreportingmodule.core.service; + +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.data.entity.InformationNeed; +import de.uniregensburg.iamreportingmodule.data.repository.InformationNeedRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +/** + * Service for persisting information needs + * + * @author Julian Bauer + */ +@Service +public class InformationNeedService { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final InformationNeedRepository informationNeedRepository; + + /** + * + * @param informationNeedRepository + */ + public InformationNeedService(InformationNeedRepository informationNeedRepository) { + this.informationNeedRepository = informationNeedRepository; + } + + /** + * Returns all information needs + * + * @return + */ + public List findAllInformationNeeds() { + logger.info("Returning all information needs"); + // get and return all + return informationNeedRepository.findAll(); + } + + /** + * Saves an information need + * + * @param informationNeed + * @throws SaveEntityException + */ + public void saveInformationNeed(InformationNeed informationNeed) throws SaveEntityException { + logger.info("Saving information need"); + // check information need + if (informationNeed == null) { + logger.info("Information need is null"); + throw new SaveEntityException("No information need provided"); + } + // save information need + try { + informationNeedRepository.save(informationNeed); + logger.info("Information need saved"); + } catch (Exception e) { + logger.info("Error while saving information need: " + e.getMessage()); + throw new SaveEntityException("Error while saving information need"); + } + } + + /** + * Deletes an information need + * + * @param informationNeed + * @throws DeleteEntityException + */ + public void deleteInformationNeed(InformationNeed informationNeed) throws DeleteEntityException { + logger.info("Deleting information need"); + // check information need + if (informationNeed == null) { + logger.info("Information need is null"); + return; + } + // delete information need + try { + informationNeedRepository.delete(informationNeed); + logger.info("Information need deleted"); + } catch (Exception ex) { + logger.info("Cannot delete information need: " + ex.getMessage()); + throw new DeleteEntityException("Information need is probably used in one or more measurables"); + } + } + + /** + * Returns an information need by id + * + * @param id + * @return + */ + public InformationNeed findInformationNeedById(UUID id) { + logger.info("Searching information need with id " + id); + // search information need by id + Optional informationNeed = informationNeedRepository.findById(id); + + // check information need + if (informationNeed.isEmpty()) { + logger.info("InformationNeed not found"); + return null; + } + + logger.info("InformationNeed found"); + // return information need + return informationNeed.get(); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/service/JobSchedulingService.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/JobSchedulingService.java new file mode 100644 index 0000000..ab2fce2 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/JobSchedulingService.java @@ -0,0 +1,282 @@ +package de.uniregensburg.iamreportingmodule.core.service; + +import de.uniregensburg.iamreportingmodule.core.exception.JobSchedulingException; +import de.uniregensburg.iamreportingmodule.core.scheduling.CalculateJob; +import de.uniregensburg.iamreportingmodule.core.scheduling.MeasureJob; +import de.uniregensburg.iamreportingmodule.data.entity.*; +import org.quartz.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.time.Duration; + +/** + * Service for scheduling quartz jobs + * + * @author Julian Bauer + */ +@Service +public class JobSchedulingService { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final Scheduler scheduler; + + /** + * + * @param scheduler + */ + public JobSchedulingService(Scheduler scheduler) { + this.scheduler = scheduler; + } + + /** + * Schedules job for calculation of metric + * + * @param metric + * @throws JobSchedulingException + */ + public void calculateMetric(Metric metric) throws JobSchedulingException { + logger.info("Scheduling calculation of metric"); + // check metric + if (metric == null) { + logger.info("Metric is null"); + throw new JobSchedulingException("Metric is null"); + } + logger.info("Metric: " + metric.getName()); + + logger.info("Checking formula"); + // check formula + Formula formula = metric.getFormula(); + if (formula == null) { + logger.info("Formula is null"); + throw new JobSchedulingException("Formula is null"); + } + if (formula.getFormula().isBlank()) { + logger.info("Formula is blank"); + throw new JobSchedulingException("Formula is blank"); + } + logger.info("Formula: " + formula.getFormula()); + + logger.info("Checking if a calculation job for metric already exists"); + // check if job for metric already exists + TriggerKey triggerKey = TriggerKey.triggerKey(metric.getId().toString(), "calculateMetrics"); + JobKey jobKey = JobKey.jobKey(metric.getId().toString(), "calculateMetrics"); + + Trigger trigger = getTrigger(metric, triggerKey); + + if (checkJobAndTriggerExists(jobKey, triggerKey)) { // job and trigger exist + // reschedule job + rescheduleJob(trigger); + } else { // job and trigger do not exist + logger.info("Job and trigger do not already exist"); + + logger.info("Adding metric to job data map"); + // add id of metric to job information + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("metricId", metric.getId().toString()); + + logger.info("Creating job"); + // create job + JobDetail job = JobBuilder.newJob(CalculateJob.class) + .withIdentity(jobKey) + .withDescription("Calculate metric " + metric) + .setJobData(jobDataMap) + .build(); + logger.info("Scheduling job"); + + // schedule job + scheduleJob(job, trigger); + } + + logger.info("Calculation of metric scheduled"); + } + + /** + * Schedules job for determination of measurement + * + * @param measurement + * @throws JobSchedulingException + */ + public void measureMeasurement(Measurement measurement) throws JobSchedulingException { + logger.info("Scheduling measuring of measurement"); + // check measurement + if (measurement == null) { + logger.info("Measurement is null"); + throw new JobSchedulingException("Measurement is null"); + } + logger.info("Measurement: " + measurement.getName()); + + logger.info("Checking if a measuring job for measurement already exists"); + // check if job for measurement already exists + TriggerKey triggerKey = TriggerKey.triggerKey(measurement.getId().toString(), "measureMeasurement"); + JobKey jobKey = JobKey.jobKey(measurement.getId().toString(), "measureMeasurement"); + + Trigger trigger = getTrigger(measurement, triggerKey); + + if (checkJobAndTriggerExists(jobKey, triggerKey)) { // job and trigger exist + // reschedule job + rescheduleJob(trigger); + } else { // job and trigger do not exist + logger.info("Job and trigger do not already exist"); + + logger.info("Adding measurement to job data map"); + // add id of metric to job information + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("measurementId", measurement.getId().toString()); + + logger.info("Creating job"); + // create job + JobDetail job = JobBuilder.newJob(MeasureJob.class) + .withIdentity(jobKey) + .withDescription("Measure measurement " + measurement) + .setJobData(jobDataMap) + .build(); + + // schedule job + scheduleJob(job, trigger); + } + + logger.info("Measuring of measurement scheduled"); + } + + /** + * Checks if job and trigger exists + * + * @param jobKey + * @param triggerKey + * @return + * @throws JobSchedulingException + */ + private boolean checkJobAndTriggerExists(JobKey jobKey, TriggerKey triggerKey) throws JobSchedulingException { + try { + return (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)); + } catch (SchedulerException e) { + logger.info("Error while checking if job exists"); + throw new JobSchedulingException(e.getMessage()); + } + } + + /** + * Reschedules job with new trigger + * + * @param trigger + * @throws JobSchedulingException + */ + private void rescheduleJob(Trigger trigger) throws JobSchedulingException { + logger.info("Job and trigger exist"); + try { + logger.info("Rescheduling existing job"); + scheduler.rescheduleJob(trigger.getKey(), trigger); + } catch (SchedulerException e) { + logger.info("Error while rescheduling existing job"); + throw new JobSchedulingException(e.getMessage()); + } + } + + /** + * Schedules job using trigger + * + * @param job + * @param trigger + * @throws JobSchedulingException + */ + private void scheduleJob(JobDetail job, Trigger trigger) throws JobSchedulingException { + logger.info("Scheduling job"); + try { + // schedule job + scheduler.scheduleJob(job, trigger); + } catch (SchedulerException e) { + logger.info("Scheduling of job failed: " + e.getMessage()); + throw new JobSchedulingException(e.getMessage()); + } + } + + /** + * Returns trigger for measurable + * + * @param measurable + * @param triggerKey + * @return + * @throws JobSchedulingException + */ + private Trigger getTrigger(Measurable measurable, TriggerKey triggerKey) throws JobSchedulingException { + logger.info("Checking frequency"); + // check frequency + Frequency frequency = measurable.getFrequency(); + if (frequency == null) { + throw new JobSchedulingException("Frequency is null"); + } + // check duration + Duration duration = frequency.getDuration(); + if (duration == null) { + throw new JobSchedulingException("Duration is null"); + } + logger.info("Frequency: " + duration); + + logger.info("Creating trigger"); + // create trigger using duration + return TriggerBuilder.newTrigger().startNow() + .withIdentity(triggerKey) + .withSchedule(SimpleScheduleBuilder.simpleSchedule() + .repeatForever() + .withIntervalInMilliseconds(duration.toMillis())) + .build(); + } + + /** + * Stops job for calculation of metric + * + * @param metric + * @return + * @throws JobSchedulingException + */ + public boolean stopCalculation(Metric metric) throws JobSchedulingException { + logger.info("Stop calculation of metric"); + if (metric == null) { + logger.info("Metric is null"); + throw new JobSchedulingException("Metric is null"); + } + logger.info("Metric: " + metric.getName()); + + JobKey jobKey = JobKey.jobKey(metric.getId().toString(), "calculateMetrics"); + return deleteJob(jobKey); + } + + /** + * Stops job for determination of measurement + * + * @param measurement + * @return + * @throws JobSchedulingException + */ + public boolean stopMeasurement(Measurement measurement) throws JobSchedulingException { + logger.info("Stop measuring of measurement"); + if (measurement == null) { + logger.info("Measurement is null"); + throw new JobSchedulingException("Measurement is null"); + } + logger.info("Measurement: " + measurement.getName()); + + JobKey jobKey = JobKey.jobKey(measurement.getId().toString(), "measureMeasurement"); + return deleteJob(jobKey); + } + + /** + * Deletes job + * + * @param jobKey + * @return + * @throws JobSchedulingException + */ + private boolean deleteJob(JobKey jobKey) throws JobSchedulingException { + logger.info("Deleting job"); + try { + return scheduler.deleteJob(jobKey); + } catch (SchedulerException e) { + logger.info("Error while deleting job"); + throw new JobSchedulingException(e.getMessage()); + } + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/service/MeasurableService.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/MeasurableService.java new file mode 100644 index 0000000..f2c87b7 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/MeasurableService.java @@ -0,0 +1,378 @@ +package de.uniregensburg.iamreportingmodule.core.service; + +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.data.entity.*; +import de.uniregensburg.iamreportingmodule.data.repository.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Service for persisting measureables (metrics and measurements) + * + * @author Julian Bauer + */ +@Service +public class MeasurableService { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final MeasurementRepository measurementRepository; + private final MetricRepository metricRepository; + private final StakeholderRepository stakeholderRepository; + private final AudienceRepository audienceRepository; + private final InformationNeedRepository informationNeedRepository; + private final ManualDataSourceRepository manualDataSourceRepository; + private final DatabaseDataSourceRepository databaseDataSourceRepository; + private final ResultRepository resultRepository; + private final JobSchedulingService jobSchedulingService; + private final FileDataSourceRepository fileDataSourceRepository; + + /** + * + * @param measurementRepository + * @param metricRepository + * @param stakeholderRepository + * @param audienceRepository + * @param informationNeedRepository + * @param manualDataSourceRepository + * @param databaseDataSourceRepository + * @param resultRepository + * @param jobSchedulingService + * @param fileDataSourceRepository + */ + public MeasurableService(MeasurementRepository measurementRepository, MetricRepository metricRepository, StakeholderRepository stakeholderRepository, AudienceRepository audienceRepository, InformationNeedRepository informationNeedRepository, ManualDataSourceRepository manualDataSourceRepository, DatabaseDataSourceRepository databaseDataSourceRepository, + ResultRepository resultRepository, JobSchedulingService jobSchedulingService, + FileDataSourceRepository fileDataSourceRepository) { + this.measurementRepository = measurementRepository; + this.metricRepository = metricRepository; + this.stakeholderRepository = stakeholderRepository; + this.audienceRepository = audienceRepository; + this.informationNeedRepository = informationNeedRepository; + this.manualDataSourceRepository = manualDataSourceRepository; + this.databaseDataSourceRepository = databaseDataSourceRepository; + this.resultRepository = resultRepository; + this.jobSchedulingService = jobSchedulingService; + this.fileDataSourceRepository = fileDataSourceRepository; + } + + /** + * Returns all measurements + * + * @return + */ + public List findAllMeasurements() { + logger.info("Returning all measurements"); + // get and return all measurements + return measurementRepository.findAll(); + } + + /** + * Saves a measurement + * + * @param measurement + * @throws SaveEntityException + */ + public void saveMeasurement(Measurement measurement) throws SaveEntityException { + logger.info("Saving measurement"); + // check measurement + if (measurement == null) { + logger.info("Measurement is null"); + throw new SaveEntityException("No measurement provided"); + } + try { + // save measurement + measurementRepository.save(measurement); + logger.info("Measurement saved"); + // schedule job + jobSchedulingService.measureMeasurement(measurement); + logger.info("Measuring of measurement scheduled"); + } catch (Exception e) { + logger.info("Error while saving measurement: " + e.getMessage()); + throw new SaveEntityException("Error while saving measurement"); + } + } + + /** + * Deletes a measurement + * + * @param measurement + * @throws DeleteEntityException + */ + public void deleteMeasurement(Measurement measurement) throws DeleteEntityException { + logger.info("Deleting measurement"); + // check measurement + if (measurement == null) { + logger.info("Measurement is null"); + throw new DeleteEntityException("Measurement is null"); + } + try { + // delete measurement + measurementRepository.delete(measurement); + // stop job + jobSchedulingService.stopMeasurement(measurement); + logger.info("Measurement deleted"); + } catch (Exception ex) { + logger.info("Cannot delete measurement: " + ex.getMessage()); + throw new DeleteEntityException("Measurement is probably used in one or more formulas"); + } + } + + /** + * Returns a measurement by id + * + * @param id + * @return + */ + public Measurement findMeasurementById(UUID id) { + logger.info("Searching measurement with id " + id); + // search measurement by id + Optional measurement = measurementRepository.findById(id); + + // check measurement + if (measurement.isEmpty()) { + logger.info("Measurement not found"); + return null; + } + + logger.info("Measurement found"); + // return measurement + return measurement.get(); + } + + /** + * Returns all metrics + * + * @return + */ + public List findAllMetrics() { + logger.info("Returning all metrics"); + // get and return all metrics + return metricRepository.findAll(); + } + + /** + * Saves a metric + * + * @param metric + * @throws SaveEntityException + */ + public void saveMetric(Metric metric) throws SaveEntityException { + logger.info("Saving metric"); + // check metric + if (metric == null) { + logger.info("metric is null"); + throw new SaveEntityException("No metric provided"); + } + try { + // save metric + metricRepository.save(metric); + logger.info("Metric saved"); + // schedule job + jobSchedulingService.calculateMetric(metric); + logger.info("Calculation of metric scheduled"); + } catch (Exception e) { + logger.info("Error while saving metric: " + e.getMessage()); + throw new SaveEntityException("Error while saving metric"); + } + } + + /** + * Deletes a metric + * + * @param metric + * @throws DeleteEntityException + */ + public void deleteMetric(Metric metric) throws DeleteEntityException { + logger.info("Deleting metric"); + // check metric + if (metric == null) { + logger.info("Metric is null"); + throw new DeleteEntityException("Metric is null"); + } + try { + // delete metric + metricRepository.delete(metric); + // stop job + jobSchedulingService.stopCalculation(metric); + logger.info("Metric deleted"); + } catch (Exception ex) { + logger.info("Cannot delete metric: " + ex.getMessage()); + throw new DeleteEntityException("Metric is probably used in one or more formulas"); + } + } + + /** + * Returns an metric by id + * + * @param id + * @return + */ + public Metric findMetricById(UUID id) { + logger.info("Searching metric with id " + id); + // search metric by id + Optional metric = metricRepository.findById(id); + + // check metric + if (metric.isEmpty()) { + logger.info("Metric not found"); + return null; + } + + logger.info("Metric found"); + // return metric + return metric.get(); + } + + /** + * Returns all stakeholders + * + * @return + */ + public List findAllStakeholders() { + logger.info("Returning all stakeholders"); + // get and return all + return stakeholderRepository.findAll(); + } + + /** + * Returns all information needs + * + * @return + */ + public List findAllInformationNeeds() { + logger.info("Returning all information needs"); + // get and return all + return informationNeedRepository.findAll(); + } + + /** + * Returns all audiences + * + * @return + */ + public List findAllAudiences() { + logger.info("Returning all audiences"); + // get and return all + return audienceRepository.findAll(); + } + + /** + * Returns all datasources + * + * @return + */ + public List findAllDataSources() { + logger.info("Returning all datasources"); + // get datasources of all three types + List dataSources = new ArrayList<>(); + dataSources.addAll(manualDataSourceRepository.findAll()); + dataSources.addAll(databaseDataSourceRepository.findAll()); + dataSources.addAll(fileDataSourceRepository.findAll()); + // return all datasources sorted by name + return dataSources.stream().sorted(Comparator.comparing(DataSource::getName)).collect(Collectors.toList()); + } + + /** + * Returns measureables by label + * + * @param label + * @return + */ + public List findAllMeasurablesByLabel(String label) { + logger.info("Returning all measurables with label " + label); + // search measurables by label + List measurables = new ArrayList<>(); + measurables.addAll(metricRepository.findAllByLabel(label)); + measurables.addAll(measurementRepository.findAllByLabel(label)); + // return measurables + return measurables; + } + + /** + * Returns latest 10 results by measurable + * + * @param measurable + * @return + */ + public List findFirst10ResultsByMeasurableOrderByPointInTimeDesc(Measurable measurable) { + logger.info("Returning all results of measureable " + measurable.getName()); + // search and return latest 10 results by measurable + return resultRepository.findFirst10ByMeasurableOrderByPointInTimeDesc(measurable); + } + + /** + * Returns latest result by measurable + * + * @param measurable + * @return + */ + public Result findLatestResultByMeasurable(Measurable measurable) { + logger.info("Returning latest result of measureable " + measurable.getName()); + // search and return latest result by measurable + return resultRepository.findFirstByMeasurableOrderByPointInTimeDesc(measurable); + } + + /** + * Saves result + * + * @param result + */ + public void saveResult(Result result) { + logger.info("Saving result"); + // check result + if (result == null) { + logger.info("Result is null"); + return; + } + + // save result + resultRepository.save(result); + logger.info("Result saved"); + } + + /** + * Returns metrics by information need and audiences + * @param informationNeed + * @param audiences + * @return + */ + public List findMetricsByInformationNeedAndAudiences(InformationNeed informationNeed, Set audiences) { + logger.info("Returning all metrics with information need " + informationNeed); + // search and return metrics by information needs and audiences + return metricRepository.findAllByInformationNeedsInAndAudiencesIn(Set.of(informationNeed), audiences); + } + + /** + * Returns measurable by id + * + * @param id + * @return + */ + public Measurable findMeasurableById(UUID id) { + // search metric by id + Optional metric = metricRepository.findById(id); + // search measurement by id + Optional measurement = measurementRepository.findById(id); + + // check if metric exists + if (metric.isPresent()) { + logger.info("Metric found"); + // return metric + return metric.get(); + } + // check if measurement exists + if (measurement.isPresent()) { + logger.info("Measurement found"); + // return measurement + return measurement.get(); + } + + logger.info("Measurable not found"); + // nothing found, return null + return null; + } +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/service/UserService.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/UserService.java new file mode 100644 index 0000000..97209e7 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/service/UserService.java @@ -0,0 +1,61 @@ +package de.uniregensburg.iamreportingmodule.core.service; + +import de.uniregensburg.iamreportingmodule.data.entity.User; +import de.uniregensburg.iamreportingmodule.data.repository.UserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * Service for persisting users + * + * @author Julian Bauer + */ +@Service +public class UserService { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final UserRepository userRepository; + + /** + * + * @param userRepository + */ + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + /** + * Returns all users + * @return + */ + public List findAllUsers() { + logger.info("Returning all users"); + // get and return all users + return userRepository.findAll(); + } + + /** + * Returns user by username + * + * @param username + * @return + */ + public User findUserByUsername(String username) { + logger.info("Searching user with username " + username); + // search user by username + User user = userRepository.findByUsername(username); + + // check user + if (user == null) { + logger.info("User not found"); + return null; + } + + logger.info("User found"); + // return user + return user; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/util/CsvUtil.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/util/CsvUtil.java new file mode 100644 index 0000000..22d353f --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/util/CsvUtil.java @@ -0,0 +1,228 @@ +package de.uniregensburg.iamreportingmodule.core.util; + +import de.uniregensburg.iamreportingmodule.core.exception.FileException; +import de.uniregensburg.iamreportingmodule.data.entity.CsvAggregationMethod; +import de.uniregensburg.iamreportingmodule.data.entity.FileDataSource; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.util.*; + +/** + * Utility to query csv files + * + * @author + */ +public class CsvUtil { + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final FileDataSource fileDataSource; + + /** + * + * @param fileDataSource + */ + public CsvUtil(FileDataSource fileDataSource) { + this.fileDataSource = fileDataSource; + } + + /** + * Returns result of measurement specified by attributes header, column, delimiter and aggregation method + * + * @param attributes + * @return + * @throws FileException + */ + public Result measure(Map attributes) throws FileException { + logger.info("Getting attributes"); + // check header + if (attributes.get("csvHeader") == null) { + logger.info("No header attribute provided"); + throw new FileException("No header attribute provided"); + } + // get header + boolean header = Boolean.parseBoolean(attributes.get("csvHeader")); + + // get column + String columnName = ""; + int columnIndex = -1; + // header + if (header) { + // check column name + if (attributes.get("csvColumnName") == null) { + logger.info("No column name attribute provided"); + throw new FileException("No column name attribute provided"); + } + // get column name + columnName = attributes.get("csvColumnName"); + // no header + } else { + // check column index + if (attributes.get("csvColumnIndex") == null) { + logger.info("No column index attribute provided"); + throw new FileException("No column index attribute provided"); + } + // get column index + try { + columnIndex = Integer.parseInt(attributes.get("csvColumnIndex")); + } catch (NumberFormatException e) { + logger.info("Cannot convert column index to integer: " + e.getMessage()); + throw new FileException("Cannot convert column index to integer: " + e.getMessage()); + } + } + // check delimiter + if (attributes.get("csvDelimiter") == null) { + logger.info("No delimiter attribute provided"); + throw new FileException("No delimiter attribute provided"); + } + // get delimiter + String delimiter = attributes.get("csvDelimiter"); + // check aggregation method + if (attributes.get("csvAggregationMethod") == null) { + logger.info("No delimiter attribute provided"); + throw new FileException("No delimiter attribute provided"); + } + // get aggregation method + CsvAggregationMethod aggregationMethod = CsvAggregationMethod.valueOf(attributes.get("csvAggregationMethod")); + + // get file + fileDataSource.getFile(); + + // read in file row by row + String line; + List> lines = new ArrayList<>(); + try (ByteArrayInputStream is = new ByteArrayInputStream(fileDataSource.getFile()); BufferedReader br = new BufferedReader(new InputStreamReader(is))) { + while((line = br.readLine()) != null){ + List rowValues = Arrays.asList(line.split(delimiter)); + lines.add(rowValues); + } + } catch (IOException e){ + e.printStackTrace(); + } + + // check if rows exist + if (lines.size() == 0) { + logger.info("No data found"); + throw new FileException("No data found"); + } + + // header + if (header) { + // get header row + List headerLine = lines.get(0); + // check if column name exists in header + if (headerLine.contains(columnName)) { + columnIndex = headerLine.indexOf(columnName); + } else { + logger.info("No column with name " + columnName + " found"); + throw new FileException("No column with name " + columnName + " found"); + } + // remove header line + lines.remove(0); + } + + // get values of specified column + List columnValues = new ArrayList<>(); + int i = columnIndex; + try { + lines.forEach(l -> columnValues.add(l.get(i))); + } catch (ArrayIndexOutOfBoundsException e) { + logger.info("Column not found" + e.getMessage()); + throw new FileException("Column not found: " + e.getMessage()); + } + + // check if column contains values + if (columnValues.size() == 0) { + logger.info("No data found"); + throw new FileException("No data found"); + } + + // aggregate columns to result using specified aggregation method + Result result; + try { + result = switch (aggregationMethod) { + // count rows + case COUNT: + yield new Result(new BigDecimal(columnValues.size())); + // build sum of values of all rows + case SUM: + BigDecimal sum = null; + Iterator itSum = columnValues.iterator(); + if(itSum.hasNext()){ + sum = new BigDecimal(itSum.next()); + while(itSum.hasNext()){ + sum = sum.add(new BigDecimal(itSum.next())); + } + } + yield new Result(sum); + // get minimum value + case MINIMUM: + BigDecimal min = null; + Iterator itMinimum = columnValues.iterator(); + if(itMinimum.hasNext()){ + min = new BigDecimal(itMinimum.next()); + while(itMinimum.hasNext()){ + min = min.min(new BigDecimal(itMinimum.next())); + } + } + yield new Result(min); + // get maximum value + case MAXIMUM: + BigDecimal max = null; + Iterator itMaximum = columnValues.iterator(); + if(itMaximum.hasNext()){ + max = new BigDecimal(itMaximum.next()); + while(itMaximum.hasNext()){ + max = max.max(new BigDecimal(itMaximum.next())); + } + } + yield new Result(max); + // get average value + case AVERAGE: + BigDecimal numerator = null; + Iterator itNumerator = columnValues.iterator(); + if(itNumerator.hasNext()){ + numerator = new BigDecimal(itNumerator.next()); + while(itNumerator.hasNext()){ + numerator = numerator.add(new BigDecimal(itNumerator.next())); + } + } + BigDecimal denominator = new BigDecimal(columnValues.size()); + if (denominator.equals(BigDecimal.ZERO) || numerator == null) { + yield new Result(null); + } else { + yield new Result(numerator.divide(denominator, MathContext.DECIMAL128.getPrecision(), RoundingMode.HALF_UP)); + } + // get median value + case MEDIAN: + ArrayList bigDecimals = new ArrayList<>(); + columnValues.forEach(v -> bigDecimals.add(new BigDecimal(v))); // convert to BigDecimal + bigDecimals.sort(BigDecimal::compareTo); // sort bigDecimals + BigDecimal median; + if (bigDecimals.size() == 0) { + median = null; + } else if (bigDecimals.size() % 2 == 1) { + median = bigDecimals.get((bigDecimals.size() + 1) / 2 - 1 ); + } else { + median = bigDecimals.get(bigDecimals.size() / 2 - 1); + median = median.add(bigDecimals.get(bigDecimals.size() / 2)); + median = median.divide(new BigDecimal(2), MathContext.DECIMAL128.getPrecision(), RoundingMode.HALF_UP); + } + yield new Result(median); + }; + } catch (Exception e) { + logger.info("Error during aggregation: " + e.getMessage()); + throw new FileException("Error during aggregation: " + e.getMessage()); + } + + // return result + return result; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/util/DatabaseUtil.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/util/DatabaseUtil.java new file mode 100644 index 0000000..cb29a83 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/util/DatabaseUtil.java @@ -0,0 +1,133 @@ +package de.uniregensburg.iamreportingmodule.core.util; + +import de.uniregensburg.iamreportingmodule.core.exception.DatabaseException; +import de.uniregensburg.iamreportingmodule.data.entity.DatabaseDataSource; +import de.uniregensburg.iamreportingmodule.data.entity.Dbms; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.sql.*; +import java.util.Properties; + +/** + * Utility to execute database queries + * + * @author Julian Bauer + */ +public class DatabaseUtil { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final DatabaseDataSource databaseDataSource; + + /** + * + * @param databaseDataSource + */ + public DatabaseUtil(DatabaseDataSource databaseDataSource) { + this.databaseDataSource = databaseDataSource; + } + + /** + * Tests database connection + * + * @return + * @throws DatabaseException + */ + public boolean testConnection() throws DatabaseException { + boolean success; + + logger.info("Testing database connection"); + + // try connecting to database + try (Connection conn = getConnection()) { + success = (conn != null); + } catch (SQLException e) { + logger.info("Connection failed"); + logger.info(e.getMessage()); + throw new DatabaseException(e.getMessage()); + } + + if (success) { + logger.info("Connection established"); + } else { + logger.info("Connection failed"); + } + + // return connection result + return success; + } + + /** + * Returns database connection + * + * @return + * @throws SQLException + */ + public Connection getConnection() throws SQLException { + // get and return database connection by dbms type + if (databaseDataSource.getDbmsType().equals(Dbms.POSTGRESQL)) { + return getPostgresqlConnection(); + } else { + logger.info("Method not implemented yet for " + databaseDataSource.getDbmsType()); + return null; // not implemented yet + } + } + + /** + * Returns postgresql database connection + * + * @return + * @throws SQLException + */ + private Connection getPostgresqlConnection() throws SQLException { + // setup jdbc postgresql connection url: host, port and database + String url = "jdbc:" + + "postgresql://" + + databaseDataSource.getHost() + + ":" + databaseDataSource.getPort() + + "/" + databaseDataSource.getDatabase(); + + // append credentials: username and password + Properties props = new Properties(); + if (!databaseDataSource.getUsername().isEmpty()) { + props.setProperty("user", databaseDataSource.getUsername()); + } + if (!databaseDataSource.getPassword().isEmpty()) { + props.setProperty("password", databaseDataSource.getPassword()); + } + + logger.info("Returning connection url " + url + " and properties username " + databaseDataSource.getUsername() + + " and password ******* (not logged)"); + + // return postgresql connection + return DriverManager.getConnection(url, props); + } + + /** + * Returns measurement result of executing sql query + * + * @param query + * @return + * @throws DatabaseException + */ + public Result measure(String query) throws DatabaseException { + logger.info("Executing query " + query); + // open connection + try (Statement stmt = getConnection().createStatement()) { + // execute query + ResultSet rs = stmt.executeQuery(query); + // get value + rs.next(); + BigDecimal value = rs.getBigDecimal(1); + logger.info("Query result: " + value); + // return result + return new Result(value); + } catch (SQLException e) { + logger.info(e.toString()); + throw new DatabaseException(e.getMessage()); + } + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/core/util/FormulaUtil.java b/src/main/java/de/uniregensburg/iamreportingmodule/core/util/FormulaUtil.java new file mode 100644 index 0000000..1c4dfd8 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/core/util/FormulaUtil.java @@ -0,0 +1,281 @@ +package de.uniregensburg.iamreportingmodule.core.util; + +import com.ezylang.evalex.EvaluationException; +import com.ezylang.evalex.Expression; +import com.ezylang.evalex.data.EvaluationValue; +import com.ezylang.evalex.parser.ParseException; +import de.uniregensburg.iamreportingmodule.core.exception.FormulaException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.data.entity.Measurable; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Utility to validate and calculate formulas + * + * @author Julian Bauer + */ +public class FormulaUtil { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final MeasurableService service; + + /** + * + * @param service + */ + public FormulaUtil(MeasurableService service) { + this.service = service; + } + + /** + * Calculates results based on formula + * + * @param formula + * @return + * @throws FormulaException + */ + public Result calculate(String formula) throws FormulaException { + logger.info("Calculating " + formula); + // replace variables with values + formula = replaceVariablesWithMeasurableValues(formula); + // evaluate formula + Expression expression = new Expression(formula); + try { + EvaluationValue value = expression.evaluate(); + logger.info("Evaluation value: " + value.getNumberValue()); + // return result + return new Result(value.getNumberValue()); + } catch (EvaluationException | ParseException e) { + logger.info("Failed to calculate: " + e.getMessage()); + throw new FormulaException(e.getMessage()); + } + } + + /** + * Validates braces of formula: + * variables are composed of two opening braces {{, + * the label of the measurable + * and two closing braces }} + * + * @param formula + * @return + */ + public boolean validateBraces(String formula) { + logger.info("Validating brackets of formula: " + formula); + // init counter + int openBraces = 0; + // init variable last character + char lastChar = Character.MIN_VALUE; + // iterate over all characters of the formula + for (char c : formula.toCharArray()) { + // if not first round + if (lastChar != Character.MIN_VALUE) { + // first opening brace not followed by second opening brace + if (lastChar == '{' && openBraces < 2 && c != '{') { + logger.info("Error: Opening brace '{' not followed by second opening bracket '{'"); + return false; + } + // first closing brace not followed by second closing brace + if (lastChar == '}' && openBraces > 0 && c != '}') { + logger.info("Error: Closing brace '}' not followed by second closing bracket '}'"); + return false; + } + } + // opening brace + if (c == '{') { + // more than 2 braces opened + if (openBraces > 2) { + logger.info("Error: More than two opening brace '{"); + return false; + } else { + // increment + openBraces++; + } + } + // closing brace + if (c == '}') { + // no opened brace + if (openBraces < 1) { + logger.info("Error: Closing bracket '}' but no brace are opened'"); + return false; + } else { + // decrement + openBraces--; + } + } + // set last character + lastChar = c; + } + // iteration finished + // check if all braces are closed + if (openBraces != 0) { + logger.info("Not all brace closed"); + return false; + } + return true; + } + + /** + * Replaces variables with the latest result of measurable + * + * @param formula + * @return + * @throws FormulaException + */ + public String replaceVariablesWithMeasurableValues(String formula) throws FormulaException { + logger.info("Replacing variables of formula with measurable values"); + logger.info("Formula: " + formula); + // check if formula contains a variable and braces are set correctly + if (validateBraces(formula) && containsVariable(formula)) { + // get label + String variable = getFirstVariable(formula); + // find measurables by label + List measurables = service.findAllMeasurablesByLabel(variable); + // check if measurable exists + if (measurables.isEmpty()) { + throw new FormulaException("No measurables found with label: " + variable); + } + // get first measurable, in theory only list should contain only one measurable because a label is unique + Measurable measurable = measurables.get(0); + // get the latest result of measurable + Result result = service.findLatestResultByMeasurable(measurable); + // check if result exists + if (result == null) { + throw new FormulaException("No results of " + measurable.getName() + " available for calculation"); + } + + // replace variable with result value in formula + int start = getStartIndexOfFirstVariable(formula); + String substring = formula.substring(start + 2); // get substring after {{ + int end = getEndIndexOfFirstVariable(substring); + String newFormula = formula.substring(0, start) + result.getValue() + substring.substring(end + 2); + // recursive method call with new formula + return replaceVariablesWithMeasurableValues(newFormula); + } + // return formula with replaced variables by result values + return formula; + } + + /** + * Returns first variable in formula + * + * @param formula + * @return + * @throws FormulaException + */ + private String getFirstVariable(String formula) throws FormulaException { + logger.info("Get variable"); + // check if a variable contains in formula + if (containsVariable(formula)) { + // get start and end index + int start = getStartIndexOfFirstVariable(formula); + int end = getEndIndexOfFirstVariable(formula); + // get variable substring + String variable = formula.substring(start + 2, end); // get variable name + logger.info("Variable: " + variable); + // return variable + return variable; + } else { + return null; + } + } + + /** + * Returns start index of first variable in formula + * + * @param formula + * @return + */ + private int getStartIndexOfFirstVariable(String formula) { + logger.info("Get index of start of variable"); + int start = formula.indexOf("{{"); // get start index of variable + logger.info("Index of start: " + start); + return start; + } + + /** + * Returns end index of first variable in formula + * + * @param formula + * @return + */ + private int getEndIndexOfFirstVariable(String formula) { + logger.info("Get index of end of variable"); + int end = formula.indexOf("}}"); // get end index of variable + logger.info("Index of end: " + end); + return end; + } + + /** + * Check if formula contains a variable + * + * @param formula + * @return + * @throws FormulaException + */ + private boolean containsVariable(String formula) throws FormulaException { + logger.info("Checking if formula contains variable"); + int start = getStartIndexOfFirstVariable(formula); + if (start == -1) { // variable start definition does not exist + logger.info("No variable start definition"); + return false; + } else { // variable start definition exists + int end = getEndIndexOfFirstVariable(formula); + if (end == -1) { // variable end definition does not exist + logger.info("No variable end definition"); + return false; + } else { // variable end definition exists + String variable = formula.substring(start + 2, end); // get variable name + String pattern = "[a-z]+((\\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?"; // regex expression for lower camel case + if (variable.matches(pattern)) { // variable name is lower camel case + logger.info("Variable found"); + return true; + } else { // variable name not is lower camel case + logger.info("Variable does not match lower camel case"); + throw new FormulaException("Variable does not match lower camel case"); + } + } + } + } + + /** + * Returns all measurables referenced by formula + * + * @param formula + * @return + * @throws FormulaException + */ + public Set getMeasurables(String formula) throws FormulaException { + Set measurables = new HashSet<>(); + logger.info("Getting referenced measurables of formula"); + logger.info("Formula: " + formula); + // while formula a variable and braces are set correctly + while (validateBraces(formula) && containsVariable(formula)) { + // get first variable + String variable = getFirstVariable(formula); + // find measurable by label / variable + List m = service.findAllMeasurablesByLabel(variable); + // check if measurable exists + if (m.isEmpty()) { + throw new FormulaException("No measurables found with label: " + variable); + } + // get first measurable, in theory only list should contain only one measurable because a label is unique + Measurable measurable = m.get(0); + // add measurable to set + measurables.add(measurable); + // shorten formula: new start index is after current variable + int start = getStartIndexOfFirstVariable(formula); + String substring = formula.substring(start + 2); // get substring after {{ + int end = getEndIndexOfFirstVariable(substring); + formula = formula.substring(0, start) + 1 + substring.substring(end + 2); + } + // return all measurables + return measurables; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToFormulaConverter.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToFormulaConverter.java new file mode 100644 index 0000000..36b7641 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToFormulaConverter.java @@ -0,0 +1,112 @@ +package de.uniregensburg.iamreportingmodule.data.converter; + +import com.vaadin.flow.data.binder.ErrorMessageProvider; +import com.vaadin.flow.data.binder.Result; +import com.vaadin.flow.data.binder.ValueContext; +import com.vaadin.flow.data.converter.Converter; +import de.uniregensburg.iamreportingmodule.data.entity.Formula; +import de.uniregensburg.iamreportingmodule.data.entity.Metric; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.exception.FormulaException; +import de.uniregensburg.iamreportingmodule.core.util.FormulaUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Converter of string to formula and vice versa + * + * @author Julian Bauer + */ +public class StringToFormulaConverter implements Converter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final ErrorMessageProvider errorMessageProvider; + private final FormulaUtil util; + private final Metric metric; + + /** + * + * @param errorMessageProvider + * @param service + * @param metric + */ + public StringToFormulaConverter(ErrorMessageProvider errorMessageProvider, MeasurableService service, Metric metric) { + this.errorMessageProvider = errorMessageProvider; + this.util = new FormulaUtil(service); + this.metric = metric; + } + + /** + * + * @param errorMessage + * @param service + * @param metric + */ + public StringToFormulaConverter(String errorMessage, MeasurableService service, Metric metric) { + this(valueContext -> errorMessage, service, metric); + } + + /** + * + * @param context + * @return + */ + private String getErrorMessage(ValueContext context) { + return errorMessageProvider.apply(context); + } + + /** + * Converts string to formula + * + * @param fieldValue + * @param context + * @return + */ + @Override + public Result convertToModel(String fieldValue, ValueContext context) { + logger.info("Converting string to formula"); + // check string + if (fieldValue == null) { + logger.info("Field value is null"); + return Result.error(getErrorMessage(context)); + } else { + // create formula object + Formula formula = new Formula(fieldValue); + if (metric != null) { + if (metric.getFormula() != null) { + formula = metric.getFormula(); + formula.setFormula(fieldValue); + } + } + try { + formula.setMeasurables(util.getMeasurables(fieldValue)); + } catch (FormulaException e) { + logger.info(e.getMessage()); + return Result.error(e.getMessage()); + } + // return formula + return Result.ok(formula); + } + } + + /** + * Converts formula to string + * + * @param formula + * @param context + * @return + */ + @Override + public String convertToPresentation(Formula formula, ValueContext context) { + logger.info("Converting formula to string"); + // check formula + if (formula == null) { + logger.info("Formula is null"); + return ""; + } else { + // return string + return formula.getFormula(); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToFrequencyConverter.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToFrequencyConverter.java new file mode 100644 index 0000000..22a8004 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToFrequencyConverter.java @@ -0,0 +1,114 @@ +package de.uniregensburg.iamreportingmodule.data.converter; + +import com.vaadin.flow.data.binder.ErrorMessageProvider; +import com.vaadin.flow.data.binder.Result; +import com.vaadin.flow.data.binder.ValueContext; +import com.vaadin.flow.data.converter.Converter; +import de.uniregensburg.iamreportingmodule.data.entity.Frequency; +import de.uniregensburg.iamreportingmodule.data.entity.Measurable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.time.format.DateTimeParseException; + +/** + * Converter of string to frequency and vice versa + * + * @author Julian Bauer + */ +public class StringToFrequencyConverter implements Converter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final ErrorMessageProvider errorMessageProvider; + private final Measurable measurable; + + /** + * + * @param errorMessageProvider + * @param measurable + */ + public StringToFrequencyConverter(ErrorMessageProvider errorMessageProvider, Measurable measurable) { + this.errorMessageProvider = errorMessageProvider; + this.measurable = measurable; + } + + /** + * + * @param errorMessage + * @param measurable + */ + public StringToFrequencyConverter(String errorMessage, Measurable measurable) { + this(valueContext -> errorMessage, measurable); + } + + /** + * + * @param context + * @return + */ + private String getErrorMessage(ValueContext context) { + return errorMessageProvider.apply(context); + } + + /** + * Converts string to frequency + * + * @param fieldValue + * @param context + * @return + */ + @Override + public Result convertToModel(String fieldValue, ValueContext context) { + logger.info("Converting string to frequency"); + // check string + if (fieldValue == null) { + logger.info("Field value is null"); + return Result.error(getErrorMessage(context)); + } else { + // create frequency object + try { + Duration duration = Duration.parse(fieldValue); + Frequency frequency = new Frequency(duration); + logger.info("Duration: " + duration.toString()); + if (measurable != null) { + if (measurable.getFrequency() != null) { + frequency = measurable.getFrequency(); + frequency.setDuration(duration); + } + } + // return frequency + return Result.ok(frequency); + } catch (DateTimeParseException e) { + logger.info(e.getMessage()); + return Result.error(getErrorMessage(context)); + } + } + } + + /** + * Converts frequency to string + * + * @param frequency + * @param context + * @return + */ + @Override + public String convertToPresentation(Frequency frequency, ValueContext context) { + logger.info("Converting frequency to string"); + // check frequency + if (frequency == null) { + logger.info("Frequency is null"); + return ""; + } + Duration duration = frequency.getDuration(); + // check duration + if (duration == null) { + logger.info("Duration is null"); + return ""; + } + // return string + return duration.toString(); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToPortConverter.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToPortConverter.java new file mode 100644 index 0000000..c024635 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/converter/StringToPortConverter.java @@ -0,0 +1,106 @@ +package de.uniregensburg.iamreportingmodule.data.converter; + +import com.vaadin.flow.data.binder.ErrorMessageProvider; +import com.vaadin.flow.data.binder.Result; +import com.vaadin.flow.data.binder.ValueContext; +import com.vaadin.flow.data.converter.Converter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Converter of string to port and vice versa + * + * @author Julian Bauer + */ +public class StringToPortConverter implements Converter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final ErrorMessageProvider errorMessageProvider; + private int min; + private int max; + + /** + * + * @param errorMessageProvider + * @param min + * @param max + */ + public StringToPortConverter(ErrorMessageProvider errorMessageProvider, int min, int max) { + this.errorMessageProvider = errorMessageProvider; + } + + /** + * + * @param errorMessageProvider + */ + public StringToPortConverter(ErrorMessageProvider errorMessageProvider) { + this.min = 1; + this.max = 65535; + this.errorMessageProvider = errorMessageProvider; + } + + /** + * + * @param errorMessage + */ + public StringToPortConverter(String errorMessage) { + this(valueContext -> errorMessage); + } + + /** + * + * @param context + * @return + */ + private String getErrorMessage(ValueContext context) { + return errorMessageProvider.apply(context); + } + + /** + * Converts string to port + * + * @param fieldValue + * @param context + * @return + */ + @Override + public Result convertToModel(String fieldValue, ValueContext context) { + logger.info("Converting string to port"); + // check string + if (fieldValue == null) { + logger.info("Field value is null"); + return Result.error(getErrorMessage(context)); + } else { + // create port + Integer port = Integer.valueOf(fieldValue); + // check port + if (port >= min && port <= max) { + // return port + return Result.ok(port); + } else { + return Result.error(getErrorMessage(context)); + } + } + } + + /** + * Converts port to string + * + * @param port + * @param context + * @return + */ + @Override + public String convertToPresentation(Integer port, ValueContext context) { + logger.info("Converting port to string"); + // check port + if (port == null) { + logger.info("Port is null"); + return ""; + } else { + // return string + return port.toString(); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/AbstractEntity.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/AbstractEntity.java new file mode 100644 index 0000000..7c71c8c --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/AbstractEntity.java @@ -0,0 +1,73 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import org.hibernate.annotations.Type; + +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import java.util.UUID; + +/** + * Abstract entity containing attribute id (UUID). + * All other entities inherit this entity. + * + * @author Julian Bauer + */ +@MappedSuperclass +public abstract class AbstractEntity { + + @Id + @GeneratedValue + @Type(type = "uuid-char") + private UUID id; + + /** + * Returns id + * + * @return + */ + public UUID getId() { + return id; + } + + /** + * Sets id + * + * @param id + */ + public void setId(UUID id) { + this.id = id; + } + + /** + * Returns hash code + * + * @return + */ + @Override + public int hashCode() { + if (id != null) { + return id.hashCode(); + } + return super.hashCode(); + } + + /** + * Returns if two objects are equal + * + * @param obj + * @return + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof AbstractEntity)) { + return false; // null or other class + } + AbstractEntity other = (AbstractEntity) obj; + + if (id != null) { + return id.equals(other.id); + } + return super.equals(other); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Audience.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Audience.java new file mode 100644 index 0000000..2efd1de --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Audience.java @@ -0,0 +1,64 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.annotation.Nullable; +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; + +/** + * Entity audience extends entity group + * Attributes: members (Set), measurables (Set) + * + * @author Julian Bauer + */ +@Entity +public class Audience extends Group { + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable( + name = "audience_memberships", + joinColumns = @JoinColumn(name = "audience_id"), + inverseJoinColumns = @JoinColumn(name = "user_id") + ) + private Set members = new HashSet<>(); + + @ManyToMany(mappedBy = "audiences") + @Nullable + private Set measurables = new HashSet<>(); + + /** + * Returns members + * + * @return + */ + public Set getMembers() { + return members; + } + + /** + * Sets members + * + * @param members + */ + public void setMembers(Set members) { + this.members = members; + } + + /** + * Returns measurables + * + * @return + */ + @Nullable + public Set getMeasurables() { + return measurables; + } + + /** + * Sets measurables + * + * @param measurables + */ + public void setMeasurables(@Nullable Set measurables) { + this.measurables = measurables; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/CsvAggregationMethod.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/CsvAggregationMethod.java new file mode 100644 index 0000000..e0dfe9b --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/CsvAggregationMethod.java @@ -0,0 +1,16 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +/** + * Enumeration csv aggregation method + * Values: COUNT, SUM, MINIMUM, MAXIMUM, AVERAGE, MEDIAN + * + * @author Julian Bauer + */ +public enum CsvAggregationMethod { + COUNT, + SUM, + MINIMUM, + MAXIMUM, + AVERAGE, + MEDIAN +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/CustomUserDetails.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/CustomUserDetails.java new file mode 100644 index 0000000..c8c9968 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/CustomUserDetails.java @@ -0,0 +1,114 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Entity custom user details implements spring user details + * Authorities: ROLE_ADMIN + * + * @author Julian Bauer + */ +public class CustomUserDetails implements UserDetails { + + private Logger logger = LoggerFactory.getLogger(getClass()); + private User user; + + /** + * + * @param user + */ + public CustomUserDetails(User user) { + this.user = user; + } + + /** + * Returns authorities + * if User isAdmin == true -> ROLE_ADMIN + * + * @return + */ + @Override + public Collection getAuthorities() { + Set authorities = new HashSet<>(); + if (user.isAdmin()) { + authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN")); + } + logger.info("Authorities: " + authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(", "))); + return authorities; + } + + /** + * Returns password of user + * + * @return + */ + @Override + public String getPassword() { + logger.info("Returning user password"); + return user.getPassword(); + } + + /** + * Returns username of user + * + * @return + */ + @Override + public String getUsername() { + logger.info("Returning username"); + return user.getUsername(); + } + + /** + * Returns account non expired (always true) + * + * @return + */ + @Override + public boolean isAccountNonExpired() { + logger.info("Returning is account not expired?"); + return true; + } + + /** + * Returns account non locked (always true) + * + * @return + */ + @Override + public boolean isAccountNonLocked() { + logger.info("Returning is account not locked?"); + return true; + } + + /** + * Returns credentials non expired (always true) + * + * @return + */ + @Override + public boolean isCredentialsNonExpired() { + logger.info("Returning is account credentials not expired?"); + return true; + } + + /** + * Returns account enabled (always true) + * + * @return + */ + @Override + public boolean isEnabled() { + logger.info("Returning is account enabled?"); + return true; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DataSource.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DataSource.java new file mode 100644 index 0000000..a5dab91 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DataSource.java @@ -0,0 +1,117 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.annotation.Nullable; +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; + +/** + * Abstract entity data source + * Attributes: name (String), description (int), type (DataSourceType), measurements (List) + * + * @author Julian Bauer + */ +@Entity +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +public abstract class DataSource extends AbstractEntity { + + @NotBlank + private String name; + + @NotBlank + private String description; + + @Enumerated(EnumType.STRING) + @NotNull + private DataSourceType type; + + @OneToMany(mappedBy = "dataSource", fetch = FetchType.EAGER) + @Nullable + private List measurements = new ArrayList<>(); + + /** + * Returns name + * + * @return + */ + public String getName() { + return name; + } + + /** + * Sets name + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns description + * + * @return + */ + public String getDescription() { + return description; + } + + /** + * Sets description + * + * @param description + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Returns type + * + * @return + */ + public DataSourceType getType() { + return type; + } + + /** + * Sets type + * + * @param type + */ + public void setType(DataSourceType type) { + this.type = type; + } + + /** + * Returns measurements + * + * @return + */ + public List getMeasurements() { + return measurements; + } + + /** + * Sets measurements + * + * @param measurements + */ + public void setMeasurements(List measurements) { + this.measurements = measurements; + } + + /** + * Checks before deleting datasource if it is in use by any measurements + * + * @throws RuntimeException + */ + @PreRemove + public void checkMeasurementAssociationBeforeRemoval() { + if (!this.measurements.isEmpty()) { + throw new RuntimeException("Cannot remove a datasource that is used by measurements."); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DataSourceType.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DataSourceType.java new file mode 100644 index 0000000..128ea28 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DataSourceType.java @@ -0,0 +1,13 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +/** + * Enumeration data source type + * Values: DATABASE, FILE, MANUAL + * + * @author Julian Bauer + */ +public enum DataSourceType { + DATABASE, + FILE, + MANUAL +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DatabaseDataSource.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DatabaseDataSource.java new file mode 100644 index 0000000..d2796b3 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/DatabaseDataSource.java @@ -0,0 +1,158 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * Entity database data source extends data source + * Attributes: host (String), port (int), database (String), dbmsType (Dbms), username (String), password (String) + * + * @author Julian Bauer + */ +@Entity +public class DatabaseDataSource extends DataSource { + + /** + * + */ + public DatabaseDataSource() { + setType(DataSourceType.DATABASE); + } + + /** + * + * @param dbmsType + */ + public DatabaseDataSource(Dbms dbmsType) { + setType(DataSourceType.DATABASE); + this.dbmsType = dbmsType; + } + + @NotBlank + private String host; + + @NotNull + private int port; + + @NotBlank + private String database; + + @NotNull + @Enumerated(EnumType.STRING) + private Dbms dbmsType; + + @NotNull + private String username; + + @NotNull + private String password; + + /** + * Returns host + * + * @return + */ + public String getHost() { + return host; + } + + /** + * Sets host + * + * @param host + */ + public void setHost(String host) { + this.host = host; + } + + /** + * Returns port + * + * @return + */ + public int getPort() { + return port; + } + + /** + * Sets port + * + * @param port + */ + public void setPort(int port) { + this.port = port; + } + + /** + * Returns database + * + * @return + */ + public String getDatabase() { + return database; + } + + /** + * Sets database + * + * @param database + */ + public void setDatabase(String database) { + this.database = database; + } + + /** + * Returns dbms type + * + * @return + */ + public Dbms getDbmsType() { + return dbmsType; + } + + /** + * Sets dbms type + * + * @param dbmsType + */ + public void setDbmsType(Dbms dbmsType) { + this.dbmsType = dbmsType; + } + + /** + * Returns username + * + * @return + */ + public String getUsername() { + return username; + } + + /** + * Sets username + * + * @param username + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * Returns password + * + * @return + */ + public String getPassword() { + return password; + } + + /** + * Sets password + * + * @param password + */ + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Dbms.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Dbms.java new file mode 100644 index 0000000..1956abb --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Dbms.java @@ -0,0 +1,13 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +/** + * Enumeration dbms + * Values: POSTGRESQL, MYSQL, MSSQL + * + * @author Julian Bauer + */ +public enum Dbms { + POSTGRESQL, + MYSQL, + MSSQL +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/FileDataSource.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/FileDataSource.java new file mode 100644 index 0000000..a57baa5 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/FileDataSource.java @@ -0,0 +1,91 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import org.hibernate.annotations.Type; + +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * Entity file data source extends data source + * Attributes: file (byte[]), fileType (FileType), fileName (String) + * + * @author Julian Bauer + */ +@Entity +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +public class FileDataSource extends DataSource { + + /** + * + */ + public FileDataSource() { + setType(DataSourceType.FILE); + } + + @Lob + @Type(type = "org.hibernate.type.BinaryType") + @NotNull + private byte[] file; + + @Enumerated(EnumType.STRING) + @NotNull + private FileType fileType; + + @NotBlank + private String fileName; + + /** + * Returns file + * + * @return + */ + public byte[] getFile() { + return file; + } + + /** + * Sets file + * + * @param file + */ + public void setFile(byte[] file) { + this.file = file; + } + + /** + * Returns file type + * + * @return + */ + public FileType getFileType() { + return fileType; + } + + /** + * Sets file type + * + * @param fileType + */ + public void setFileType(FileType fileType) { + this.fileType = fileType; + } + + /** + * Returns file name + * + * @return + */ + public String getFileName() { + return fileName; + } + + /** + * Sets file name + * + * @param fileName + */ + public void setFileName(String fileName) { + this.fileName = fileName; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/FileType.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/FileType.java new file mode 100644 index 0000000..1a73b8a --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/FileType.java @@ -0,0 +1,13 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +/** + * Enumeration file type + * Values: JSON, XML, CSV + * + * @author Julian Bauer + */ +public enum FileType { + JSON, + XML, + CSV +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Formula.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Formula.java new file mode 100644 index 0000000..f91576e --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Formula.java @@ -0,0 +1,107 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.HashSet; +import java.util.Set; + +/** + * Entity formula + * Attributes: measurables (Set), formula (String), metric (Metric) + * + * @author Julian Bauer + */ +@Entity +public class Formula extends AbstractEntity { + + @ManyToMany + @JoinTable( + name = "formulas_measurables", + joinColumns = @JoinColumn(name = "formula_id"), + inverseJoinColumns = @JoinColumn(name = "measureable_id") + ) + private Set measurables = new HashSet<>(); + + @NotBlank + private String formula; + + @NotNull + @OneToOne(mappedBy = "formula") + private Metric metric; + + /** + * + */ + public Formula() {} + + /** + * + * @param metric + */ + public Formula(Metric metric) { + this.metric = metric; + } + + /** + * + * @param formula + */ + public Formula(String formula) { + this.formula = formula; + } + + /** + * Returns measurables + * + * @return + */ + public Set getMeasurables() { + return measurables; + } + + /** + * Sets measurables + * + * @param measurables + */ + public void setMeasurables(Set measurables) { + this.measurables = measurables; + } + + /** + * Returns formula + * + * @return + */ + public String getFormula() { + return formula; + } + + /** + * Sets formula + * + * @param formula + */ + public void setFormula(String formula) { + this.formula = formula; + } + + /** + * Returns metric + * + * @return + */ + public Metric getMetric() { + return metric; + } + + /** + * Sets metric + * + * @param metric + */ + public void setMetric(Metric metric) { + this.metric = metric; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Frequency.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Frequency.java new file mode 100644 index 0000000..82915e1 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Frequency.java @@ -0,0 +1,91 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import org.hibernate.validator.constraints.time.DurationMin; + +import javax.persistence.Entity; +import javax.persistence.OneToOne; +import javax.validation.constraints.NotNull; +import java.time.Duration; + +/** + * Entity frequency + * Attributes: duration (Duration), measurable (Measurable) + * + * @author Julian Bauer + */ +@Entity +public class Frequency extends AbstractEntity { + @DurationMin(seconds = 1L) + private Duration duration; + + @NotNull + @OneToOne(mappedBy = "frequency") + private Measurable measurable; + + /** + * + */ + public Frequency() {} + + /** + * + * @param measurable + * @param duration + */ + public Frequency(Measurable measurable, Duration duration) { + this.measurable = measurable; + this.duration = duration; + } + + /** + * + * @param measurable + */ + public Frequency(Measurable measurable) { + this.measurable = measurable; + } + + /** + * + * @param duration + */ + public Frequency(Duration duration) { + this.duration = duration; + } + + /** + * Returns duration + * + * @return + */ + public Duration getDuration() { + return duration; + } + + /** + * Sets duration + * + * @param duration + */ + public void setDuration(Duration duration) { + this.duration = duration; + } + + /** + * Returns measurable + * + * @return + */ + public Measurable getMeasurable() { + return measurable; + } + + /** + * Sets measurable + * + * @param measurable + */ + public void setMeasurable(Measurable measurable) { + this.measurable = measurable; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Group.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Group.java new file mode 100644 index 0000000..5e2c626 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Group.java @@ -0,0 +1,56 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.persistence.Entity; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Transient; +import javax.validation.constraints.NotBlank; +import java.util.Set; + +/** + * Abstract entity group + * Attributes: name (String), members (Set) + * + * @author Julian Bauer + */ +@Entity +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +public abstract class Group extends AbstractEntity { + + @NotBlank + private String name; + + /** + * Returns name + * + * @return + */ + public String getName() { + return name; + } + + /** + * Sets name + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns members + * + * @return + */ + @Transient + public abstract Set getMembers(); + + /** + * Sets members + * + * @param members + */ + @Transient + public abstract void setMembers(Set members); +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/InformationNeed.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/InformationNeed.java new file mode 100644 index 0000000..69679ed --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/InformationNeed.java @@ -0,0 +1,93 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.annotation.Nullable; +import javax.persistence.Entity; +import javax.persistence.ManyToMany; +import javax.validation.constraints.NotBlank; +import java.util.HashSet; +import java.util.Set; + +/** + * Entity group + * Attributes: name (String), measurables (Set) + * + * @author Julian Bauer + */ +@Entity +public class InformationNeed extends AbstractEntity { + + @NotBlank + private String name; + + @NotBlank + private String description; + + @ManyToMany(mappedBy = "informationNeeds") + @Nullable + private Set measurables = new HashSet<>(); + + /** + * Returns name + * + * @return + */ + public String getName() { + return name; + } + + /** + * Sets name + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns description + * + * @return + */ + public String getDescription() { + return description; + } + + /** + * Sets description + * + * @param description + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Returns measurables + * + * @return + */ + public Set getMeasurables() { + return measurables; + } + + /** + * Sets measurables + * + * @param measurables + */ + public void setMeasurables(Set measurables) { + this.measurables = measurables; + } + + /** + * Returns name + * Overrides toString method + * + * @return + */ + @Override + public String toString() { + return getName(); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/ManualDataSource.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/ManualDataSource.java new file mode 100644 index 0000000..efb611c --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/ManualDataSource.java @@ -0,0 +1,48 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * Entity file data source extends data source + * Attributes: value (BigDecimal) + * + * @author Julian Bauer + */ +@Entity +public class ManualDataSource extends DataSource { + + @NotNull + // name 'value' is reserved, see https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/reservewords.htm + // https://coderanch.com/t/638935/databases/Hibernate-setting-decimal-points-BigDecimal + @Column(name = "value_", precision = 20, scale = 10, columnDefinition="DECIMAL(20,10)") + private BigDecimal value = BigDecimal.ZERO; + + /** + * + */ + public ManualDataSource() { + setType(DataSourceType.MANUAL); + } + + /** + * Returns value + * + * @return + */ + public BigDecimal getValue() { + return value; + } + + /** + * Sets value + * + * @param value + */ + public void setValue(BigDecimal value) { + this.value = value; + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Measurable.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Measurable.java new file mode 100644 index 0000000..a34b762 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Measurable.java @@ -0,0 +1,292 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.CascadeType; + +import javax.annotation.Nullable; +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Abstract entity measurable + * Attributes: name (String), description (String), results (List), audiences (Set), + * stakeholders (Set), informationNeeds (Set), scale (Scale), unit (Unit), + * frequency (Frequency), formulas (Set), label (String), + * + * @author Julian Bauer + */ +@Entity +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +public abstract class Measurable extends AbstractEntity { + + @NotBlank + @Column(nullable = false, unique = true) + private String name; + + @NotBlank + private String description; + + @OneToMany(mappedBy = "measurable") + @Nullable + private List results = new ArrayList<>(); + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable( + name = "measurables_audiences", + joinColumns = @JoinColumn(name = "measurable_id"), + inverseJoinColumns = @JoinColumn(name = "audience_id") + ) + private Set audiences = new HashSet<>(); + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable( + name = "measurables_stakeholders", + joinColumns = @JoinColumn(name = "measurable_id"), + inverseJoinColumns = @JoinColumn(name = "stakeholder_id") + ) + private Set stakeholders = new HashSet<>(); + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable( + name = "measurables_informationneeds", + joinColumns = @JoinColumn(name = "measurable_id"), + inverseJoinColumns = @JoinColumn(name = "informationneed_id") + ) + private Set informationNeeds = new HashSet<>(); + + @Enumerated(EnumType.STRING) + private Scale scale; + + @Enumerated(EnumType.STRING) + private Unit unit; + + @OneToOne + @JoinColumn(name = "frequency_id") + @Cascade(CascadeType.ALL) + private Frequency frequency = new Frequency(this); + + @ManyToMany(mappedBy = "measurables", fetch = FetchType.EAGER) + @Nullable + private Set formulas = new HashSet<>(); + + @NotBlank + @Column(unique = true) + @Pattern(regexp = "[a-z]+((\\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?", message = "label must be lower camel case") + private String label; + + /** + * Returns name + * + * @return + */ + public String getName() { + return name; + } + + /** + * Sets name + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns description + * + * @return + */ + public String getDescription() { + return description; + } + + /** + * Sets description + * + * @param description + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Returns results + * + * @return + */ + public List getResults() { + return results; + } + + /** + * Sets results + * + * @param results + */ + public void setResults(List results) { + this.results = results; + } + + /** + * Returns audiences + * + * @return + */ + public Set getAudiences() { + return audiences; + } + + /** + * Sets audiences + * + * @param audiences + */ + public void setAudiences(Set audiences) { + this.audiences = audiences; + } + + /** + * Returns stakeholders + * + * @return + */ + public Set getStakeholders() { + return stakeholders; + } + + /** + * Sets stakeholders + * + * @param stakeholders + */ + public void setStakeholders(Set stakeholders) { + this.stakeholders = stakeholders; + } + + /** + * Returns information needs + * + * @return + */ + public Set getInformationNeeds() { + return informationNeeds; + } + + /** + * Sets information needs + * + * @param informationNeeds + */ + public void setInformationNeeds(Set informationNeeds) { + this.informationNeeds = informationNeeds; + } + + /** + * Returns scale + * + * @return + */ + public Scale getScale() { + return scale; + } + + /** + * Sets scale + * + * @param scale + */ + public void setScale(Scale scale) { + this.scale = scale; + } + + /** + * Returns unit + * + * @return + */ + public Unit getUnit() { + return unit; + } + + /** + * Sets unit + * + * @param unit + */ + public void setUnit(Unit unit) { + this.unit = unit; + } + + /** + * Returns frequency + * + * @return + */ + public Frequency getFrequency() { + return frequency; + } + + /** + * Sets frequency + * + * @param frequency + */ + public void setFrequency(Frequency frequency) { + frequency.setMeasurable(this); + this.frequency = frequency; + } + + /** + * Returns formulas + * + * @return + */ + public Set getFormulas() { + return formulas; + } + + /** + * Sets formulas + * + * @param formulas + */ + public void setFormulas(Set formulas) { + this.formulas = formulas; + } + + /** + * Returns label + * + * @return + */ + public String getLabel() { + return label; + } + + /** + * Sets label + * + * @param label + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * Checks before deleting measurable if it part of any formulas + * + * @throws RuntimeException + */ + @PreRemove + public void checkFormulaAssociationBeforeRemoval() { + if (!this.formulas.isEmpty()) { + throw new RuntimeException("Cannot remove a measurable that is part of formulas."); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Measurement.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Measurement.java new file mode 100644 index 0000000..90d98ec --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Measurement.java @@ -0,0 +1,61 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.util.HashMap; +import java.util.Map; + +/** + * Entity measurement extends measurable + * Attributes: dataSource (DataSource), attributes (Map) + * + * @author Julian Bauer + */ +@Entity +public class Measurement extends Measurable { + + @ManyToOne + @JoinColumn(name = "datasource_id") + @NotNull + private DataSource dataSource; + + @ElementCollection(fetch = FetchType.EAGER) + @MapKeyColumn(name="key_") // key reserved -> key_ + @Column(name="value_") // value reserved -> value_ + private Map attributes = new HashMap<>(); + + /** + * Returns data source + * @return + */ + public DataSource getDataSource() { + return dataSource; + } + + /** + * Sets data source + * + * @param dataSource + */ + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * Returns attributes + * + * @return + */ + public Map getAttributes() { + return attributes; + } + + /** + * Sets attributes + * + * @param attributes + */ + public void setAttributes(Map attributes) { + this.attributes = attributes; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Metric.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Metric.java new file mode 100644 index 0000000..71ce3fd --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Metric.java @@ -0,0 +1,69 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.CascadeType; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * Entity metric extends measurable + * Attributes: formula (Formula), targetValue (BigDecimal) + * + * @author Julian Bauer + */ +@Entity +public class Metric extends Measurable { + + @OneToOne + @JoinColumn(name = "formula_id") + @NotNull + @Cascade(CascadeType.ALL) + private Formula formula = new Formula(this); + + @NotNull + // https://coderanch.com/t/638935/databases/Hibernate-setting-decimal-points-BigDecimal + @Column(precision = 20, scale = 10, columnDefinition="DECIMAL(20,10)") + private BigDecimal targetValue = BigDecimal.ZERO; + + /** + * Returns formula + * + * @return + */ + public Formula getFormula() { + return formula; + } + + /** + * Sets formula + * + * @param formula + */ + public void setFormula(Formula formula) { + formula.setMetric(this); + this.formula = formula; + } + + /** + * Returns target value + * + * @return + */ + public BigDecimal getTargetValue() { + return targetValue; + } + + /** + * Sets target value + * + * @param targetValue + */ + public void setTargetValue(BigDecimal targetValue) { + this.targetValue = targetValue; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Result.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Result.java new file mode 100644 index 0000000..2aa48cd --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Result.java @@ -0,0 +1,103 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import org.springframework.data.annotation.CreatedDate; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.util.Date; + +/** + * Entity result + * Attributes: value (BigDecimal), pointInTime (Date), measurable (Measurable) + * + * @author Julian Bauer + */ +@Entity +public class Result extends AbstractEntity { + + @NotNull + // name 'value' is reserved, see https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/reservewords.htm + // https://coderanch.com/t/638935/databases/Hibernate-setting-decimal-points-BigDecimal + @Column(name = "value_", precision = 20, scale = 10, columnDefinition="DECIMAL(20,10)") + private BigDecimal value; + + @CreatedDate + @Temporal(TemporalType.TIMESTAMP) + private Date pointInTime; + + @ManyToOne + @JoinColumn(name = "measurable_id") + @NotNull + private Measurable measurable; + + /** + * + */ + public Result() { + this.pointInTime = new Date(System.currentTimeMillis()); + } + + /** + * + * @param value + */ + public Result(BigDecimal value) { + this(); + this.value = value; + } + + /** + * Returns measurable + * + * @return + */ + public Measurable getMeasurable() { + return measurable; + } + + /** + * Sets measurable + * + * @param measurable + */ + public void setMeasurable(Measurable measurable) { + this.measurable = measurable; + } + + /** + * Returns value + * + * @return + */ + public BigDecimal getValue() { + return value; + } + + /** + * Sets value + * + * @param value + */ + public void setValue(BigDecimal value) { + this.value = value; + } + + /** + * Returns point in time + * + * @return + */ + public Date getPointInTime() { + return pointInTime; + } + + /** + * Sets point in time + * + * @param pointInTime + */ + public void setPointInTime(Date pointInTime) { + this.pointInTime = pointInTime; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Scale.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Scale.java new file mode 100644 index 0000000..4664856 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Scale.java @@ -0,0 +1,14 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +/** + * Enumeration scale + * Values: NOMINAL, ORDINAL, INTERVAL, RATIO + * + * @author Julian Bauer + */ +public enum Scale { + NOMINAL, + ORDINAL, + INTERVAL, + RATIO, +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Stakeholder.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Stakeholder.java new file mode 100644 index 0000000..97f35a4 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Stakeholder.java @@ -0,0 +1,64 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.annotation.Nullable; +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; + +/** + * Entity stakeholder extends entity group + * Attributes: members (Set), measurables (Set) + * + * @author Julian Bauer + */ +@Entity +public class Stakeholder extends Group { + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable( + name = "stakeholder_memberships", + joinColumns = @JoinColumn(name = "stakeholder_id"), + inverseJoinColumns = @JoinColumn(name = "user_id") + ) + private Set members = new HashSet<>(); + + @ManyToMany(mappedBy = "stakeholders") + @Nullable + private Set measurables = new HashSet<>(); + + /** + * Returns members + * + * @return + */ + public Set getMembers() { + return members; + } + + /** + * Sets members + * + * @param members + */ + public void setMembers(Set members) { + this.members = members; + } + + /** + * Returns measurables + * + * @return + */ + @Nullable + public Set getMeasurables() { + return measurables; + } + + /** + * Sets measurables + * + * @param measurables + */ + public void setMeasurables(@Nullable Set measurables) { + this.measurables = measurables; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Unit.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Unit.java new file mode 100644 index 0000000..b4a439a --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/Unit.java @@ -0,0 +1,12 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +/** + * Enumeration unit + * Values: PERCENT, TOTAL + * + * @author Julian Bauer + */ +public enum Unit { + PERCENT, + TOTAL +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/User.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/User.java new file mode 100644 index 0000000..d8d6227 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/entity/User.java @@ -0,0 +1,177 @@ +package de.uniregensburg.iamreportingmodule.data.entity; + +import javax.annotation.Nullable; +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.HashSet; +import java.util.Set; + +/** + * Entity user + * Attributes: username (String), firstName (String), lastName (String), password (String), isAdmin (boolean), + * audienceMemberships (Set), stakeholderMemberships (Set) + * + * @author Julian Bauer + */ +@Entity +@Table(name="user_account") // name 'users' is reserved, see https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/reservewords.htm +public class User extends AbstractEntity { + + @NotBlank + @Column(nullable = false, unique = true) + private String username; + @NotBlank + private String firstName; + @NotBlank + private String lastName; + @NotBlank + private String password; + @NotNull + private boolean admin = false; + + @ManyToMany(mappedBy = "members") + @Nullable + private Set audienceMemberships = new HashSet<>(); + + @ManyToMany(mappedBy = "members") + @Nullable + private Set stakeholderMemberships = new HashSet<>(); + + /** + * Returns username + * + * @return + */ + public String getUsername() { + return username; + } + + /** + * Sets username + * + * @param username + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * Returns first name + * + * @return + */ + public String getFirstName() { + return firstName; + } + + /** + * Sets first name + * @param firstName + */ + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + /** + * Returns last name + * + * @return + */ + public String getLastName() { + return lastName; + } + + /** + * Sets last name + * + * @param lastName + */ + public void setLastName(String lastName) { + this.lastName = lastName; + } + + /** + * Returns full name consisting of first and last name + * + * @return + */ + @Transient + public String getFullName() { + return firstName + " " + lastName; + } + + /** + * Returns password + * + * @return + */ + public String getPassword() { + return password; + } + + /** + * Sets password + * + * @param password + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Returns if user is admin + * + * @return + */ + public boolean isAdmin() { + return admin; + } + + /** + * Sets admin + * + * @param admin + */ + public void setAdmin(boolean admin) { + this.admin = admin; + } + + /** + * Returns audience memberships + * + * @return + */ + @Nullable + public Set getAudienceMemberships() { + return audienceMemberships; + } + + /** + * Sets audience memberships + * + * @param audienceMemberships + */ + public void setAudienceMemberships(@Nullable Set audienceMemberships) { + this.audienceMemberships = audienceMemberships; + } + + /** + * Returns stakeholder memberships + * + * @return + */ + @Nullable + public Set getStakeholderMemberships() { + return stakeholderMemberships; + } + + /** + * Sets stakeholder memberships + * + * @param stakeholderMemberships + */ + public void setStakeholderMemberships(@Nullable Set stakeholderMemberships) { + this.stakeholderMemberships = stakeholderMemberships; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/generator/DataGenerator.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/generator/DataGenerator.java new file mode 100644 index 0000000..891e8d7 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/generator/DataGenerator.java @@ -0,0 +1,500 @@ +package de.uniregensburg.iamreportingmodule.data.generator; + +import com.vaadin.flow.spring.annotation.SpringComponent; +import de.uniregensburg.iamreportingmodule.core.service.JobSchedulingService; +import de.uniregensburg.iamreportingmodule.data.entity.*; +import de.uniregensburg.iamreportingmodule.data.repository.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Profile; +import org.springframework.security.crypto.password.PasswordEncoder; + +import java.math.BigDecimal; +import java.time.Duration; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Generator of demo data for local development and testing + * + * @author Julian Bauer + */ +@SpringComponent +@Profile("!production") +public class DataGenerator { + Logger logger = LoggerFactory.getLogger(getClass()); + + /** + * Generates demo data + * + * @param userRepository + * @param encoder + * @param stakeholderRepository + * @param audienceRepository + * @param informationNeedRepository + * @param manualDataSourceRepository + * @param databaseDataSourceRepository + * @param fileDataSourceRepository + * @param measurementRepository + * @param jobSchedulingService + * @param metricRepository + * @return + */ + @Bean CommandLineRunner generateData(UserRepository userRepository, + PasswordEncoder encoder, + StakeholderRepository stakeholderRepository, + AudienceRepository audienceRepository, + InformationNeedRepository informationNeedRepository, + ManualDataSourceRepository manualDataSourceRepository, + DatabaseDataSourceRepository databaseDataSourceRepository, + FileDataSourceRepository fileDataSourceRepository, + MeasurementRepository measurementRepository, + JobSchedulingService jobSchedulingService, + MetricRepository metricRepository) { + + return args -> { + + if (userRepository.count() != 0L) { + logger.info("Using existing database"); + return; + } + + logger.info("Generating database entries"); + + logger.info("Generating users"); + + logger.info("Adding admin user"); + User admin = new User(); + admin.setUsername("admin"); + admin.setPassword(encoder.encode("password")); + admin.setFirstName("Application"); + admin.setLastName("Administrator"); + admin.setAdmin(true); + + logger.info("Adding default user"); + User user = new User(); + user.setAdmin(false); + user.setUsername("user"); + user.setPassword(encoder.encode("password")); + user.setFirstName("Application"); + user.setLastName("User"); + + logger.info("Saving users"); + userRepository.saveAll(Set.of(admin, user)); + + logger.info("Generating stakeholders"); + + logger.info("CIO - members: user"); + Stakeholder cio = new Stakeholder(); + cio.setName("CIO"); + cio.setMembers(Set.of(user)); + + logger.info("CISO - members: admin"); + Stakeholder ciso = new Stakeholder(); + ciso.setName("CISO"); + ciso.setMembers(Set.of(admin)); + + logger.info("Saving stakeholders"); + stakeholderRepository.saveAll(Set.of(cio, ciso)); + + logger.info("Generating audiences"); + + logger.info("C-Level - members: admin, user"); + Audience cLevel = new Audience(); + cLevel.setName("C-Level"); + cLevel.setMembers(Set.of(admin, user)); + + logger.info("Manager - members:"); + Audience manager = new Audience(); + manager.setName("Manager"); + + logger.info("Saving audiences"); + audienceRepository.saveAll(Set.of(cLevel, manager)); + + logger.info("Generating information needs"); + + logger.info("Risk reduction"); + InformationNeed riskReduction = new InformationNeed(); + riskReduction.setName("Risk reduction"); + riskReduction.setDescription("Reduce risk"); + + logger.info("Improvement of process and data quality"); + InformationNeed improvementOfProcessAndDataQuality = new InformationNeed(); + improvementOfProcessAndDataQuality.setName("Improvement of process and data quality"); + improvementOfProcessAndDataQuality.setDescription("Improve process and data quality"); + + logger.info("Regulatory compliance"); + InformationNeed regulatoryCompliance = new InformationNeed(); + regulatoryCompliance.setName("Regulatory compliance"); + regulatoryCompliance.setDescription("Comply with the legal requirements"); + + logger.info("Business faciliatation"); + InformationNeed businessFacilitation = new InformationNeed(); + businessFacilitation.setName("Business facilitation"); + businessFacilitation.setDescription("Facilitate business"); + + logger.info("Saving information needs"); + informationNeedRepository.saveAll(Set.of(riskReduction, improvementOfProcessAndDataQuality, + regulatoryCompliance, businessFacilitation)); + + logger.info("Generating manual datasources"); + + logger.info("Paswords"); + ManualDataSource manualDataSourcePasswords = new ManualDataSource(); + manualDataSourcePasswords.setName("Passwords"); + manualDataSourcePasswords.setDescription("Total number of all passwords"); + manualDataSourcePasswords.setValue(BigDecimal.valueOf(1000)); + + logger.info("Leaked passwords"); + ManualDataSource manualDataSourceLeakedPasswords = new ManualDataSource(); + manualDataSourceLeakedPasswords.setName("Leaked passwords"); + manualDataSourceLeakedPasswords.setDescription("Total number of leaked passwords"); + manualDataSourceLeakedPasswords.setValue(BigDecimal.valueOf(4)); + + logger.info("Weak passwords"); + ManualDataSource manualDataSourceWeakPasswords = new ManualDataSource(); + manualDataSourceWeakPasswords.setName("Weak passwords"); + manualDataSourceWeakPasswords.setDescription("Total number of weak passwords"); + manualDataSourceWeakPasswords.setValue(BigDecimal.valueOf(115)); + + logger.info("Identical passwords"); + ManualDataSource manualDataSourceIdenticalPasswords = new ManualDataSource(); + manualDataSourceIdenticalPasswords.setName("Identical passwords"); + manualDataSourceIdenticalPasswords.setDescription("Total number of Identical passwords"); + manualDataSourceIdenticalPasswords.setValue(BigDecimal.valueOf(23)); + + logger.info("Average password length"); + ManualDataSource manualDataSourcePasswordLength = new ManualDataSource(); + manualDataSourcePasswordLength.setName("Average password length"); + manualDataSourcePasswordLength.setDescription("Average length of passwords"); + manualDataSourcePasswordLength.setValue(BigDecimal.valueOf(9.3)); + + logger.info("Average password age"); + ManualDataSource manualDataSourcePasswordAge = new ManualDataSource(); + manualDataSourcePasswordAge.setName("Average password age"); + manualDataSourcePasswordAge.setDescription("Average age of passwords in days"); + manualDataSourcePasswordAge.setValue(BigDecimal.valueOf(983)); + + logger.info("Saving manual datasources"); + manualDataSourceRepository.saveAll(Set.of(manualDataSourcePasswords, + manualDataSourceLeakedPasswords, + manualDataSourceWeakPasswords, + manualDataSourceIdenticalPasswords, + manualDataSourcePasswordLength, + manualDataSourcePasswordAge)); + + logger.info("Generating database datasources"); + + logger.info("Test database: postgresql://localhost:5432/test - user: test - password: Test123!"); + DatabaseDataSource databaseDataSourceTest = new DatabaseDataSource(); + databaseDataSourceTest.setName("Test database"); + databaseDataSourceTest.setDescription("PostgreSQL localhost"); + databaseDataSourceTest.setHost("localhost"); + databaseDataSourceTest.setPort(5432); + databaseDataSourceTest.setDatabase("test"); + databaseDataSourceTest.setUsername("test"); + databaseDataSourceTest.setPassword("Test123!"); + databaseDataSourceTest.setDbmsType(Dbms.POSTGRESQL); + + logger.info("Saving database datasources"); + databaseDataSourceRepository.saveAll(Set.of(databaseDataSourceTest)); + + logger.info("Generating file datasources"); + + logger.info("CSV datasource - useraccounts.csv"); + FileDataSource csvfileDataSource = new FileDataSource(); + csvfileDataSource.setName("User accounts"); + csvfileDataSource.setDescription("CSV file datasource"); + csvfileDataSource.setFileType(FileType.CSV); + csvfileDataSource.setFile(Base64.getDecoder().decode("Vm9ybmFtZTtOYWNobmFtZTtBbHRlcg0KQW5uZTtNYXVlcjszMA0KTWFyY287TWV5ZXI7MjMNCkthdHJpbjtGaW5rOzU0DQpCcmlnaXR0ZTtGbGVpc2NoZXI7MzQNCkRvbWluaWs7SG9sem1hbm47MjANCkFubmE7V2ViZXI7MzQNCg==")); + csvfileDataSource.setFileName("useraccounts.csv"); + + logger.info("Saving file datasources"); + fileDataSourceRepository.saveAll(Set.of(csvfileDataSource)); + + logger.info("Generating measurements"); + + // average age (csv) + logger.info("Average age"); + Measurement averageAge = new Measurement(); + averageAge.setDataSource(csvfileDataSource); + Map averageAgeAttributes = new HashMap<>(); + averageAgeAttributes.put("csvHeader", "true"); + averageAgeAttributes.put("csvColumnName", "Alter"); + averageAgeAttributes.put("csvAggregationMethod", CsvAggregationMethod.AVERAGE.toString()); + averageAgeAttributes.put("csvDelimiter", ";"); + averageAge.setAttributes(averageAgeAttributes); + averageAge.setName("Average age"); + averageAge.setLabel("averageAge"); + averageAge.setDescription("Average age of users"); + averageAge.setAudiences(Set.of(cLevel, manager)); + averageAge.setInformationNeeds(Set.of(businessFacilitation)); + averageAge.setStakeholders(Set.of(ciso)); + averageAge.setScale(Scale.RATIO); + averageAge.setUnit(Unit.TOTAL); + averageAge.setFrequency(new Frequency(Duration.parse("PT1M"))); + + // maximum age (csv) + logger.info("Maximum age"); + Measurement maximumAge = new Measurement(); + maximumAge.setDataSource(csvfileDataSource); + Map maximumAgeAttributes = new HashMap<>(); + maximumAgeAttributes.put("csvHeader", "true"); + maximumAgeAttributes.put("csvColumnName", "Alter"); + maximumAgeAttributes.put("csvAggregationMethod", CsvAggregationMethod.MAXIMUM.toString()); + maximumAgeAttributes.put("csvDelimiter", ";"); + maximumAge.setAttributes(maximumAgeAttributes); + maximumAge.setName("Maximum age"); + maximumAge.setLabel("maximumAge"); + maximumAge.setDescription("Maximum age of users"); + maximumAge.setAudiences(Set.of(cLevel, manager)); + maximumAge.setInformationNeeds(Set.of(businessFacilitation)); + maximumAge.setStakeholders(Set.of(ciso)); + maximumAge.setScale(Scale.RATIO); + maximumAge.setUnit(Unit.TOTAL); + maximumAge.setFrequency(new Frequency(Duration.parse("PT5M"))); + + // total accounts (csv) + logger.info("total accounts (csv)"); + Measurement totalAccountsCsv = new Measurement(); + totalAccountsCsv.setDataSource(csvfileDataSource); + Map totalAccountsCsvAttributes = new HashMap<>(); + totalAccountsCsvAttributes.put("csvHeader", "true"); + totalAccountsCsvAttributes.put("csvColumnName", "Alter"); + totalAccountsCsvAttributes.put("csvAggregationMethod", CsvAggregationMethod.MAXIMUM.toString()); + totalAccountsCsvAttributes.put("csvDelimiter", ";"); + totalAccountsCsv.setAttributes(totalAccountsCsvAttributes); + totalAccountsCsv.setName("Total accounts (csv)"); + totalAccountsCsv.setLabel("totalAccountsCsv"); + totalAccountsCsv.setDescription("Total accounts in csv file"); + totalAccountsCsv.setAudiences(Set.of(cLevel, manager)); + totalAccountsCsv.setInformationNeeds(Set.of(businessFacilitation)); + totalAccountsCsv.setStakeholders(Set.of(ciso)); + totalAccountsCsv.setScale(Scale.RATIO); + totalAccountsCsv.setUnit(Unit.TOTAL); + totalAccountsCsv.setFrequency(new Frequency(Duration.parse("PT30S"))); + + // average password length (manual) + logger.info("average password length"); + Measurement averagePasswordLength = new Measurement(); + averagePasswordLength.setDataSource(manualDataSourcePasswordLength); + averagePasswordLength.setName("Average password length"); + averagePasswordLength.setLabel("averagePasswordLength"); + averagePasswordLength.setDescription("Average length of passwords"); + averagePasswordLength.setAudiences(Set.of(cLevel, manager)); + averagePasswordLength.setInformationNeeds(Set.of(riskReduction)); + averagePasswordLength.setStakeholders(Set.of(ciso)); + averagePasswordLength.setScale(Scale.RATIO); + averagePasswordLength.setUnit(Unit.TOTAL); + averagePasswordLength.setFrequency(new Frequency(Duration.parse("PT1M"))); + + // passwords (manual) + logger.info("passwords"); + Measurement passwords = new Measurement(); + passwords.setDataSource(manualDataSourcePasswords); + passwords.setName("Passwords"); + passwords.setLabel("passwords"); + passwords.setDescription("Total number of passwords"); + passwords.setAudiences(Set.of(cLevel, manager)); + passwords.setInformationNeeds(Set.of(riskReduction)); + passwords.setStakeholders(Set.of(ciso)); + passwords.setScale(Scale.RATIO); + passwords.setUnit(Unit.TOTAL); + passwords.setFrequency(new Frequency(Duration.parse("PT10S"))); + + // weak passwords (manual) + logger.info("weak passwords"); + Measurement weakPasswords = new Measurement(); + weakPasswords.setDataSource(manualDataSourceWeakPasswords); + weakPasswords.setName("Weak passwords"); + weakPasswords.setLabel("weakPasswords"); + weakPasswords.setDescription("Total number of weak passwords"); + weakPasswords.setAudiences(Set.of(cLevel, manager)); + weakPasswords.setInformationNeeds(Set.of(riskReduction)); + weakPasswords.setStakeholders(Set.of(ciso)); + weakPasswords.setScale(Scale.RATIO); + weakPasswords.setUnit(Unit.TOTAL); + weakPasswords.setFrequency(new Frequency(Duration.parse("PT30S"))); + + // leaked passwords (manual) + logger.info("leaked passwords"); + Measurement leakedPasswords = new Measurement(); + leakedPasswords.setDataSource(manualDataSourceLeakedPasswords); + leakedPasswords.setName("Leaked passwords"); + leakedPasswords.setLabel("leakedPasswords"); + leakedPasswords.setDescription("Total number of leaked passwords"); + leakedPasswords.setAudiences(Set.of(cLevel, manager)); + leakedPasswords.setInformationNeeds(Set.of(riskReduction)); + leakedPasswords.setStakeholders(Set.of(ciso)); + leakedPasswords.setScale(Scale.RATIO); + leakedPasswords.setUnit(Unit.TOTAL); + leakedPasswords.setFrequency(new Frequency(Duration.parse("PT90S"))); + + // identical passwords (manual) + logger.info("identical passwords"); + Measurement identicalPasswords = new Measurement(); + identicalPasswords.setDataSource(manualDataSourceIdenticalPasswords); + identicalPasswords.setName("Identical passwords"); + identicalPasswords.setLabel("identicalPasswords"); + identicalPasswords.setDescription("Total number of identical passwords"); + identicalPasswords.setAudiences(Set.of(cLevel, manager)); + identicalPasswords.setInformationNeeds(Set.of(riskReduction)); + identicalPasswords.setStakeholders(Set.of(ciso)); + identicalPasswords.setScale(Scale.RATIO); + identicalPasswords.setUnit(Unit.TOTAL); + identicalPasswords.setFrequency(new Frequency(Duration.parse("PT1M"))); + + // average password age in days (manual) + logger.info("average password age"); + Measurement averagePasswordAge = new Measurement(); + averagePasswordAge.setDataSource(manualDataSourcePasswordAge); + averagePasswordAge.setName("Average password age"); + averagePasswordAge.setLabel("averagePasswordAge"); + averagePasswordAge.setDescription("Average age of passwords"); + averagePasswordAge.setAudiences(Set.of(cLevel, manager)); + averagePasswordAge.setInformationNeeds(Set.of(riskReduction, businessFacilitation)); + averagePasswordAge.setStakeholders(Set.of(ciso)); + averagePasswordAge.setScale(Scale.RATIO); + averagePasswordAge.setUnit(Unit.TOTAL); + averagePasswordAge.setFrequency(new Frequency(Duration.parse("PT45S"))); + + // total accounts (database) + logger.info("total accounts (database)"); + Measurement totalAccountsDatabase = new Measurement(); + totalAccountsDatabase.setDataSource(databaseDataSourceTest); + Map totalAccountsDatabaseAttributes = new HashMap<>(); + totalAccountsDatabaseAttributes.put("sqlQuery", "SELECT COUNT(*) FROM users;"); + totalAccountsDatabase.setAttributes(totalAccountsDatabaseAttributes); + totalAccountsDatabase.setName("Total accounts (database)"); + totalAccountsDatabase.setLabel("totalAccountsDatabase"); + totalAccountsDatabase.setDescription("Total accounts in database"); + totalAccountsDatabase.setAudiences(Set.of(cLevel, manager)); + totalAccountsDatabase.setInformationNeeds(Set.of(businessFacilitation)); + totalAccountsDatabase.setStakeholders(Set.of(ciso)); + totalAccountsDatabase.setScale(Scale.RATIO); + totalAccountsDatabase.setUnit(Unit.TOTAL); + totalAccountsDatabase.setFrequency(new Frequency(Duration.parse("PT30S"))); + + logger.info("Saving measurements"); + Set measurements = Set.of(averageAge, maximumAge, totalAccountsCsv, totalAccountsDatabase, averagePasswordLength, + passwords, weakPasswords, leakedPasswords, identicalPasswords, averagePasswordAge); + measurementRepository.saveAll(measurements); + + logger.info("Scheduling measurements"); + for (Measurement m : measurements) { + jobSchedulingService.measureMeasurement(m); + } + + // percentage of weak passwords + Metric percentageOfWeakPasswords = new Metric(); + Formula percentageOfWeakPasswordsFormula = new Formula("{{weakPasswords}}/{{passwords}}"); + percentageOfWeakPasswordsFormula.setMeasurables(Set.of(weakPasswords, passwords)); + percentageOfWeakPasswords.setFormula(percentageOfWeakPasswordsFormula); + percentageOfWeakPasswords.setName("Weak passwords"); + percentageOfWeakPasswords.setLabel("weakPasswordsPercentage"); + percentageOfWeakPasswords.setDescription("Percentage of weak passwords"); + percentageOfWeakPasswords.setAudiences(Set.of(cLevel, manager)); + percentageOfWeakPasswords.setInformationNeeds(Set.of(riskReduction)); + percentageOfWeakPasswords.setStakeholders(Set.of(ciso)); + percentageOfWeakPasswords.setScale(Scale.RATIO); + percentageOfWeakPasswords.setUnit(Unit.PERCENT); + percentageOfWeakPasswords.setTargetValue(BigDecimal.ZERO); + percentageOfWeakPasswords.setFrequency(new Frequency(Duration.parse("PT10S"))); + + // percentage of identical passwords + Metric percentageOfIdenticalPasswords = new Metric(); + Formula percentageOfIdenticalPasswordsFormula = new Formula("{{identicalPasswords}}/{{passwords}}"); + percentageOfIdenticalPasswordsFormula.setMeasurables(Set.of(identicalPasswords, passwords)); + percentageOfIdenticalPasswords.setFormula(percentageOfIdenticalPasswordsFormula); + percentageOfIdenticalPasswords.setName("Identical passwords"); + percentageOfIdenticalPasswords.setLabel("identicalPasswordsPercentage"); + percentageOfIdenticalPasswords.setDescription("Percentage of identical passwords"); + percentageOfIdenticalPasswords.setAudiences(Set.of(cLevel, manager)); + percentageOfIdenticalPasswords.setInformationNeeds(Set.of(riskReduction)); + percentageOfIdenticalPasswords.setStakeholders(Set.of(ciso)); + percentageOfIdenticalPasswords.setScale(Scale.RATIO); + percentageOfIdenticalPasswords.setUnit(Unit.PERCENT); + percentageOfIdenticalPasswords.setTargetValue(BigDecimal.ZERO); + percentageOfIdenticalPasswords.setFrequency(new Frequency(Duration.parse("PT10S"))); + + // percentage of leaked passwords + Metric percentageOfLeakedPasswords = new Metric(); + Formula percentageOfLeakedPasswordsFormula = new Formula("{{leakedPasswords}}/{{passwords}}"); + percentageOfLeakedPasswordsFormula.setMeasurables(Set.of(leakedPasswords, passwords)); + percentageOfLeakedPasswords.setFormula(percentageOfLeakedPasswordsFormula); + percentageOfLeakedPasswords.setName("Leaked passwords"); + percentageOfLeakedPasswords.setLabel("leakedPasswordsPercentage"); + percentageOfLeakedPasswords.setDescription("Percentage of leaked passwords"); + percentageOfLeakedPasswords.setAudiences(Set.of(cLevel, manager)); + percentageOfLeakedPasswords.setInformationNeeds(Set.of(riskReduction)); + percentageOfLeakedPasswords.setStakeholders(Set.of(ciso)); + percentageOfLeakedPasswords.setScale(Scale.RATIO); + percentageOfLeakedPasswords.setUnit(Unit.PERCENT); + percentageOfLeakedPasswords.setTargetValue(BigDecimal.ZERO); + percentageOfLeakedPasswords.setFrequency(new Frequency(Duration.parse("PT10S"))); + + // average password age + Metric passwordAgeAverage = new Metric(); + Formula passwordAgeAverageFormula = new Formula("{{averagePasswordAge}}"); + passwordAgeAverageFormula.setMeasurables(Set.of(averagePasswordAge)); + passwordAgeAverage.setFormula(passwordAgeAverageFormula); + passwordAgeAverage.setName("Password age"); + passwordAgeAverage.setLabel("passwordAgeAverage"); + passwordAgeAverage.setDescription("Average age of passwords"); + passwordAgeAverage.setAudiences(Set.of(cLevel, manager)); + passwordAgeAverage.setInformationNeeds(Set.of(riskReduction, businessFacilitation)); + passwordAgeAverage.setStakeholders(Set.of(ciso)); + passwordAgeAverage.setScale(Scale.RATIO); + passwordAgeAverage.setUnit(Unit.TOTAL); + passwordAgeAverage.setTargetValue(BigDecimal.valueOf(365)); + passwordAgeAverage.setFrequency(new Frequency(Duration.parse("PT10S"))); + + // average password length + Metric passwordLengthAverage = new Metric(); + Formula averagePasswordLengthFormula = new Formula("{{averagePasswordLength}}"); + averagePasswordLengthFormula.setMeasurables(Set.of(averagePasswordLength)); + passwordLengthAverage.setFormula(averagePasswordLengthFormula); + passwordLengthAverage.setName("Password length"); + passwordLengthAverage.setLabel("passwordLengthAverage"); + passwordLengthAverage.setDescription("Average age of passwords"); + passwordLengthAverage.setAudiences(Set.of(cLevel, manager)); + passwordLengthAverage.setInformationNeeds(Set.of(riskReduction, businessFacilitation)); + passwordLengthAverage.setStakeholders(Set.of(ciso)); + passwordLengthAverage.setScale(Scale.RATIO); + passwordLengthAverage.setUnit(Unit.TOTAL); + passwordLengthAverage.setTargetValue(BigDecimal.valueOf(12)); + passwordLengthAverage.setFrequency(new Frequency(Duration.parse("PT10S"))); + + // average password length + Metric totalAccounts = new Metric(); + Formula totalAccountsFormula = new Formula("{{totalAccountsCsv}} + {{totalAccountsDatabase}}"); + totalAccountsFormula.setMeasurables(Set.of(totalAccountsCsv, totalAccountsDatabase)); + totalAccounts.setFormula(totalAccountsFormula); + totalAccounts.setName("Total accounts"); + totalAccounts.setLabel("totalAccounts"); + totalAccounts.setDescription("Count all accounts"); + totalAccounts.setAudiences(Set.of(cLevel, manager)); + totalAccounts.setInformationNeeds(Set.of(businessFacilitation)); + totalAccounts.setStakeholders(Set.of(ciso)); + totalAccounts.setScale(Scale.RATIO); + totalAccounts.setUnit(Unit.TOTAL); + totalAccounts.setTargetValue(BigDecimal.valueOf(17)); + totalAccounts.setFrequency(new Frequency(Duration.parse("PT60S"))); + + logger.info("Saving measurements"); + Set metrics = Set.of(percentageOfWeakPasswords, percentageOfIdenticalPasswords, + percentageOfLeakedPasswords, passwordAgeAverage, passwordLengthAverage, totalAccounts); + metricRepository.saveAll(metrics); + + logger.info("Scheduling metrics"); + for (Metric m : metrics) { + jobSchedulingService.calculateMetric(m); + } + + }; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/AudienceRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/AudienceRepository.java new file mode 100644 index 0000000..7d50d21 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/AudienceRepository.java @@ -0,0 +1,25 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.Audience; +import de.uniregensburg.iamreportingmodule.data.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Set; +import java.util.UUID; + +/** + * Repository for audiences + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface AudienceRepository extends JpaRepository { + + /** + * Returns all audiences by members + * @param members + * @return + */ + List findAllByMembersIn(Set members); +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/DatabaseDataSourceRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/DatabaseDataSourceRepository.java new file mode 100644 index 0000000..87c90c6 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/DatabaseDataSourceRepository.java @@ -0,0 +1,14 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.DatabaseDataSource; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +/** + * Repository for database datasources + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface DatabaseDataSourceRepository extends JpaRepository {} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/FileDataSourceRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/FileDataSourceRepository.java new file mode 100644 index 0000000..99aa7a4 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/FileDataSourceRepository.java @@ -0,0 +1,14 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.FileDataSource; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +/** + * Repository for file datasources + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface FileDataSourceRepository extends JpaRepository {} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/GroupRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/GroupRepository.java new file mode 100644 index 0000000..e8e4167 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/GroupRepository.java @@ -0,0 +1,15 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.Group; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +/** + * Repository for groups + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface GroupRepository extends JpaRepository { +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/InformationNeedRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/InformationNeedRepository.java new file mode 100644 index 0000000..c190f14 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/InformationNeedRepository.java @@ -0,0 +1,14 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.InformationNeed; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +/** + * Repository for information needs + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface InformationNeedRepository extends JpaRepository {} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/ManualDataSourceRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/ManualDataSourceRepository.java new file mode 100644 index 0000000..8afede3 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/ManualDataSourceRepository.java @@ -0,0 +1,14 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.ManualDataSource; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +/** + * Repository for manual datasources + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface ManualDataSourceRepository extends JpaRepository {} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/MeasurementRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/MeasurementRepository.java new file mode 100644 index 0000000..79903f6 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/MeasurementRepository.java @@ -0,0 +1,24 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.Measurement; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.UUID; + +/** + * Repository for measurements + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface MeasurementRepository extends JpaRepository { + + /** + * Returns all measurements by label + * + * @param label + * @return + */ + List findAllByLabel(String label); +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/MetricRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/MetricRepository.java new file mode 100644 index 0000000..4335c16 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/MetricRepository.java @@ -0,0 +1,36 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.Audience; +import de.uniregensburg.iamreportingmodule.data.entity.InformationNeed; +import de.uniregensburg.iamreportingmodule.data.entity.Metric; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Set; +import java.util.UUID; + +/** + * Repository for metrics + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface MetricRepository extends JpaRepository { + + /** + * Returns all metrics by information needs and audiences + * + * @param informationNeeds + * @param audiences + * @return + */ + List findAllByInformationNeedsInAndAudiencesIn(Set informationNeeds, Set audiences); + + /** + * Returns all metrics by label + * + * @param label + * @return + */ + List findAllByLabel(String label); +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/ResultRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/ResultRepository.java new file mode 100644 index 0000000..e4a751b --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/ResultRepository.java @@ -0,0 +1,33 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.Measurable; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.UUID; + +/** + * Repository for results + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface ResultRepository extends JpaRepository { + + /** + * Returns first 10 results by measurable ordered by point in time descending + * + * @param measurable + * @return + */ + List findFirst10ByMeasurableOrderByPointInTimeDesc(Measurable measurable); + + /** + * Returns first result by measurable ordered by point in time descending + * + * @param measurable + * @return + */ + Result findFirstByMeasurableOrderByPointInTimeDesc(Measurable measurable); +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/StakeholderRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/StakeholderRepository.java new file mode 100644 index 0000000..efc4b38 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/StakeholderRepository.java @@ -0,0 +1,14 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.Stakeholder; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +/** + * Repository for stakeholders + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface StakeholderRepository extends JpaRepository {} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/UserRepository.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/UserRepository.java new file mode 100644 index 0000000..ad5c78e --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/repository/UserRepository.java @@ -0,0 +1,23 @@ +package de.uniregensburg.iamreportingmodule.data.repository; + +import de.uniregensburg.iamreportingmodule.data.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +/** + * Repository for users + * extends JpaRepository + * + * @author Julian Bauer + */ +public interface UserRepository extends JpaRepository { + + /** + * Returns user by username + * + * @param username + * @return + */ + User findByUsername(String username); +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/validator/FormulaValidator.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/validator/FormulaValidator.java new file mode 100644 index 0000000..536aba5 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/validator/FormulaValidator.java @@ -0,0 +1,63 @@ +package de.uniregensburg.iamreportingmodule.data.validator; + +import com.ezylang.evalex.Expression; +import com.ezylang.evalex.parser.ParseException; +import com.vaadin.flow.data.binder.ValidationResult; +import com.vaadin.flow.data.binder.Validator; +import com.vaadin.flow.data.binder.ValueContext; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.exception.FormulaException; +import de.uniregensburg.iamreportingmodule.core.util.FormulaUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Validator for formulas + * + * @author Julian Bauer + */ +public class FormulaValidator implements Validator { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final FormulaUtil util; + + /** + * + * @param service + */ + public FormulaValidator(MeasurableService service) { + this.util = new FormulaUtil(service); + } + + /** + * Validates formula + * + * @param value the first function argument + * @param context the second function argument + * @return + */ + @Override + public ValidationResult apply(String value, ValueContext context) { + // check formula + if (value == null) { + logger.info("Provided formula is null"); + return ValidationResult.error("Formula is null"); + } + try { + // validate formula + String formula = util.replaceVariablesWithMeasurableValues(value); + Expression expression = new Expression(formula); + expression.validate(); + // return ok + return ValidationResult.ok(); + } catch (FormulaException e) { + logger.info("Formula exception: " + e.getMessage()); + // return error + return ValidationResult.error(e.getMessage()); + } catch (ParseException e) { + logger.info("Parse exception: " + e.getMessage()); + // return error + return ValidationResult.error(e.getMessage()); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/data/validator/MeasurableLabelValidator.java b/src/main/java/de/uniregensburg/iamreportingmodule/data/validator/MeasurableLabelValidator.java new file mode 100644 index 0000000..b3f798e --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/data/validator/MeasurableLabelValidator.java @@ -0,0 +1,84 @@ +package de.uniregensburg.iamreportingmodule.data.validator; + +import com.vaadin.flow.data.binder.ValidationResult; +import com.vaadin.flow.data.binder.Validator; +import com.vaadin.flow.data.binder.ValueContext; +import de.uniregensburg.iamreportingmodule.data.entity.Measurable; +import de.uniregensburg.iamreportingmodule.data.entity.Measurement; +import de.uniregensburg.iamreportingmodule.data.entity.Metric; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.Set; + +/** + * Validator for labels of measurables + * + * @author Julian Bauer + */ +public class MeasurableLabelValidator implements Validator { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final MeasurableService service; + private final Measurable measurable; + + /** + * + * @param service + * @param measurable + */ + public MeasurableLabelValidator(MeasurableService service, Measurable measurable) { + this.measurable = measurable; + this.service = service; + } + + /** + * Validates label of measurable + * + * @param value the first function argument + * @param context the second function argument + * @return + */ + @Override + public ValidationResult apply(String value, ValueContext context) { + // check label + if (value == null) { + logger.info("Provided label is null"); + return ValidationResult.error("Label is null"); + } + // check if measurable is not null + if (measurable != null) { + logger.info("Checking if label for validation is equal to current label of measurable"); + // check if label equals + if (value.equals(measurable.getLabel())) { + logger.info("Provided label equals current label"); + // return ok + return ValidationResult.ok(); + } else { + logger.info("Provided label differs current label"); + } + } + logger.info("Collecting labels of all measurables"); + // adding all already used labels to set + Set labels = new HashSet<>(); + for (Measurement measurement : service.findAllMeasurements()) { + labels.add(measurement.getLabel()); + } + for (Metric metric : service.findAllMetrics()) { + labels.add(metric.getLabel()); + } + logger.info("Checking if label for validation with value " + value + " is unique"); + // checking if label is unique + if (labels.contains(value)) { + logger.info("Label is not unique"); + // return error: not unique + return ValidationResult.error("Label not unique"); + } else { + // return ok: unique + logger.info("Label is unique"); + return ValidationResult.ok(); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/component/appnav/AppNav.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/appnav/AppNav.java new file mode 100644 index 0000000..a903318 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/appnav/AppNav.java @@ -0,0 +1,147 @@ +package de.uniregensburg.iamreportingmodule.web.component.appnav; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.HasSize; +import com.vaadin.flow.component.HasStyle; +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.component.dependency.JsModule; +import com.vaadin.flow.dom.Element; +import java.util.Optional; + +/** + * A navigation menu with support for hierarchical and flat menus. + *

+ * Items can be added using {@link #addItem(AppNavItem)} and hierarchy can be + * created by adding {@link AppNavItem} instances to other {@link AppNavItem} + * instances. + * + * Source: https://github.com/vaadin/flow-crm-tutorial/ + */ +@JsModule("@vaadin-component-factory/vcf-nav") +@Tag("vcf-nav") +public class AppNav extends Component implements HasSize, HasStyle { + + /** + * Creates a new menu without any label. + */ + public AppNav() { + } + + /** + * Creates a new menu with the given label. + * + * @param label + * the label to use + */ + public AppNav(String label) { + setLabel(label); + } + + /** + * Adds menu item(s) to the menu. + * + * @param appNavItems + * the menu item(s) to add + * @return the menu for chaining + */ + public AppNav addItem(AppNavItem... appNavItems) { + for (AppNavItem appNavItem : appNavItems) { + getElement().appendChild(appNavItem.getElement()); + } + + return this; + } + + /** + * Removes the menu item from the menu. + *

+ * If the given menu item is not a child of this menu, does nothing. + * + * @param appNavItem + * the menu item to remove + * @return the menu for chaining + */ + public AppNav removeItem(AppNavItem appNavItem) { + Optional parent = appNavItem.getParent(); + if (parent.isPresent() && parent.get() == this) { + getElement().removeChild(appNavItem.getElement()); + } + + return this; + } + + /** + * Removes all menu items from this item. + * + * @return this item for chaining + */ + public AppNav removeAllItems() { + getElement().removeAllChildren(); + return this; + } + + /** + * Gets the textual label for the navigation. + * + * @return the label or null if no label has been set + */ + public String getLabel() { + return getExistingLabelElement().map(e -> e.getText()).orElse(null); + } + + /** + * Set a textual label for the navigation. + *

+ * This can help the end user to distinguish groups of navigation items. The + * label is also available for screen reader users. + * + * @param label + * the label to set + * @return this instance for chaining + */ + public AppNav setLabel(String label) { + getLabelElement().setText(label); + return this; + } + + private Optional getExistingLabelElement() { + return getElement().getChildren().filter(child -> "label".equals(child.getAttribute("slot"))).findFirst(); + } + + private Element getLabelElement() { + return getExistingLabelElement().orElseGet(() -> { + Element element = new Element("span"); + element.setAttribute("slot", "label"); + getElement().appendChild(element); + return element; + }); + } + + /** + * Check if the end user is allowed to collapse/hide and expand/show the + * navigation items. + *

+ * NOTE: The navigation has to have a label for it to be collapsible. + * + * @return true if the menu is collapsible, false otherwise + */ + public boolean isCollapsible() { + return getElement().hasAttribute("collapsible"); + } + + /** + * Allow the end user to collapse/hide and expand/show the navigation items. + *

+ * NOTE: The navigation has to have a label for it to be collapsible. + * + * @param collapsible + * true to make the whole navigation component collapsible, false + * otherwise + * @return this instance for chaining + */ + public AppNav setCollapsible(boolean collapsible) { + getElement().setAttribute("collapsible", ""); + return this; + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/component/appnav/AppNavItem.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/appnav/AppNavItem.java new file mode 100644 index 0000000..24d7209 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/appnav/AppNavItem.java @@ -0,0 +1,316 @@ +package de.uniregensburg.iamreportingmodule.web.component.appnav; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.component.dependency.JsModule; +import com.vaadin.flow.component.html.Span; +import com.vaadin.flow.component.icon.Icon; +import com.vaadin.flow.dom.Element; +import com.vaadin.flow.internal.StateTree; +import com.vaadin.flow.router.RouteConfiguration; +import com.vaadin.flow.router.Router; +import com.vaadin.flow.server.VaadinService; +import java.util.Optional; + +/** + * A menu item for the {@link AppNav} component. + *

+ * Can contain a label and/or an icon and links to a given {@code path}. + * + * Source: https://github.com/vaadin/flow-crm-tutorial/ + */ +@JsModule("@vaadin-component-factory/vcf-nav") +@Tag("vcf-nav-item") +public class AppNavItem extends Component { + + /** + * Creates a menu item which does not link to any view but only shows the given + * label. + * + * @param label + * the label for the item + */ + public AppNavItem(String label) { + setLabel(label); + } + + /** + * Creates a new menu item using the given label that links to the given path. + * + * @param label + * the label for the item + * @param path + * the path to link to + */ + public AppNavItem(String label, String path) { + setPath(path); + setLabel(label); + } + + /** + * Creates a new menu item using the given label that links to the given view. + * + * @param label + * the label for the item + * @param view + * the view to link to + */ + public AppNavItem(String label, Class view) { + setPath(view); + setLabel(label); + } + + /** + * Creates a new menu item using the given label and icon that links to the + * given path. + * + * @param label + * the label for the item + * @param path + * the path to link to + * @param icon + * the icon for the item + */ + public AppNavItem(String label, String path, Icon icon) { + setPath(path); + setLabel(label); + setIcon(icon); + } + + /** + * Creates a new menu item using the given label that links to the given view. + * + * @param label + * the label for the item + * @param view + * the view to link to + * @param icon + * the icon for the item + */ + public AppNavItem(String label, Class view, Icon icon) { + setPath(view); + setLabel(label); + setIcon(icon); + } + + /** + * Creates a new menu item using the given label and icon that links to the + * given path. + * + * @param label + * the label for the item + * @param path + * the path to link to + * @param iconClass + * the CSS class to use for showing the icon + */ + public AppNavItem(String label, String path, String iconClass) { + setPath(path); + setLabel(label); + + setIconClass(iconClass); + } + + /** + * Creates a new menu item using the given label and icon that links to the + * given path. + * + * @param label + * the label for the item + * @param view + * the view to link to + * @param iconClass + * the CSS class to use for showing the icon + */ + public AppNavItem(String label, Class view, String iconClass) { + setPath(view); + setLabel(label); + + setIconClass(iconClass); + } + + /** + * Adds menu item(s) inside this item, creating a hierarchy. + * + * @param appNavItems + * the menu item(s) to add + * @return this item for chaining + */ + public AppNavItem addItem(AppNavItem... appNavItems) { + for (AppNavItem appNavItem : appNavItems) { + appNavItem.getElement().setAttribute("slot", "children"); + getElement().appendChild(appNavItem.getElement()); + } + + return this; + } + + /** + * Removes the given menu item from this item. + *

+ * If the given menu item is not a child of this menu item, does nothing. + * + * @param appNavItem + * the menu item to remove + * @return this item for chaining + */ + public AppNavItem removeItem(AppNavItem appNavItem) { + Optional parent = appNavItem.getParent(); + if (parent.isPresent() && parent.get() == this) { + getElement().removeChild(appNavItem.getElement()); + } + + return this; + } + + /** + * Removes all menu items from this item. + * + * @return this item for chaining + */ + public AppNavItem removeAllItems() { + getElement().removeAllChildren(); + return this; + } + + /** + * Gets the label for the item. + * + * @return the label or null if no label has been set + */ + public String getLabel() { + return getExistingLabelElement().map(e -> e.getText()).orElse(null); + } + + /** + * Set a textual label for the item. + *

+ * The label is also available for screen rader users. + * + * @param label + * the label to set + * @return this instance for chaining + */ + public AppNavItem setLabel(String label) { + getLabelElement().setText(label); + return this; + } + + private Optional getExistingLabelElement() { + return getElement().getChildren().filter(child -> !child.hasAttribute("slot")).findFirst(); + } + + private Element getLabelElement() { + return getExistingLabelElement().orElseGet(() -> { + Element element = Element.createText(""); + getElement().appendChild(element); + return element; + }); + } + + /** + * Sets the path this item links to. + * + * @param path + * the path to link to + * @return this instance for chaining + */ + public AppNavItem setPath(String path) { + getElement().setAttribute("path", path); + return this; + } + + /** + * Sets the view this item links to. + * + * @param view + * the view to link to + * @return this instance for chaining + */ + public AppNavItem setPath(Class view) { + String url = RouteConfiguration.forRegistry(getRouter().getRegistry()).getUrl(view); + setPath(url); + return this; + } + + private Router getRouter() { + Router router = null; + if (getElement().getNode().isAttached()) { + StateTree tree = (StateTree) getElement().getNode().getOwner(); + router = tree.getUI().getInternals().getRouter(); + } + if (router == null) { + router = VaadinService.getCurrent().getRouter(); + } + if (router == null) { + throw new IllegalStateException("Implicit router instance is not available. " + + "Use overloaded method with explicit router parameter."); + } + return router; + } + + public String getPath() { + return getElement().getAttribute("path"); + } + + private int getIconElementIndex() { + for (int i = 0; i < getElement().getChildCount(); i++) { + if ("prefix".equals(getElement().getChild(i).getAttribute("slot"))) { + return i; + } + } + return -1; + } + + /** + * Sets the icon for the item. + *

+ * Can also be used to set a custom component to be shown in front of the label. + * + * @param icon + * the icon to show + * @return this instance for chaining + */ + public AppNavItem setIcon(Component icon) { + icon.getElement().setAttribute("slot", "prefix"); + int iconElementIndex = getIconElementIndex(); + if (iconElementIndex != -1) { + getElement().setChild(iconElementIndex, icon.getElement()); + } else { + getElement().appendChild(icon.getElement()); + } + return this; + } + + /** + * Sets the icon using a CSS class for the item. + *

+ * Can also be used to set a custom component to be shown in front of the label. + * + * @param iconClass + * the CSS class to use for showing the icon + * @return this instance for chaining + */ + public AppNavItem setIconClass(String iconClass) { + Span icon = new Span(); + icon.setClassName(iconClass); + setIcon(icon); + return this; + } + + /** + * Sets the expanded status of the item. + * + * @param value + * true to expand the item, false to collapse it + */ + public AppNavItem setExpanded(boolean value) { + if (value) { + getElement().setAttribute("expanded", ""); + } else { + getElement().removeAttribute("expanded"); + } + return this; + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/component/dashboard/Indicator.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/dashboard/Indicator.java new file mode 100644 index 0000000..44da689 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/dashboard/Indicator.java @@ -0,0 +1,158 @@ +package de.uniregensburg.iamreportingmodule.web.component.dashboard; + +import com.vaadin.flow.component.Composite; +import com.vaadin.flow.component.HasSize; +import com.vaadin.flow.component.HasStyle; +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.dependency.CssImport; +import com.vaadin.flow.component.html.Anchor; +import com.vaadin.flow.component.html.Div; + +/** + * Component for displaying an indicator on a card. + * Information displayed: title, value, unit + * Card can include href link + * + * @author Julian Bauer + */ +@CssImport("./themes/iamreportingmodule/indicator.css") +public class Indicator extends Composite

implements HasStyle, HasSize { + + private final Text title = new Text("Unknown"); + private final Text value = new Text("0"); + private final Text unit = new Text(""); + private final Anchor anchor = new Anchor(); + + /** + * + * @param title + * @param value + * @param unit + */ + public Indicator(String title, String value, String unit) { + this.title.setText(title); + this.value.setText(value); + this.unit.setText(unit); + init(); + } + + /** + * + * @param title + * @param value + */ + public Indicator(String title, String value) { + this.title.setText(title); + this.value.setText(value); + + init(); + } + + /** + * + * @param title + */ + public Indicator(String title) { + this.title.setText(title); + + init(); + } + + /** + * + */ + public Indicator() { + init(); + } + + /** + * Initializes component + */ + private void init() { + Div titleDiv = new Div(title); + titleDiv.setClassName("indicator-title"); + + Div valueDiv = new Div(value); + valueDiv.setClassName("indicator-value"); + + Div unitDiv = new Div(unit); + unitDiv.setClassName("indicator-unit"); + + anchor.addClassName("indicator-link"); + + getContent().add(titleDiv, valueDiv, unitDiv, anchor); + addClassName("indicator"); + } + + /** + * Returns title + * + * @return + */ + public String getTitle() { + return title.getText(); + } + + /** + * Sets title + * + * @param title + */ + public void setTitle(String title) { + this.title.setText(title); + } + + /** + * Returns value + * + * @return + */ + public String getValue() { + return value.getText(); + } + + /** + * Sets value + * + * @param value + */ + public void setValue(String value) { + this.value.setText(value); + } + + /** + * Returns unit + * + * @return + */ + public String getUnit() { + return unit.getText(); + } + + /** + * Sets unit + * + * @param unit + */ + public void setUnit(String unit) { + this.unit.setText(unit); + } + + /** + * Returns href link + * + * @return + */ + public String getLink() { + return anchor.getHref(); + } + + /** + * Sets href link + * + * @param href + */ + public void setLink(String href) { + anchor.setHref(href); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/CustomNotification.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/CustomNotification.java new file mode 100644 index 0000000..e66863c --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/CustomNotification.java @@ -0,0 +1,131 @@ +package de.uniregensburg.iamreportingmodule.web.component.notification; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.icon.Icon; +import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.orderedlayout.FlexComponent; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; + +/** + * Component for displaying customized notifications + * Composed of a header, a message and a close button + * The notification is shown in the bottom right corner for five seconds. + * + * @author Julian Bauer + */ +@Tag("notification") +public class CustomNotification extends Component { + + private final Text headerText; + private final Text messageText; + private final Notification notification = new Notification(); + + /** + * + */ + public CustomNotification() { + this("", ""); + } + + /** + * + * @param message + */ + public CustomNotification(String message) { + this("", message); + } + + /** + * + * @param header + * @param message + */ + public CustomNotification(String header, String message) { + headerText = new Text(header); + messageText = new Text(message); + init(); + } + + /** + * Initializes component + */ + private void init() { + Div headerDiv = new Div(headerText); // add header + headerDiv.getStyle().set("font-weight", "600"); // bold + Div messageDiv = new Div(messageText); // add message + messageDiv.getStyle().set("font-size", "var(--lumo-font-size-s)"); // text size + Button closeButton = new Button(new Icon("lumo", "cross")); // add button + closeButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE); // style: tertiary inline + closeButton.getElement().setAttribute("aria-label", "Close"); // label + closeButton.addClickListener(event -> notification.close()); // listener -> close + HorizontalLayout layout = new HorizontalLayout(new Div(headerDiv, messageDiv), closeButton); // layout + layout.setAlignItems(FlexComponent.Alignment.CENTER); // center items + notification.setPosition(Notification.Position.BOTTOM_END); // show in button right corner + notification.setDuration(5000); // show for five seconds + notification.add(layout); // add layout to notification + } + + /** + * Shows notification + */ + public void open() { + notification.open(); + } + + /** + * Closes notification + */ + public void close() { + notification.close(); + } + + /** + * Returns message + * + * @return + */ + public String getMessage() { + return messageText.getText(); + } + + /** + * Sets message + * + * @param message + */ + public void setMessage(String message) { + messageText.setText(message); + } + + /** + * Returns header + * + * @return + */ + public String getHeader() { + return headerText.getText(); + } + + /** + * Sets header + * + * @param header + */ + public void setHeader(String header) { + headerText.setText(header); + } + + /** + * Returns notification component + * + * @return + */ + public Notification getNotification() { + return notification; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/ErrorNotification.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/ErrorNotification.java new file mode 100644 index 0000000..9a0124d --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/ErrorNotification.java @@ -0,0 +1,45 @@ +package de.uniregensburg.iamreportingmodule.web.component.notification; + +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.component.notification.NotificationVariant; + +/** + * Component for displaying error notifications (extends custom notification) + * + * @author Julian Bauer + */ +@Tag("error-notification") +public class ErrorNotification extends CustomNotification { + + /** + * + */ + public ErrorNotification() { + this("", ""); + } + + /** + * + * @param message + */ + public ErrorNotification(String message) { + this("Error", message); + } + + /** + * + * @param header + * @param message + */ + public ErrorNotification(String header, String message) { + super(header, message); + init(); + } + + /** + * Initializes component + */ + public void init() { + getNotification().addThemeVariants(NotificationVariant.LUMO_ERROR); // color: red + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/SuccessNotification.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/SuccessNotification.java new file mode 100644 index 0000000..bcc7029 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/component/notification/SuccessNotification.java @@ -0,0 +1,45 @@ +package de.uniregensburg.iamreportingmodule.web.component.notification; + +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.component.notification.NotificationVariant; + +/** + * Component for displaying success notifications (extends custom notification) + * + * @author Julian Bauer + */ +@Tag("success-notification") +public class SuccessNotification extends CustomNotification { + + /** + * + */ + public SuccessNotification() { + this("", ""); + } + + /** + * + * @param message + */ + public SuccessNotification(String message) { + this("Success", message); + } + + /** + * + * @param header + * @param message + */ + public SuccessNotification(String header, String message) { + super(header, message); + init(); + } + + /** + * Initializes component + */ + public void init() { + getNotification().addThemeVariants(NotificationVariant.LUMO_SUCCESS); // color: green + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/form/DatabaseDataSourceForm.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/DatabaseDataSourceForm.java new file mode 100644 index 0000000..6e6eb9d --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/DatabaseDataSourceForm.java @@ -0,0 +1,311 @@ +package de.uniregensburg.iamreportingmodule.web.form; + +import com.vaadin.flow.component.*; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.textfield.PasswordField; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import com.vaadin.flow.data.binder.ValidationException; +import com.vaadin.flow.shared.Registration; +import de.uniregensburg.iamreportingmodule.core.exception.DatabaseException; +import de.uniregensburg.iamreportingmodule.core.util.DatabaseUtil; +import de.uniregensburg.iamreportingmodule.data.converter.StringToPortConverter; +import de.uniregensburg.iamreportingmodule.data.entity.DatabaseDataSource; +import de.uniregensburg.iamreportingmodule.data.entity.Dbms; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.view.MainLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Form for editing database datasource + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/list/ContactForm.java + * + * @author Julian Bauer + */ +public class DatabaseDataSourceForm extends FormLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private DatabaseDataSource dataSource; + private final Binder binder = new BeanValidationBinder<>(DatabaseDataSource.class); + + private final Button save = new Button("Save"); + private final Button delete = new Button("Delete"); + private final Button cancel = new Button("Cancel"); + private final Button testConnection = new Button("Test connection"); + + private final TextField name = new TextField("Name"); + private final TextField description = new TextField("Description"); + private final ComboBox dbmsType = new ComboBox<>("Database management system"); + private final TextField host = new TextField("Host"); + private final TextField port = new TextField("Port"); + private final TextField database = new TextField("Database"); + private final TextField username = new TextField("Username"); + private final PasswordField password = new PasswordField("Password"); + + /** + * + * @param dbmsTypeList + */ + public DatabaseDataSourceForm(List dbmsTypeList) { + init(dbmsTypeList); + } + + /** + * Initializes form + * + * @param dbmsTypeList list of dbms types + */ + private void init(List dbmsTypeList) { + addClassName("datasource-form"); + + // configure form binders + binder.forField(port) + .withConverter( + new StringToPortConverter("Not in range from 1 to 65535")) + .bind(DatabaseDataSource::getPort,DatabaseDataSource::setPort); + binder.bindInstanceFields(this); + + // configure form components + configureComboBox(dbmsTypeList); + + // add components to layout + add(name, description, dbmsType, host, port, database, username, password); + } + + /** + * Tests connection based on form inputs + * + * @param silent hide notifications + * @return + */ + private boolean testConnection(boolean silent) { + boolean invalid = dbmsType.isInvalid() || dbmsType.isEmpty() || host.isInvalid() || host.isEmpty() || port.isInvalid() || port.isEmpty() || database.isInvalid() || database.isEmpty() || username.isInvalid() || password.isInvalid(); + if (invalid) { + if (dbmsType.isInvalid() || dbmsType.isEmpty()) { + if (!silent) { + new ErrorNotification("Database management system invalid").open(); + } + } + if (host.isInvalid() || host.isEmpty()) { + if (!silent) { + new ErrorNotification("Host invalid").open(); + } + } + if (port.isInvalid() || port.isEmpty()) { + if (!silent) { + new ErrorNotification("Port invalid").open(); + } + } + if (database.isInvalid() || database.isEmpty()) { + if (!silent) { + new ErrorNotification("Database invalid").open(); + } + } + if (username.isInvalid()) { + if (!silent) { + new ErrorNotification("Username invalid").open(); + } + } + if (password.isInvalid()) { + if (!silent) { + new ErrorNotification("Password invalid").open(); + } + } + return false; + } else { // valid + DatabaseDataSource testDataSource = new DatabaseDataSource(Dbms.POSTGRESQL); + testDataSource.setHost(host.getValue()); + testDataSource.setPort(Integer.parseInt(port.getValue())); + testDataSource.setDatabase(database.getValue()); + testDataSource.setUsername(username.getValue()); + testDataSource.setPassword(password.getValue()); + DatabaseUtil databaseUtil = new DatabaseUtil(testDataSource); + try { + if (databaseUtil.testConnection()) { + logger.info("Connection successful"); + if (!silent) { + new SuccessNotification("Connection successful").open(); + } + return true; + } else { + logger.info("Connection failed"); + if (!silent) { + new ErrorNotification("Connection failed").open(); + } + return false; + } + } catch (DatabaseException ex) { + logger.info("Connection failed " + ex.getMessage()); + if (!silent) { + new ErrorNotification("Connection failed").open(); + } + return false; + } + } + } + + /** + * Configures combo box with dbms types + * + * @param dbmsTypeList + */ + private void configureComboBox(List dbmsTypeList) { + dbmsType.setItems(dbmsTypeList); + dbmsType.setPlaceholder("Select database management system"); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(delete, cancel, testConnection, save); + + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + + save.addClickShortcut(Key.ENTER); + cancel.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new DeleteEvent(this, dataSource))); + cancel.addClickListener(event -> fireEvent(new CloseEvent(this))); + testConnection.addClickListener(event -> testConnection(false)); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + } + + /** + * Shows or hides delete button + * + * @param show + */ + public void showDelete(boolean show) { + delete.setVisible(show); + } + + /** + * Validates and saves database datasource + */ + private void validateAndSave() { + if (binder.validate().hasErrors()) { + new ErrorNotification("Form contains errors").open(); + } else if (testConnection(false)) { + try { + binder.writeBean(dataSource); + fireEvent(new SaveEvent(this, dataSource)); + } catch (ValidationException e) { + logger.info(e.getMessage()); + } + } + } + + /** + * Fills form based on datasource + * + * @param dataSource + */ + public void setDataSource(DatabaseDataSource dataSource) { + this.dataSource = dataSource; + binder.readBean(dataSource); + } + + /** + * Event definition + */ + public static abstract class DatabaseDataSourceFormEvent extends ComponentEvent { + private final DatabaseDataSource dataSource; + + public DatabaseDataSourceFormEvent(DatabaseDataSourceForm source, DatabaseDataSource dataSource) { + super(source, false); + this.dataSource = dataSource; + } + + public DatabaseDataSource getDataSource() { + return dataSource; + } + } + + /** + * Save event + */ + public static class SaveEvent extends DatabaseDataSourceFormEvent { + SaveEvent(DatabaseDataSourceForm source, DatabaseDataSource dataSource) { + super(source, dataSource); + } + } + + /** + * Delete event + */ + public static class DeleteEvent extends DatabaseDataSourceFormEvent { + DeleteEvent(DatabaseDataSourceForm source, DatabaseDataSource dataSource) { + super(source, dataSource); + } + } + + /** + * Close event + */ + public static class CloseEvent extends DatabaseDataSourceFormEvent { + CloseEvent(DatabaseDataSourceForm source) { + super(source, null); + } + } + + /** + * Event listener + * + * @param eventType + * @param listener + * @return + * @param + */ + public > Registration addListener(Class eventType, ComponentEventListener listener) { + return getEventBus().addListener(eventType, listener); + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/form/FileDataSourceForm.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/FileDataSourceForm.java new file mode 100644 index 0000000..e334a56 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/FileDataSourceForm.java @@ -0,0 +1,352 @@ +package de.uniregensburg.iamreportingmodule.web.form; + +import com.vaadin.flow.component.*; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.html.Anchor; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.Paragraph; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.component.upload.Upload; +import com.vaadin.flow.component.upload.receivers.MemoryBuffer; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import com.vaadin.flow.data.binder.ValidationException; +import com.vaadin.flow.server.StreamResource; +import com.vaadin.flow.shared.Registration; +import de.uniregensburg.iamreportingmodule.data.entity.FileDataSource; +import de.uniregensburg.iamreportingmodule.data.entity.FileType; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.view.MainLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * Form for editing file datasource + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/list/ContactForm.java + * + * @author Julian Bauer + */ +public class FileDataSourceForm extends FormLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private FileDataSource dataSource; + private final Binder binder = new BeanValidationBinder<>(FileDataSource.class); + + private final Button save = new Button("Save"); + private final Button delete = new Button("Delete"); + private final Button cancel = new Button("Cancel"); + private final Button download = new Button("Download"); + private Anchor downloadAnchor; + + private final TextField name = new TextField("Name"); + private final TextField description = new TextField("Description"); + private final TextField fileName = new TextField("File name"); + private final TextField fileType = new TextField("File type"); + private final MemoryBuffer buffer = new MemoryBuffer(); + private final Upload upload = new Upload(buffer); + + /** + * + */ + public FileDataSourceForm() { + init(); + } + + /** + * Initializes form + */ + public void init() { + addClassName("datasource-form"); + + // configure for mbinder + binder.bind(name, "name"); + binder.bind(description, "description"); + binder.bind(fileName, "fileName"); + binder.forField(fileType) + .withConverter(FileType::valueOf,String::valueOf) + .bind("fileType"); + + // configure form components + configureUpload(); + configureDownload(); + + // add upload field and hint to div + Div uploadDiv = new Div(); + Paragraph hint = new Paragraph("Maximum file size: 100 MB"); + uploadDiv.add(hint, upload); + + // read only fields + fileName.setEnabled(false); + fileType.setEnabled(false); + + // add components to layout + add(name, description, fileName, fileType, uploadDiv); + } + + /** + * Configures download button + * Source: https://stackoverflow.com/a/60822730 + */ + private void configureDownload() { + downloadAnchor = new Anchor(getStreamResource(), ""); + downloadAnchor.getElement().setAttribute("download", true); + downloadAnchor.add(download); + + download.setEnabled(false); + downloadAnchor.setEnabled(false); + + binder.addValueChangeListener(event -> { + if (event.getHasValue().equals(fileName)) { + boolean fileAvailable = !fileName.getValue().isBlank(); + download.setEnabled(fileAvailable); + downloadAnchor.setEnabled(fileAvailable); + } + }); + } + + /** + * Returns file as stream resource + * Source: https://stackoverflow.com/a/74046358 + * + * @return + */ + private StreamResource getStreamResource() { + // + return new StreamResource("", FileDataSourceForm.this::makeInputStreamOfContent) { + @Override + public Map getHeaders() { + Map headers = new HashMap<>(super.getHeaders()); + String name1 = fileName.getValue(); + headers.put("Content-Disposition", "attachment; filename=\""+ name1 +"\""); + return headers; + }}; + } + + /** + * Returns input stream of file + * + * @return + */ + private InputStream makeInputStreamOfContent() { + return new ByteArrayInputStream(dataSource.getFile()); + } + + /** + * Configures upload field + */ + private void configureUpload() { + upload.setMaxFiles(1); // limit to one file + upload.setMaxFileSize(100 * 1024 * 1024); // limit file size to 100 MB + upload.setAcceptedFileTypes("text/csv"); // limit mime types + + upload.addSucceededListener(event -> { + logger.info("File uploaded sucessfully"); + InputStream fileData = buffer.getInputStream(); + try { + logger.info("Adding file content to bean"); + if (event.getMIMEType().equals("text/csv")) { + fileType.setValue(FileType.CSV.toString()); + } else { + logger.info("MIME type unknown: " + event.getMIMEType()); + new ErrorNotification("File upload failed", "Unknown MIME type " + event.getMIMEType()).open(); + return; + } + fileName.setValue(event.getFileName()); + dataSource.setFile(fileData.readAllBytes()); + new SuccessNotification("Success", "File uploaded successfully").open(); + logger.info("Added file content to bean"); + } catch (IOException e) { + logger.info("Error while writing file content to bean: " + e.getMessage()); + new ErrorNotification("File upload failed", "Cannot save file content").open(); + } + + }); + + upload.addFileRejectedListener(event -> { + logger.info("File upload failed: " + event.getErrorMessage()); + new ErrorNotification("File upload failed", event.getErrorMessage()).open(); + }); + + upload.addFailedListener(event -> { + logger.info("File upload failed: " + event.getReason().getMessage()); + new ErrorNotification("File upload failed", event.getReason().getMessage()).open(); + }); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(delete, cancel, downloadAnchor, save); + + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + + save.addClickShortcut(Key.ENTER); + cancel.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new DeleteEvent(this, dataSource))); + cancel.addClickListener(event -> fireEvent(new CloseEvent(this))); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + } + + /** + * Shows or hides delete button + * + * @param show + */ + public void showDelete(boolean show) { + delete.setVisible(show); + } + + /** + * Validates and saves file datasource + */ + private void validateAndSave() { + if (!uploadSuccessful()) { + new ErrorNotification("No uploaded file found").open(); + } else if (binder.validate().hasErrors()) { + new ErrorNotification("Form contains errors").open(); + } else { + try { + binder.writeBean(dataSource); + fireEvent(new SaveEvent(this, dataSource)); + } catch (ValidationException e) { + logger.info(e.getMessage()); + } + } + } + + /** + * Returns if file was uploaded successfully + * + * @return + */ + private boolean uploadSuccessful() { + if (dataSource.getFile() == null) { + logger.info("No file provided"); + return false; + } + if (dataSource.getFile().length == 0) { + logger.info("No file data set"); + return false; + } + return true; + } + + /** + * Fills form based on datasource + * + * @param dataSource + */ + public void setDataSource(FileDataSource dataSource) { + this.dataSource = dataSource; + binder.readBean(dataSource); + boolean fileAvailable = !fileName.getValue().isBlank(); + download.setEnabled(fileAvailable); + downloadAnchor.setEnabled(fileAvailable); + } + + /** + * Event definition + */ + public static abstract class FileDataSourceFormEvent extends ComponentEvent { + private final FileDataSource dataSource; + + public FileDataSourceFormEvent(FileDataSourceForm source, FileDataSource dataSource) { + super(source, false); + this.dataSource = dataSource; + } + + public FileDataSource getDataSource() { + return dataSource; + } + } + + /** + * Save event + */ + public static class SaveEvent extends FileDataSourceForm.FileDataSourceFormEvent { + SaveEvent(FileDataSourceForm source, FileDataSource dataSource) { + super(source, dataSource); + } + } + + /** + * Delete event + */ + public static class DeleteEvent extends FileDataSourceForm.FileDataSourceFormEvent { + DeleteEvent(FileDataSourceForm source, FileDataSource dataSource) { + super(source, dataSource); + } + } + + /** + * Close event + */ + public static class CloseEvent extends FileDataSourceForm.FileDataSourceFormEvent { + CloseEvent(FileDataSourceForm source) { + super(source, null); + } + } + + /** + * Event listener + * + * @param eventType + * @param listener + * @return + * @param + */ + public > Registration addListener(Class eventType, ComponentEventListener listener) { + return getEventBus().addListener(eventType, listener); + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/form/GroupForm.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/GroupForm.java new file mode 100644 index 0000000..e5f0946 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/GroupForm.java @@ -0,0 +1,222 @@ +package de.uniregensburg.iamreportingmodule.web.form; + +import com.vaadin.flow.component.*; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.combobox.MultiSelectComboBox; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import com.vaadin.flow.data.binder.ValidationException; +import com.vaadin.flow.shared.Registration; +import de.uniregensburg.iamreportingmodule.core.service.UserService; +import de.uniregensburg.iamreportingmodule.data.entity.Group; +import de.uniregensburg.iamreportingmodule.data.entity.User; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.view.MainLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Form for editing a group + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/list/ContactForm.java + * + * @author Julian Bauer + */ +public class GroupForm extends FormLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private Group group; + private final Binder binder = new BeanValidationBinder<>(Group.class); + private final UserService userService; + + private final Button save = new Button("Save"); + private final Button delete = new Button("Delete"); + private final Button cancel = new Button("Cancel"); + + private final TextField name = new TextField("Name"); + private final MultiSelectComboBox members = new MultiSelectComboBox<>("Members"); + + /** + * + * @param userService + */ + public GroupForm(UserService userService) { + this.userService = userService; + init(); + } + + /** + * Initializes form + */ + private void init() { + addClassName("group-form"); + + // configure form binders + binder.bindInstanceFields(this); + + // configure form components + initMembers(); + + // add components to layout + add(name, members); + } + + /** + * Initializes multiselect combo box with users + */ + private void initMembers() { + members.setItems(userService.findAllUsers()); + members.setItemLabelGenerator(User::getFullName); + members.setPlaceholder("Select members"); + members.addSelectionListener(e -> group.setMembers(e.getAllSelectedItems())); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(delete, cancel, save); + + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + + save.addClickShortcut(Key.ENTER); + cancel.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new DeleteEvent(this, group))); + cancel.addClickListener(event -> fireEvent(new CloseEvent(this))); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + } + + /** + * Shows or hides delete button + * + * @param show + */ + public void showDelete(boolean show) { + delete.setVisible(show); + } + + /** + * Validates and saves group + */ + private void validateAndSave() { + if (binder.validate().hasErrors()) { + new ErrorNotification("Form contains errors").open(); + } else { + try { + binder.writeBean(group); + fireEvent(new SaveEvent(this, group)); + } catch (ValidationException e) { + logger.info(e.getMessage()); + } + } + } + + /** + * Fills form based on group + * + * @param group + */ + public void setGroup(Group group) { + this.group = group; + binder.readBean(group); + members.select(group.getMembers()); + } + + /** + * Event definition + */ + public static abstract class GroupFormEvent extends ComponentEvent { + private final Group group; + + public GroupFormEvent(GroupForm source, Group group) { + super(source, false); + this.group = group; + } + + public Group getGroup() { + return group; + } + } + + /** + * Save event + */ + public static class SaveEvent extends GroupFormEvent { + SaveEvent(GroupForm source, Group group) { + super(source, group); + } + } + + /** + * Delete event + */ + public static class DeleteEvent extends GroupFormEvent { + DeleteEvent(GroupForm source, Group group) { + super(source, group); + } + } + + /** + * Close event + */ + public static class CloseEvent extends GroupFormEvent { + CloseEvent(GroupForm source) { + super(source, null); + } + } + + /** + * Event listener + * + * @param eventType + * @param listener + * @return + * @param + */ + public > Registration addListener(Class eventType, ComponentEventListener listener) { + return getEventBus().addListener(eventType, listener); + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/form/InformationNeedForm.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/InformationNeedForm.java new file mode 100644 index 0000000..bfd0e19 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/InformationNeedForm.java @@ -0,0 +1,202 @@ +package de.uniregensburg.iamreportingmodule.web.form; + +import com.vaadin.flow.component.*; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import com.vaadin.flow.data.binder.ValidationException; +import com.vaadin.flow.shared.Registration; +import de.uniregensburg.iamreportingmodule.data.entity.InformationNeed; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.view.MainLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Form for editing information need + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/list/ContactForm.java + * + * @author Julian Bauer + */ +public class InformationNeedForm extends FormLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private InformationNeed informationNeed; + private final Binder binder = new BeanValidationBinder<>(InformationNeed.class); + + private final Button save = new Button("Save"); + private final Button delete = new Button("Delete"); + private final Button cancel = new Button("Cancel"); + + private final TextField name = new TextField("Name"); + private final TextField description = new TextField("Description"); + + /** + * + */ + public InformationNeedForm() { + init(); + } + + /** + * Initializes form + */ + private void init() { + addClassName("informationneed-form"); + + // configure form binders + binder.bindInstanceFields(this); + + // add components to layout + add(name, description); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(delete, cancel, save); + + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + + save.addClickShortcut(Key.ENTER); + cancel.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new DeleteEvent(this, informationNeed))); + cancel.addClickListener(event -> fireEvent(new CloseEvent(this))); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + } + + /** + * Shows or hides delete button + * + * @param show + */ + public void showDelete(boolean show) { + delete.setVisible(show); + } + + /** + * Validates and saves information need + */ + private void validateAndSave() { + if (binder.validate().hasErrors()) { + new ErrorNotification("Form contains errors").open(); + } else { + try { + binder.writeBean(informationNeed); + fireEvent(new SaveEvent(this, informationNeed)); + } catch (ValidationException e) { + logger.info(e.getMessage()); + } + } + } + + /** + * Fills form based on information need + * + * @param informationNeed + */ + public void setInformationNeed(InformationNeed informationNeed) { + this.informationNeed = informationNeed; + binder.readBean(informationNeed); + } + + /** + * Event definition + */ + public static abstract class InformationNeedFormEvent extends ComponentEvent { + private final InformationNeed informationNeed; + + public InformationNeedFormEvent(InformationNeedForm source, InformationNeed informationNeed) { + super(source, false); + this.informationNeed = informationNeed; + } + + public InformationNeed getInformationNeed() { + return informationNeed; + } + } + + /** + * Save event + */ + public static class SaveEvent extends InformationNeedFormEvent { + SaveEvent(InformationNeedForm source, InformationNeed informationNeed) { + super(source, informationNeed); + } + } + + /** + * Delete event + */ + public static class DeleteEvent extends InformationNeedFormEvent { + DeleteEvent(InformationNeedForm source, InformationNeed informationNeed) { + super(source, informationNeed); + } + } + + /** + * Close event + */ + public static class CloseEvent extends InformationNeedFormEvent { + CloseEvent(InformationNeedForm source) { + super(source, null); + } + } + + /** + * Event listener + * + * @param eventType + * @param listener + * @return + * @param + */ + public > Registration addListener(Class eventType, ComponentEventListener listener) { + return getEventBus().addListener(eventType, listener); + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/form/ManualDataSourceForm.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/ManualDataSourceForm.java new file mode 100644 index 0000000..bc052db --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/ManualDataSourceForm.java @@ -0,0 +1,208 @@ +package de.uniregensburg.iamreportingmodule.web.form; + +import com.vaadin.flow.component.*; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import com.vaadin.flow.data.binder.ValidationException; +import com.vaadin.flow.data.converter.StringToBigDecimalConverter; +import com.vaadin.flow.shared.Registration; +import de.uniregensburg.iamreportingmodule.data.entity.ManualDataSource; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.view.MainLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Form for editing manual datasource + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/list/ContactForm.java + * + * @author Julian Bauer + */ +public class ManualDataSourceForm extends FormLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private ManualDataSource dataSource; + private final Binder binder = new BeanValidationBinder<>(ManualDataSource.class); + + private final Button save = new Button("Save"); + private final Button delete = new Button("Delete"); + private final Button cancel = new Button("Cancel"); + + private final TextField name = new TextField("Name"); + private final TextField description = new TextField("Description"); + private final TextField value = new TextField("Value"); + + /** + * + */ + public ManualDataSourceForm() { + init(); + } + + /** + * Initializes form + */ + private void init() { + addClassName("datasource-form"); + + // configure form binders + binder.forField(value) + .withConverter( + new StringToBigDecimalConverter("Not a number")) + .bind(ManualDataSource::getValue,ManualDataSource::setValue); + binder.bindInstanceFields(this); + + // add components to layout + add(name, description, value); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(delete, cancel, save); + + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + + save.addClickShortcut(Key.ENTER); + cancel.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new DeleteEvent(this, dataSource))); + cancel.addClickListener(event -> fireEvent(new CloseEvent(this))); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + } + + /** + * Shows or hides delete button + * + * @param show + */ + public void showDelete(boolean show) { + delete.setVisible(show); + } + + /** + * Validates and saves manual datasource + */ + private void validateAndSave() { + if (binder.validate().hasErrors()) { + new ErrorNotification("Form contains errors").open(); + } else { + try { + binder.writeBean(dataSource); + fireEvent(new SaveEvent(this, dataSource)); + } catch (ValidationException e) { + logger.info(e.getMessage()); + } + } + } + + /** + * Fills form based on datasource + * + * @param dataSource + */ + public void setDataSource(ManualDataSource dataSource) { + this.dataSource = dataSource; + binder.readBean(dataSource); + } + + /** + * Event definition + */ + public static abstract class ManualDataSourceFormEvent extends ComponentEvent { + private final ManualDataSource dataSource; + + public ManualDataSourceFormEvent(ManualDataSourceForm source, ManualDataSource dataSource) { + super(source, false); + this.dataSource = dataSource; + } + + public ManualDataSource getDataSource() { + return dataSource; + } + } + + /** + * Save event + */ + public static class SaveEvent extends ManualDataSourceFormEvent { + SaveEvent(ManualDataSourceForm source, ManualDataSource dataSource) { + super(source, dataSource); + } + } + + /** + * Delete event + */ + public static class DeleteEvent extends ManualDataSourceFormEvent { + DeleteEvent(ManualDataSourceForm source, ManualDataSource dataSource) { + super(source, dataSource); + } + } + + /** + * Close event + */ + public static class CloseEvent extends ManualDataSourceFormEvent { + CloseEvent(ManualDataSourceForm source) { + super(source, null); + } + } + + /** + * Event listener + * + * @param eventType + * @param listener + * @return + * @param + */ + public > Registration addListener(Class eventType, ComponentEventListener listener) { + return getEventBus().addListener(eventType, listener); + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/form/MeasurementForm.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/MeasurementForm.java new file mode 100644 index 0000000..de4d8d6 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/MeasurementForm.java @@ -0,0 +1,636 @@ +package de.uniregensburg.iamreportingmodule.web.form; + +import com.vaadin.flow.component.*; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.checkbox.Checkbox; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.combobox.MultiSelectComboBox; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.Paragraph; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.textfield.TextArea; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import com.vaadin.flow.data.binder.ValidationException; +import com.vaadin.flow.data.validator.BeanValidator; +import com.vaadin.flow.shared.Registration; +import de.uniregensburg.iamreportingmodule.core.exception.DatabaseException; +import de.uniregensburg.iamreportingmodule.core.exception.FileException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.util.CsvUtil; +import de.uniregensburg.iamreportingmodule.core.util.DatabaseUtil; +import de.uniregensburg.iamreportingmodule.data.converter.StringToFrequencyConverter; +import de.uniregensburg.iamreportingmodule.data.entity.Unit; +import de.uniregensburg.iamreportingmodule.data.entity.*; +import de.uniregensburg.iamreportingmodule.data.validator.MeasurableLabelValidator; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.view.MainLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Form for editing a measurement + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/list/ContactForm.java + * + * @author Julian Bauer + */ +public class MeasurementForm extends FormLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private Measurement measurement; + private final Binder binder = new BeanValidationBinder<>(Measurement.class); + private final MeasurableService service; + + private final Button save = new Button("Save"); + private final Button delete = new Button("Delete"); + private final Button cancel = new Button("Cancel"); + private final Button test = new Button("Test"); + + private final TextField name = new TextField("Name"); + private final TextField description = new TextField("Description"); + private final TextField label = new TextField("Label"); + private final MultiSelectComboBox stakeholders = new MultiSelectComboBox<>("Stakeholders"); + private final MultiSelectComboBox audiences = new MultiSelectComboBox<>("Audiences"); + private final MultiSelectComboBox informationNeeds = new MultiSelectComboBox<>("Information Needs"); + private final ComboBox scale = new ComboBox<>("Scale"); + private final ComboBox unit = new ComboBox<>("Unit"); + private final TextField frequency = new TextField("Frequency"); + private final ComboBox dataSources = new ComboBox<>("Data Source"); + private final TextArea sqlQuery = new TextArea("SQL Query"); + private final Div db = new Div(); + private final TextField csvColumnName = new TextField("Column name"); + private final TextField csvColumnIndex = new TextField("Column index"); + private final TextField csvDelimiter = new TextField("Delimiter"); + private final Checkbox csvHeader = new Checkbox("Heading"); + private final FormLayout csv = new FormLayout(); + ComboBox csvAggregationMethod = new ComboBox<>("Aggregation method"); + + /** + * + * @param scales + * @param units + * @param service + */ + public MeasurementForm(List scales, List units, MeasurableService service) { + this.service = service; + init(scales, units); + } + + /** + * Initializes form + * + * @param scales + * @param units + */ + private void init(List scales, List units) { + addClassName("measurement-form"); + + // configure form binders + updateBinders(measurement); + binder.bindInstanceFields(this); + + // configure form components + scale.setItems(scales); + unit.setItems(units); + initStakeholders(); + initAudiences(); + initInformationNeeds(); + initDataSources(); + initCsv(); + + // add database specific components + Paragraph dbParagrapth = new Paragraph("Database specific attributes"); + sqlQuery.setWidthFull(); + db.add(dbParagrapth, sqlQuery); + + // add csv file specific components + Paragraph csvParagrapth = new Paragraph("CSV specific attributes"); + csv.add(csvParagrapth, csvHeader, csvColumnName, csvColumnIndex, csvDelimiter, csvAggregationMethod); + + // add components to layout + add(name, description, label, scale, unit, frequency, stakeholders, audiences, informationNeeds, dataSources, db, csv); + } + + /** + * Initializes csv components + */ + private void initCsv() { + csvHeader.addValueChangeListener(event -> { + if (event.getValue()) { + csvColumnName.setVisible(true); + csvColumnIndex.setVisible(false); + csvColumnIndex.clear(); + } else { + csvColumnName.setVisible(false); + csvColumnIndex.setVisible(true); + csvColumnName.clear(); + } + }); + csvHeader.setValue(false); + csvColumnName.setVisible(false); + csvAggregationMethod.setItems(List.of(CsvAggregationMethod.COUNT, CsvAggregationMethod.SUM, CsvAggregationMethod.AVERAGE, CsvAggregationMethod.MEDIAN, CsvAggregationMethod.MAXIMUM, CsvAggregationMethod.MINIMUM)); + } + + /** + * Initializes data sources components + */ + private void initDataSources() { + setDbVisible(false); + setCsvVisible(false); + dataSources.setItems(service.findAllDataSources()); + dataSources.setItemLabelGenerator(DataSource::getName); + dataSources.setPlaceholder("Select datasource"); + dataSources.addValueChangeListener(e -> { + measurement.setDataSource(e.getValue()); + if (e.getValue() != null) { + if (e.getOldValue() != null) { + if (e.getValue() == e.getOldValue()) { + return; + } + } + setDbVisible(false); + setCsvVisible(false); + DataSourceType type = e.getValue().getType(); + if (DataSourceType.DATABASE.equals(type)) { // Database + setDbVisible(true); + } + if (DataSourceType.FILE.equals(type)) { // File + FileDataSource fileDataSource = (FileDataSource) e.getValue(); + if (FileType.CSV.equals(fileDataSource.getFileType())) { // CSV + setCsvVisible(true); + } + } + } + }); + } + + /** + * Shows or hides database specific fields + * + * @param visible + */ + private void setDbVisible(boolean visible) { + db.setVisible(visible); + if (!visible) { + sqlQuery.clear(); + } + } + + /** + * Shows or hides csv file specific fields + * + * @param visible + */ + private void setCsvVisible(boolean visible) { + csv.setVisible(visible); + if (!visible) { + csvHeader.clear(); + csvDelimiter.clear(); + csvAggregationMethod.clear(); + csvColumnIndex.clear(); + csvColumnName.clear(); + } + } + + /** + * Initializes stakeholders field + */ + private void initStakeholders() { + stakeholders.setItems(service.findAllStakeholders()); + stakeholders.setItemLabelGenerator(Stakeholder::getName); + stakeholders.setPlaceholder("Select stakeholders"); + stakeholders.addSelectionListener(e -> measurement.setStakeholders(e.getAllSelectedItems())); + } + + /** + * Initializes audiences fields + */ + private void initAudiences() { + audiences.setItems(service.findAllAudiences()); + audiences.setItemLabelGenerator(Audience::getName); + audiences.setPlaceholder("Select audiences"); + audiences.addSelectionListener(e -> measurement.setAudiences(e.getAllSelectedItems())); + } + + /** + * Initializes information needs fields + */ + private void initInformationNeeds() { + informationNeeds.setItems(service.findAllInformationNeeds()); + informationNeeds.setItemLabelGenerator(InformationNeed::getName); + informationNeeds.setPlaceholder("Select information needs"); + informationNeeds.addSelectionListener(e -> measurement.setInformationNeeds(e.getAllSelectedItems())); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(delete, cancel, test, save); + + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + + save.addClickShortcut(Key.ENTER); + cancel.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new DeleteEvent(this, measurement))); + cancel.addClickListener(event -> fireEvent(new CloseEvent(this))); + test.addClickListener(event -> testConfiguration(false)); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + } + + /** + * Shows or hides delete button + * + * @param show + */ + public void showDelete(boolean show) { + delete.setVisible(show); + } + + /** + * Tests configuration based on form inputs + * + * @param silent hide notifications + * @return + */ + private boolean testConfiguration(boolean silent) { + logger.info("Testing configuration"); + DataSource dataSource = dataSources.getValue(); + if (dataSource == null) { + logger.info("No datasource selected"); + if (!silent) { + new ErrorNotification("No datasource selected").open(); + } + return false; + } + DataSourceType type = dataSource.getType(); + if (DataSourceType.MANUAL.equals(type)) { + logger.info("Manual datasource"); + ManualDataSource manualDataSource = (ManualDataSource) dataSource; + return testManualConfiguration(manualDataSource, silent); + } + if (DataSourceType.DATABASE.equals(type)) { + logger.info("Database datasource"); + DatabaseDataSource databaseDataSource = (DatabaseDataSource) dataSource; + return testDatabaseConfiguration(databaseDataSource, silent); + } + if (DataSourceType.FILE.equals(type)) { + logger.info("File datasource"); + FileDataSource fileDataSource = (FileDataSource) dataSource; + FileType fileType = fileDataSource.getFileType(); + if (FileType.CSV.equals(fileType)) { + return testCsvConfiguration(fileDataSource, silent); + } + } + return false; + } + + /** + * Tests csv configuration based on form inputs + * + * @param fileDataSource + * @param silent hide notifications + * @return + */ + private boolean testCsvConfiguration(FileDataSource fileDataSource, boolean silent) { + logger.info("Testing file datasource"); + HashMap attributes = new HashMap<>(); + boolean csvHeaderAttribute = csvHeader.getValue(); + attributes.put("csvHeader", String.valueOf(csvHeaderAttribute)); + if (csvHeaderAttribute) { + String csvColumnNameAttribute = csvColumnName.getValue(); + if (csvColumnNameAttribute.isBlank()) { + logger.info("Column name is blank"); + if (!silent) { + new ErrorNotification("Column name is blank").open(); + } + return false; + } + attributes.put("csvColumnName", csvColumnNameAttribute); + } else { + String csvColumnIndexAttribute = csvColumnIndex.getValue(); + if (csvColumnIndexAttribute.isBlank()) { + logger.info("Column index is blank"); + if (!silent) { + new ErrorNotification("Column index is blank").open(); + } + return false; + } + attributes.put("csvColumnIndex", csvColumnIndexAttribute); + } + String csvDelimiterAttribute = csvDelimiter.getValue(); + if (csvDelimiterAttribute.isBlank()) { + logger.info("Delimiter is blank"); + if (!silent) { + new ErrorNotification("Delimiter is blank").open(); + } + return false; + } + attributes.put("csvDelimiter", csvDelimiterAttribute); + if (csvAggregationMethod.getValue() == null) { + logger.info("No aggregation method selected"); + if (!silent) { + new ErrorNotification("No aggregation method selected").open(); + } + return false; + } + String csvAggregationMethodAttribute = csvAggregationMethod.getValue().name(); + attributes.put("csvAggregationMethod", csvAggregationMethodAttribute); + CsvUtil csvUtil = new CsvUtil(fileDataSource); + try { + Result result = csvUtil.measure(attributes); + logger.info("Measurement successful: " + result.getValue()); + if (!silent) { + new SuccessNotification("Measurement successful: " + result.getValue().stripTrailingZeros().toPlainString()).open(); + } + return true; + } catch (FileException e) { + logger.info("Measurement failed: " + e.getMessage()); + if (!silent) { + new ErrorNotification("Measurement failed: " + e.getMessage()).open(); + } + return false; + } + } + + /** + * Tests database configuration based on form inputs + * + * @param databaseDataSource + * @param silent hide notifications + * @return + */ + private boolean testDatabaseConfiguration(DatabaseDataSource databaseDataSource, boolean silent) { + logger.info("Testing database datasource"); + if (sqlQuery.getValue().isBlank()) { + logger.info("Query is blank"); + if (!silent) { + new ErrorNotification("Query is blank").open(); + } + return false; + } + DatabaseUtil databaseUtil = new DatabaseUtil(databaseDataSource); + try { + Result result = databaseUtil.measure(sqlQuery.getValue()); + logger.info("Query successful: " + result.getValue()); + if (!silent) { + new SuccessNotification("Query successful: " + result.getValue()).open(); + } + return true; + } catch (DatabaseException e) { + logger.info("Query failed: " + e.getMessage()); + if (!silent) { + new ErrorNotification("Query failed: " + e.getMessage()).open(); + } + return false; + } + } + + /** + * Tests manual datasource configuration based on form inputs + * @param manualDataSource + * @param silent hide notifications + * @return + */ + private boolean testManualConfiguration(ManualDataSource manualDataSource, boolean silent) { + logger.info("Testing manual datasource"); + BigDecimal value = manualDataSource.getValue(); + if (value == null) { + if (!silent) { + new ErrorNotification("Manual value null").open(); + } + logger.info("Manual value null"); + return false; + } + if (!silent) { + new SuccessNotification("Manual value: " + value).open(); + } + logger.info("Success - Manual value: " + value); + return true; + } + + /** + * Validates and saves group + */ + private void validateAndSave() { + if (binder.validate().hasErrors()) { + new ErrorNotification("Form contains errors").open(); + } else if (testConfiguration(false)) { + try { + binder.writeBean(measurement); + updateAttributes(); + fireEvent(new SaveEvent(this, measurement)); + } catch (ValidationException e) { + logger.info(e.getMessage()); + } + } + } + + /** + * Updates attributes + * Automatic binding with form binder not possible for attributes as they are optional + */ + private void updateAttributes() { + logger.info("Adding attributes"); + Map attributes = measurement.getAttributes(); + DataSource dataSource = measurement.getDataSource(); + if (dataSource == null) { + logger.info("Datasource is null"); + return; + } + DataSourceType type = dataSource.getType(); + if (type == null) { + logger.info("Datasource type is null"); + return; + } + if (DataSourceType.DATABASE.equals(type)) { + attributes.put("sqlQuery", sqlQuery.getValue()); + } + if (DataSourceType.FILE.equals(type)) { + FileDataSource fileDataSource = (FileDataSource) dataSource; + FileType fileType = fileDataSource.getFileType(); + if (FileType.CSV.equals(fileType)) { + boolean heading = csvHeader.getValue(); + attributes.put("csvHeader", String.valueOf(heading)); + if (heading) { + attributes.put("csvColumnName", csvColumnName.getValue()); + } else { + attributes.put("csvColumnIndex", csvColumnIndex.getValue()); + } + attributes.put("csvDelimiter", csvDelimiter.getValue()); + if (csvAggregationMethod.getValue() != null) { + attributes.put("csvAggregationMethod", csvAggregationMethod.getValue().name()); + } + } + } + measurement.setAttributes(attributes); + } + + /** + * Fills form based on measurement + * + * @param measurement + */ + public void setMeasurement(Measurement measurement) { + this.measurement = measurement; + updateBinders(measurement); + binder.readBean(measurement); + stakeholders.select(measurement.getStakeholders()); + audiences.select(measurement.getAudiences()); + informationNeeds.select(measurement.getInformationNeeds()); + dataSources.setValue(measurement.getDataSource()); + Map attributes = measurement.getAttributes(); + String sqlQueryAttribute = attributes.get("sqlQuery"); + if (sqlQueryAttribute != null) { + sqlQuery.setValue(sqlQueryAttribute); + } + String csvHeaderAttribute = attributes.get("csvHeader"); + if (csvHeaderAttribute != null) { + boolean header = Boolean.parseBoolean(csvHeaderAttribute); + csvHeader.setValue(header); + if (header) { + csvColumnName.setVisible(true); + csvColumnIndex.setVisible(false); + } else { + csvColumnName.setVisible(false); + csvColumnIndex.setVisible(true); + } + } + String csvColumnNameAttribute = attributes.get("csvColumnName"); + if (csvColumnNameAttribute != null) { + csvColumnName.setValue(csvColumnNameAttribute); + } + String csvColumnIndexAttribute = attributes.get("csvColumnIndex"); + if (csvColumnIndexAttribute != null) { + csvColumnIndex.setValue(csvColumnIndexAttribute); + } + String csvDelimiterAttribute = attributes.get("csvDelimiter"); + if (csvDelimiterAttribute != null) { + csvDelimiter.setValue(csvDelimiterAttribute); + } + String csvAggregationMethodAttribute = attributes.get("csvAggregationMethod"); + if (csvAggregationMethodAttribute != null) { + csvAggregationMethod.setValue(CsvAggregationMethod.valueOf(csvAggregationMethodAttribute)); + } + } + + /** + * Updates form binders + * + * @param measurement + */ + private void updateBinders(Measurement measurement) { + binder.forField(label) + .withValidator(new MeasurableLabelValidator(service, measurement)) + .withValidator(new BeanValidator(Measurement.class, "label")) + .bind(Measurement::getLabel,Measurement::setLabel); + binder.forField(frequency) + .withConverter( + new StringToFrequencyConverter("Not a duration", measurement)) + .bind(Measurement::getFrequency,Measurement::setFrequency); + } + + /** + * Event definition + */ + public static abstract class MeasurementFormEvent extends ComponentEvent { + private final Measurement measurement; + + public MeasurementFormEvent(MeasurementForm source, Measurement measurement) { + super(source, false); + this.measurement = measurement; + } + + public Measurement getMeasurement() { + return measurement; + } + } + + /** + * Save event + */ + public static class SaveEvent extends MeasurementFormEvent { + SaveEvent(MeasurementForm source, Measurement measurement) { + super(source, measurement); + } + } + + /** + * Delete event + */ + public static class DeleteEvent extends MeasurementFormEvent { + DeleteEvent(MeasurementForm source, Measurement measurement) { + super(source, measurement); + } + } + + /** + * Close event + */ + public static class CloseEvent extends MeasurementFormEvent { + CloseEvent(MeasurementForm source) { + super(source, null); + } + } + + /** + * Event listener + * + * @param eventType + * @param listener + * @return + * @param + */ + public > Registration addListener(Class eventType, ComponentEventListener listener) { + return getEventBus().addListener(eventType, listener); + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/form/MetricForm.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/MetricForm.java new file mode 100644 index 0000000..2b82847 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/form/MetricForm.java @@ -0,0 +1,331 @@ +package de.uniregensburg.iamreportingmodule.web.form; + +import com.vaadin.flow.component.*; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.combobox.MultiSelectComboBox; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.textfield.TextArea; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import com.vaadin.flow.data.binder.ValidationException; +import com.vaadin.flow.data.converter.StringToBigDecimalConverter; +import com.vaadin.flow.data.validator.BeanValidator; +import com.vaadin.flow.shared.Registration; +import de.uniregensburg.iamreportingmodule.core.exception.FormulaException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.util.FormulaUtil; +import de.uniregensburg.iamreportingmodule.data.converter.StringToFormulaConverter; +import de.uniregensburg.iamreportingmodule.data.converter.StringToFrequencyConverter; +import de.uniregensburg.iamreportingmodule.data.entity.Unit; +import de.uniregensburg.iamreportingmodule.data.entity.*; +import de.uniregensburg.iamreportingmodule.data.validator.FormulaValidator; +import de.uniregensburg.iamreportingmodule.data.validator.MeasurableLabelValidator; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.view.MainLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Form for editing a metric + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/list/ContactForm.java + * + * @author Julian Bauer + */public class MetricForm extends FormLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private Metric metric; + private final Binder binder = new BeanValidationBinder<>(Metric.class); + private final MeasurableService service; + private final FormulaUtil util; + + private final Button save = new Button("Save"); + private final Button delete = new Button("Delete"); + private final Button cancel = new Button("Cancel"); + private final Button test = new Button("Test formula"); + + private final TextField name = new TextField("Name"); + private final TextField description = new TextField("Description"); + private final TextField label = new TextField("label"); + private final TextArea formula = new TextArea("Formula"); + private final TextField targetValue = new TextField("Target value"); + private final MultiSelectComboBox stakeholders = new MultiSelectComboBox<>("Stakeholders"); + private final MultiSelectComboBox audiences = new MultiSelectComboBox<>("Audiences"); + private final MultiSelectComboBox informationNeeds = new MultiSelectComboBox<>("Information Needs"); + private final ComboBox scale = new ComboBox<>("Scale"); + private final ComboBox unit = new ComboBox<>("Unit"); + private final TextField frequency = new TextField("Frequency"); + + /** + * + * @param scales + * @param units + * @param service + */ + public MetricForm(List scales, List units, MeasurableService service) { + this.service = service; + this.util = new FormulaUtil(service); + init(scales, units); + } + + /** + * Initializes form + * + * @param scales + * @param units + */ + private void init(List scales, List units) { + addClassName("metric-form"); + + // configure form binders + updateBinders(metric); + binder.forField(targetValue) + .withConverter( + new StringToBigDecimalConverter("Not a number")) + .bind(Metric::getTargetValue,Metric::setTargetValue); + binder.bindInstanceFields(this); + + // configure form components + scale.setItems(scales); + unit.setItems(units); + initStakeholders(); + initAudiences(); + initInformationNeeds(); + + // add components to layout + add(name, description, label, formula, targetValue, scale, unit, frequency, stakeholders, audiences, informationNeeds); + } + + /** + * Initializes stakeholders field + */ + private void initStakeholders() { + stakeholders.setItems(service.findAllStakeholders()); + stakeholders.setItemLabelGenerator(Stakeholder::getName); + stakeholders.setPlaceholder("Select stakeholders"); + stakeholders.addSelectionListener(e -> metric.setStakeholders(e.getAllSelectedItems())); + } + + /** + * Initializes audiences fields + */ + private void initAudiences() { + audiences.setItems(service.findAllAudiences()); + audiences.setItemLabelGenerator(Audience::getName); + audiences.setPlaceholder("Select audiences"); + audiences.addSelectionListener(e -> metric.setAudiences(e.getAllSelectedItems())); + } + + /** + * Initializes information needs fields + */ + private void initInformationNeeds() { + informationNeeds.setItems(service.findAllInformationNeeds()); + informationNeeds.setItemLabelGenerator(InformationNeed::getName); + informationNeeds.setPlaceholder("Select information needs"); + informationNeeds.addSelectionListener(e -> metric.setInformationNeeds(e.getAllSelectedItems())); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(delete, cancel, test, save); + + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + + save.addClickShortcut(Key.ENTER); + cancel.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new DeleteEvent(this, metric))); + cancel.addClickListener(event -> fireEvent(new CloseEvent(this))); + test.addClickListener(event -> testFormula(false)); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + } + + /** + * Shows or hides delete button + * + * @param show + */ + public void showDelete(boolean show) { + delete.setVisible(show); + } + + /** + * Tests formula based on form inputs + * + * @param silent hide notifications + * @return + */ + private boolean testFormula(boolean silent) { + logger.info("Testing formula"); + String formulaString = formula.getValue(); + try { + Result result = util.calculate(formulaString); + new SuccessNotification("Calculation result: " + result.getValue().stripTrailingZeros().toPlainString()).open(); + return true; + } catch (FormulaException e) { + logger.info("Formula calculation failed: " + e.getMessage()); + if (!silent) { + new ErrorNotification("Formula calculation failed: " + e.getMessage()).open(); + } + return false; + } + } + + /** + * Validates and saves group + */ + private void validateAndSave() { + if (binder.validate().hasErrors()) { + new ErrorNotification("Form contains errors").open(); + } else if (testFormula(false)) { + try { + binder.writeBean(metric); + fireEvent(new SaveEvent(this, metric)); + } catch (ValidationException e) { + logger.info(e.getMessage()); + } + } + } + + /** + * Fills form based on metric + * + * @param metric + */ + public void setMetric(Metric metric) { + this.metric = metric; + updateBinders(metric); + binder.readBean(metric); + stakeholders.select(metric.getStakeholders()); + audiences.select(metric.getAudiences()); + informationNeeds.select(metric.getInformationNeeds()); + } + + + /** + * Updates form binders + * + * @param metric + */ + private void updateBinders(Metric metric) { + binder.forField(label) + .withValidator(new MeasurableLabelValidator(service, metric)) + .withValidator(new BeanValidator(Metric.class, "label")) + .bind(Metric::getLabel,Metric::setLabel); + + binder.forField(formula) + .withNullRepresentation("") + .withValidator(new FormulaValidator(service)) + .withValidator(new BeanValidator(Metric.class, "formula")) + .withConverter( + new StringToFormulaConverter("Invalid formula", service, metric)) + .bind(Metric::getFormula,Metric::setFormula); + binder.forField(frequency) + .withConverter( + new StringToFrequencyConverter("Not a duration", metric)) + .bind(Metric::getFrequency,Metric::setFrequency); + } + + /** + * Event definition + */ + public static abstract class MetricFormEvent extends ComponentEvent { + private final Metric metric; + + public MetricFormEvent(MetricForm source, Metric metric) { + super(source, false); + this.metric = metric; + } + + public Metric getMetric() { + return metric; + } + } + + /** + * Save event + */ + public static class SaveEvent extends MetricFormEvent { + SaveEvent(MetricForm source, Metric metric) { + super(source, metric); + } + } + + /** + * Delete event + */ + public static class DeleteEvent extends MetricFormEvent { + DeleteEvent(MetricForm source, Metric metric) { + super(source, metric); + } + } + + /** + * Close event + */ + public static class CloseEvent extends MetricFormEvent { + CloseEvent(MetricForm source) { + super(source, null); + } + } + + /** + * Event listener + * + * @param eventType + * @param listener + * @return + * @param + */ + public > Registration addListener(Class eventType, ComponentEventListener listener) { + return getEventBus().addListener(eventType, listener); + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/security/SecurityConfig.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/security/SecurityConfig.java new file mode 100644 index 0000000..ab19f6e --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/security/SecurityConfig.java @@ -0,0 +1,48 @@ +package de.uniregensburg.iamreportingmodule.web.security; + +import com.vaadin.flow.spring.security.VaadinWebSecurity; +import de.uniregensburg.iamreportingmodule.web.view.LoginView; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * Configuration of login security: pages that require no authentication, login page, password encoder + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/security/SecurityConfig.java + * + * @author Julian Bauer + */ +@EnableWebSecurity +@Configuration +public class SecurityConfig extends VaadinWebSecurity { + + /** + * Configures pages that require no authentication and login page + * + * @param http + * @throws Exception + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + // Authorize access to /images/ and /icons/ without authentication + http.authorizeRequests().antMatchers("/images/**", "/icons/**").permitAll(); + // Set default security policy that permits Vaadin internal requests and + // denies all other + super.configure(http); + setLoginView(http, LoginView.class); + } + + /** + * Returns password encoder: bcrypt + * + * @return + */ + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/security/SecurityService.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/security/SecurityService.java new file mode 100644 index 0000000..0abe023 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/security/SecurityService.java @@ -0,0 +1,47 @@ +package de.uniregensburg.iamreportingmodule.web.security; + +import com.vaadin.flow.component.UI; +import com.vaadin.flow.server.VaadinServletRequest; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; +import org.springframework.stereotype.Component; + +/** + * Service for configuring security: login and logout + * + * Source: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/security/SecurityService.java + */ +@Component +public class SecurityService { + private static final String LOGOUT_SUCCESS_URL = "/"; + + /** + * Returns authenticated user + * + * @return + */ + public UserDetails getAuthenticatedUser() { + SecurityContext context = SecurityContextHolder.getContext(); + Object principal = context.getAuthentication().getPrincipal(); + if (principal instanceof UserDetails) { + return (UserDetails) context.getAuthentication().getPrincipal(); + } + // Anonymous or no authentication. + return null; + } + + /** + * Configures logout + * + */ + public void logout() { + UI.getCurrent().getPage().setLocation(LOGOUT_SUCCESS_URL); + SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler(); + logoutHandler.logout( + VaadinServletRequest.getCurrent().getHttpServletRequest(), null, + null); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddAudienceView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddAudienceView.java new file mode 100644 index 0000000..ab65d70 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddAudienceView.java @@ -0,0 +1,92 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.GroupService; +import de.uniregensburg.iamreportingmodule.core.service.UserService; +import de.uniregensburg.iamreportingmodule.data.entity.Audience; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.GroupForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; + +/** + * View for adding audience configuration + * + * @author Julian Bauer + */ +@PageTitle("Add Audience | IAM Reporting Modul") +@Route(value = "audiences/add", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AddAudienceView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final GroupService groupService; + private final UserService userService; + private GroupForm form; + private final Audience audience = new Audience(); + + /** + * + * @param groupService + * @param userService + */ + public AddAudienceView(GroupService groupService, UserService userService) { + this.groupService = groupService; + this.userService = userService; + addClassName("audience-add"); // CSS class name + setSizeFull(); // whole browser size + + // configure form + configureForm(); + + // add form to layout + add(form); + } + + /** + * Configures form + */ + private void configureForm() { + form = new GroupForm(userService); + + form.addListener(GroupForm.SaveEvent.class, this::saveAudience); + form.addListener(GroupForm.CloseEvent.class, this::close); + + form.setGroup(audience); + + form.showDelete(false); // hide delete button + } + + /** + * Handles the save event: saves audience configuration and forwards to overview + * + * @param event + */ + private void saveAudience(GroupForm.SaveEvent event) { + logger.info("Save audience event"); + try { + groupService.saveGroup(event.getGroup()); + new SuccessNotification("Success", "Audience with name " + event.getGroup().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("audiences")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save audience", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(GroupForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("audiences")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddDatabaseDataSourceView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddDatabaseDataSourceView.java new file mode 100644 index 0000000..3855031 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddDatabaseDataSourceView.java @@ -0,0 +1,91 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.DataSourceService; +import de.uniregensburg.iamreportingmodule.data.entity.DatabaseDataSource; +import de.uniregensburg.iamreportingmodule.data.entity.Dbms; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.DatabaseDataSourceForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.List; + +/** + * View for adding database datasource configuration + * + * @author Julian Bauer + */ +@PageTitle("Add database datasource | IAM Reporting Modul") +@Route(value = "datasources/database/add", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AddDatabaseDataSourceView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final List dbmsTypeList = List.of(Dbms.POSTGRESQL); + private final DataSourceService service; + private DatabaseDataSourceForm form; + private final DatabaseDataSource dataSource = new DatabaseDataSource(); + + /** + * + * @param service + */ + public AddDatabaseDataSourceView(DataSourceService service) { + this.service = service; + addClassName("datasource-add"); // CSS class name + setSizeFull(); // whole browser size + + // configure form + configureForm(); + + // add form to layout + add(form); + } + + /** + * Configures form + */ + private void configureForm() { + form = new DatabaseDataSourceForm(dbmsTypeList); + + form.addListener(DatabaseDataSourceForm.SaveEvent.class, this::saveDataSource); + form.addListener(DatabaseDataSourceForm.CloseEvent.class, this::close); + + form.setDataSource(dataSource); + + form.showDelete(false); // hide delete button + } + + /** + * Handles the save event: saves database datasource configuration and forwards to overview + * + * @param event + */ + private void saveDataSource(DatabaseDataSourceForm.SaveEvent event) { + logger.info("Save datasource event"); + try { + service.saveDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save datasource", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(DatabaseDataSourceForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddFileDataSourceView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddFileDataSourceView.java new file mode 100644 index 0000000..6b7adcd --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddFileDataSourceView.java @@ -0,0 +1,86 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.data.entity.FileDataSource; +import de.uniregensburg.iamreportingmodule.core.service.DataSourceService; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.FileDataSourceForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; + +/** + * View for adding file datasource configuration + * + * @author Julian Bauer + */ +@PageTitle("Add file datasource | IAM Reporting Modul") +@Route(value = "datasources/file/add", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AddFileDataSourceView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final DataSourceService service; + private final FileDataSourceForm form = new FileDataSourceForm(); + private final FileDataSource dataSource = new FileDataSource(); + + /** + * + * @param service + */ + public AddFileDataSourceView(DataSourceService service) { + this.service = service; + addClassName("datasource-add"); // CSS class name + setSizeFull(); // whole browser size + + // configure form + configureForm(); + + // add form to layout + add(form); + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(FileDataSourceForm.SaveEvent.class, this::saveDataSource); + form.addListener(FileDataSourceForm.CloseEvent.class, this::close); + + form.setDataSource(dataSource); + + form.showDelete(false); // hide delete button + } + + /** + * Handles the save event: saves file datasource configuration and forwards to overview + * + * @param event + */ + private void saveDataSource(FileDataSourceForm.SaveEvent event) { + logger.info("Save datasource event"); + try { + service.saveDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save datasource", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(FileDataSourceForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddInformationNeedView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddInformationNeedView.java new file mode 100644 index 0000000..03104ea --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddInformationNeedView.java @@ -0,0 +1,86 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.InformationNeedService; +import de.uniregensburg.iamreportingmodule.data.entity.InformationNeed; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.InformationNeedForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; + +/** + * View for adding information need configuration + * + * @author Julian Bauer + */ +@PageTitle("Add Information Need | IAM Reporting Modul") +@Route(value = "informationneeds/add", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AddInformationNeedView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final InformationNeedService informationNeedService; + private final InformationNeedForm form = new InformationNeedForm(); + private final InformationNeed informationNeed = new InformationNeed(); + + /** + * + * @param informationNeedService + */ + public AddInformationNeedView(InformationNeedService informationNeedService) { + this.informationNeedService = informationNeedService; + addClassName("informationneed-add"); // CSS class name + setSizeFull(); // whole browser size + + // configure form + configureForm(); + + // add form to layout + add(form); + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(InformationNeedForm.SaveEvent.class, this::saveInformationNeed); + form.addListener(InformationNeedForm.CloseEvent.class, this::close); + + form.setInformationNeed(informationNeed); + + form.showDelete(false); // hide delete button + } + + /** + * Handles the save event: saves information need configuration and forwards to overview + * + * @param event + */ + private void saveInformationNeed(InformationNeedForm.SaveEvent event) { + logger.info("Save information need event"); + try { + informationNeedService.saveInformationNeed(event.getInformationNeed()); + new SuccessNotification("Success", "Information need with name " + event.getInformationNeed().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("informationneeds")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save information need", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(InformationNeedForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("informationneeds")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddManualDataSourceView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddManualDataSourceView.java new file mode 100644 index 0000000..b2d9915 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddManualDataSourceView.java @@ -0,0 +1,86 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.DataSourceService; +import de.uniregensburg.iamreportingmodule.data.entity.ManualDataSource; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.ManualDataSourceForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; + +/** + * View for adding manual datasource configuration + * + * @author Julian Bauer + */ +@PageTitle("Add manual datasource | IAM Reporting Modul") +@Route(value = "datasources/manual/add", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AddManualDataSourceView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final DataSourceService service; + private final ManualDataSourceForm form = new ManualDataSourceForm(); + private final ManualDataSource dataSource = new ManualDataSource(); + + /** + * + * @param service + */ + public AddManualDataSourceView(DataSourceService service) { + this.service = service; + addClassName("datasource-add"); // CSS class name + setSizeFull(); // whole browser size + + // configure form + configureForm(); + + // add form to layout + add(form); + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(ManualDataSourceForm.SaveEvent.class, this::saveDataSource); + form.addListener(ManualDataSourceForm.CloseEvent.class, this::close); + + form.setDataSource(dataSource); + + form.showDelete(false); // hide delete button + } + + /** + * Handles the save event: saves manual datasource configuration and forwards to overview + * + * @param event + */ + private void saveDataSource(ManualDataSourceForm.SaveEvent event) { + logger.info("Save datasource event"); + try { + service.saveDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save datasource", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(ManualDataSourceForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddMeasurementView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddMeasurementView.java new file mode 100644 index 0000000..ec05285 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddMeasurementView.java @@ -0,0 +1,94 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.data.entity.Measurement; +import de.uniregensburg.iamreportingmodule.data.entity.Scale; +import de.uniregensburg.iamreportingmodule.data.entity.Unit; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.MeasurementForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.Arrays; +import java.util.List; + +/** + * View for adding measurement configuration + * + * @author Julian Bauer + */ +@PageTitle("Add Measurement | IAM Reporting Modul") +@Route(value = "measurements/add", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AddMeasurementView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final MeasurableService service; + private MeasurementForm form; + private final Measurement measurement = new Measurement(); + + /** + * + * @param service + */ + public AddMeasurementView(MeasurableService service) { + this.service = service; + addClassName("measurement-add"); // CSS class name + setSizeFull(); // whole browser size + + // configure form + configureForm(); + + // add form to layout + add(form); + } + + /** + * Configures form + */ + private void configureForm() { + List scales = Arrays.asList(Scale.values()); + List units = Arrays.asList(Unit.values()); + form = new MeasurementForm(scales, units, service); + + form.addListener(MeasurementForm.SaveEvent.class, this::saveMeasurement); + form.addListener(MeasurementForm.CloseEvent.class, this::close); + + form.setMeasurement(measurement); + + form.showDelete(false); // hide delete button + } + + /** + * Handles the save event: saves measurement configuration and forwards to overview + * + * @param event + */ + private void saveMeasurement(MeasurementForm.SaveEvent event) { + logger.info("Save measurement event"); + try { + service.saveMeasurement(event.getMeasurement()); + new SuccessNotification("Success", "Measurement with name " + event.getMeasurement().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("measurements")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save measurement", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(MeasurementForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("measurements")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddMetricView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddMetricView.java new file mode 100644 index 0000000..7c1051e --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddMetricView.java @@ -0,0 +1,94 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.data.entity.Metric; +import de.uniregensburg.iamreportingmodule.data.entity.Scale; +import de.uniregensburg.iamreportingmodule.data.entity.Unit; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.MetricForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.Arrays; +import java.util.List; + +/** + * View for adding metric configuration + * + * @author Julian Bauer + */ +@PageTitle("Add Metric | IAM Reporting Modul") +@Route(value = "metrics/add", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AddMetricView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final MeasurableService service; + private MetricForm form; + private final Metric metric = new Metric(); + + /** + * + * @param service + */ + public AddMetricView(MeasurableService service) { + this.service = service; + addClassName("metric-add"); // CSS class name + setSizeFull(); // whole browser size + + // configure form + configureForm(); + + // add form to layout + add(form); + } + + /** + * Configures form + */ + private void configureForm() { + List scales = Arrays.asList(Scale.values()); + List units = Arrays.asList(Unit.values()); + form = new MetricForm(scales, units, service); + + form.addListener(MetricForm.SaveEvent.class, this::saveMetric); + form.addListener(MetricForm.CloseEvent.class, this::close); + + form.setMetric(metric); + + form.showDelete(false); // hide delete button + } + + /** + * Handles the save event: saves metric configuration and forwards to overview + * + * @param event + */ + private void saveMetric(MetricForm.SaveEvent event) { + logger.info("Save metric event"); + try { + service.saveMetric(event.getMetric()); + new SuccessNotification("Success", "Metric with name " + event.getMetric().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("metrics")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save metric", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(MetricForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("metrics")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddStakeholderView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddStakeholderView.java new file mode 100644 index 0000000..a8a0597 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AddStakeholderView.java @@ -0,0 +1,92 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.data.entity.Stakeholder; +import de.uniregensburg.iamreportingmodule.core.service.GroupService; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.UserService; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.GroupForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; + +/** + * View for adding stakeholder configuration + * + * @author Julian Bauer + */ +@PageTitle("Add Stakeholder | IAM Reporting Modul") +@Route(value = "stakeholders/add", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AddStakeholderView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final GroupService groupService; + private final UserService userService; + private GroupForm form; + private final Stakeholder stakeholder = new Stakeholder(); + + /** + * + * @param groupService + * @param userService + */ + public AddStakeholderView(GroupService groupService, UserService userService) { + this.groupService = groupService; + this.userService = userService; + addClassName("stakeholder-add"); // CSS class name + setSizeFull(); // whole browser size + + // configure form + configureForm(); + + // add form to layout + add(form); + } + + /** + * Configures form + */ + private void configureForm() { + form = new GroupForm(userService); + + form.addListener(GroupForm.SaveEvent.class, this::saveStakeholder); + form.addListener(GroupForm.CloseEvent.class, this::close); + + form.setGroup(stakeholder); + + form.showDelete(false); // hide delete button + } + + /** + * Handles the save event: saves stakeholder configuration and forwards to overview + * + * @param event + */ + private void saveStakeholder(GroupForm.SaveEvent event) { + logger.info("Save stakeholder event"); + try { + groupService.saveGroup(event.getGroup()); + new SuccessNotification("Success", "Stakeholder with name " + event.getGroup().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("stakeholders")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save stakeholder", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(GroupForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("stakeholders")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AudiencesView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AudiencesView.java new file mode 100644 index 0000000..6d8ac6a --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/AudiencesView.java @@ -0,0 +1,131 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.AttachEvent; +import com.vaadin.flow.component.DetachEvent; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.service.GroupService; +import de.uniregensburg.iamreportingmodule.data.entity.Audience; +import de.uniregensburg.iamreportingmodule.data.entity.User; + +import javax.annotation.security.RolesAllowed; +import java.util.stream.Collectors; + +/** + * View for displaying all audience configurations + * + * @author Julian Bauer + */ +@PageTitle("Audiences | IAM Reporting Modul") +@Route(value = "audiences", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class AudiencesView extends VerticalLayout { + + private final Grid grid = new Grid<>(Audience.class); + private final GroupService service; + + private final Button addButton = new Button("Add audience"); // add button + + /** + * + * @param service + */ + public AudiencesView(GroupService service) { + this.service = service; + addClassName("audience-view"); // CSS class name + setSizeFull(); // whole browser size + + configureGrid(); // configure grid + + add(grid); // add grid to view + + updateList(); // update data + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.addClassName("audience-grid"); // set css class name + grid.setSizeFull(); // use full size available + grid.setColumns("name"); // set primitive columns: name + grid.addColumn(audience -> audience.getMembers().stream().map(User::getFullName).collect(Collectors.joining(", "))).setHeader("Members"); // set complex column: members + + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + + grid.asSingleSelect().addValueChangeListener(e -> editAudience(e.getValue())); + } + + /** + * Updates list of items + */ + private void updateList() { + grid.setItems(service.findAllAudiences()); + } + + /** + * Forwards to page for adding audience configuration + */ + private void addAudience() { + getUI().ifPresent(ui -> ui.navigate("audiences/add")); + } + + /** + * Forwards to page for editing audience configuration + * + * @param audience + */ + private void editAudience(Audience audience) { + getUI().ifPresent(ui -> ui.navigate("audiences/edit/" + audience.getId())); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(addButton); + + addButton.addClickListener(e -> addAudience()); // button action + addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); // primary button + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/DashboardView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/DashboardView.java new file mode 100644 index 0000000..7ac58cb --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/DashboardView.java @@ -0,0 +1,234 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.*; +import com.vaadin.flow.theme.lumo.LumoUtility; +import de.uniregensburg.iamreportingmodule.core.service.GroupService; +import de.uniregensburg.iamreportingmodule.core.service.InformationNeedService; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.service.UserService; +import de.uniregensburg.iamreportingmodule.data.entity.*; +import de.uniregensburg.iamreportingmodule.web.component.dashboard.Indicator; +import de.uniregensburg.iamreportingmodule.web.security.SecurityService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.userdetails.UserDetails; +import org.vaadin.addons.tatu.GridLayout; + +import javax.annotation.security.PermitAll; +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * View for displaying report + * + * @author Julian Bauer + */ +@PageTitle("Dashboard | IAM Reporting Modul") +@Route(value = "dashboard", layout = MainLayout.class) +@RouteAlias(value = "", layout = MainLayout.class) +@PermitAll +public class DashboardView extends VerticalLayout implements HasUrlParameter { + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final MeasurableService measurableService; + private final InformationNeedService informationNeedService; + private final GridLayout gridLayout = new GridLayout(); + private final Set audiences; + private final ComboBox informationNeedList = new ComboBox<>("Information Need"); + private final Text warningText = new Text("No information need selected"); + private final Div warning = new Div(); + + /** + * + * @param measurableService + * @param securityService + * @param groupService + * @param userService + * @param informationNeedService + */ + public DashboardView(MeasurableService measurableService, SecurityService securityService, GroupService groupService, UserService userService, InformationNeedService informationNeedService) { + this.measurableService = measurableService; + this.informationNeedService = informationNeedService; + + setSizeFull(); // use full size + + UserDetails userDetails = securityService.getAuthenticatedUser(); + String username = userDetails.getUsername(); + User user = userService.findUserByUsername(username); + audiences = new HashSet<>(groupService.findAudiencesByMember(user)); + + addClassName("dashboard"); + + configureWarning(); + + Div gridRoot = new Div(); + gridRoot.addClassName("grid-root"); + gridRoot.addClassName(LumoUtility.Position.RELATIVE); + gridRoot.setSizeFull(); + + gridRoot.add(getGridLayout(), warning); + + add(getToolbar(), gridRoot); + } + + /** + * Configures grid layout + * + * @return + */ + private Component getGridLayout() { + logger.info("Initializing grid layout"); + + gridLayout.setSizeFull(); + gridLayout.setGap(GridLayout.Gap.LARGE); + gridLayout.setJustify(GridLayout.Justify.EVENLY); + gridLayout.setAlign(GridLayout.Align.START); + gridLayout.setOrientation(GridLayout.Orientation.BY_COLUMNS,3); + gridLayout.addClassName(LumoUtility.Position.ABSOLUTE); + gridLayout.getStyle().set("top", "0px"); + gridLayout.getStyle().set("left", "0px"); + + return gridLayout; + } + + /** + * Configures warning + * + */ + private void configureWarning() { + warning.addClassName("warning"); + warning.addClassName(LumoUtility.JustifyContent.CENTER); + warning.addClassName(LumoUtility.AlignItems.CENTER); + warning.addClassName(LumoUtility.FontSize.XXLARGE); + warning.setSizeFull(); + warning.addClassName(LumoUtility.Position.ABSOLUTE); + warning.getStyle().set("top", "0px"); + warning.getStyle().set("left", "0px"); + warning.addClassName(LumoUtility.Display.FLEX); + warning.add(warningText); + } + + /** + * Configures and returns toolbar + * + * @return + */ + private Component getToolbar() { + logger.info("Initializing toolbar"); + + informationNeedList.setItems(informationNeedService.findAllInformationNeeds()); + informationNeedList.addValueChangeListener(value -> { + updateIndicators(value.getValue()); + updateQueryParameters(value.getValue()); + }); + informationNeedList.setPlaceholder("Select information need"); + + HorizontalLayout toolbar = new HorizontalLayout(informationNeedList); // horizontal layout + toolbar.addClassName("toolbar"); // set css class name + + return toolbar; + } + + /** + * Updates indicators + * + * @param informationNeed + */ + private void updateIndicators(InformationNeed informationNeed) { + logger.info("Updating indicators"); + gridLayout.removeAll(); + if (informationNeed == null) { + logger.info("Information need null"); + warningText.setText("Information need is null"); + warning.removeClassName(LumoUtility.Display.HIDDEN); + return; + } + logger.info("Information need: " + informationNeed.getName()); + if (audiences.isEmpty()) { + logger.info("User is not part of any audiences"); + warningText.setText("You are not part of any audiences"); + warning.removeClassName(LumoUtility.Display.HIDDEN); + return; + } + logger.info("Audiences: " + audiences.stream().map(Audience::getName).collect(Collectors.joining(", "))); + List metrics = measurableService.findMetricsByInformationNeedAndAudiences(informationNeed, audiences); + if (metrics.isEmpty()) { + logger.info("No metrics found"); + warningText.setText("No metrics found"); + warning.removeClassName(LumoUtility.Display.HIDDEN); + return; + } + Set metricSet = new HashSet<>(metrics); // remove duplicates + warning.addClassName(LumoUtility.Display.HIDDEN); + for (Metric metric : metricSet) { + Result result = measurableService.findLatestResultByMeasurable(metric); + Indicator indicator = new Indicator(); + indicator.setTitle(metric.getName()); + if (metric.getUnit() != null) { + indicator.setUnit(metric.getUnit().toString()); + } + indicator.setLink("/results/" + metric.getId()); + if (result == null) { + indicator.setValue("null"); + } else { + BigDecimal resultValue = result.getValue();; + if (metric.getUnit() != null) { + if (Unit.PERCENT.equals(metric.getUnit())) { + resultValue = resultValue.multiply(BigDecimal.valueOf(100)); + } + } + indicator.setValue(resultValue.stripTrailingZeros().toPlainString()); + } + gridLayout.add(indicator); + } + } + + /** + * Updates query parameter based on currently selected information need + * + * @param informationNeed + */ + private void updateQueryParameters(InformationNeed informationNeed) { + String deepLinkingUrl = RouteConfiguration.forSessionScope() + .getUrl(getClass(), informationNeed.getId().toString()); + // Assign the full deep linking URL directly using + // History object: changes the URL in the browser, + // but doesn't reload the page. + if (getUI().isPresent()) { + getUI().get().getPage().getHistory() + .replaceState(null, deepLinkingUrl); + } + } + + /** + * Searches for url parameter id and starts indicator update + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, @OptionalParameter String id) { + if (id == null) { + return; + } + logger.info("Searching information need with id " + id); + try { + InformationNeed informationNeed = informationNeedService.findInformationNeedById(UUID.fromString(id)); + informationNeedList.setValue(informationNeed); + updateIndicators(informationNeed); + } catch (IllegalArgumentException e) { + logger.info("Error finding measurable"); + logger.info(e.getMessage()); + } + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/DataSourcesView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/DataSourcesView.java new file mode 100644 index 0000000..611b64f --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/DataSourcesView.java @@ -0,0 +1,196 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.AttachEvent; +import com.vaadin.flow.component.DetachEvent; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.dialog.Dialog; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.orderedlayout.FlexComponent; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.service.DataSourceService; +import de.uniregensburg.iamreportingmodule.data.entity.DataSource; +import de.uniregensburg.iamreportingmodule.data.entity.DataSourceType; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; + +/** + * View for displaying all datasource configurations + * + * @author Julian Bauer + */ +@PageTitle("Datasources | IAM Reporting Modul") +@Route(value = "datasources", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class DataSourcesView extends VerticalLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final Grid grid = new Grid<>(DataSource.class); + private final DataSourceService service; + + private final Button addButton = new Button("Add datasource"); // add button + + /** + * + * @param service + */ + public DataSourcesView(DataSourceService service) { + this.service = service; + addClassName("datasource-view"); // CSS class name + setSizeFull(); // whole browser size + + configureGrid(); // configure grid + + add(grid); // add grid to view + + updateList(); // update data + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.addClassName("datasource-grid"); // set css class name + grid.setSizeFull(); // use full size available + grid.setColumns("name"); // set primitiv columns: name + grid.addColumn(DataSource::getType).setHeader("Type"); + grid.addColumn(dataSource -> { + if (dataSource.getMeasurements() == null) { + return 0; + } + return dataSource.getMeasurements().size(); + }).setHeader("Measurements"); + + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + + grid.asSingleSelect().addValueChangeListener(e -> editDataSource(e.getValue())); + } + + /** + * Updates list of items + */ + private void updateList() { + grid.setItems(service.findAllDataSources()); + } + + /** + * Forwards to page for adding datasource configuration after selection of type of datasource + */ + private void addDataSource() { + logger.info("New datasource"); + + Dialog dialog = new Dialog(); + dialog.setHeaderTitle("New datasource"); + + ComboBox type = new ComboBox<>("Type"); + type.setItems(DataSourceType.MANUAL, DataSourceType.DATABASE, DataSourceType.FILE); + type.setPlaceholder("Select type"); + + VerticalLayout dialogLayout = new VerticalLayout(type); + dialogLayout.setPadding(false); + dialogLayout.setSpacing(false); + dialogLayout.setAlignItems(FlexComponent.Alignment.STRETCH); + dialogLayout.getStyle().set("width", "18rem").set("max-width", "100%"); + + dialog.add(dialogLayout); + + Button confirmButton = new Button("Add", e -> { + if (type.getValue() == null) { + new ErrorNotification("No type selected").open(); + } else { + if (type.getValue().equals(DataSourceType.MANUAL)) { + dialog.close(); + getUI().ifPresent(ui -> ui.navigate("datasources/manual/add")); + } else if (type.getValue().equals(DataSourceType.DATABASE)) { + dialog.close(); + getUI().ifPresent(ui -> ui.navigate("datasources/database/add")); + } else if (type.getValue().equals(DataSourceType.FILE)) { + dialog.close(); + getUI().ifPresent(ui -> ui.navigate("datasources/file/add")); + } else { + new ErrorNotification("Not implemented yet").open(); + } + } + }); + confirmButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + Button cancelButton = new Button("Cancel", e -> { + dialog.close(); + logger.info("Creation canceled"); + }); + + dialog.getFooter().add(cancelButton); + dialog.getFooter().add(confirmButton); + + dialog.open(); + } + + /** + * Forwards to page for editing datasource configuration + * + * @param dataSource + */ + private void editDataSource(DataSource dataSource) { + DataSourceType type = dataSource.getType(); + if (type.equals(DataSourceType.MANUAL)) { + getUI().ifPresent(ui -> ui.navigate("datasources/manual/edit/" + dataSource.getId())); + } else if (type.equals(DataSourceType.DATABASE)) { + getUI().ifPresent(ui -> ui.navigate("datasources/database/edit/" + dataSource.getId())); + } else if (type.equals(DataSourceType.FILE)) { + getUI().ifPresent(ui -> ui.navigate("datasources/file/edit/" + dataSource.getId())); + } else { + new ErrorNotification("Not implemented yet").open(); + } + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(addButton); + + addButton.addClickListener(e -> addDataSource()); // button action + addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); // primary button + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditAudienceView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditAudienceView.java new file mode 100644 index 0000000..248342f --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditAudienceView.java @@ -0,0 +1,145 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.confirmdialog.ConfirmDialog; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.GroupService; +import de.uniregensburg.iamreportingmodule.core.service.UserService; +import de.uniregensburg.iamreportingmodule.data.entity.Audience; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.GroupForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.UUID; + +/** + * View for editing audience configuration + * + * @author Julian Bauer + */ +@PageTitle("Edit Audience | IAM Reporting Modul") +@Route(value = "audiences/edit", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class EditAudienceView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private Audience audience = null; + private final GroupForm form; + private String id; + + private final GroupService groupService; + + /** + * + * @param groupService + * @param userService + */ + public EditAudienceView(GroupService groupService, UserService userService) { + this.groupService = groupService; + form = new GroupForm(userService); + addClassName("audience-edit"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view + */ + private void init() { + if (audience == null) { + logger.info("Audience is null"); + add(new Text("Cannot find audience with id " + id)); + } else { + configureForm(); + add(form); + } + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(GroupForm.SaveEvent.class, this::saveAudience); + form.addListener(GroupForm.CloseEvent.class, this::close); + form.addListener(GroupForm.DeleteEvent.class, this::deleteAudience); + + form.setGroup(audience); + } + + /** + * Searches for url parameter id and sets audience configuration + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching audience with id " + id); + try { + audience = groupService.findAudienceById(UUID.fromString(id)); + } catch (IllegalArgumentException e) { + logger.info("Error finding audience"); + logger.info(e.getMessage()); + } + init(); + } + + /** + * Handles the save event: saves audience configuration and forwards to overview + * + * @param event + */ + private void saveAudience(GroupForm.SaveEvent event) { + logger.info("Save audience event"); + try { + groupService.saveGroup(event.getGroup()); + new SuccessNotification("Success", "Audience with name " + event.getGroup().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("audiences")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save audience", e.getMessage()).open(); + } + } + + /** + * Handles the delete event: shows confirmation dialog, deletes audience configuration and forwards to overview + * + * @param event + */ + private void deleteAudience(GroupForm.DeleteEvent event) { + logger.info("Delete audience event"); + ConfirmDialog dialog = new ConfirmDialog(); + dialog.setHeader("Delete audience"); + dialog.setText("Are you sure you want to delete audience " + audience.getName() + "?"); + dialog.setCancelable(true); + dialog.addConfirmListener(e -> { + try { + groupService.deleteGroup(event.getGroup()); + new SuccessNotification("Success", "Datasource with name " + event.getGroup().getName() + " deleted successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("audiences")); + } catch (DeleteEntityException ex) { + new ErrorNotification("Cannot delete audience", ex.getMessage()).open(); + } + }); + dialog.addCancelListener(e -> logger.info("Deletion canceled")); + dialog.open(); + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(GroupForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("audiences")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditDatabaseDataSourceView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditDatabaseDataSourceView.java new file mode 100644 index 0000000..a24337e --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditDatabaseDataSourceView.java @@ -0,0 +1,145 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.confirmdialog.ConfirmDialog; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.DataSourceService; +import de.uniregensburg.iamreportingmodule.data.entity.DatabaseDataSource; +import de.uniregensburg.iamreportingmodule.data.entity.Dbms; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.DatabaseDataSourceForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.List; +import java.util.UUID; + +/** + * View for editing database datasource configuration + * + * @author Julian Bauer + */ +@PageTitle("Edit database datasource | IAM Reporting Modul") +@Route(value = "datasources/database/edit", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class EditDatabaseDataSourceView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final List dbmsTypeList = List.of(Dbms.POSTGRESQL); + private final DataSourceService service; + private final DatabaseDataSourceForm form = new DatabaseDataSourceForm(dbmsTypeList); + private DatabaseDataSource dataSource = null; + private String id; + + /** + * + * @param service + */ + public EditDatabaseDataSourceView(DataSourceService service) { + this.service = service; + addClassName("datasource-edit"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view + */ + private void init() { + if (dataSource == null) { + logger.info("Data Source is null"); + add(new Text("Cannot find datasource with id " + id)); + } else { + configureForm(); + add(form); + } + } + + /** + * Searches for url parameter id and sets database datasource configuration + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching manual datasource id " + id); + try { + dataSource = service.findDatabaseDataSourceById(UUID.fromString(id)); + } catch (IllegalArgumentException e) { + logger.info("Error finding manual datasource"); + logger.info(e.getMessage()); + } + init(); + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(DatabaseDataSourceForm.SaveEvent.class, this::saveDataSource); + form.addListener(DatabaseDataSourceForm.CloseEvent.class, this::close); + form.addListener(DatabaseDataSourceForm.DeleteEvent.class, this::deleteDataSource); + + form.setDataSource(dataSource); + } + + /** + * Handles the save event: saves database datasource configuration and forwards to overview + * + * @param event + */ + private void saveDataSource(DatabaseDataSourceForm.SaveEvent event) { + logger.info("Save datasource event"); + try { + service.saveDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save datasource", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(DatabaseDataSourceForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } + + /** + * Handles the delete event: shows confirmation dialog, deletes database datasource configuration and + * forwards to overview + * + * @param event + */ + private void deleteDataSource(DatabaseDataSourceForm.DeleteEvent event) { + logger.info("Delete database datasource event"); + ConfirmDialog dialog = new ConfirmDialog(); + dialog.setHeader("Delete datasource"); + dialog.setText("Are you sure you want to delete datasource " + dataSource.getName() + "?"); + dialog.setCancelable(true); + dialog.addConfirmListener(e -> {try { + service.deleteDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " deleted successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (DeleteEntityException ex) { + new ErrorNotification("Cannot delete datasource", ex.getMessage()).open(); + } + }); + dialog.addCancelListener(e -> logger.info("Deletion canceled")); + dialog.open(); + } +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditFileDataSourceView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditFileDataSourceView.java new file mode 100644 index 0000000..b67ff12 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditFileDataSourceView.java @@ -0,0 +1,142 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.confirmdialog.ConfirmDialog; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.DataSourceService; +import de.uniregensburg.iamreportingmodule.data.entity.FileDataSource; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.FileDataSourceForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.UUID; + +/** + * View for editing file datasource configuration + * + * @author Julian Bauer + */ +@PageTitle("Edit file datasource | IAM Reporting Modul") +@Route(value = "datasources/file/edit", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class EditFileDataSourceView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final DataSourceService service; + private final FileDataSourceForm form = new FileDataSourceForm(); + private FileDataSource dataSource = null; + private String id; + + /** + * + * @param service + */ + public EditFileDataSourceView(DataSourceService service) { + this.service = service; + addClassName("datasource-add"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view + */ + private void init() { + if (dataSource == null) { + logger.info("Data Source is null"); + add(new Text("Cannot find datasource with id " + id)); + } else { + configureForm(); + add(form); + } + } + + /** + * Searches for url parameter id and sets file datasource configuration + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching file datasource id " + id); + try { + dataSource = service.findFileDataSourceById(UUID.fromString(id)); + } catch (IllegalArgumentException e) { + logger.info("Error finding file datasource"); + logger.info(e.getMessage()); + } + init(); + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(FileDataSourceForm.SaveEvent.class, this::saveDataSource); + form.addListener(FileDataSourceForm.CloseEvent.class, this::close); + form.addListener(FileDataSourceForm.DeleteEvent.class, this::deleteDataSource); + + form.setDataSource(dataSource); + } + + /** + * Handles the save event: saves file datasource configuration and forwards to overview + * + * @param event + */ + private void saveDataSource(FileDataSourceForm.SaveEvent event) { + logger.info("Save datasource event"); + try { + service.saveDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save datasource", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(FileDataSourceForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } + + /** + * Handles the delete event: shows confirmation dialog, deletes file datasource configuration and + * forwards to overview + * + * @param event + */ + private void deleteDataSource(FileDataSourceForm.DeleteEvent event) { + logger.info("Delete file datasource event"); + ConfirmDialog dialog = new ConfirmDialog(); + dialog.setHeader("Delete datasource"); + dialog.setText("Are you sure you want to delete file source " + dataSource.getName() + "?"); + dialog.setCancelable(true); + dialog.addConfirmListener(e -> {try { + service.deleteDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " deleted successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (DeleteEntityException ex) { + new ErrorNotification("Cannot delete datasource", ex.getMessage()).open(); + } + }); + dialog.addCancelListener(e -> logger.info("Deletion canceled")); + dialog.open(); + } +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditInformationNeedView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditInformationNeedView.java new file mode 100644 index 0000000..f0c7371 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditInformationNeedView.java @@ -0,0 +1,142 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.confirmdialog.ConfirmDialog; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.InformationNeedService; +import de.uniregensburg.iamreportingmodule.data.entity.InformationNeed; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.InformationNeedForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.UUID; + +/** + * View for editing information need configuration + * + * @author Julian Bauer + */ +@PageTitle("Edit Information Need | IAM Reporting Modul") +@Route(value = "informationneeds/edit", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class EditInformationNeedView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private InformationNeed informationNeed = null; + private final InformationNeedForm form = new InformationNeedForm(); + private String id; + private final InformationNeedService informationNeedService; + + /** + * + * @param informationNeedService + */ + public EditInformationNeedView(InformationNeedService informationNeedService) { + this.informationNeedService = informationNeedService; + addClassName("informationneed-edit"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view + */ + private void init() { + if (informationNeed == null) { + logger.info("Information need is null"); + add(new Text("Cannot find information need with id " + id)); + } else { + configureForm(); + add(form); + } + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(InformationNeedForm.SaveEvent.class, this::saveInformationNeed); + form.addListener(InformationNeedForm.CloseEvent.class, this::close); + form.addListener(InformationNeedForm.DeleteEvent.class, this::deleteInformationNeed); + + form.setInformationNeed(informationNeed); + } + + /** + * Searches for url parameter id and sets audience configuration + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching information need with id " + id); + try { + informationNeed = informationNeedService.findInformationNeedById(UUID.fromString(id)); + } catch (IllegalArgumentException e) { + logger.info("Error finding information need"); + logger.info(e.getMessage()); + } + init(); + } + + /** + * Handles the save event: saves information need configuration and forwards to overview + * + * @param event + */ + private void saveInformationNeed(InformationNeedForm.SaveEvent event) { + logger.info("Save information need event"); + try { + informationNeedService.saveInformationNeed(event.getInformationNeed()); + new SuccessNotification("Success", "Information need with name " + event.getInformationNeed().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("informationneeds")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save information need", e.getMessage()).open(); + } + } + + /** + * Handles the delete event: shows confirmation dialog, deletes information need configuration and + * forwards to overview + * + * @param event + */ + private void deleteInformationNeed(InformationNeedForm.DeleteEvent event) { + logger.info("Delete information need event"); + ConfirmDialog dialog = new ConfirmDialog(); + dialog.setHeader("Delete information need"); + dialog.setText("Are you sure you want to delete information need " + informationNeed.getName() + "?"); + dialog.setCancelable(true); + dialog.addConfirmListener(e -> { + try { + informationNeedService.deleteInformationNeed(event.getInformationNeed()); + new SuccessNotification("Success", "Information need with name " + event.getInformationNeed().getName() + " deleted successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("informationneeds")); + } catch (DeleteEntityException ex) { + new ErrorNotification("Cannot delete information need", ex.getMessage()).open(); + } + }); + dialog.addCancelListener(e -> logger.info("Deletion canceled")); + dialog.open(); + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(InformationNeedForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("informationneeds")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditManualDataSourceView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditManualDataSourceView.java new file mode 100644 index 0000000..0e2aa7d --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditManualDataSourceView.java @@ -0,0 +1,142 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.confirmdialog.ConfirmDialog; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.data.entity.ManualDataSource; +import de.uniregensburg.iamreportingmodule.core.service.DataSourceService; +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.ManualDataSourceForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.UUID; + +/** + * View for editing manual datasource configuration + * + * @author Julian Bauer + */ +@PageTitle("Edit manual datasource | IAM Reporting Modul") +@Route(value = "datasources/manual/edit", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class EditManualDataSourceView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final DataSourceService service; + private final ManualDataSourceForm form = new ManualDataSourceForm(); + private ManualDataSource dataSource = null; + private String id; + + /** + * + * @param service + */ + public EditManualDataSourceView(DataSourceService service) { + this.service = service; + addClassName("datasource-edit"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view + */ + private void init() { + if (dataSource == null) { + logger.info("Data Source is null"); + add(new Text("Cannot find datasource with id " + id)); + } else { + configureForm(); + add(form); + } + } + + /** + * Searches for url parameter id and sets audience configuration + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching manual datasource id " + id); + try { + dataSource = service.findManualDataSourceById(UUID.fromString(id)); + } catch (IllegalArgumentException e) { + logger.info("Error finding manual datasource"); + logger.info(e.getMessage()); + } + init(); + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(ManualDataSourceForm.SaveEvent.class, this::saveDataSource); + form.addListener(ManualDataSourceForm.CloseEvent.class, this::close); + form.addListener(ManualDataSourceForm.DeleteEvent.class, this::deleteDataSource); + + form.setDataSource(dataSource); + } + + /** + * Handles the save event: saves manual datasource configuration and forwards to overview + * + * @param event + */ + private void saveDataSource(ManualDataSourceForm.SaveEvent event) { + logger.info("Save datasource event"); + try { + service.saveDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save datasource", e.getMessage()).open(); + } + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(ManualDataSourceForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } + + /** + * Handles the delete event: shows confirmation dialog, deletes manual datasource configuration and + * forwards to overview + * + * @param event + */ + private void deleteDataSource(ManualDataSourceForm.DeleteEvent event) { + logger.info("Delete manual datasource event"); + ConfirmDialog dialog = new ConfirmDialog(); + dialog.setHeader("Delete datasource"); + dialog.setText("Are you sure you want to delete datasource " + dataSource.getName() + "?"); + dialog.setCancelable(true); + dialog.addConfirmListener(e -> {try { + service.deleteDataSource(event.getDataSource()); + new SuccessNotification("Success", "Datasource with name " + event.getDataSource().getName() + " deleted successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("datasources")); + } catch (DeleteEntityException ex) { + new ErrorNotification("Cannot delete datasource", ex.getMessage()).open(); + } + }); + dialog.addCancelListener(e -> logger.info("Deletion canceled")); + dialog.open(); + } +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditMeasurementView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditMeasurementView.java new file mode 100644 index 0000000..79e79ea --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditMeasurementView.java @@ -0,0 +1,225 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.confirmdialog.ConfirmDialog; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.grid.GridSortOrder; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.H2; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.data.provider.SortDirection; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.theme.lumo.LumoUtility; +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.data.entity.Measurement; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import de.uniregensburg.iamreportingmodule.data.entity.Scale; +import de.uniregensburg.iamreportingmodule.data.entity.Unit; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.MeasurementForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +/** + * View for editing measurement configuration + * + * @author Julian Bauer + */ +@PageTitle("Edit Measurement | IAM Reporting Modul") +@Route(value = "measurements/edit", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class EditMeasurementView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private Measurement measurement = null; + private MeasurementForm form; + private String id; + private final MeasurableService service; + private final Grid grid = new Grid<>(Result.class); + private final Text warningText = new Text("There is no data to display"); + private final Div warning = new Div(); + + /** + * + * @param service + */ + public EditMeasurementView(MeasurableService service) { + this.service = service; + addClassName("measurement-edit"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view + */ + private void init() { + if (measurement == null) { + logger.info("Measurement is null"); + add(new Text("Cannot find measurement with id " + id)); + } else { + configureForm(); + configureGrid(); + configureWarning(); + + H2 formHeading = new H2("Form"); + H2 gridHeading = new H2("Latest ten results"); + + Div gridRoot = new Div(); + gridRoot.addClassName("grid-root"); + gridRoot.addClassName(LumoUtility.Position.RELATIVE); + gridRoot.setSizeFull(); + + gridRoot.add(grid, warning); + + add(formHeading, form, gridHeading, gridRoot); + updateResults(); + } + } + + /** + * Updates results + */ + private void updateResults() { + List results = service.findFirst10ResultsByMeasurableOrderByPointInTimeDesc(measurement); + logger.info("Results: " + results.size()); + grid.setItems(results); + if (results.isEmpty()) { + warning.removeClassName(LumoUtility.Display.HIDDEN); + } else { + warning.addClassName(LumoUtility.Display.HIDDEN); + } + } + + /** + * Configures warning + */ + private void configureWarning() { + warning.addClassName("warning"); + warning.addClassName(LumoUtility.JustifyContent.CENTER); + warning.addClassName(LumoUtility.AlignItems.CENTER); + warning.addClassName(LumoUtility.FontSize.XLARGE); + warning.getStyle().set("width", "100%"); // use full width available + warning.getStyle().set("height", "420px"); // set height + warning.addClassName(LumoUtility.Position.ABSOLUTE); + warning.getStyle().set("top", "0px"); + warning.getStyle().set("left", "0px"); + warning.addClassName(LumoUtility.Display.FLEX); + warning.add(warningText); + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.setPageSize(10); // show only ten elements + grid.addClassName("result-grid"); // set css class name + grid.getStyle().set("width", "100%"); // use full width available + grid.getStyle().set("height", "420px"); // set height + grid.addClassName(LumoUtility.Position.ABSOLUTE); + grid.getStyle().set("top", "0px"); + grid.getStyle().set("left", "0px"); + grid.removeAllColumns(); + grid.setAllRowsVisible(true); + grid.addColumn(result -> result.getValue().stripTrailingZeros().toPlainString()).setHeader("Value").setKey("value"); + grid.addColumn(Result::getPointInTime).setHeader("Point in Time").setKey("pointInTime"); + Grid.Column pointInTime = grid.getColumnByKey("pointInTime"); + GridSortOrder order = new GridSortOrder<>(pointInTime, SortDirection.DESCENDING); + grid.sort(List.of(order)); // set sorting + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + } + + /** + * Configures form + */ + private void configureForm() { + List scales = Arrays.asList(Scale.values()); + List units = Arrays.asList(Unit.values()); + form = new MeasurementForm(scales, units, service); + + form.addListener(MeasurementForm.SaveEvent.class, this::saveMeasurement); + form.addListener(MeasurementForm.CloseEvent.class, this::close); + form.addListener(MeasurementForm.DeleteEvent.class, this::deleteMeasurement); + + form.setMeasurement(measurement); + } + + /** + * Searches for url parameter id and sets audience configuration + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching measurement with id " + id); + try { + measurement = service.findMeasurementById(UUID.fromString(id)); + } catch (IllegalArgumentException e) { + logger.info("Error finding measurement"); + logger.info(e.getMessage()); + } + init(); + } + + /** + * Handles the save event: saves measurement configuration and forwards to overview + * + * @param event + */ + private void saveMeasurement(MeasurementForm.SaveEvent event) { + logger.info("Save measurement event"); + try { + service.saveMeasurement(event.getMeasurement()); + new SuccessNotification("Success", "Measurement with name " + event.getMeasurement().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("measurements")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save measurement", e.getMessage()).open(); + } + } + + /** + * Handles the delete event: shows confirmation dialog, deletes measurement configuration and forwards to overview + * + * @param event + */ + private void deleteMeasurement(MeasurementForm.DeleteEvent event) { + logger.info("Delete measurement event"); + ConfirmDialog dialog = new ConfirmDialog(); + dialog.setHeader("Delete measurement"); + dialog.setText("Are you sure you want to delete measurement " + measurement.getName() + "?"); + dialog.setCancelable(true); + dialog.addConfirmListener(e -> { + try { + service.deleteMeasurement(event.getMeasurement()); + new SuccessNotification("Success", "Measurement with name " + event.getMeasurement().getName() + " deleted successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("measurements")); + } catch (DeleteEntityException ex) { + new ErrorNotification("Cannot delete measurement", ex.getMessage()).open(); + } + }); + dialog.addCancelListener(e -> logger.info("Deletion canceled")); + dialog.open(); + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(MeasurementForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("measurements")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditMetricView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditMetricView.java new file mode 100644 index 0000000..7c2db2f --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditMetricView.java @@ -0,0 +1,225 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.confirmdialog.ConfirmDialog; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.grid.GridSortOrder; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.H2; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.data.provider.SortDirection; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.theme.lumo.LumoUtility; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.data.entity.Metric; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import de.uniregensburg.iamreportingmodule.data.entity.Scale; +import de.uniregensburg.iamreportingmodule.data.entity.Unit; +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.MetricForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +/** + * View for editing metric configuration + * + * @author Julian Bauer + */ +@PageTitle("Edit Metric | IAM Reporting Modul") +@Route(value = "metrics/edit", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class EditMetricView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private Metric metric = null; + private MetricForm form; + private String id; + private final MeasurableService service; + private final Grid grid = new Grid<>(Result.class); + private final Text warningText = new Text("There is no data to display"); + private final Div warning = new Div(); + + /** + * + * @param service + */ + public EditMetricView(MeasurableService service) { + this.service = service; + addClassName("metric-edit"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view + */ + private void init() { + if (metric == null) { + logger.info("Metric is null"); + add(new Text("Cannot find metric with id " + id)); + } else { + configureForm(); + configureGrid(); + configureWarning(); + + H2 formHeading = new H2("Form"); + H2 gridHeading = new H2("Latest ten results"); + + Div gridRoot = new Div(); + gridRoot.addClassName("grid-root"); + gridRoot.addClassName(LumoUtility.Position.RELATIVE); + gridRoot.setSizeFull(); + + gridRoot.add(grid, warning); + + add(formHeading, form, gridHeading, gridRoot); + updateResults(); + } + } + + /** + * Updates results + */ + private void updateResults() { + List results = service.findFirst10ResultsByMeasurableOrderByPointInTimeDesc(metric); + logger.info("Results: " + results.size()); + grid.setItems(results); + if (results.isEmpty()) { + warning.removeClassName(LumoUtility.Display.HIDDEN); + } else { + warning.addClassName(LumoUtility.Display.HIDDEN); + } + } + + /** + * Configures warning + */ + private void configureWarning() { + warning.addClassName("warning"); + warning.addClassName(LumoUtility.JustifyContent.CENTER); + warning.addClassName(LumoUtility.AlignItems.CENTER); + warning.addClassName(LumoUtility.FontSize.XLARGE); + warning.getStyle().set("width", "100%"); // use full width available + warning.getStyle().set("height", "420px"); // set height + warning.addClassName(LumoUtility.Position.ABSOLUTE); + warning.getStyle().set("top", "0px"); + warning.getStyle().set("left", "0px"); + warning.addClassName(LumoUtility.Display.FLEX); + warning.add(warningText); + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.setPageSize(10); // show only ten elements + grid.addClassName("result-grid"); // set css class name + grid.getStyle().set("width", "100%"); // use full width available + grid.getStyle().set("height", "420px"); // set height + grid.addClassName(LumoUtility.Position.ABSOLUTE); + grid.getStyle().set("top", "0px"); + grid.getStyle().set("left", "0px"); + grid.removeAllColumns(); + grid.setAllRowsVisible(true); + grid.addColumn(result -> result.getValue().stripTrailingZeros().toPlainString()).setHeader("Value").setKey("value"); + grid.addColumn(Result::getPointInTime).setHeader("Point in Time").setKey("pointInTime"); + Grid.Column pointInTime = grid.getColumnByKey("pointInTime"); + GridSortOrder order = new GridSortOrder<>(pointInTime, SortDirection.DESCENDING); + grid.sort(List.of(order)); // set sorting + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + } + + /** + * Configures form + */ + private void configureForm() { + List scales = Arrays.asList(Scale.values()); + List units = Arrays.asList(Unit.values()); + form = new MetricForm(scales, units, service); + + form.addListener(MetricForm.SaveEvent.class, this::saveMetric); + form.addListener(MetricForm.CloseEvent.class, this::close); + form.addListener(MetricForm.DeleteEvent.class, this::deleteMetric); + + form.setMetric(metric); + } + + /** + * Searches for url parameter id and sets audience configuration + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching metric with id " + id); + try { + metric = service.findMetricById(UUID.fromString(id)); + } catch (IllegalArgumentException e) { + logger.info("Error finding metric"); + logger.info(e.getMessage()); + } + init(); + } + + /** + * Handles the save event: saves metric configuration and forwards to overview + * + * @param event + */ + private void saveMetric(MetricForm.SaveEvent event) { + logger.info("Save metric event"); + try { + service.saveMetric(event.getMetric()); + new SuccessNotification("Success", "Metric with name " + event.getMetric().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("metrics")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save metric", e.getMessage()).open(); + } + } + + /** + * Handles the delete event: shows confirmation dialog, deletes metric configuration and forwards to overview + * + * @param event + */ + private void deleteMetric(MetricForm.DeleteEvent event) { + logger.info("Delete metric event"); + ConfirmDialog dialog = new ConfirmDialog(); + dialog.setHeader("Delete metric"); + dialog.setText("Are you sure you want to delete metric " + metric.getName() + "?"); + dialog.setCancelable(true); + dialog.addConfirmListener(e -> { + try { + service.deleteMetric(event.getMetric()); + new SuccessNotification("Success", "Metric with name " + event.getMetric().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("metrics")); + } catch (DeleteEntityException ex) { + new ErrorNotification("Cannot delete metric", ex.getMessage()).open(); + } + }); + dialog.addCancelListener(e -> logger.info("Deletion canceled")); + dialog.open(); + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(MetricForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("metrics")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditStakeholderView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditStakeholderView.java new file mode 100644 index 0000000..728c45e --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/EditStakeholderView.java @@ -0,0 +1,145 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.confirmdialog.ConfirmDialog; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.exception.DeleteEntityException; +import de.uniregensburg.iamreportingmodule.core.exception.SaveEntityException; +import de.uniregensburg.iamreportingmodule.core.service.GroupService; +import de.uniregensburg.iamreportingmodule.core.service.UserService; +import de.uniregensburg.iamreportingmodule.data.entity.Stakeholder; +import de.uniregensburg.iamreportingmodule.web.component.notification.ErrorNotification; +import de.uniregensburg.iamreportingmodule.web.component.notification.SuccessNotification; +import de.uniregensburg.iamreportingmodule.web.form.GroupForm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.RolesAllowed; +import java.util.UUID; + +/** + * View for editing stakeholder configuration + * + * @author Julian Bauer + */ +@PageTitle("Edit Stakeholder | IAM Reporting Modul") +@Route(value = "stakeholders/edit", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class EditStakeholderView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private Stakeholder stakeholder = null; + private final GroupForm form; + private String id; + + private final GroupService groupService; + + /** + * + * @param groupService + * @param userService + */ + public EditStakeholderView(GroupService groupService, UserService userService) { + this.groupService = groupService; + form = new GroupForm(userService); + addClassName("stakeholder-edit"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view + */ + private void init() { + if (stakeholder == null) { + logger.info("Stakeholder is null"); + add(new Text("Cannot find stakeholder with id " + id)); + } else { + configureForm(); + add(form); + } + } + + /** + * Configures form + */ + private void configureForm() { + form.addListener(GroupForm.SaveEvent.class, this::saveStakeholder); + form.addListener(GroupForm.CloseEvent.class, this::close); + form.addListener(GroupForm.DeleteEvent.class, this::deleteStakeholder); + + form.setGroup(stakeholder); + } + + /** + * Searches for url parameter id and sets audience configuration + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching stakeholder with id " + id); + try { + stakeholder = groupService.findStakeholderById(UUID.fromString(id)); + } catch (IllegalArgumentException e) { + logger.info("Error finding stakeholder"); + logger.info(e.getMessage()); + } + init(); + } + + /** + * Handles the save event: saves stakeholder configuration and forwards to overview + * + * @param event + */ + private void saveStakeholder(GroupForm.SaveEvent event) { + logger.info("Save stakeholder event"); + try { + groupService.saveGroup(event.getGroup()); + new SuccessNotification("Success", "Stakeholder with name " + event.getGroup().getName() + " saved successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("stakeholders")); + } catch (SaveEntityException e) { + new ErrorNotification("Cannot save stakeholder", e.getMessage()).open(); + } + } + + /** + * Handles the delete event: shows confirmation dialog, deletes stakeholder configuration and forwards to overview + * + * @param event + */ + private void deleteStakeholder(GroupForm.DeleteEvent event) { + logger.info("Delete stakeholder event"); + ConfirmDialog dialog = new ConfirmDialog(); + dialog.setHeader("Delete stakeholder"); + dialog.setText("Are you sure you want to delete stakeholder " + stakeholder.getName() + "?"); + dialog.setCancelable(true); + dialog.addConfirmListener(e -> { + try { + groupService.deleteGroup(event.getGroup()); + new SuccessNotification("Success", "Stakeholder with name " + event.getGroup().getName() + " deleted successfully." ).open(); + form.getUI().ifPresent(ui -> ui.navigate("stakeholders")); + } catch (DeleteEntityException ex) { + new ErrorNotification("Cannot delete stakeholder", ex.getMessage()).open(); + } + }); + dialog.addCancelListener(e -> logger.info("Deletion canceled")); + dialog.open(); + } + + /** + * Handles the close event: forwards to overview + * + * @param event + */ + private void close(GroupForm.CloseEvent event) { + logger.info("Close event"); + form.getUI().ifPresent(ui -> ui.navigate("stakeholders")); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/InformationNeedsView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/InformationNeedsView.java new file mode 100644 index 0000000..95d3452 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/InformationNeedsView.java @@ -0,0 +1,128 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.AttachEvent; +import com.vaadin.flow.component.DetachEvent; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.data.entity.InformationNeed; +import de.uniregensburg.iamreportingmodule.core.service.InformationNeedService; + +import javax.annotation.security.RolesAllowed; + +/** + * View for displaying all information need configurations + * + * @author Julian Bauer + */ +@PageTitle("Information Needs | IAM Reporting Modul") +@Route(value = "informationneeds", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class InformationNeedsView extends VerticalLayout { + + private final Grid grid = new Grid<>(InformationNeed.class); + private final InformationNeedService service; + + private final Button addButton = new Button("Add information need"); // add button + + /** + * + * @param service + */ + public InformationNeedsView(InformationNeedService service) { + this.service = service; + addClassName("informationneed-view"); // CSS class name + setSizeFull(); // whole browser size + + configureGrid(); // configure grid + + add(grid); // add grid to view + + updateList(); // update data + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.addClassName("informationneed-grid"); // set css class name + grid.setSizeFull(); // use full size available + grid.setColumns("name", "description"); // set primitiv columns: name, description + + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + + grid.asSingleSelect().addValueChangeListener(e -> editInformationNeed(e.getValue())); + } + + /** + * Updates list of items + */ + private void updateList() { + grid.setItems(service.findAllInformationNeeds()); + } + + /** + * Forwards to page for adding information need configuration + */ + private void addInformationNeed() { + getUI().ifPresent(ui -> ui.navigate("informationneeds/add")); + } + + /** + * Forwards to page for editing information need configuration + * + * @param informationNeed + */ + private void editInformationNeed(InformationNeed informationNeed) { + getUI().ifPresent(ui -> ui.navigate("informationneeds/edit/" + informationNeed.getId())); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(addButton); + + addButton.addClickListener(e -> addInformationNeed()); // button action + addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); // primary button + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/LoginView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/LoginView.java new file mode 100644 index 0000000..18ae003 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/LoginView.java @@ -0,0 +1,57 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.html.H1; +import com.vaadin.flow.component.login.LoginForm; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.BeforeEnterEvent; +import com.vaadin.flow.router.BeforeEnterListener; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; + +// Source: https://github.com/vaadin/flow-crm-tutorial/ + +/** + * View for login of user + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/LoginView.java + * + * @author Julian Bauer + */ +@Route("login") +@PageTitle("Login | IAM Reporting Module") +public class LoginView extends VerticalLayout implements BeforeEnterListener { + + private final LoginForm login = new LoginForm(); + + /** + * + */ + public LoginView() { + addClassName("login-view"); + setSizeFull(); + setAlignItems(Alignment.CENTER); + setJustifyContentMode(JustifyContentMode.CENTER); + + login.setAction("login"); + login.setForgotPasswordButtonVisible(false); // do not show forgot password button + + add( + new H1("IAM Reporting Modul"), + login + ); + } + + /** + * Show error message if url parameter "error" is present + * + * @param beforeEnterEvent + */ + @Override + public void beforeEnter(BeforeEnterEvent beforeEnterEvent) { + if (beforeEnterEvent.getLocation().getQueryParameters().getParameters().containsKey("error")) { + login.setError(true); + } + + } + +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/LogoutView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/LogoutView.java new file mode 100644 index 0000000..9bafab5 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/LogoutView.java @@ -0,0 +1,23 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.web.security.SecurityService; + +import javax.annotation.security.PermitAll; + +/** + * View for logging user out + * + * @author Julian Bauer + */ +@Route(value = "logout") +@PageTitle("Logout | IAM Reporting Module") +@PermitAll +public class LogoutView extends Div { + + public LogoutView(SecurityService service) { + service.logout(); + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MainLayout.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MainLayout.java new file mode 100644 index 0000000..ed0c50b --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MainLayout.java @@ -0,0 +1,155 @@ +package de.uniregensburg.iamreportingmodule.web.view; + + +import com.vaadin.flow.component.UI; +import com.vaadin.flow.component.applayout.AppLayout; +import com.vaadin.flow.component.applayout.DrawerToggle; +import com.vaadin.flow.component.html.Footer; +import com.vaadin.flow.component.html.H1; +import com.vaadin.flow.component.html.H2; +import com.vaadin.flow.component.html.Header; +import com.vaadin.flow.component.orderedlayout.FlexComponent; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.Scroller; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.theme.lumo.LumoUtility; +import de.uniregensburg.iamreportingmodule.web.component.appnav.AppNav; +import de.uniregensburg.iamreportingmodule.web.component.appnav.AppNavItem; +import de.uniregensburg.iamreportingmodule.web.security.SecurityService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * Layout for all views + * + * Template: https://github.com/vaadin/flow-crm-tutorial/blob/v23/src/main/java/com/example/application/views/MainLayout.java + * + * @author Julian Bauer + */ +public class MainLayout extends AppLayout { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final H2 viewTitle = new H2(); + private final SecurityService securityService; + private final HorizontalLayout navbarButtons = new HorizontalLayout(); + + /** + * + * @param securityService + */ + public MainLayout(SecurityService securityService) { + this.securityService = securityService; + setPrimarySection(Section.DRAWER); + createDrawer(); + createHeader(); + } + + /** + * Creates Header + */ + private void createHeader() { + DrawerToggle toggle = new DrawerToggle(); + toggle.getElement().setAttribute("aria-label", "Menu toggle"); + + viewTitle.addClassNames(LumoUtility.FontSize.LARGE, LumoUtility.Margin.NONE); + + HorizontalLayout header = new HorizontalLayout(toggle, viewTitle, navbarButtons); + header.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER); + header.expand(viewTitle); + header.setWidthFull(); + header.addClassNames("py-0", "px-m"); + + addToNavbar(true, header); + } + + /** + * Creates Drawer + */ + private void createDrawer() { + H1 appName = new H1("IAM Reporting Module"); + appName.addClassNames(LumoUtility.FontSize.LARGE, LumoUtility.Margin.NONE); + Header header = new Header(appName); + + Scroller scroller = new Scroller(createNavigation()); + + addToDrawer(header, scroller, createFooter()); + } + + /** + * Creates global navigation + * + * @return + */ + private AppNav createNavigation() { + // AppNav is not yet an official component. + // For documentation, visit https://github.com/vaadin/vcf-nav#readme + AppNav nav = new AppNav(); + + UserDetails userDetails = securityService.getAuthenticatedUser(); + boolean isAdmin = userDetails.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN")); + + nav.addItem(new AppNavItem("Dashboard", DashboardView.class, "la la-chart-bar")); + if (isAdmin) { + nav.addItem(new AppNavItem("Metrics", MetricsView.class, "la la-percent")); + nav.addItem(new AppNavItem("Measurements", MeasurementsView.class, "la la-ruler")); + nav.addItem(new AppNavItem("Datasources", DataSourcesView.class, "la la-database")); + nav.addItem(new AppNavItem("Information needs", InformationNeedsView.class, "la la-bullseye")); + nav.addItem(new AppNavItem("Stakeholders", StakeholdersView.class, "la la-user-friends")); + nav.addItem(new AppNavItem("Audiences", AudiencesView.class, "la la-users")); + } + nav.addItem(new AppNavItem("Log out", LogoutView.class, "la la-sign-out-alt")); + + return nav; + } + + /** + * Creates footer + * + * @return + */ + private Footer createFooter() { + return new Footer(); + } + + /** + * Changes page title after navigation + */ + @Override + protected void afterNavigation() { + super.afterNavigation(); + viewTitle.setText(getCurrentPageTitle()); + } + + /** + * Returns current page title + * + * @return + */ + private String getCurrentPageTitle() { + PageTitle title = getContent().getClass().getAnnotation(PageTitle.class); + return title == null ? "" : title.value(); + } + + /** + * Returns current active main layout + * + * Template: https://vaadin.com/forum/thread/18552728/change-navbar-content-in-applayout-dynamically-when-navigation-occurs + * + * @return + */ + public static MainLayout getInstance() { + return (MainLayout) UI.getCurrent().getChildren() + .filter(component -> component.getClass() == MainLayout.class).findFirst().orElse(null); + } + + /** + * Returns navbar buttons + * + * @return + */ + public HorizontalLayout getNavbarButtons() { + return navbarButtons; + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MeasurementsView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MeasurementsView.java new file mode 100644 index 0000000..54b20a2 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MeasurementsView.java @@ -0,0 +1,134 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.AttachEvent; +import com.vaadin.flow.component.DetachEvent; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.data.entity.Measurement; + +import javax.annotation.security.RolesAllowed; + +/** + * View for displaying all measurement configurations + * + * @author Julian Bauer + */ +@PageTitle("Measurements | IAM Reporting Modul") +@Route(value = "measurements", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class MeasurementsView extends VerticalLayout { + + private final Grid grid = new Grid<>(Measurement.class); + private final MeasurableService service; + + private final Button addButton = new Button("Add measurement"); // add button + + /** + * + * @param service + */ + public MeasurementsView(MeasurableService service) { + this.service = service; + addClassName("measurement-view"); // CSS class name + setSizeFull(); // whole browser size + + configureGrid(); // configure grid + + add(grid); // add grid to view + + updateList(); // update data + } + + /** + * Updates list of items + */ + private void updateList() { + grid.setItems(service.findAllMeasurements()); + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.addClassName("measurement-grid"); // set css class name + grid.setSizeFull(); // use full size available + grid.setColumns("name"); // set primitiv columns: name + grid.addColumn(measurement -> measurement.getDataSource().getName()).setHeader("Datasource"); // set complex column: datasource + grid.addColumn(measurement -> { + if (measurement.getFormulas() == null) { + return 0; + } + return measurement.getFormulas().size(); + }).setHeader("Metrics"); + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + + grid.asSingleSelect().addValueChangeListener(e -> editMeasurement(e.getValue())); + } + + /** + * Forwards to page for adding measurement configuration + */ + private void addMeasurement() { + getUI().ifPresent(ui -> ui.navigate("measurements/add")); + } + + /** + * Forwards to page for editing measurement configuration + * + * @param measurement + */ + private void editMeasurement(Measurement measurement) { + getUI().ifPresent(ui -> ui.navigate("measurements/edit/" + measurement.getId())); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(addButton); + + addButton.addClickListener(e -> addMeasurement()); // button action + addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); // primary button + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MetricsView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MetricsView.java new file mode 100644 index 0000000..9502056 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/MetricsView.java @@ -0,0 +1,132 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.AttachEvent; +import com.vaadin.flow.component.DetachEvent; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.data.entity.InformationNeed; +import de.uniregensburg.iamreportingmodule.data.entity.Metric; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; + +import javax.annotation.security.RolesAllowed; +import java.util.stream.Collectors; + +/** + * View for displaying all metric configurations + * + * @author Julian Bauer + */ +@PageTitle("Metrics | IAM Reporting Modul") +@Route(value = "metrics", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class MetricsView extends VerticalLayout { + + private final Grid grid = new Grid<>(Metric.class); + private final MeasurableService service; + + private final Button addButton = new Button("Add metric"); // add button + + /** + * + * @param service + */ + public MetricsView(MeasurableService service) { + this.service = service; + addClassName("metric-view"); // CSS class name + setSizeFull(); // whole browser size + + configureGrid(); // configure grid + + add(grid); // add grid to view + + updateList(); // update data + } + + + /** + * Updates list of items + */ + private void updateList() { + grid.setItems(service.findAllMetrics()); + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.addClassName("metric-grid"); // set css class name + grid.setSizeFull(); // use full size available + grid.setColumns("name"); // set primitiv columns: name + grid.addColumn(metric -> metric.getInformationNeeds().stream().map(InformationNeed::getName).collect(Collectors.joining(", "))).setHeader("Information needs"); // set complex column: information needs + grid.addColumn(metric -> metric.getFormula().getFormula()).setHeader("Formula"); // set complex column: frequency + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + + grid.asSingleSelect().addValueChangeListener(e -> editMetric(e.getValue())); + } + + /** + * Forwards to page for adding metric configuration + */ + private void addMetric() { + getUI().ifPresent(ui -> ui.navigate("metrics/add")); + } + + /** + * Forwards to page for editing metric configuration + * + * @param metric + */ + private void editMetric(Metric metric) { + getUI().ifPresent(ui -> ui.navigate("metrics/edit/" + metric.getId())); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(addButton); + + addButton.addClickListener(e -> addMetric()); // button action + addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); // primary button + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} \ No newline at end of file diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/ResultsView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/ResultsView.java new file mode 100644 index 0000000..56bdb33 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/ResultsView.java @@ -0,0 +1,146 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.grid.GridSortOrder; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.H2; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.data.provider.SortDirection; +import com.vaadin.flow.router.BeforeEvent; +import com.vaadin.flow.router.HasUrlParameter; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.theme.lumo.LumoUtility; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.data.entity.Measurable; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.security.PermitAll; +import java.util.List; +import java.util.UUID; + +/** + * View for displaying results + * + * @author Julian Bauer + */ +@PageTitle("Results | IAM Reporting Modul") +@Route(value = "results", layout = MainLayout.class) +@PermitAll +public class ResultsView extends VerticalLayout implements HasUrlParameter { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private Measurable measurable = null; + private String id; + private final MeasurableService service; + private final Grid grid = new Grid<>(Result.class); + private final Text warningText = new Text("There is no data to display"); + private final Div warning = new Div(); + + /** + * + * @param service + */ + public ResultsView(MeasurableService service) { + this.service = service; + addClassName("result-view"); // CSS class name + setSizeFull(); // whole browser size + } + + /** + * Initializes view components + */ + private void init() { + if (measurable == null) { + logger.info("Measurable is null"); + add(new Text("Cannot find measurable with id " + id)); + } else { + configureGrid(); + configureWarning(); + + H2 gridHeading = new H2("Latest ten results of " + measurable.getName()); + + Div gridRoot = new Div(); + gridRoot.addClassName("grid-root"); + gridRoot.addClassName(LumoUtility.Position.RELATIVE); + gridRoot.setSizeFull(); + + gridRoot.add(grid, warning); + + add(gridHeading, gridRoot); + updateResults(); + } + } + + /** + * Updates results + */ + private void updateResults() { + List results = service.findFirst10ResultsByMeasurableOrderByPointInTimeDesc(measurable); + logger.info("Results: " + results.size()); + grid.setItems(results); + if (results.isEmpty()) { + warning.removeClassName(LumoUtility.Display.HIDDEN); + } else { + warning.addClassName(LumoUtility.Display.HIDDEN); + } + } + + /** + * Configures warning + */ + private void configureWarning() { + warning.addClassName("warning"); + warning.addClassName(LumoUtility.JustifyContent.CENTER); + warning.addClassName(LumoUtility.AlignItems.CENTER); + warning.addClassName(LumoUtility.FontSize.XLARGE); + warning.setSizeFull(); + warning.addClassName(LumoUtility.Position.ABSOLUTE); + warning.getStyle().set("top", "0px"); + warning.getStyle().set("left", "0px"); + warning.addClassName(LumoUtility.Display.FLEX); + warning.add(warningText); + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.setPageSize(10); // show only ten elements + grid.addClassName("result-grid"); // set css class name + grid.setSizeFull(); // use full size available + grid.addClassName(LumoUtility.Position.ABSOLUTE); + grid.getStyle().set("top", "0px"); + grid.getStyle().set("left", "0px"); + grid.removeAllColumns(); + grid.setAllRowsVisible(true); + grid.addColumn(result -> result.getValue().stripTrailingZeros().toPlainString()).setHeader("Value").setKey("value"); + grid.addColumn(Result::getPointInTime).setHeader("Point in Time").setKey("pointInTime"); + Grid.Column pointInTime = grid.getColumnByKey("pointInTime"); + GridSortOrder order = new GridSortOrder<>(pointInTime, SortDirection.DESCENDING); + grid.sort(List.of(order)); // set sorting + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + } + + /** + * Searches for url parameter id and starts view initialization + * + * @param event + * @param id + */ + @Override + public void setParameter(BeforeEvent event, String id) { + this.id = id; + logger.info("Searching measurable with id " + id); + try { + measurable = service.findMeasurableById(UUID.fromString(id)); + init(); + } catch (IllegalArgumentException e) { + logger.info("Error finding measurable"); + logger.info(e.getMessage()); + } + } +} diff --git a/src/main/java/de/uniregensburg/iamreportingmodule/web/view/StakeholdersView.java b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/StakeholdersView.java new file mode 100644 index 0000000..f938540 --- /dev/null +++ b/src/main/java/de/uniregensburg/iamreportingmodule/web/view/StakeholdersView.java @@ -0,0 +1,131 @@ +package de.uniregensburg.iamreportingmodule.web.view; + +import com.vaadin.flow.component.AttachEvent; +import com.vaadin.flow.component.DetachEvent; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import de.uniregensburg.iamreportingmodule.core.service.GroupService; +import de.uniregensburg.iamreportingmodule.data.entity.Stakeholder; +import de.uniregensburg.iamreportingmodule.data.entity.User; + +import javax.annotation.security.RolesAllowed; +import java.util.stream.Collectors; + +/** + * View for displaying all stakeholder configurations + * + * @author Julian Bauer + */ +@PageTitle("Stakeholders | IAM Reporting Modul") +@Route(value = "stakeholders", layout = MainLayout.class) +@RolesAllowed({"ADMIN"}) +public class StakeholdersView extends VerticalLayout { + + private final Grid grid = new Grid<>(Stakeholder.class); + private final GroupService service; + + private final Button addButton = new Button("Add stakeholder"); // add button + + /** + * + * @param service + */ + public StakeholdersView(GroupService service) { + this.service = service; + addClassName("stakeholder-view"); // CSS class name + setSizeFull(); // whole browser size + + configureGrid(); // configure grid + + add(grid); // add grid to view + + updateList(); // update data + } + + /** + * Configures grid + */ + private void configureGrid() { + grid.addClassName("stakeholder-grid"); // set css class name + grid.setSizeFull(); // use full size available + grid.setColumns("name"); // set primitive columns: name + grid.addColumn(stakeholder -> stakeholder.getMembers().stream().map(User::getFullName).collect(Collectors.joining(", "))).setHeader("Members"); // set complex column: members + + grid.getColumns().forEach(col -> col.setAutoWidth(true)); // auto resize + + grid.asSingleSelect().addValueChangeListener(e -> editStakeholder(e.getValue())); + } + + /** + * Updates list of items + */ + private void updateList() { + grid.setItems(service.findAllStakeholders()); + } + + /** + * Forwards to page for adding stakeholder configuration + */ + private void addStakeholder() { + getUI().ifPresent(ui -> ui.navigate("stakeholders/add")); + } + + /** + * Forwards to page for editing stakeholder configuration + * + * @param stakeholder + */ + private void editStakeholder(Stakeholder stakeholder) { + getUI().ifPresent(ui -> ui.navigate("stakeholders/edit/" + stakeholder.getId())); + } + + /** + * Initializes buttons in navbar + * + * @param navbarButtons + */ + private void initNavbarButtons(HorizontalLayout navbarButtons) { + navbarButtons.add(addButton); + + addButton.addClickListener(e -> addStakeholder()); // button action + addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); // primary button + } + + /** + * Adds button to navbar on attach event + * + * @param attachEvent + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + + // Add menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + initNavbarButtons(ml.getNavbarButtons()); + } + } + + /** + * Removes buttons from navbar on detach event + * + * @param detachEvent + */ + @Override + protected void onDetach(DetachEvent detachEvent) { + // Remove menu bar + MainLayout ml = MainLayout.getInstance(); + if (ml != null) { + ml.getNavbarButtons().removeAll(); + } + + super.onDetach(detachEvent); + } + +} diff --git a/src/main/resources/META-INF/resources/icons/icon.png b/src/main/resources/META-INF/resources/icons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..df2ed4bd80778f7141c825ce9275984b4a34a15c GIT binary patch literal 2424 zcmb7GYdDl!8(!}_2Xi!xLSytzg|bPKGNKGdQ9{O+Mmf~5kr)bTi+7yjDmC;)Ax){I z!*)I-hJgV-~m>2#eiJdBKFd<3_8n6Io=hB2qm7CYu9O3 z0zkOu#&z^L08O-tR0RN${3zEeSF8KK#;IF&j$SWAQbB5s2(9EKzB z^Da35@IY%rH25Kcr3n#9Ea%9Z*qN$1Wn5aY^N2E|+p)g)VbS&ec{7g|RF_7zhQ9P@ z9yJtfd|8OyXCdeydcAzqT!x*f=r2AxXPA(bI&rxlm(Na~g!_06#7yqw%;pP2qxKW0 z6ekI)$kl&X1E*PbcXllP`;=MKDEWH-L1 zJqwMdAhJ)hd_>y^#1AECemZQfh2zWviA$auf@u4!aAZaKRY zzt3EQ&m*BaGq!6w!#6!QjVp^k`l^OPLIXZE{;(bPC>>2Eal&8cQ!do}fhTbSO8alG zTtPfKWo;-jt#)^Wq*{>P_TOkrLh~PZD%woFAO$Zs#BP|Ur)%DpWk617z1QQ88-)1z zQFk^LH&jMod<)$pvYS!Cl zlvPo+lA14Ikh02`Kd3WzuPUh}_%2sR*MHp}(E`)QsX$7ijsdr}5}}T|+&tFNw^y4n`en55hinWX3eD zrUd*`52D}1#C7m44j*)A<+5{qM3hNVlTz@ z&}_OK2K!qbBa5PBOPPX=CQ(E2!EWMGVb#a2*UV*tjHks26w7Xy9k`=g)T?*UXA4b4 zT+JhAiFZeQ3cR-nU$Hz!ynEAZ_JUZS5{D^+Sf89sP>2gBU3NozlO2ymlpmlNk&tU~ z8l21~3~T4hG|t!zM%*4d8-OskJwDtT*uBi_M35oopzFgx(ns+U|Icx(ICfeJMm@NM9 z5gt}L>Y#XDe6ZO!g)yo$zx07wvZcrLBXwYH^QN^Lx3w#Xc@?jfE1P1IcfRh@>{?ug z(lY8K9SXA&C+~L8obn4DY{A9AxKZWKvZ5KBTwD;466+ydnrO8LzB7|InNWPcjV|du z+srCh)$&Fs_KEV_=}k@h);n1h6tAD(oin#PLttU6HzFK5o{qimAKNoD!#r(s>@}Pc z_Mpb_em^W2Jbpt)Wwl#yLg${Jx(bch5weEylfompA_MC;)*u$K=X5T=6w3hqQVcgr zo6PT|B!aG8d=%YcKLRywF<*Kl-5%I9<@W$rDH$H*nNkt420<2PdJ)1(&0Zxe3Q@RQ z^_y}S`Q7j%*|^OJ`?c8Zu1>JcK4WVHBxdCobAQ7bhvYkL_w=cnYT|iNwU3T?MmffhO+zP#O<}9>mfrr z(08-6*k_mJvC^@SO)FMmEOlf`-<;zl+NJCb-y8<$zs;O0t2Z=(DvqHXHd7>;vH;eu z01*!CSR~}Y6R;a9#beX=h)~SKujH0|BB0U%D=BL|i3Jq|Q>2HWdv_6hVb2L95*yDy zKu3hsrUWc&o=9Yg#kcjwP^7oE8WNX%i8c_AneJ!9Pb7IcC`TdFMz|{8xF4Ay)&UIM zruFS*cNR})X^Cp>_HeQ^ATEBZHLIW~M&vnK%QLDS& zaBx>D7&3-MBB8=Ui`pcR!_W|3^nvIihx>F6UUBRrP|}r-gL-FpG{PTpxLa}$D?5(~ z^1OUtfz^ZENGMzs094B2z12!LQcCn%U;4xLj?1FUAswpf}2X^=6!9UzsZV2rin zQW!QL5n%EVSXASvFb8AuO(ae|-f)qSO>hn(261k%9w101NRJSM$C6{VE){=anRx%@ zDu$yEV}c=xpuqj5VVhnMewR-r=oNq zGDe`pZF$g*4Ld-XSS3>>kMgrt7pMfNlT@c~R=1HtAduBB#Q3bZz#Vr*^BVl&$`eeGVHm@3l9-1XQ{j&!?^`(YTdq~qC z@SZh%)lLn!tB`-_u2O$IP*%$Ooi)ocCRY8A-w*_xH{bdCE)GXm7r422aQ|`&O8pO# C@ant( literal 0 HcmV?d00001 diff --git a/src/main/resources/META-INF/resources/images/empty-plant.png b/src/main/resources/META-INF/resources/images/empty-plant.png new file mode 100644 index 0000000000000000000000000000000000000000..9777f260a67891001eb2444f49569037a74f671d GIT binary patch literal 70951 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 z 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 +spring.datasource.username= +spring.datasource.password= +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL10Dialect + +# Quartz configuration +spring.quartz.jdbc.schema=classpath:quartz/schema.sql \ No newline at end of file diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties new file mode 100644 index 0000000..7dec768 --- /dev/null +++ b/src/main/resources/application-local.properties @@ -0,0 +1,12 @@ +# Launch the default browser when starting the application in development mode +vaadin.launch-browser=true + +# Hibernate configuration +spring.jpa.hibernate.ddl-auto=create-drop + +# Database connection prameters +spring.datasource.url=jdbc:h2:mem:iamreportingmodule +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=pass +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties new file mode 100644 index 0000000..89ae1fd --- /dev/null +++ b/src/main/resources/application-production.properties @@ -0,0 +1,11 @@ +# Hibernate configuration +spring.jpa.hibernate.ddl-auto=update + +# Database connection parameters +spring.datasource.url=jdbc:postgresql://localhost:5432/ +spring.datasource.username= +spring.datasource.password= +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL10Dialect + +# Quartz configuration +spring.quartz.jdbc.schema=classpath:quartz/schema.sql \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..3156e9c --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,22 @@ +server.port=${PORT:8080} +logging.level.org.atmosphere = warn +spring.mustache.check-template-location = false + +# To improve the performance during development. +# For more information https://vaadin.com/docs/flow/spring/tutorial-spring-configuration.html#special-configuration-parameters +vaadin.whitelisted-packages = com.vaadin,org.vaadin,dev.hilla,de.uniregensburg.iamreportingmodule +# spring.jpa.defer-datasource-initialization = true + +spring.profiles.active=@spring.profiles.active@ + +# Hibernate configuration +spring.jpa.generate-ddl=true + +# Quartz configuration +spring.quartz.job-store-type=jdbc +spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate +spring.quartz.jdbc.initialize-schema=always + +# Logging configuration +logging.file.path=. +logging.file.name=iamreportingmodule.log \ No newline at end of file diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000..6d987f3 --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,6 @@ + ___ _ __ __ ____ _ _ __ __ _ _ +|_ _| / \ | \/ | | _ \ ___ _ __ ___ _ __ | |_ (_) _ __ __ _ | \/ | ___ __| | _ _ | | ___ + | | / _ \ | |\/| | | |_) | / _ \| '_ \ / _ \ | '__|| __|| || '_ \ / _` | | |\/| | / _ \ / _` || | | || | / _ \ + | | / ___ \ | | | | | _ < | __/| |_) || (_) || | | |_ | || | | || (_| | | | | || (_) || (_| || |_| || || __/ +|___|/_/ \_\|_| |_| |_| \_\ \___|| .__/ \___/ |_| \__||_||_| |_| \__, | |_| |_| \___/ \__,_| \__,_||_| \___| + |_| |___/ diff --git a/src/main/resources/quartz/schema.sql b/src/main/resources/quartz/schema.sql new file mode 100644 index 0000000..4af54c5 --- /dev/null +++ b/src/main/resources/quartz/schema.sql @@ -0,0 +1,199 @@ +-- Thanks to Patrick Lightbody for submitting this... +-- +-- In your Quartz properties file, you'll need to set +-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate +-- +-- Source: https://raw.githubusercontent.com/quartz-scheduler/quartz/master/quartz-core/src/main/resources/org/quartz/impl/jdbcjobstore/tables_postgres.sql +-- Modified by: Julian Bauer +-- Removed DROP TABLE and appended IF NOT EXISTS to CREATE Statements + +CREATE TABLE IF NOT EXISTS QRTZ_JOB_DETAILS +( + SCHED_NAME VARCHAR(120) NOT NULL, + JOB_NAME VARCHAR(200) NOT NULL, + JOB_GROUP VARCHAR(200) NOT NULL, + DESCRIPTION VARCHAR(250) NULL, + JOB_CLASS_NAME VARCHAR(250) NOT NULL, + IS_DURABLE BOOL NOT NULL, + IS_NONCONCURRENT BOOL NOT NULL, + IS_UPDATE_DATA BOOL NOT NULL, + REQUESTS_RECOVERY BOOL NOT NULL, + JOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME, JOB_NAME, JOB_GROUP) +); + +CREATE TABLE IF NOT EXISTS QRTZ_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + JOB_NAME VARCHAR(200) NOT NULL, + JOB_GROUP VARCHAR(200) NOT NULL, + DESCRIPTION VARCHAR(250) NULL, + NEXT_FIRE_TIME BIGINT NULL, + PREV_FIRE_TIME BIGINT NULL, + PRIORITY INTEGER NULL, + TRIGGER_STATE VARCHAR(16) NOT NULL, + TRIGGER_TYPE VARCHAR(8) NOT NULL, + START_TIME BIGINT NOT NULL, + END_TIME BIGINT NULL, + CALENDAR_NAME VARCHAR(200) NULL, + MISFIRE_INSTR SMALLINT NULL, + JOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, JOB_NAME, JOB_GROUP) + REFERENCES QRTZ_JOB_DETAILS (SCHED_NAME, JOB_NAME, JOB_GROUP) +); + +CREATE TABLE IF NOT EXISTS QRTZ_SIMPLE_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + REPEAT_COUNT BIGINT NOT NULL, + REPEAT_INTERVAL BIGINT NOT NULL, + TIMES_TRIGGERED BIGINT NOT NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) +); + +CREATE TABLE IF NOT EXISTS QRTZ_CRON_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + CRON_EXPRESSION VARCHAR(120) NOT NULL, + TIME_ZONE_ID VARCHAR(80), + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) +); + +CREATE TABLE IF NOT EXISTS QRTZ_SIMPROP_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + STR_PROP_1 VARCHAR(512) NULL, + STR_PROP_2 VARCHAR(512) NULL, + STR_PROP_3 VARCHAR(512) NULL, + INT_PROP_1 INT NULL, + INT_PROP_2 INT NULL, + LONG_PROP_1 BIGINT NULL, + LONG_PROP_2 BIGINT NULL, + DEC_PROP_1 NUMERIC(13, 4) NULL, + DEC_PROP_2 NUMERIC(13, 4) NULL, + BOOL_PROP_1 BOOL NULL, + BOOL_PROP_2 BOOL NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) +); + +CREATE TABLE IF NOT EXISTS QRTZ_BLOB_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + BLOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) +); + +CREATE TABLE IF NOT EXISTS QRTZ_CALENDARS +( + SCHED_NAME VARCHAR(120) NOT NULL, + CALENDAR_NAME VARCHAR(200) NOT NULL, + CALENDAR BYTEA NOT NULL, + PRIMARY KEY (SCHED_NAME, CALENDAR_NAME) +); + + +CREATE TABLE IF NOT EXISTS QRTZ_PAUSED_TRIGGER_GRPS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_GROUP) +); + +CREATE TABLE IF NOT EXISTS QRTZ_FIRED_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + ENTRY_ID VARCHAR(95) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + INSTANCE_NAME VARCHAR(200) NOT NULL, + FIRED_TIME BIGINT NOT NULL, + SCHED_TIME BIGINT NOT NULL, + PRIORITY INTEGER NOT NULL, + STATE VARCHAR(16) NOT NULL, + JOB_NAME VARCHAR(200) NULL, + JOB_GROUP VARCHAR(200) NULL, + IS_NONCONCURRENT BOOL NULL, + REQUESTS_RECOVERY BOOL NULL, + PRIMARY KEY (SCHED_NAME, ENTRY_ID) +); + +CREATE TABLE IF NOT EXISTS QRTZ_SCHEDULER_STATE +( + SCHED_NAME VARCHAR(120) NOT NULL, + INSTANCE_NAME VARCHAR(200) NOT NULL, + LAST_CHECKIN_TIME BIGINT NOT NULL, + CHECKIN_INTERVAL BIGINT NOT NULL, + PRIMARY KEY (SCHED_NAME, INSTANCE_NAME) +); + +CREATE TABLE IF NOT EXISTS QRTZ_LOCKS +( + SCHED_NAME VARCHAR(120) NOT NULL, + LOCK_NAME VARCHAR(40) NOT NULL, + PRIMARY KEY (SCHED_NAME, LOCK_NAME) +); + +CREATE INDEX IF NOT EXISTS IDX_QRTZ_J_REQ_RECOVERY + ON QRTZ_JOB_DETAILS (SCHED_NAME, REQUESTS_RECOVERY); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_J_GRP + ON QRTZ_JOB_DETAILS (SCHED_NAME, JOB_GROUP); + +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_J + ON QRTZ_TRIGGERS (SCHED_NAME, JOB_NAME, JOB_GROUP); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_JG + ON QRTZ_TRIGGERS (SCHED_NAME, JOB_GROUP); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_C + ON QRTZ_TRIGGERS (SCHED_NAME, CALENDAR_NAME); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_G + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_STATE + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_N_STATE + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP, TRIGGER_STATE); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_N_G_STATE + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP, TRIGGER_STATE); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_NEXT_FIRE_TIME + ON QRTZ_TRIGGERS (SCHED_NAME, NEXT_FIRE_TIME); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_NFT_ST + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE, NEXT_FIRE_TIME); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_NFT_MISFIRE + ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_NFT_ST_MISFIRE + ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_STATE); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_T_NFT_ST_MISFIRE_GRP + ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_GROUP, TRIGGER_STATE); + +CREATE INDEX IF NOT EXISTS IDX_QRTZ_FT_TRIG_INST_NAME + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_FT_INST_JOB_REQ_RCVRY + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME, REQUESTS_RECOVERY); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_FT_J_G + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_NAME, JOB_GROUP); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_FT_JG + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_GROUP); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_FT_T_G + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP); +CREATE INDEX IF NOT EXISTS IDX_QRTZ_FT_TG + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_GROUP); + + +COMMIT; \ No newline at end of file diff --git a/src/test/java/de/uniregensburg/iamreportingmodule/core/util/DatabaseUtilTest.java b/src/test/java/de/uniregensburg/iamreportingmodule/core/util/DatabaseUtilTest.java new file mode 100644 index 0000000..c984372 --- /dev/null +++ b/src/test/java/de/uniregensburg/iamreportingmodule/core/util/DatabaseUtilTest.java @@ -0,0 +1,75 @@ +package de.uniregensburg.iamreportingmodule.core.util; + +import de.uniregensburg.iamreportingmodule.core.exception.DatabaseException; +import de.uniregensburg.iamreportingmodule.data.entity.DatabaseDataSource; +import de.uniregensburg.iamreportingmodule.data.entity.Dbms; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.math.BigDecimal; + +/** + * Tests database util: connection to postgresql database and execution of simple select statement + *

+ * Requirements: + *

+ * Postgresql database: + * host=localhost, port=5432, database=test, username=test, password=Test123! + *

+ * Tables: accounts + * CREATE TABLE users (username character varying(50) NOT NULL); + *

+ * Data: + * INSERT INTO users (username) VALUES ('user'); + * INSERT INTO users (username) VALUES ('admin'); + *

+ * Rights: + * GRANT ALL ON TABLE public.users TO test; + * + * @author Julian Bauer + * + */ +public class DatabaseUtilTest { + private DatabaseUtil databaseUtil; + + /** + * Initializes database util + */ + @Before + public void setupData() { + DatabaseDataSource postgresqlDataSource = new DatabaseDataSource(); + postgresqlDataSource.setDbmsType(Dbms.POSTGRESQL); + postgresqlDataSource.setHost("localhost"); + postgresqlDataSource.setPort(5432); + postgresqlDataSource.setDatabase("test"); + postgresqlDataSource.setUsername("test"); + postgresqlDataSource.setPassword("Test123!"); + databaseUtil = new DatabaseUtil(postgresqlDataSource); + } + + /** + * Tests database connection + * + * @throws DatabaseException + */ + @Test + public void dbConnection() throws DatabaseException { + Assert.assertTrue(databaseUtil.testConnection()); + } + + /** + * Tests executing sql queries: counts rows in table users + * + * @throws DatabaseException + */ + @Test + public void countAccounts() throws DatabaseException { + String query = "SELECT COUNT(*) FROM users;"; + Result result = databaseUtil.measure(query); + BigDecimal expected = new BigDecimal(2); + BigDecimal actual = result.getValue(); + Assert.assertEquals(expected,actual); + } +} diff --git a/src/test/java/de/uniregensburg/iamreportingmodule/core/util/FormulaUtilTest.java b/src/test/java/de/uniregensburg/iamreportingmodule/core/util/FormulaUtilTest.java new file mode 100644 index 0000000..54e948f --- /dev/null +++ b/src/test/java/de/uniregensburg/iamreportingmodule/core/util/FormulaUtilTest.java @@ -0,0 +1,255 @@ +package de.uniregensburg.iamreportingmodule.core.util; + +import com.ezylang.evalex.BaseException; +import com.ezylang.evalex.EvaluationException; +import com.ezylang.evalex.Expression; +import com.ezylang.evalex.data.EvaluationValue; +import com.ezylang.evalex.parser.ParseException; +import de.uniregensburg.iamreportingmodule.core.exception.FormulaException; +import de.uniregensburg.iamreportingmodule.core.service.MeasurableService; +import de.uniregensburg.iamreportingmodule.data.entity.Metric; +import de.uniregensburg.iamreportingmodule.data.entity.Result; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +/** + * Tests formula util + * + * @author Julian Bauer + */ +@ActiveProfiles(profiles = "local") +@RunWith(SpringRunner.class) +@SpringBootTest +public class FormulaUtilTest { + + @Autowired + private MeasurableService service; + private FormulaUtil util; + + /** + * Initializes formula util + */ + @Before + public void setupData() { + this.util = new FormulaUtil(service); + } + + /** + * Tests metric calculation + * + * @throws FormulaException + */ + @Test + public void testMetricCalculation() throws FormulaException { + Metric metric = null; + for (Metric m : service.findAllMetrics()) { + if (m.getLabel().equals("identicalPasswordsPercentage")) { + metric = m; + break; + } + } + + assert metric != null; + Result result = util.calculate(metric.getFormula().getFormula()); + + BigDecimal expected = BigDecimal.valueOf(0.023); + BigDecimal actual = result.getValue(); + + Assert.assertEquals(expected, actual); + } + + /** + * Tests basic math formula + * + * @throws EvaluationException + * @throws ParseException + */ + @Test + public void testBasicMathFormula() throws EvaluationException, ParseException { + Expression expression = new Expression("1 + 2 / (4 * SQRT(4))"); + EvaluationValue result = expression.evaluate(); + + Assert.assertEquals(new BigDecimal("1.25"), result.getNumberValue()); + } + + /** + * Tests basic math formula with variables I + * + * @throws EvaluationException + * @throws ParseException + */ + @Test + public void testBasicMathFormulaUsingVariables() throws EvaluationException, ParseException { + Expression expression = new Expression("(a + b) * (a - b)"); + EvaluationValue result = expression + .with("a", 3.5) + .with("b", 2.5) + .evaluate(); + + Assert.assertEquals(new BigDecimal("6"), result.getNumberValue()); + } + + /** + * Tests basic math formula with variables II + * + * @throws EvaluationException + * @throws ParseException + */ + @Test + public void testBasicMathFormulaUsingVariables2() throws EvaluationException, ParseException { + Expression expression = new Expression("(a + b) * (a - b)"); + + Map values = new HashMap<>(); + values.put("a", 3.5); + values.put("b", 2.5); + + EvaluationValue result = expression.withValues(values).evaluate(); + + Assert.assertEquals(new BigDecimal("6"), result.getNumberValue()); + } + + /** + * Tests basic math formula with variables III + * + * @throws EvaluationException + * @throws ParseException + */ + @Test + public void testBasicMathFormulaUsingCustomVariables3() throws EvaluationException, ParseException, FormulaException { + String formulaWithVariables = "({{identicalPasswords}} + 3)"; + String formula = util.replaceVariablesWithMeasurableValues(formulaWithVariables); + + Expression expression = new Expression(formula); + + EvaluationValue result = expression.evaluate(); + + Assert.assertEquals(new BigDecimal("26"), result.getNumberValue()); + } + + /** + * Tests uppercase variable + * + * @throws EvaluationException + * @throws ParseException + */ + @Test + public void testUppercaseVariable() { + String formula = "({{UPPERCASE}} + 1) * (2 - 3)"; + + Exception exception = Assertions.assertThrows(FormulaException.class, () -> util.replaceVariablesWithMeasurableValues(formula)); + + String expectedMessage = "Variable does not match lower camel case"; + String actualMessage = exception.getMessage(); + + Assert.assertEquals(expectedMessage, actualMessage); + } + + /** + * Tests division by zero + */ + @Test + public void testDivisionByZero() { + String formula = "1 / 0"; + + Expression expression = new Expression(formula); + + Exception exception = Assertions.assertThrows(BaseException.class, expression::evaluate); + + String expectedMessage = "Division by zero"; + String actualMessage = exception.getMessage(); + + Assert.assertEquals(expectedMessage, actualMessage); + } + + /** + * Tests brace validation I + */ + @Test + public void testBraceValidation1() { + String formula = "({{identicalPasswords}} + 1) * (2 - 3)"; + boolean condition = util.validateBraces(formula); + Assert.assertTrue(condition); + } + + /** + * Tests brace validation II + */ + @Test + public void testBraceValidation2() { + String formula = "({{identicalPasswords}} + }}weakPasswords{{) * (2 - 3)"; + boolean condition = util.validateBraces(formula); + Assert.assertFalse(condition); + } + + /** + * Tests brace validation III + */ + @Test + public void testBraceValidation3() { + String formula = "({identicalPasswords}} + 1) * (2 - 3)"; + boolean condition = util.validateBraces(formula); + Assert.assertFalse(condition); + } + + /** + * Tests brace validation IV + */ + @Test + public void testBraceValidation4() { + String formula = "({{identicalPasswords} + 1) * (2 - 3)"; + boolean condition = util.validateBraces(formula); + Assert.assertFalse(condition); + } + + /** + * Tests brace validation V + */ + @Test + public void testBraceValidation5() { + String formula = "({{identicalPasswords}} + {{weakPasswords) * (2 - 3)"; + boolean condition = util.validateBraces(formula); + Assert.assertFalse(condition); + } + + /** + * Tests brace validation VI + */ + @Test + public void testBraceValidation6() { + String formula = "({{identicalPasswords}} + weakPasswords}}) * (2 - 3)"; + boolean condition = util.validateBraces(formula); + Assert.assertFalse(condition); + } + + /** + * Tests brace validation VII + */ + @Test + public void testBraceValidation7() { + String formula = "({{identicalPasswords}} + {{weakPasswords}) * (2 - 3)"; + boolean condition = util.validateBraces(formula); + Assert.assertFalse(condition); + } + + /** + * Tests brace validation VIII + */ + @Test + public void testBraceValidation8() { + String formula = "({{identicalPasswords}} + {{weakPasswords}}) * (2 - 3)"; + boolean condition = util.validateBraces(formula); + Assert.assertTrue(condition); + } + +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..37f32e7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,39 @@ +// This TypeScript configuration file is generated by vaadin-maven-plugin. +// This is needed for TypeScript compiler to compile your TypeScript code in the project. +// It is recommended to commit this file to the VCS. +// You might want to change the configurations to fit your preferences +// For more information about the configurations, please refer to http://www.typescriptlang.org/docs/handbook/tsconfig-json.html +{ + "flow_version": "23.3.4", + "compilerOptions": { + "sourceMap": true, + "jsx": "react-jsx", + "inlineSources": true, + "module": "esNext", + "target": "es2020", + "moduleResolution": "node", + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noImplicitAny": true, + "noImplicitThis": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "experimentalDecorators": true, + "useDefineForClassFields": false, + "baseUrl": "frontend", + "paths": { + "@vaadin/flow-frontend": ["generated/jar-resources"], + "@vaadin/flow-frontend/*": ["generated/jar-resources/*"], + "Frontend/*": ["*"] + } + }, + "include": [ + "frontend/**/*", + "types.d.ts" + ], + "exclude": [ + "frontend/generated/jar-resources/**" + ] +} diff --git a/types.d.ts b/types.d.ts new file mode 100644 index 0000000..b86a239 --- /dev/null +++ b/types.d.ts @@ -0,0 +1,5 @@ +declare module '*.css' { + import { CSSResultGroup } from 'lit'; + const content: CSSResultGroup; + export default content; +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..4d6a022 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,9 @@ +import { UserConfigFn } from 'vite'; +import { overrideVaadinConfig } from './vite.generated'; + +const customConfig: UserConfigFn = (env) => ({ + // Here you can add custom Vite parameters + // https://vitejs.dev/config/ +}); + +export default overrideVaadinConfig(customConfig);