diff --git a/.github/workflows/codecov-report.yml b/.github/workflows/codecov-report.yml
index 20ec118028..53a11c68cd 100644
--- a/.github/workflows/codecov-report.yml
+++ b/.github/workflows/codecov-report.yml
@@ -1,6 +1,98 @@
-- name: Upload coverage reports to Codecov
- uses: codecov/codecov-action@v3
- with:
- fail_ci_if_error: false
- env:
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+name: CodCov, Run Backend and Frontend Tests
+
+on:
+ push:
+ branches:
+ - '**'
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ # Set up Java for backend tests
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'zulu'
+ java-version: '8'
+
+ # Set up Node.js for frontend tests
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '16'
+
+ # Install dependencies for backend
+ - name: Install backend dependencies
+ run: |
+ #cd src/test
+ mvn clean install
+ mkdir -p src/surefire-reports
+ mkdir -p frontend/coverage
+
+ # Run backend tests with coverage
+ - name: Run backend tests
+ run: mvn test -e
+ working-directory: ./
+ continue-on-error: true
+
+ # Install dependencies for frontend
+ - name: Install frontend dependencies
+ run: |
+ cd frontend
+ npm install
+
+ # Run frontend tests with coverage
+ - name: Run frontend tests
+ run: npm run test --coverage
+ working-directory: frontend
+ continue-on-error: true
+
+ # Upload test results and coverage
+ - name: Upload coverage results
+ uses: actions/upload-artifact@v3
+ with:
+ name: test-results
+ path: |
+ target/surefire-reports
+ frontend/coverage
+
+ # List coverage files
+ - name: Verify coverage files
+ run: |
+ echo "Checking backend coverage files..."
+ ls -l target/site/jacoco/ || echo "No backend coverage files found"
+ echo "Checking frontend coverage files..."
+ ls -l frontend/coverage/ || echo "No frontend coverage files found"
+
+
+ # Upload to Codecov
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v3
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }} # Add Codecov token as a secret in GitHub
+ files: |
+ target/site/jacoco/jacoco.xml
+ frontend/coverage/lcov.info
+ flags: backend,frontend
+ name: codecov-coverage-report
+ fail_ci_if_error: false # Does not block merge if there’s an error
+
+ - name: List files
+ run: |
+ #cd src/test
+ ls -l target/surefire-reports
+ ls -l frontend/coverage
+
+
+ # Display test coverage in the summary (optional)
+ - name: Display test coverage summary
+ run: |
+ echo "Backend Test Results:"
+ cat target/surefire-reports/*.txt || true
+ echo "Frontend Test Coverage Summary:"
+ cat frontend/coverage/*.* || true
diff --git a/config/youtube_extract.sh b/config/youtube_extract.sh
deleted file mode 100755
index 4052ffa27d..0000000000
--- a/config/youtube_extract.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-mp4in=$1
-outputdir=$2
-fps=$3
-
-if [ "$fps" = "" ] ; then
- fps=0.5
-fi
-
-if [ ! -d $outputdir ] ; then
- mkdir -p $outputdir
-fi
-rm -f $outputdir/*jpg
-export FFREPORT="file=$outputdir/ffreport.log:level=32"
-
-### note: keyframes doesnt really seem to work well... :( best to go with framerate
-#keyframes
-###ffmpeg -i mn5a3XJhJd4/mn5a3XJhJd4.mp4 -qscale:v 2 -vf select="eq(pict_type\,I)" -vsync 0 frame%05d.jpg
-
-#by framerate (r = fps)
-ffmpeg -report -loglevel quiet -i $mp4in -r $fps -f image2 $outputdir/frame%05d.jpg
-
-ls $outputdir/frame*jpg
diff --git a/config/youtube_get.sh b/config/youtube_get.sh
deleted file mode 100755
index 07710fe6c9..0000000000
--- a/config/youtube_get.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-ytid=$1
-dir=$2
-yturl="https://www.youtube.com/watch?v=$ytid"
-
-if [ ! -d $dir ] ; then
- mkdir $dir
-fi
-
-
- #--write-annotations \
- #--write-description \
-
-youtube-dl -o $dir/$ytid.mp4 \
- -q \
- -f mp4 \
- --write-info-json \
- --write-all-thumbnails \
- $yturl
diff --git a/config/ytCron.pl b/config/ytCron.pl
deleted file mode 100755
index 66d07ae849..0000000000
--- a/config/ytCron.pl
+++ /dev/null
@@ -1,146 +0,0 @@
-#!/usr/bin/perl
-
-use utf8;
-use open ':std', ':encoding(UTF-8)';
-use JSON;
-use URI::Escape;
-use Data::Dumper;
-use File::Slurp;
-
-
-my $BASE_URL = 'http://localhost';
-my $search_keyword = $ARGV[0] || '"whale shark"';
-my $max_videos = $ARGV[1] || 1;
-my $tmp_prefix = '/tmp/yt-ws.' . time;
-
-print "searching on keyword '$search_keyword' at $BASE_URL\n";
-my $search_results = &search_for($search_keyword);
-#print Dumper($search_results);
-die "failed search_results return value" if (!$search_results || !$search_results->{success} || !$search_results->{videos});
-printf("count: %d (max %d); since %s\n", $search_results->{count}, $max_videos, $search_results->{sinceDateTime});
-if ($search_results->{count} < 1) {
- print "no results on search; exiting\n";
- exit;
-}
-
-my $ct = 1;
-foreach my $v (@{$search_results->{videos}}) {
- last if ($ct > $max_videos);
- printf("- %2d %s https://www.youtube.com/watch?v=%s %s\n", $ct, $v->{id}->{videoId}, $v->{id}->{videoId}, $v->{snippet}->{title});
- my $res = &create($v->{id}->{videoId});
- $ct++;
- if (!$res || !$res->{success}) {
- print " * failed to create MediaAsset (usually means not downloadable); skipping\n";
- next;
- }
- my $vurl = "$BASE_URL/obrowse.jsp?type=MediaAsset&id=" . ($res->{assetId} + 2);
- if ($res->{info} =~ /already exists/) {
- print " . MediaAsset already exists at $res->{assetId}; (video $vurl) skipping\n";
- next;
- }
- print " + successfully created MediaAsset $res->{assetId} (video $vurl)\n";
- my $ext = &extract($res->{assetId});
- if (!$ext || !$ext->{success} || !$ext->{frameAssets}) {
- print " * failed to extract MediaAsset id=$res->{assetId}; skipping\n";
- next;
- }
- print " + successfully extracted " . scalar(@{$ext->{frameAssets}}) . " frames\n";
- my $ia = &ia($ext->{frameAssets});
- if (!$ia || !$ia->{success}) {
- print " * failed to sent to IA for detection; skipping\n";
- next;
- }
- print " + successfully sent to IA for detection: $BASE_URL/yt.html?$ia->{taskId}\n";
-}
-
-
-
-
-sub search_for {
- my $keyword = uri_escape(shift);
- #my $cmd = "curl -s '$BASE_URL/ytSearch.jsp?keyword=$keyword'";
- my $raw_file = "$tmp_prefix-search-raw.json";
- my $since = (time - (2.5*60*60*24)) * 1000;
-#$since = 1517097600001;
-#warn "($since)";
- system("curl -s '$BASE_URL/ytSearch.jsp?keyword=$keyword&since=$since' > $raw_file");
- return &json_from_file($raw_file);
-
- open(R, $raw_file) || die "unable to open $raw_file";
- my $raw = join('', );
- close(R);
- my $json;
- eval { $json = from_json($raw); };
- print " !!! could not parse json in $raw_file: $@" if $@;
- return $json;
-}
-
-
-sub create {
- my $id = shift;
- return {} unless $id;
- my $create_out = "$tmp_prefix-create-$id-out.json";
- system("curl -s $BASE_URL/ytCreate.jsp?id=$id > $create_out");
- return &json_from_file($create_out);
-
- open(O, $create_out) || die "unable to open $create_out";
- my $raw = join('', );
- close(O);
- my $json;
- eval { $json = from_json($raw); };
- print " !!! could not parse json in $create_out: $@" if $@;
- return $json;
-}
-
-
-sub extract {
- my $id = shift;
- return {} unless $id;
- my $extract_out = "$tmp_prefix-extract-$id-out.json";
- system("curl -s $BASE_URL/ytExtract.jsp?id=$id > $extract_out");
- return &json_from_file($extract_out);
-
- open(O, $extract_out) || die "unable to open $extract_out";
- my $raw = join('', );
- close(O);
- my $json;
- eval { $json = from_json($raw); };
- print " !!! could not parse json in $extract_out: $@" if $@;
- return $json;
-}
-
-
-sub ia {
- my $ids = shift;
- return {} unless ($ids && scalar(@$ids));
- my $ia_data = to_json({ detect => { mediaAssetIds => $ids } });
- my $ia_out = "$tmp_prefix-ia-" . $ids->[0] . "-out.json";
- system("curl -s -X POST -H 'Content-Type: application/json' -d '$ia_data' $BASE_URL/ia > $ia_out");
- return &json_from_file($ia_out);
-
- open(O, $ia_out) || die "unable to open $ia_out";
- my $raw = join('', );
- close(O);
- my $json;
- eval { $json = from_json($raw); };
- print " !!! could not parse json in $ia_out: $@" if $@;
- return $json;
-}
-
-
-
-sub json_from_file {
- my $filename = shift;
- sleep 1; #cuz i dont trust that system() was done?
- return unless -e $filename;
- my $content = read_file($filename);
- return unless $content;
- my $json;
- eval { $json = from_json($content); };
- if ($@) {
-#print "---------($filename)---------\n" . substr($content, 0, 1000) . "\n-------------------\n";
- #print " !!! could not parse json in $filename: $@";
- print " !!! could not parse json in $filename\n";
- }
- return $json;
-}
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 4129a6b0c8..3de883b5a2 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -8,20 +8,24 @@ export default [
pluginJs.configs.recommended,
pluginReactConfig,
{
- files: ["**/*.{js,mjs,cjs,jsx}"],
+ files: ["**/*.{js,mjs,cjs,jsx}"],
plugins: {
- "react-hooks": reactHooks,
+ "react-hooks": reactHooks,
},
languageOptions: {
- globals: globals.browser,
+ globals: {
+ ...globals.browser,
+ process: "readonly",
+ },
parser: babelParser,
+
},
settings: {
react: {
version: "detect"
}
- },
-
+ },
+
rules: {
"semi": 2,
"react/prop-types": 0,
@@ -54,19 +58,19 @@ export default [
"no-param-reassign": 0,
"no-mixed-operators": 0,
"no-else-return": 0,
-
+
},
},
{
files: ['frontend/babel.config.js', 'frontend/jest.config.js', 'babel.config.js'], // Specify the config files
languageOptions: {
globals: {
- require: "readonly",
+ require: "readonly",
module: "readonly",
- __dirname: "readonly",
+ __dirname: "readonly",
process: "readonly",
},
- },
+ },
},
{
files: ["**/__tests__/**/*.{js,jsx}", "**/*.test.{js,jsx}"],
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 4c940481dd..4a01c9476f 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,20 +8,28 @@
"name": "frontend",
"version": "0.1.0",
"dependencies": {
+ "@flowjs/flow.js": "^2.14.1",
"@testing-library/user-event": "^13.5.0",
+ "antd": "^5.21.5",
"autoprefixer": "^10.4.18",
"axios": "^1.7.4",
"bootstrap": "^5.3.2",
"copy-webpack-plugin": "^12.0.2",
+ "exif-js": "^2.3.0",
+ "flow.js": "^0.2.6",
"google-map-react": "^2.2.1",
"js-cookie": "^3.0.5",
"lodash-es": "^4.17.21",
+ "mobx": "6.13.3",
+ "mobx-react-lite": "^4.0.7",
+ "moment": "^2.30.1",
"postcss-cli": "^11.0.0",
"rc-slider": "^10.6.2",
"react": "^18.2.0",
"react-bootstrap": "^2.10.1",
"react-burger-menu": "^3.0.9",
"react-data-table-component": "^7.6.2",
+ "react-datetime": "^3.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.52.1",
"react-intl": "^6.6.2",
@@ -54,7 +62,7 @@
"@testing-library/react": "^16.0.1",
"bootstrap-icons": "^1.11.3",
"css-loader": "^6.10.0",
- "date-fns": "^3.6.0",
+ "date-fns": "^4.1.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.35.0",
"globals": "^15.9.0",
@@ -111,6 +119,121 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@ant-design/colors": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.1.0.tgz",
+ "integrity": "sha512-MMoDGWn1y9LdQJQSHiCC20x3uZ3CwQnv9QMz6pCmJOrqdgM9YxsoVVY0wtrdXbmfSgnV0KNk6zi09NAhMR2jvg==",
+ "license": "MIT",
+ "dependencies": {
+ "@ctrl/tinycolor": "^3.6.1"
+ }
+ },
+ "node_modules/@ant-design/cssinjs": {
+ "version": "1.21.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.21.1.tgz",
+ "integrity": "sha512-tyWnlK+XH7Bumd0byfbCiZNK43HEubMoCcu9VxwsAwiHdHTgWa+tMN0/yvxa+e8EzuFP1WdUNNPclRpVtD33lg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.11.1",
+ "@emotion/hash": "^0.8.0",
+ "@emotion/unitless": "^0.7.5",
+ "classnames": "^2.3.1",
+ "csstype": "^3.1.3",
+ "rc-util": "^5.35.0",
+ "stylis": "^4.3.3"
+ },
+ "peerDependencies": {
+ "react": ">=16.0.0",
+ "react-dom": ">=16.0.0"
+ }
+ },
+ "node_modules/@ant-design/cssinjs-utils": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.1.tgz",
+ "integrity": "sha512-2HAiyGGGnM0es40SxdszeQAU5iWp41wBIInq+ONTCKjlSKOrzQfnw4JDtB8IBmqE6tQaEKwmzTP2LGdt5DSwYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@ant-design/cssinjs": "^1.21.0",
+ "@babel/runtime": "^7.23.2",
+ "rc-util": "^5.38.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/@ant-design/cssinjs/node_modules/@emotion/hash": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
+ "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==",
+ "license": "MIT"
+ },
+ "node_modules/@ant-design/cssinjs/node_modules/@emotion/unitless": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
+ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==",
+ "license": "MIT"
+ },
+ "node_modules/@ant-design/cssinjs/node_modules/stylis": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz",
+ "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==",
+ "license": "MIT"
+ },
+ "node_modules/@ant-design/fast-color": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz",
+ "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=8.x"
+ }
+ },
+ "node_modules/@ant-design/icons": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.5.1.tgz",
+ "integrity": "sha512-0UrM02MA2iDIgvLatWrj6YTCYe0F/cwXvVE0E2SqGrL7PZireQwgEKTKBisWpZyal5eXZLvuM98kju6YtYne8w==",
+ "license": "MIT",
+ "dependencies": {
+ "@ant-design/colors": "^7.0.0",
+ "@ant-design/icons-svg": "^4.4.0",
+ "@babel/runtime": "^7.24.8",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.31.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "peerDependencies": {
+ "react": ">=16.0.0",
+ "react-dom": ">=16.0.0"
+ }
+ },
+ "node_modules/@ant-design/icons-svg": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz",
+ "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==",
+ "license": "MIT"
+ },
+ "node_modules/@ant-design/react-slick": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz",
+ "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.4",
+ "classnames": "^2.2.5",
+ "json2mq": "^0.2.0",
+ "resize-observer-polyfill": "^1.5.1",
+ "throttle-debounce": "^5.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
@@ -2037,9 +2160,10 @@
"integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
},
"node_modules/@babel/runtime": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
- "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz",
+ "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==",
+ "license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -2376,6 +2500,15 @@
"postcss-selector-parser": "^6.0.10"
}
},
+ "node_modules/@ctrl/tinycolor": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
+ "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/@discoveryjs/json-ext": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
@@ -2454,11 +2587,6 @@
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
"integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="
},
- "node_modules/@emotion/cache/node_modules/@emotion/weak-memoize": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
- "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="
- },
"node_modules/@emotion/cache/node_modules/stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
@@ -2483,17 +2611,18 @@
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
},
"node_modules/@emotion/react": {
- "version": "11.11.4",
- "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
- "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
+ "version": "11.13.3",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz",
+ "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==",
+ "license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
- "@emotion/babel-plugin": "^11.11.0",
- "@emotion/cache": "^11.11.0",
- "@emotion/serialize": "^1.1.3",
- "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
- "@emotion/utils": "^1.2.1",
- "@emotion/weak-memoize": "^0.3.1",
+ "@emotion/babel-plugin": "^11.12.0",
+ "@emotion/cache": "^11.13.0",
+ "@emotion/serialize": "^1.3.1",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
+ "@emotion/utils": "^1.4.0",
+ "@emotion/weak-memoize": "^0.4.0",
"hoist-non-react-statics": "^3.3.1"
},
"peerDependencies": {
@@ -2506,14 +2635,15 @@
}
},
"node_modules/@emotion/serialize": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.1.tgz",
- "integrity": "sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz",
+ "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==",
+ "license": "MIT",
"dependencies": {
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/unitless": "^0.10.0",
- "@emotion/utils": "^1.4.0",
+ "@emotion/utils": "^1.4.1",
"csstype": "^3.0.2"
}
},
@@ -2546,14 +2676,16 @@
}
},
"node_modules/@emotion/utils": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz",
- "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ=="
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz",
+ "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==",
+ "license": "MIT"
},
"node_modules/@emotion/weak-memoize": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
- "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
+ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
+ "license": "MIT"
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
@@ -2667,9 +2799,15 @@
}
},
"node_modules/@floating-ui/utils": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz",
- "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA=="
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
+ "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
+ "license": "MIT"
+ },
+ "node_modules/@flowjs/flow.js": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/@flowjs/flow.js/-/flow.js-2.14.1.tgz",
+ "integrity": "sha512-99DWlPnksOOS8uHfo+bhSjvs8d2MfLTB/22JBDC2ONwz/OCdP+gL/iiM4puMSTE2wH4A2/+J0eMc7pKwusXunw=="
},
"node_modules/@formatjs/ecma402-abstract": {
"version": "1.18.2",
@@ -3744,6 +3882,155 @@
"url": "https://opencollective.com/popperjs"
}
},
+ "node_modules/@rc-component/async-validator": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz",
+ "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.24.4"
+ },
+ "engines": {
+ "node": ">=14.x"
+ }
+ },
+ "node_modules/@rc-component/color-picker": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz",
+ "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@ant-design/fast-color": "^2.0.6",
+ "@babel/runtime": "^7.23.6",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.38.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/@rc-component/context": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz",
+ "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "rc-util": "^5.27.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/@rc-component/mini-decimal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz",
+ "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.0"
+ },
+ "engines": {
+ "node": ">=8.x"
+ }
+ },
+ "node_modules/@rc-component/mutate-observer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz",
+ "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.0",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.24.4"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/@rc-component/portal": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz",
+ "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.0",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.24.4"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/@rc-component/qrcode": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz",
+ "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.24.7",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.38.0"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/@rc-component/tour": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz",
+ "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.0",
+ "@rc-component/portal": "^1.0.0-9",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.24.4"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/@rc-component/trigger": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.3.tgz",
+ "integrity": "sha512-X1oFIpKoXAMXNDYCviOmTfuNuYxE4h5laBsyCqVAVMjNHxoF3/uiyA7XdegK1XbCvBbCZ6P6byWrEoDRpKL8+A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2",
+ "@rc-component/portal": "^1.1.0",
+ "classnames": "^2.3.2",
+ "rc-motion": "^2.0.0",
+ "rc-resize-observer": "^1.3.1",
+ "rc-util": "^5.38.0"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
"node_modules/@react-aria/ssr": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.2.tgz",
@@ -4593,9 +4880,10 @@
"integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA=="
},
"node_modules/@types/prop-types": {
- "version": "15.7.12",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
- "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
+ "version": "15.7.13",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
+ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
+ "license": "MIT"
},
"node_modules/@types/q": {
"version": "1.5.8",
@@ -5364,6 +5652,89 @@
"node": ">=4"
}
},
+ "node_modules/antd": {
+ "version": "5.21.5",
+ "resolved": "https://registry.npmjs.org/antd/-/antd-5.21.5.tgz",
+ "integrity": "sha512-g/c8VkdruKDCVA6di9Ow1fG6dLtYJ1IOraPo7vXaY7DoQ56A3HExaFaH0fBEwTYKC0ICeftC4iA5eAjrF6/b9w==",
+ "license": "MIT",
+ "dependencies": {
+ "@ant-design/colors": "^7.1.0",
+ "@ant-design/cssinjs": "^1.21.1",
+ "@ant-design/cssinjs-utils": "^1.1.1",
+ "@ant-design/icons": "^5.5.1",
+ "@ant-design/react-slick": "~1.1.2",
+ "@babel/runtime": "^7.25.6",
+ "@ctrl/tinycolor": "^3.6.1",
+ "@rc-component/color-picker": "~2.0.1",
+ "@rc-component/mutate-observer": "^1.1.0",
+ "@rc-component/qrcode": "~1.0.0",
+ "@rc-component/tour": "~1.15.1",
+ "@rc-component/trigger": "^2.2.3",
+ "classnames": "^2.5.1",
+ "copy-to-clipboard": "^3.3.3",
+ "dayjs": "^1.11.11",
+ "rc-cascader": "~3.28.2",
+ "rc-checkbox": "~3.3.0",
+ "rc-collapse": "~3.8.0",
+ "rc-dialog": "~9.6.0",
+ "rc-drawer": "~7.2.0",
+ "rc-dropdown": "~4.2.0",
+ "rc-field-form": "~2.4.0",
+ "rc-image": "~7.11.0",
+ "rc-input": "~1.6.3",
+ "rc-input-number": "~9.2.0",
+ "rc-mentions": "~2.16.1",
+ "rc-menu": "~9.15.1",
+ "rc-motion": "^2.9.3",
+ "rc-notification": "~5.6.2",
+ "rc-pagination": "~4.3.0",
+ "rc-picker": "~4.6.15",
+ "rc-progress": "~4.0.0",
+ "rc-rate": "~2.13.0",
+ "rc-resize-observer": "^1.4.0",
+ "rc-segmented": "~2.5.0",
+ "rc-select": "~14.15.2",
+ "rc-slider": "~11.1.7",
+ "rc-steps": "~6.0.1",
+ "rc-switch": "~4.1.0",
+ "rc-table": "~7.47.5",
+ "rc-tabs": "~15.3.0",
+ "rc-textarea": "~1.8.2",
+ "rc-tooltip": "~6.2.1",
+ "rc-tree": "~5.9.0",
+ "rc-tree-select": "~5.23.0",
+ "rc-upload": "~4.8.1",
+ "rc-util": "^5.43.0",
+ "scroll-into-view-if-needed": "^3.1.0",
+ "throttle-debounce": "^5.0.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/ant-design"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/antd/node_modules/rc-slider": {
+ "version": "11.1.7",
+ "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.7.tgz",
+ "integrity": "sha512-ytYbZei81TX7otdC0QvoYD72XSlxvTihNth5OeZ6PMXyEDq/vHdWFulQmfDGyXK1NwKwSlKgpvINOa88uT5g2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.5",
+ "rc-util": "^5.36.0"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
@@ -5441,6 +5812,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/array-tree-filter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
+ "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==",
+ "license": "MIT"
+ },
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -6705,6 +7082,12 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
+ "node_modules/compute-scroll-into-view": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz",
+ "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==",
+ "license": "MIT"
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -6760,6 +7143,15 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "license": "MIT",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
"node_modules/copy-webpack-plugin": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz",
@@ -7436,15 +7828,22 @@
}
},
"node_modules/date-fns": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
- "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
- "dev": true,
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "devOptional": true,
+ "license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
+ "node_modules/dayjs": {
+ "version": "1.11.13",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
+ "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
+ "license": "MIT"
+ },
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
@@ -8902,6 +9301,12 @@
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
+ "node_modules/exif-js": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/exif-js/-/exif-js-2.3.0.tgz",
+ "integrity": "sha512-1Og9pAzG2FZRVlaavH8bB8BTeHcjMdJhKmeQITkX+uLRCD0xPtKAdZ2clZmQdJ56p9adXtJ8+jwrGp/4505lYg==",
+ "license": "MIT"
+ },
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -9228,6 +9633,11 @@
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="
},
+ "node_modules/flow.js": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/flow.js/-/flow.js-0.2.6.tgz",
+ "integrity": "sha512-KvXsCPNj3uIOnXu07qXiqsxjqEveAe5nAM8W3ULTEDPynoMZlWvMyKZdH8pOh5oCFy7uXtgWnZQZOzgoH9Epdw=="
+ },
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
@@ -13085,6 +13495,15 @@
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
},
+ "node_modules/json2mq": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
+ "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==",
+ "license": "MIT",
+ "dependencies": {
+ "string-convert": "^0.2.0"
+ }
+ },
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -13626,6 +14045,48 @@
"mkdirp": "bin/cmd.js"
}
},
+ "node_modules/mobx": {
+ "version": "6.13.3",
+ "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.13.3.tgz",
+ "integrity": "sha512-YtAS+ZMbdpbHYUU4ESht3na8KiX11KuMT1yOiKtbKlQ0GZkHDYPKyEw/Tdp7h7aHyLrTWj2TBaSNJ6bCr638iQ==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mobx"
+ }
+ },
+ "node_modules/mobx-react-lite": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-4.0.7.tgz",
+ "integrity": "sha512-RjwdseshK9Mg8On5tyJZHtGD+J78ZnCnRaxeQDSiciKVQDUbfZcXhmld0VMxAwvcTnPEHZySGGewm467Fcpreg==",
+ "dependencies": {
+ "use-sync-external-store": "^1.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mobx"
+ },
+ "peerDependencies": {
+ "mobx": "^6.9.0",
+ "react": "^16.8.0 || ^17 || ^18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/moment": {
+ "version": "2.30.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/mrmime": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
@@ -15998,6 +16459,401 @@
"node": ">=0.10.0"
}
},
+ "node_modules/rc-cascader": {
+ "version": "3.28.2",
+ "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.28.2.tgz",
+ "integrity": "sha512-8f+JgM83iLTvjgdkgU7GfI4qY8icXOBP0cGZjOdx2iJAkEe8ucobxDQAVE69UD/c3ehCxZlcgEHeD5hFmypbUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "array-tree-filter": "^2.1.0",
+ "classnames": "^2.3.1",
+ "rc-select": "~14.15.0",
+ "rc-tree": "~5.9.0",
+ "rc-util": "^5.37.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-checkbox": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.3.0.tgz",
+ "integrity": "sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.25.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-collapse": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.8.0.tgz",
+ "integrity": "sha512-YVBkssrKPBG09TGfcWWGj8zJBYD9G3XuTy89t5iUmSXrIXEAnO1M+qjUxRW6b4Qi0+wNWG6MHJF/+US+nmIlzA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-motion": "^2.3.4",
+ "rc-util": "^5.27.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-dialog": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz",
+ "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/portal": "^1.0.0-8",
+ "classnames": "^2.2.6",
+ "rc-motion": "^2.3.0",
+ "rc-util": "^5.21.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-drawer": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz",
+ "integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.9",
+ "@rc-component/portal": "^1.1.1",
+ "classnames": "^2.2.6",
+ "rc-motion": "^2.6.1",
+ "rc-util": "^5.38.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-dropdown": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz",
+ "integrity": "sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.17.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.11.0",
+ "react-dom": ">=16.11.0"
+ }
+ },
+ "node_modules/rc-field-form": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.4.0.tgz",
+ "integrity": "sha512-XZ/lF9iqf9HXApIHQHqzJK5v2w4mkUMsVqAzOyWVzoiwwXEavY6Tpuw7HavgzIoD+huVff4JghSGcgEfX6eycg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.0",
+ "@rc-component/async-validator": "^5.0.3",
+ "rc-util": "^5.32.2"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-image": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.11.0.tgz",
+ "integrity": "sha512-aZkTEZXqeqfPZtnSdNUnKQA0N/3MbgR7nUnZ+/4MfSFWPFHZau4p5r5ShaI0KPEMnNjv4kijSCFq/9wtJpwykw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.11.2",
+ "@rc-component/portal": "^1.0.2",
+ "classnames": "^2.2.6",
+ "rc-dialog": "~9.6.0",
+ "rc-motion": "^2.6.2",
+ "rc-util": "^5.34.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-input": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.6.3.tgz",
+ "integrity": "sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.18.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.0.0",
+ "react-dom": ">=16.0.0"
+ }
+ },
+ "node_modules/rc-input-number": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.2.0.tgz",
+ "integrity": "sha512-5XZFhBCV5f9UQ62AZ2hFbEY8iZT/dm23Q1kAg0H8EvOgD3UDbYYJAayoVIkM3lQaCqYAW5gV0yV3vjw1XtzWHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/mini-decimal": "^1.0.1",
+ "classnames": "^2.2.5",
+ "rc-input": "~1.6.0",
+ "rc-util": "^5.40.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-mentions": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.16.1.tgz",
+ "integrity": "sha512-GnhSTGP9Mtv6pqFFGQze44LlrtWOjHNrUUAcsdo9DnNAhN4pwVPEWy4z+2jpjkiGlJ3VoXdvMHcNDQdfI9fEaw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.22.5",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.2.6",
+ "rc-input": "~1.6.0",
+ "rc-menu": "~9.15.1",
+ "rc-textarea": "~1.8.0",
+ "rc-util": "^5.34.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-menu": {
+ "version": "9.15.1",
+ "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.15.1.tgz",
+ "integrity": "sha512-UKporqU6LPfHnpPmtP6hdEK4iO5Q+b7BRv/uRpxdIyDGplZy9jwUjsnpev5bs3PQKB0H0n34WAPDfjAfn3kAPA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "2.x",
+ "rc-motion": "^2.4.3",
+ "rc-overflow": "^1.3.1",
+ "rc-util": "^5.27.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-motion": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.3.tgz",
+ "integrity": "sha512-rkW47ABVkic7WEB0EKJqzySpvDqwl60/tdkY7hWP7dYnh5pm0SzJpo54oW3TDUGXV5wfxXFmMkxrzRRbotQ0+w==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.43.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-notification": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.2.tgz",
+ "integrity": "sha512-Id4IYMoii3zzrG0lB0gD6dPgJx4Iu95Xu0BQrhHIbp7ZnAZbLqdqQ73aIWH0d0UFcElxwaKjnzNovTjo7kXz7g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-motion": "^2.9.0",
+ "rc-util": "^5.20.1"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-overflow": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz",
+ "integrity": "sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-resize-observer": "^1.0.0",
+ "rc-util": "^5.37.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-pagination": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.3.0.tgz",
+ "integrity": "sha512-UubEWA0ShnroQ1tDa291Fzw6kj0iOeF26IsUObxYTpimgj4/qPCWVFl18RLZE+0Up1IZg0IK4pMn6nB3mjvB7g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.38.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-picker": {
+ "version": "4.6.15",
+ "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.6.15.tgz",
+ "integrity": "sha512-OWZ1yrMie+KN2uEUfYCfS4b2Vu6RC1FWwNI0s+qypsc3wRt7g+peuZKVIzXCTaJwyyZruo80+akPg2+GmyiJjw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.24.7",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.2.1",
+ "rc-overflow": "^1.3.2",
+ "rc-resize-observer": "^1.4.0",
+ "rc-util": "^5.43.0"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "date-fns": ">= 2.x",
+ "dayjs": ">= 1.x",
+ "luxon": ">= 3.x",
+ "moment": ">= 2.x",
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ },
+ "peerDependenciesMeta": {
+ "date-fns": {
+ "optional": true
+ },
+ "dayjs": {
+ "optional": true
+ },
+ "luxon": {
+ "optional": true
+ },
+ "moment": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/rc-progress": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz",
+ "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.16.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-rate": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz",
+ "integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.5",
+ "rc-util": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-resize-observer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz",
+ "integrity": "sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.7",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.38.0",
+ "resize-observer-polyfill": "^1.5.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-segmented": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.5.0.tgz",
+ "integrity": "sha512-B28Fe3J9iUFOhFJET3RoXAPFJ2u47QvLSYcZWC4tFYNGPEjug5LAxEasZlA/PpAxhdOPqGWsGbSj7ftneukJnw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-motion": "^2.4.4",
+ "rc-util": "^5.17.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.0.0",
+ "react-dom": ">=16.0.0"
+ }
+ },
+ "node_modules/rc-select": {
+ "version": "14.15.2",
+ "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.15.2.tgz",
+ "integrity": "sha512-oNoXlaFmpqXYcQDzcPVLrEqS2J9c+/+oJuGrlXeVVX/gVgrbHa5YcyiRUXRydFjyuA7GP3elRuLF7Y3Tfwltlw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/trigger": "^2.1.1",
+ "classnames": "2.x",
+ "rc-motion": "^2.0.1",
+ "rc-overflow": "^1.3.1",
+ "rc-util": "^5.16.1",
+ "rc-virtual-list": "^3.5.2"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*"
+ }
+ },
"node_modules/rc-slider": {
"version": "10.6.2",
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.6.2.tgz",
@@ -16015,6 +16871,166 @@
"react-dom": ">=16.9.0"
}
},
+ "node_modules/rc-steps": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz",
+ "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.16.7",
+ "classnames": "^2.2.3",
+ "rc-util": "^5.16.1"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-switch": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz",
+ "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.30.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-table": {
+ "version": "7.47.5",
+ "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.47.5.tgz",
+ "integrity": "sha512-fzq+V9j/atbPIcvs3emuclaEoXulwQpIiJA6/7ey52j8+9cJ4P8DGmp4YzfUVDrb3qhgedcVeD6eRgUrokwVEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/context": "^1.4.0",
+ "classnames": "^2.2.5",
+ "rc-resize-observer": "^1.1.0",
+ "rc-util": "^5.41.0",
+ "rc-virtual-list": "^3.14.2"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-tabs": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.3.0.tgz",
+ "integrity": "sha512-lzE18r+zppT/jZWOAWS6ntdkDUKHOLJzqMi5UAij1LeKwOaQaupupAoI9Srn73GRzVpmGznkECMRrzkRusC40A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.11.2",
+ "classnames": "2.x",
+ "rc-dropdown": "~4.2.0",
+ "rc-menu": "~9.15.1",
+ "rc-motion": "^2.6.2",
+ "rc-resize-observer": "^1.0.0",
+ "rc-util": "^5.34.1"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-textarea": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.8.2.tgz",
+ "integrity": "sha512-UFAezAqltyR00a8Lf0IPAyTd29Jj9ee8wt8DqXyDMal7r/Cg/nDt3e1OOv3Th4W6mKaZijjgwuPXhAfVNTN8sw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.1",
+ "rc-input": "~1.6.0",
+ "rc-resize-observer": "^1.0.0",
+ "rc-util": "^5.27.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-tooltip": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.2.1.tgz",
+ "integrity": "sha512-rws0duD/3sHHsD905Nex7FvoUGy2UBQRhTkKxeEvr2FB+r21HsOxcDJI0TzyO8NHhnAA8ILr8pfbSBg5Jj5KBg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.11.2",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-tree": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.9.0.tgz",
+ "integrity": "sha512-CPrgOvm9d/9E+izTONKSngNzQdIEjMox2PBufWjS1wf7vxtvmCWzK1SlpHbRY6IaBfJIeZ+88RkcIevf729cRg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-motion": "^2.0.1",
+ "rc-util": "^5.16.1",
+ "rc-virtual-list": "^3.5.1"
+ },
+ "engines": {
+ "node": ">=10.x"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*"
+ }
+ },
+ "node_modules/rc-tree-select": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.23.0.tgz",
+ "integrity": "sha512-aQGi2tFSRw1WbXv0UVXPzHm09E0cSvUVZMLxQtMv3rnZZpNmdRXWrnd9QkLNlVH31F+X5rgghmdSFF3yZW0N9A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-select": "~14.15.0",
+ "rc-tree": "~5.9.0",
+ "rc-util": "^5.16.1"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*"
+ }
+ },
+ "node_modules/rc-upload": {
+ "version": "4.8.1",
+ "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.8.1.tgz",
+ "integrity": "sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "classnames": "^2.2.5",
+ "rc-util": "^5.2.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
"node_modules/rc-util": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz",
@@ -16033,10 +17049,29 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
},
+ "node_modules/rc-virtual-list": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.15.0.tgz",
+ "integrity": "sha512-dF2YQztqrU3ijAeWOqscTshCEr7vpimzSqAVjO1AyAmaqcHulaXpnGR0ptK5PXfxTUy48VkJOiglMIxlkYGs0w==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.0",
+ "classnames": "^2.2.6",
+ "rc-resize-observer": "^1.0.0",
+ "rc-util": "^5.36.0"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
"node_modules/react": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
- "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -16166,6 +17201,19 @@
}
}
},
+ "node_modules/react-datetime": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/react-datetime/-/react-datetime-3.2.0.tgz",
+ "integrity": "sha512-w5XdeNIGzBht9CadaZIJhKUhEcDTgH0XokKxGPCxeeJRYL7B3HIKA8CM6Q0xej2JFJt0n5d+zi3maMwaY3262A==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.5.7"
+ },
+ "peerDependencies": {
+ "moment": "^2.16.0",
+ "react": "^16.5.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
@@ -16284,15 +17332,15 @@
}
},
"node_modules/react-dom": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
- "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dependencies": {
"loose-envify": "^1.1.0",
- "scheduler": "^0.23.0"
+ "scheduler": "^0.23.2"
},
"peerDependencies": {
- "react": "^18.2.0"
+ "react": "^18.3.1"
}
},
"node_modules/react-error-overlay": {
@@ -16766,6 +17814,12 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
},
+ "node_modules/resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==",
+ "license": "MIT"
+ },
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -17124,9 +18178,9 @@
}
},
"node_modules/scheduler": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
- "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dependencies": {
"loose-envify": "^1.1.0"
}
@@ -17148,6 +18202,15 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/scroll-into-view-if-needed": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz",
+ "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==",
+ "license": "MIT",
+ "dependencies": {
+ "compute-scroll-into-view": "^3.0.2"
+ }
+ },
"node_modules/select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -17731,6 +18794,12 @@
"safe-buffer": "~5.2.0"
}
},
+ "node_modules/string-convert": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
+ "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==",
+ "license": "MIT"
+ },
"node_modules/string-length": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
@@ -18468,6 +19537,15 @@
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz",
"integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ=="
},
+ "node_modules/throttle-debounce": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz",
+ "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.22"
+ }
+ },
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -18502,6 +19580,12 @@
"node": ">=8.0"
}
},
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==",
+ "license": "MIT"
+ },
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -18959,6 +20043,14 @@
}
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
+ "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -20281,6 +21373,92 @@
"@jridgewell/trace-mapping": "^0.3.9"
}
},
+ "@ant-design/colors": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.1.0.tgz",
+ "integrity": "sha512-MMoDGWn1y9LdQJQSHiCC20x3uZ3CwQnv9QMz6pCmJOrqdgM9YxsoVVY0wtrdXbmfSgnV0KNk6zi09NAhMR2jvg==",
+ "requires": {
+ "@ctrl/tinycolor": "^3.6.1"
+ }
+ },
+ "@ant-design/cssinjs": {
+ "version": "1.21.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.21.1.tgz",
+ "integrity": "sha512-tyWnlK+XH7Bumd0byfbCiZNK43HEubMoCcu9VxwsAwiHdHTgWa+tMN0/yvxa+e8EzuFP1WdUNNPclRpVtD33lg==",
+ "requires": {
+ "@babel/runtime": "^7.11.1",
+ "@emotion/hash": "^0.8.0",
+ "@emotion/unitless": "^0.7.5",
+ "classnames": "^2.3.1",
+ "csstype": "^3.1.3",
+ "rc-util": "^5.35.0",
+ "stylis": "^4.3.3"
+ },
+ "dependencies": {
+ "@emotion/hash": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
+ "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
+ },
+ "@emotion/unitless": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
+ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
+ },
+ "stylis": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz",
+ "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now=="
+ }
+ }
+ },
+ "@ant-design/cssinjs-utils": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.1.tgz",
+ "integrity": "sha512-2HAiyGGGnM0es40SxdszeQAU5iWp41wBIInq+ONTCKjlSKOrzQfnw4JDtB8IBmqE6tQaEKwmzTP2LGdt5DSwYQ==",
+ "requires": {
+ "@ant-design/cssinjs": "^1.21.0",
+ "@babel/runtime": "^7.23.2",
+ "rc-util": "^5.38.0"
+ }
+ },
+ "@ant-design/fast-color": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz",
+ "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==",
+ "requires": {
+ "@babel/runtime": "^7.24.7"
+ }
+ },
+ "@ant-design/icons": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.5.1.tgz",
+ "integrity": "sha512-0UrM02MA2iDIgvLatWrj6YTCYe0F/cwXvVE0E2SqGrL7PZireQwgEKTKBisWpZyal5eXZLvuM98kju6YtYne8w==",
+ "requires": {
+ "@ant-design/colors": "^7.0.0",
+ "@ant-design/icons-svg": "^4.4.0",
+ "@babel/runtime": "^7.24.8",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.31.1"
+ }
+ },
+ "@ant-design/icons-svg": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz",
+ "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA=="
+ },
+ "@ant-design/react-slick": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz",
+ "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==",
+ "requires": {
+ "@babel/runtime": "^7.10.4",
+ "classnames": "^2.2.5",
+ "json2mq": "^0.2.0",
+ "resize-observer-polyfill": "^1.5.1",
+ "throttle-debounce": "^5.0.0"
+ }
+ },
"@babel/code-frame": {
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
@@ -21550,9 +22728,9 @@
"integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
},
"@babel/runtime": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
- "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz",
+ "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==",
"requires": {
"regenerator-runtime": "^0.14.0"
}
@@ -21732,6 +22910,11 @@
"integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==",
"requires": {}
},
+ "@ctrl/tinycolor": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
+ "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA=="
+ },
"@discoveryjs/json-ext": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
@@ -21800,11 +22983,6 @@
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
"integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="
},
- "@emotion/weak-memoize": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
- "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="
- },
"stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
@@ -21831,29 +23009,29 @@
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
},
"@emotion/react": {
- "version": "11.11.4",
- "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
- "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
+ "version": "11.13.3",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz",
+ "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==",
"requires": {
"@babel/runtime": "^7.18.3",
- "@emotion/babel-plugin": "^11.11.0",
- "@emotion/cache": "^11.11.0",
- "@emotion/serialize": "^1.1.3",
- "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
- "@emotion/utils": "^1.2.1",
- "@emotion/weak-memoize": "^0.3.1",
+ "@emotion/babel-plugin": "^11.12.0",
+ "@emotion/cache": "^11.13.0",
+ "@emotion/serialize": "^1.3.1",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
+ "@emotion/utils": "^1.4.0",
+ "@emotion/weak-memoize": "^0.4.0",
"hoist-non-react-statics": "^3.3.1"
}
},
"@emotion/serialize": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.1.tgz",
- "integrity": "sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz",
+ "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==",
"requires": {
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/unitless": "^0.10.0",
- "@emotion/utils": "^1.4.0",
+ "@emotion/utils": "^1.4.1",
"csstype": "^3.0.2"
},
"dependencies": {
@@ -21886,14 +23064,14 @@
"requires": {}
},
"@emotion/utils": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz",
- "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ=="
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz",
+ "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA=="
},
"@emotion/weak-memoize": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
- "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
+ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="
},
"@eslint-community/eslint-utils": {
"version": "4.4.0",
@@ -21976,9 +23154,14 @@
}
},
"@floating-ui/utils": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz",
- "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA=="
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
+ "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig=="
+ },
+ "@flowjs/flow.js": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/@flowjs/flow.js/-/flow.js-2.14.1.tgz",
+ "integrity": "sha512-99DWlPnksOOS8uHfo+bhSjvs8d2MfLTB/22JBDC2ONwz/OCdP+gL/iiM4puMSTE2wH4A2/+J0eMc7pKwusXunw=="
},
"@formatjs/ecma402-abstract": {
"version": "1.18.2",
@@ -22764,6 +23947,97 @@
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
},
+ "@rc-component/async-validator": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz",
+ "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==",
+ "requires": {
+ "@babel/runtime": "^7.24.4"
+ }
+ },
+ "@rc-component/color-picker": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz",
+ "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==",
+ "requires": {
+ "@ant-design/fast-color": "^2.0.6",
+ "@babel/runtime": "^7.23.6",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.38.1"
+ }
+ },
+ "@rc-component/context": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz",
+ "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "rc-util": "^5.27.0"
+ }
+ },
+ "@rc-component/mini-decimal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz",
+ "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==",
+ "requires": {
+ "@babel/runtime": "^7.18.0"
+ }
+ },
+ "@rc-component/mutate-observer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz",
+ "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==",
+ "requires": {
+ "@babel/runtime": "^7.18.0",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.24.4"
+ }
+ },
+ "@rc-component/portal": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz",
+ "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==",
+ "requires": {
+ "@babel/runtime": "^7.18.0",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.24.4"
+ }
+ },
+ "@rc-component/qrcode": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz",
+ "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==",
+ "requires": {
+ "@babel/runtime": "^7.24.7",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.38.0"
+ }
+ },
+ "@rc-component/tour": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz",
+ "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==",
+ "requires": {
+ "@babel/runtime": "^7.18.0",
+ "@rc-component/portal": "^1.0.0-9",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.24.4"
+ }
+ },
+ "@rc-component/trigger": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.3.tgz",
+ "integrity": "sha512-X1oFIpKoXAMXNDYCviOmTfuNuYxE4h5laBsyCqVAVMjNHxoF3/uiyA7XdegK1XbCvBbCZ6P6byWrEoDRpKL8+A==",
+ "requires": {
+ "@babel/runtime": "^7.23.2",
+ "@rc-component/portal": "^1.1.0",
+ "classnames": "^2.3.2",
+ "rc-motion": "^2.0.0",
+ "rc-resize-observer": "^1.3.1",
+ "rc-util": "^5.38.0"
+ }
+ },
"@react-aria/ssr": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.2.tgz",
@@ -23393,9 +24667,9 @@
"integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA=="
},
"@types/prop-types": {
- "version": "15.7.12",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
- "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
+ "version": "15.7.13",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
+ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA=="
},
"@types/q": {
"version": "1.5.8",
@@ -23971,6 +25245,74 @@
"color-convert": "^1.9.0"
}
},
+ "antd": {
+ "version": "5.21.5",
+ "resolved": "https://registry.npmjs.org/antd/-/antd-5.21.5.tgz",
+ "integrity": "sha512-g/c8VkdruKDCVA6di9Ow1fG6dLtYJ1IOraPo7vXaY7DoQ56A3HExaFaH0fBEwTYKC0ICeftC4iA5eAjrF6/b9w==",
+ "requires": {
+ "@ant-design/colors": "^7.1.0",
+ "@ant-design/cssinjs": "^1.21.1",
+ "@ant-design/cssinjs-utils": "^1.1.1",
+ "@ant-design/icons": "^5.5.1",
+ "@ant-design/react-slick": "~1.1.2",
+ "@babel/runtime": "^7.25.6",
+ "@ctrl/tinycolor": "^3.6.1",
+ "@rc-component/color-picker": "~2.0.1",
+ "@rc-component/mutate-observer": "^1.1.0",
+ "@rc-component/qrcode": "~1.0.0",
+ "@rc-component/tour": "~1.15.1",
+ "@rc-component/trigger": "^2.2.3",
+ "classnames": "^2.5.1",
+ "copy-to-clipboard": "^3.3.3",
+ "dayjs": "^1.11.11",
+ "rc-cascader": "~3.28.2",
+ "rc-checkbox": "~3.3.0",
+ "rc-collapse": "~3.8.0",
+ "rc-dialog": "~9.6.0",
+ "rc-drawer": "~7.2.0",
+ "rc-dropdown": "~4.2.0",
+ "rc-field-form": "~2.4.0",
+ "rc-image": "~7.11.0",
+ "rc-input": "~1.6.3",
+ "rc-input-number": "~9.2.0",
+ "rc-mentions": "~2.16.1",
+ "rc-menu": "~9.15.1",
+ "rc-motion": "^2.9.3",
+ "rc-notification": "~5.6.2",
+ "rc-pagination": "~4.3.0",
+ "rc-picker": "~4.6.15",
+ "rc-progress": "~4.0.0",
+ "rc-rate": "~2.13.0",
+ "rc-resize-observer": "^1.4.0",
+ "rc-segmented": "~2.5.0",
+ "rc-select": "~14.15.2",
+ "rc-slider": "~11.1.7",
+ "rc-steps": "~6.0.1",
+ "rc-switch": "~4.1.0",
+ "rc-table": "~7.47.5",
+ "rc-tabs": "~15.3.0",
+ "rc-textarea": "~1.8.2",
+ "rc-tooltip": "~6.2.1",
+ "rc-tree": "~5.9.0",
+ "rc-tree-select": "~5.23.0",
+ "rc-upload": "~4.8.1",
+ "rc-util": "^5.43.0",
+ "scroll-into-view-if-needed": "^3.1.0",
+ "throttle-debounce": "^5.0.2"
+ },
+ "dependencies": {
+ "rc-slider": {
+ "version": "11.1.7",
+ "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.7.tgz",
+ "integrity": "sha512-ytYbZei81TX7otdC0QvoYD72XSlxvTihNth5OeZ6PMXyEDq/vHdWFulQmfDGyXK1NwKwSlKgpvINOa88uT5g2A==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.5",
+ "rc-util": "^5.36.0"
+ }
+ }
+ }
+ },
"any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
@@ -24033,6 +25375,11 @@
"is-string": "^1.0.7"
}
},
+ "array-tree-filter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
+ "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
+ },
"array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -24958,6 +26305,11 @@
}
}
},
+ "compute-scroll-into-view": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz",
+ "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg=="
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -25001,6 +26353,14 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
+ "copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "requires": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
"copy-webpack-plugin": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz",
@@ -25443,10 +26803,15 @@
}
},
"date-fns": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
- "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
- "dev": true
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "devOptional": true
+ },
+ "dayjs": {
+ "version": "1.11.13",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
+ "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
},
"debounce": {
"version": "1.2.1",
@@ -26521,6 +27886,11 @@
"strip-final-newline": "^2.0.0"
}
},
+ "exif-js": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/exif-js/-/exif-js-2.3.0.tgz",
+ "integrity": "sha512-1Og9pAzG2FZRVlaavH8bB8BTeHcjMdJhKmeQITkX+uLRCD0xPtKAdZ2clZmQdJ56p9adXtJ8+jwrGp/4505lYg=="
+ },
"exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -26791,6 +28161,11 @@
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="
},
+ "flow.js": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/flow.js/-/flow.js-0.2.6.tgz",
+ "integrity": "sha512-KvXsCPNj3uIOnXu07qXiqsxjqEveAe5nAM8W3ULTEDPynoMZlWvMyKZdH8pOh5oCFy7uXtgWnZQZOzgoH9Epdw=="
+ },
"follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
@@ -29505,6 +30880,14 @@
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
},
+ "json2mq": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
+ "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==",
+ "requires": {
+ "string-convert": "^0.2.0"
+ }
+ },
"json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -29914,6 +31297,24 @@
"minimist": "^1.2.6"
}
},
+ "mobx": {
+ "version": "6.13.3",
+ "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.13.3.tgz",
+ "integrity": "sha512-YtAS+ZMbdpbHYUU4ESht3na8KiX11KuMT1yOiKtbKlQ0GZkHDYPKyEw/Tdp7h7aHyLrTWj2TBaSNJ6bCr638iQ=="
+ },
+ "mobx-react-lite": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-4.0.7.tgz",
+ "integrity": "sha512-RjwdseshK9Mg8On5tyJZHtGD+J78ZnCnRaxeQDSiciKVQDUbfZcXhmld0VMxAwvcTnPEHZySGGewm467Fcpreg==",
+ "requires": {
+ "use-sync-external-store": "^1.2.0"
+ }
+ },
+ "moment": {
+ "version": "2.30.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="
+ },
"mrmime": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
@@ -31400,6 +32801,258 @@
}
}
},
+ "rc-cascader": {
+ "version": "3.28.2",
+ "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.28.2.tgz",
+ "integrity": "sha512-8f+JgM83iLTvjgdkgU7GfI4qY8icXOBP0cGZjOdx2iJAkEe8ucobxDQAVE69UD/c3ehCxZlcgEHeD5hFmypbUw==",
+ "requires": {
+ "@babel/runtime": "^7.12.5",
+ "array-tree-filter": "^2.1.0",
+ "classnames": "^2.3.1",
+ "rc-select": "~14.15.0",
+ "rc-tree": "~5.9.0",
+ "rc-util": "^5.37.0"
+ }
+ },
+ "rc-checkbox": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.3.0.tgz",
+ "integrity": "sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.25.2"
+ }
+ },
+ "rc-collapse": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.8.0.tgz",
+ "integrity": "sha512-YVBkssrKPBG09TGfcWWGj8zJBYD9G3XuTy89t5iUmSXrIXEAnO1M+qjUxRW6b4Qi0+wNWG6MHJF/+US+nmIlzA==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-motion": "^2.3.4",
+ "rc-util": "^5.27.0"
+ }
+ },
+ "rc-dialog": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz",
+ "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/portal": "^1.0.0-8",
+ "classnames": "^2.2.6",
+ "rc-motion": "^2.3.0",
+ "rc-util": "^5.21.0"
+ }
+ },
+ "rc-drawer": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz",
+ "integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==",
+ "requires": {
+ "@babel/runtime": "^7.23.9",
+ "@rc-component/portal": "^1.1.1",
+ "classnames": "^2.2.6",
+ "rc-motion": "^2.6.1",
+ "rc-util": "^5.38.1"
+ }
+ },
+ "rc-dropdown": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz",
+ "integrity": "sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==",
+ "requires": {
+ "@babel/runtime": "^7.18.3",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.17.0"
+ }
+ },
+ "rc-field-form": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.4.0.tgz",
+ "integrity": "sha512-XZ/lF9iqf9HXApIHQHqzJK5v2w4mkUMsVqAzOyWVzoiwwXEavY6Tpuw7HavgzIoD+huVff4JghSGcgEfX6eycg==",
+ "requires": {
+ "@babel/runtime": "^7.18.0",
+ "@rc-component/async-validator": "^5.0.3",
+ "rc-util": "^5.32.2"
+ }
+ },
+ "rc-image": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.11.0.tgz",
+ "integrity": "sha512-aZkTEZXqeqfPZtnSdNUnKQA0N/3MbgR7nUnZ+/4MfSFWPFHZau4p5r5ShaI0KPEMnNjv4kijSCFq/9wtJpwykw==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@rc-component/portal": "^1.0.2",
+ "classnames": "^2.2.6",
+ "rc-dialog": "~9.6.0",
+ "rc-motion": "^2.6.2",
+ "rc-util": "^5.34.1"
+ }
+ },
+ "rc-input": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.6.3.tgz",
+ "integrity": "sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==",
+ "requires": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.18.1"
+ }
+ },
+ "rc-input-number": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.2.0.tgz",
+ "integrity": "sha512-5XZFhBCV5f9UQ62AZ2hFbEY8iZT/dm23Q1kAg0H8EvOgD3UDbYYJAayoVIkM3lQaCqYAW5gV0yV3vjw1XtzWHg==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/mini-decimal": "^1.0.1",
+ "classnames": "^2.2.5",
+ "rc-input": "~1.6.0",
+ "rc-util": "^5.40.1"
+ }
+ },
+ "rc-mentions": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.16.1.tgz",
+ "integrity": "sha512-GnhSTGP9Mtv6pqFFGQze44LlrtWOjHNrUUAcsdo9DnNAhN4pwVPEWy4z+2jpjkiGlJ3VoXdvMHcNDQdfI9fEaw==",
+ "requires": {
+ "@babel/runtime": "^7.22.5",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.2.6",
+ "rc-input": "~1.6.0",
+ "rc-menu": "~9.15.1",
+ "rc-textarea": "~1.8.0",
+ "rc-util": "^5.34.1"
+ }
+ },
+ "rc-menu": {
+ "version": "9.15.1",
+ "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.15.1.tgz",
+ "integrity": "sha512-UKporqU6LPfHnpPmtP6hdEK4iO5Q+b7BRv/uRpxdIyDGplZy9jwUjsnpev5bs3PQKB0H0n34WAPDfjAfn3kAPA==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "2.x",
+ "rc-motion": "^2.4.3",
+ "rc-overflow": "^1.3.1",
+ "rc-util": "^5.27.0"
+ }
+ },
+ "rc-motion": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.3.tgz",
+ "integrity": "sha512-rkW47ABVkic7WEB0EKJqzySpvDqwl60/tdkY7hWP7dYnh5pm0SzJpo54oW3TDUGXV5wfxXFmMkxrzRRbotQ0+w==",
+ "requires": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.43.0"
+ }
+ },
+ "rc-notification": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.2.tgz",
+ "integrity": "sha512-Id4IYMoii3zzrG0lB0gD6dPgJx4Iu95Xu0BQrhHIbp7ZnAZbLqdqQ73aIWH0d0UFcElxwaKjnzNovTjo7kXz7g==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-motion": "^2.9.0",
+ "rc-util": "^5.20.1"
+ }
+ },
+ "rc-overflow": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz",
+ "integrity": "sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==",
+ "requires": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-resize-observer": "^1.0.0",
+ "rc-util": "^5.37.0"
+ }
+ },
+ "rc-pagination": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.3.0.tgz",
+ "integrity": "sha512-UubEWA0ShnroQ1tDa291Fzw6kj0iOeF26IsUObxYTpimgj4/qPCWVFl18RLZE+0Up1IZg0IK4pMn6nB3mjvB7g==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.3.2",
+ "rc-util": "^5.38.0"
+ }
+ },
+ "rc-picker": {
+ "version": "4.6.15",
+ "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.6.15.tgz",
+ "integrity": "sha512-OWZ1yrMie+KN2uEUfYCfS4b2Vu6RC1FWwNI0s+qypsc3wRt7g+peuZKVIzXCTaJwyyZruo80+akPg2+GmyiJjw==",
+ "requires": {
+ "@babel/runtime": "^7.24.7",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.2.1",
+ "rc-overflow": "^1.3.2",
+ "rc-resize-observer": "^1.4.0",
+ "rc-util": "^5.43.0"
+ }
+ },
+ "rc-progress": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz",
+ "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.16.1"
+ }
+ },
+ "rc-rate": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz",
+ "integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.5",
+ "rc-util": "^5.0.1"
+ }
+ },
+ "rc-resize-observer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz",
+ "integrity": "sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==",
+ "requires": {
+ "@babel/runtime": "^7.20.7",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.38.0",
+ "resize-observer-polyfill": "^1.5.1"
+ }
+ },
+ "rc-segmented": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.5.0.tgz",
+ "integrity": "sha512-B28Fe3J9iUFOhFJET3RoXAPFJ2u47QvLSYcZWC4tFYNGPEjug5LAxEasZlA/PpAxhdOPqGWsGbSj7ftneukJnw==",
+ "requires": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-motion": "^2.4.4",
+ "rc-util": "^5.17.0"
+ }
+ },
+ "rc-select": {
+ "version": "14.15.2",
+ "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.15.2.tgz",
+ "integrity": "sha512-oNoXlaFmpqXYcQDzcPVLrEqS2J9c+/+oJuGrlXeVVX/gVgrbHa5YcyiRUXRydFjyuA7GP3elRuLF7Y3Tfwltlw==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/trigger": "^2.1.1",
+ "classnames": "2.x",
+ "rc-motion": "^2.0.1",
+ "rc-overflow": "^1.3.1",
+ "rc-util": "^5.16.1",
+ "rc-virtual-list": "^3.5.2"
+ }
+ },
"rc-slider": {
"version": "10.6.2",
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.6.2.tgz",
@@ -31410,6 +33063,109 @@
"rc-util": "^5.36.0"
}
},
+ "rc-steps": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz",
+ "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==",
+ "requires": {
+ "@babel/runtime": "^7.16.7",
+ "classnames": "^2.2.3",
+ "rc-util": "^5.16.1"
+ }
+ },
+ "rc-switch": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz",
+ "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.30.0"
+ }
+ },
+ "rc-table": {
+ "version": "7.47.5",
+ "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.47.5.tgz",
+ "integrity": "sha512-fzq+V9j/atbPIcvs3emuclaEoXulwQpIiJA6/7ey52j8+9cJ4P8DGmp4YzfUVDrb3qhgedcVeD6eRgUrokwVEQ==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "@rc-component/context": "^1.4.0",
+ "classnames": "^2.2.5",
+ "rc-resize-observer": "^1.1.0",
+ "rc-util": "^5.41.0",
+ "rc-virtual-list": "^3.14.2"
+ }
+ },
+ "rc-tabs": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.3.0.tgz",
+ "integrity": "sha512-lzE18r+zppT/jZWOAWS6ntdkDUKHOLJzqMi5UAij1LeKwOaQaupupAoI9Srn73GRzVpmGznkECMRrzkRusC40A==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "classnames": "2.x",
+ "rc-dropdown": "~4.2.0",
+ "rc-menu": "~9.15.1",
+ "rc-motion": "^2.6.2",
+ "rc-resize-observer": "^1.0.0",
+ "rc-util": "^5.34.1"
+ }
+ },
+ "rc-textarea": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.8.2.tgz",
+ "integrity": "sha512-UFAezAqltyR00a8Lf0IPAyTd29Jj9ee8wt8DqXyDMal7r/Cg/nDt3e1OOv3Th4W6mKaZijjgwuPXhAfVNTN8sw==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.1",
+ "rc-input": "~1.6.0",
+ "rc-resize-observer": "^1.0.0",
+ "rc-util": "^5.27.0"
+ }
+ },
+ "rc-tooltip": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.2.1.tgz",
+ "integrity": "sha512-rws0duD/3sHHsD905Nex7FvoUGy2UBQRhTkKxeEvr2FB+r21HsOxcDJI0TzyO8NHhnAA8ILr8pfbSBg5Jj5KBg==",
+ "requires": {
+ "@babel/runtime": "^7.11.2",
+ "@rc-component/trigger": "^2.0.0",
+ "classnames": "^2.3.1"
+ }
+ },
+ "rc-tree": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.9.0.tgz",
+ "integrity": "sha512-CPrgOvm9d/9E+izTONKSngNzQdIEjMox2PBufWjS1wf7vxtvmCWzK1SlpHbRY6IaBfJIeZ+88RkcIevf729cRg==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-motion": "^2.0.1",
+ "rc-util": "^5.16.1",
+ "rc-virtual-list": "^3.5.1"
+ }
+ },
+ "rc-tree-select": {
+ "version": "5.23.0",
+ "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.23.0.tgz",
+ "integrity": "sha512-aQGi2tFSRw1WbXv0UVXPzHm09E0cSvUVZMLxQtMv3rnZZpNmdRXWrnd9QkLNlVH31F+X5rgghmdSFF3yZW0N9A==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-select": "~14.15.0",
+ "rc-tree": "~5.9.0",
+ "rc-util": "^5.16.1"
+ }
+ },
+ "rc-upload": {
+ "version": "4.8.1",
+ "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.8.1.tgz",
+ "integrity": "sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==",
+ "requires": {
+ "@babel/runtime": "^7.18.3",
+ "classnames": "^2.2.5",
+ "rc-util": "^5.2.0"
+ }
+ },
"rc-util": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz",
@@ -31426,10 +33182,21 @@
}
}
},
+ "rc-virtual-list": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.15.0.tgz",
+ "integrity": "sha512-dF2YQztqrU3ijAeWOqscTshCEr7vpimzSqAVjO1AyAmaqcHulaXpnGR0ptK5PXfxTUy48VkJOiglMIxlkYGs0w==",
+ "requires": {
+ "@babel/runtime": "^7.20.0",
+ "classnames": "^2.2.6",
+ "rc-resize-observer": "^1.0.0",
+ "rc-util": "^5.36.0"
+ }
+ },
"react": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
- "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"requires": {
"loose-envify": "^1.1.0"
}
@@ -31519,6 +33286,14 @@
"deepmerge": "^4.3.1"
}
},
+ "react-datetime": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/react-datetime/-/react-datetime-3.2.0.tgz",
+ "integrity": "sha512-w5XdeNIGzBht9CadaZIJhKUhEcDTgH0XokKxGPCxeeJRYL7B3HIKA8CM6Q0xej2JFJt0n5d+zi3maMwaY3262A==",
+ "requires": {
+ "prop-types": "^15.5.7"
+ }
+ },
"react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
@@ -31606,12 +33381,12 @@
}
},
"react-dom": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
- "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"requires": {
"loose-envify": "^1.1.0",
- "scheduler": "^0.23.0"
+ "scheduler": "^0.23.2"
}
},
"react-error-overlay": {
@@ -31958,6 +33733,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
},
+ "resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+ },
"resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -32171,9 +33951,9 @@
}
},
"scheduler": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
- "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"requires": {
"loose-envify": "^1.1.0"
}
@@ -32188,6 +33968,14 @@
"ajv-keywords": "^3.5.2"
}
},
+ "scroll-into-view-if-needed": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz",
+ "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==",
+ "requires": {
+ "compute-scroll-into-view": "^3.0.2"
+ }
+ },
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -32659,6 +34447,11 @@
"safe-buffer": "~5.2.0"
}
},
+ "string-convert": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
+ "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="
+ },
"string-length": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
@@ -33192,6 +34985,11 @@
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz",
"integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ=="
},
+ "throttle-debounce": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz",
+ "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A=="
+ },
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -33220,6 +35018,11 @@
"is-number": "^7.0.0"
}
},
+ "toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
+ },
"toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -33549,6 +35352,12 @@
"integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==",
"requires": {}
},
+ "use-sync-external-store": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
+ "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
+ "requires": {}
+ },
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index d4a365b9e4..3befd3ea34 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -3,20 +3,28 @@
"version": "0.1.0",
"private": true,
"dependencies": {
+ "@flowjs/flow.js": "^2.14.1",
"@testing-library/user-event": "^13.5.0",
+ "antd": "^5.21.5",
"autoprefixer": "^10.4.18",
"axios": "^1.7.4",
"bootstrap": "^5.3.2",
"copy-webpack-plugin": "^12.0.2",
+ "exif-js": "^2.3.0",
+ "flow.js": "^0.2.6",
"google-map-react": "^2.2.1",
"js-cookie": "^3.0.5",
"lodash-es": "^4.17.21",
+ "mobx": "6.13.3",
+ "mobx-react-lite": "^4.0.7",
+ "moment": "^2.30.1",
"postcss-cli": "^11.0.0",
"rc-slider": "^10.6.2",
"react": "^18.2.0",
"react-bootstrap": "^2.10.1",
"react-burger-menu": "^3.0.9",
"react-data-table-component": "^7.6.2",
+ "react-datetime": "^3.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.52.1",
"react-intl": "^6.6.2",
@@ -74,7 +82,7 @@
"@testing-library/react": "^16.0.1",
"bootstrap-icons": "^1.11.3",
"css-loader": "^6.10.0",
- "date-fns": "^3.6.0",
+ "date-fns": "^4.1.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.35.0",
"globals": "^15.9.0",
@@ -92,5 +100,10 @@
"webpack-bundle-analyzer": "^4.10.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
+ },
+ "jest":{
+ "collectCoverage": true,
+ "coverageReporters": ["lcov", "text"],
+ "coverageDirectory": "./coverage"
}
}
diff --git a/frontend/public/images/List_of_Logs_Image.png b/frontend/public/images/List_of_Logs_Image.png
new file mode 100644
index 0000000000..93d5c57e49
Binary files /dev/null and b/frontend/public/images/List_of_Logs_Image.png differ
diff --git a/frontend/public/images/report_an_encounter.png b/frontend/public/images/report_an_encounter.png
new file mode 100644
index 0000000000..295ef283d4
Binary files /dev/null and b/frontend/public/images/report_an_encounter.png differ
diff --git a/frontend/public/index.html b/frontend/public/index.html
index 3827c6bb5d..cb02504d84 100644
--- a/frontend/public/index.html
+++ b/frontend/public/index.html
@@ -13,6 +13,8 @@
-->
+
+
" + FlowFilePath);
-
+ // System.out.println("FlowFilePath ---> " + FlowFilePath);
FlowInfoStorage storage = FlowInfoStorage.getInstance();
+/*
System.out.println("FlowChunkSize: " + FlowChunkSize);
System.out.println("FlowTotalSize: " + FlowTotalSize);
System.out.println("FlowIdentifier: " + FlowIdentifier);
System.out.println("FlowFilename: " + FlowFilename);
System.out.println("FlowRelativePath: " + FlowRelativePath);
System.out.println("FlowFilePath: " + FlowFilePath);
+ */
// hacky, but gets us userFilename
request.getSession().setAttribute("userFilename:" + FlowFilename, FlowRelativePath);
@@ -289,4 +325,10 @@ private FlowInfo getFlowInfo(List parts, HttpServletRequest request)
}
return info;
}
+
+ // a simple wrapper, in case we want to change the logic here
+ private boolean accessAllowed(HttpServletRequest request) {
+ // note: this will return true for logged-in user (indifferent to captcha)
+ return ReCAPTCHA.sessionIsHuman(request);
+ }
}
diff --git a/src/main/java/org/ecocean/servlet/ReCAPTCHA.java b/src/main/java/org/ecocean/servlet/ReCAPTCHA.java
index 6741d6eea4..b8df95ef69 100644
--- a/src/main/java/org/ecocean/servlet/ReCAPTCHA.java
+++ b/src/main/java/org/ecocean/servlet/ReCAPTCHA.java
@@ -4,6 +4,8 @@
import java.io.PrintWriter;
import java.net.URL;
import java.util.Properties;
+import java.util.Map;
+import java.util.HashMap;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -12,10 +14,16 @@
import org.ecocean.*;
import org.json.JSONObject;
-/* some ReCAPTCHA-related stuff .... note that this has some useful public utility functions, as well as is a servlet which can do standalone
- verification */
+/*
+ captcha-related functionality
+ TODO: this should be eventually renamed captcha-agnostically, but for now code is being left in for ReCAPTCHA
+ backwards compatibility.
+
+ note that this has some useful public utility functions, as well as is a servlet which can do standalone
+ verification
+*/
public class ReCAPTCHA extends HttpServlet {
- private final static String ATTRIBUTE_PASSED = "reCAPTCHA-passed";
+ private final static String ATTRIBUTE_PASSED = "captcha-passed";
public void init(ServletConfig config)
throws ServletException {
@@ -33,7 +41,12 @@ public void doGet(HttpServletRequest request, HttpServletResponse response)
response.setHeader("Access-Control-Allow-Origin", "*"); // allow us stuff from localhost
response.setContentType("application/json");
PrintWriter out = response.getWriter();
- out.println(jsonResults(request, request.getParameter("recaptchaValue")));
+ String procaptchaValue = request.getParameter("procaptchaValue");
+ if (procaptchaValue != null) {
+ out.println(jsonResultsProcaptcha(request, procaptchaValue));
+ } else {
+ out.println(jsonResults(request, request.getParameter("recaptchaValue")));
+ }
out.close();
}
@@ -43,7 +56,16 @@ public void doPost(HttpServletRequest request, HttpServletResponse response)
response.setContentType("application/json");
JSONObject j = ServletUtilities.jsonFromHttpServletRequest(request);
PrintWriter out = response.getWriter();
- out.println((j == null) ? null : jsonResults(request, j.optString("recaptchaValue", null)));
+ String procaptchaValue = null;
+ if (j != null) procaptchaValue = j.optString("procaptchaValue", null);
+ boolean useEnterprise = (j != null) && j.optBoolean("useEnterprise", false);
+ if (procaptchaValue != null) {
+ out.println(jsonResultsProcaptcha(request, procaptchaValue));
+ } else if (useEnterprise) {
+ out.println(jsonResultsEnterprise(request, j.optString("recaptchaToken", null)));
+ } else {
+ out.println((j == null) ? null : jsonResults(request, j.optString("recaptchaValue", null)));
+ }
out.close();
}
@@ -55,7 +77,7 @@ private String jsonResults(HttpServletRequest request, String recaptchaValue) {
return rtn.toString();
}
boolean valid = captchaIsValid(ServletUtilities.getContext(request), recaptchaValue,
- request.getRemoteAddr());
+ ServletUtilities.getRemoteHost(request));
request.getSession().setAttribute(ATTRIBUTE_PASSED, valid);
rtn.put("valid", valid);
rtn.put("success", true);
@@ -95,7 +117,7 @@ public static String captchaWidget(HttpServletRequest request, String params,
// note: catcha can only be tested once.... see sessionIsHuman() below for sustained verification
public static boolean captchaIsValid(HttpServletRequest request) {
return captchaIsValid(ServletUtilities.getContext(request),
- request.getParameter("g-recaptcha-response"), request.getRemoteAddr());
+ request.getParameter("g-recaptcha-response"), ServletUtilities.getRemoteHost(request));
}
public static boolean captchaIsValid(String context, String uresp, String remoteIP) {
@@ -140,6 +162,127 @@ public static boolean captchaIsValid(String context, String uresp, String remote
return valid;
}
+ public static boolean captchaIsValidEnterprise(String context, String token, String remoteIP) {
+ String EXPECTED_ACTION = "VALIDATE";
+ if (context == null) context = "context0";
+ Properties recaptchaProps = ShepherdProperties.getProperties("recaptcha.properties", "",
+ context);
+ if (recaptchaProps == null) {
+ System.out.println("WARNING: no recaptcha.properties for captchaIsValid(); failing");
+ return false;
+ }
+ String siteKey = recaptchaProps.getProperty("enterpriseSiteKey");
+ String apiKey = recaptchaProps.getProperty("enterpriseApiKey");
+ if ((siteKey == null) || (apiKey == null)) {
+ System.out.println("WARNING: could not determine keys for captchaIsValid(); failing");
+ return false;
+ }
+ if (token == null) {
+ System.out.println("WARNING: recaptcha token is null in captchaIsValid(); failing");
+ return false;
+ }
+ JSONObject cdata = new JSONObject();
+ JSONObject cevent = new JSONObject();
+ cevent.put("token", token);
+ cevent.put("userIpAddress", remoteIP);
+ cevent.put("siteKey", siteKey);
+ cevent.put("expectedAction", EXPECTED_ACTION);
+ cdata.put("event", cevent);
+ JSONObject gresp = null;
+ try {
+ gresp = RestClient.postJSON(new URL("https://recaptchaenterprise.googleapis.com/v1/projects/wildme-dev/assessments?key=" + apiKey), cdata, null);
+ } catch (Exception ex) {
+ System.out.println(
+ "WARNING: exception calling captcha api in captchaIsValid(); failing: " +
+ ex.toString());
+ return false;
+ }
+ if (gresp == null) { // would this ever happen?
+ System.out.println(
+ "WARNING: null return from captcha api in captchaIsValid(); failing");
+ return false;
+ }
+ System.out.println("INFO: captchaIsValid() api call returned: " + gresp.toString());
+ JSONObject riskAnalysis = gresp.optJSONObject("riskAnalysis");
+ JSONObject tokenProperties = gresp.optJSONObject("tokenProperties");
+ JSONObject event = gresp.optJSONObject("event");
+ System.out.println(" > riskAnalysis " + riskAnalysis);
+ System.out.println(" > tokenProperties " + tokenProperties);
+ System.out.println(" > event " + event);
+ if ((riskAnalysis == null) || (tokenProperties == null) || (event == null)) return false;
+ if (riskAnalysis.optDouble("score", 0.0) < 0.5) return false;
+ return true;
+ }
+
+ public static boolean captchaIsValidProcaptcha(String context, String token) {
+ if (context == null) context = "context0";
+ Properties captchaProps = ShepherdProperties.getProperties("captcha.properties", "", context);
+ if (captchaProps == null) {
+ System.out.println("WARNING: no captcha.properties for captchaIsValid(); failing");
+ return false;
+ }
+ String secretKey = captchaProps.getProperty("procaptchaSecretKey");
+ //String siteKey = captchaProps.getProperty("procaptchaSiteKey");
+ if (secretKey == null) {
+ System.out.println("WARNING: could not determine secretKey for captchaIsValid(); failing");
+ return false;
+ }
+ if (token == null) {
+ System.out.println("WARNING: captcha token is null in captchaIsValid(); failing");
+ return false;
+ }
+ JSONObject cdata = new JSONObject();
+ cdata.put("token", token);
+ cdata.put("secret", secretKey);
+ JSONObject resp = null;
+ Map headers = new HashMap();
+ headers.put("User-Agent", "Wildbook/wildme.org"); // :( we need this or we get a 403 from their api
+ try {
+ resp = RestClient.postJSON(new URL("https://api.prosopo.io/siteverify"), cdata, headers);
+ } catch (Exception ex) {
+ System.out.println(
+ "WARNING: exception calling captcha api in captchaIsValid(); failing: " +
+ ex.toString());
+ return false;
+ }
+ if (resp == null) { // would this ever happen?
+ System.out.println(
+ "WARNING: null return from captcha api in captchaIsValid(); failing");
+ return false;
+ }
+ System.out.println("INFO: captchaIsValid() api call returned: " + resp.toString());
+ return "ok".equals(resp.optString("status")) && resp.optBoolean("verified", false);
+ }
+
+ private String jsonResultsEnterprise(HttpServletRequest request, String recaptchaToken) {
+ JSONObject rtn = new JSONObject("{\"success\": false}");
+
+ if ((request == null) || (recaptchaToken == null)) {
+ rtn.put("error", "recaptchaToken not set (or bad request)");
+ return rtn.toString();
+ }
+ boolean valid = captchaIsValidEnterprise(ServletUtilities.getContext(request), recaptchaToken,
+ ServletUtilities.getRemoteHost(request));
+ request.getSession().setAttribute(ATTRIBUTE_PASSED, valid);
+ rtn.put("valid", valid);
+ rtn.put("success", true);
+ return rtn.toString();
+ }
+
+ private String jsonResultsProcaptcha(HttpServletRequest request, String value) {
+ JSONObject rtn = new JSONObject("{\"success\": false}");
+
+ if ((request == null) || (value == null)) {
+ rtn.put("error", "value not set (or bad request)");
+ return rtn.toString();
+ }
+ boolean valid = captchaIsValidProcaptcha(ServletUtilities.getContext(request), value);
+ request.getSession().setAttribute(ATTRIBUTE_PASSED, valid);
+ rtn.put("valid", valid);
+ rtn.put("success", true);
+ return rtn.toString();
+ }
+
/*
this does best guess at "are we human"? based on one of two things:
1. is the user logged in? if so: YES 2. if not, did they previously pass ReCAPTCHA (based on session attribute)?
diff --git a/src/main/java/org/ecocean/servlet/ServletUtilities.java b/src/main/java/org/ecocean/servlet/ServletUtilities.java
index a57fb3fe25..9d6f46af6d 100644
--- a/src/main/java/org/ecocean/servlet/ServletUtilities.java
+++ b/src/main/java/org/ecocean/servlet/ServletUtilities.java
@@ -1108,8 +1108,7 @@ public static void importJsp(String filename, HttpServletRequest request,
request.getRequestDispatcher(filename).include(request, response);
}
- // used to determine if we want to apply a custom UI style, e.g. for IndoCet or
- // the New England Aquarium to a web page
+ // used to determine if we want to apply a custom UI style, e.g. the New England Aquarium to a web page
public static boolean useCustomStyle(HttpServletRequest request, String orgName) {
// check url for "organization=____" arg
String organization = request.getParameter("organization");
diff --git a/src/main/java/org/ecocean/servlet/importer/IndocetStandardImport.java b/src/main/java/org/ecocean/servlet/importer/IndocetStandardImport.java
deleted file mode 100644
index 82ac7252f9..0000000000
--- a/src/main/java/org/ecocean/servlet/importer/IndocetStandardImport.java
+++ /dev/null
@@ -1,1040 +0,0 @@
-package org.ecocean.servlet.importer;
-
-import java.io.*;
-import java.io.File;
-import java.util.*;
-import org.ecocean.*;
-import org.ecocean.genetics.*;
-import org.ecocean.media.*;
-import org.ecocean.servlet.*;
-import org.ecocean.tag.SatelliteTag;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.joda.time.DateTime;
-
-import org.json.JSONObject;
-
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-
-/// DEPRECATED!!! This importer is not compatible with the new naming scheme and must be updated
-
-public class IndocetStandardImport extends HttpServlet {
- // variables shared by any single import instance
- Shepherd myShepherd;
- Map colIndexMap = new HashMap();
- Set unusedColumns;
- Set missingColumns; // columns we look for but don't find
- List missingPhotos = new ArrayList();
- List foundPhotos = new ArrayList();
- int numFolderRows = 0;
- boolean committing = false;
- PrintWriter out;
- // verbose variable can be switched on/off throughout the import for debugging
- boolean verbose = false;
- String photoDirectory;
-
- private AssetStore astore;
-
- // just for lazy loading a var used on each row
- Integer numMediaAssets;
-
- public void init(ServletConfig config)
- throws ServletException {
- super.init(config);
- }
-
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doPost(request, response);
- }
-
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String context = "context0";
-
- context = ServletUtilities.getContext(request);
- myShepherd = new Shepherd(context);
- out = response.getWriter();
- astore = getAssetStore(myShepherd);
-
- // photoDirectory = "/data/oman_import/photos/";
- // String filename = "/data/oman_import/ASWN_secondExport.xlsx";
- photoDirectory = "/data/indocet/";
- String filename = "/data/indocet/indocet_blended.xlsx";
- if (request.getParameter("filename") != null) filename = request.getParameter("filename");
- File dataFile = new File(filename);
- boolean dataFound = dataFile.exists();
-
- missingColumns = new HashSet();
- missingPhotos = new ArrayList();
- foundPhotos = new ArrayList();
- numFolderRows = 0;
-
- committing = (request.getParameter("commit") != null &&
- !request.getParameter("commit").toLowerCase().equals("false")); // false by default
-
- out.println("File Overview: ");
- out.println("");
- out.println("Filename: " + filename + " ");
- out.println("File found = " + dataFound + " ");
-
- Workbook wb = null;
- try {
- wb = WorkbookFactory.create(dataFile);
- } catch (org.apache.poi.openxml4j.exceptions.InvalidFormatException invalidFormat) {
- out.println("InvalidFormatException on input file " + filename +
- ". Only excel files supported. ");
- return;
- }
- Sheet sheet = wb.getSheetAt(0);
- int numSheets = wb.getNumberOfSheets();
- out.println("Num Sheets = " + numSheets + " ");
- int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
- out.println("Num Rows = " + physicalNumberOfRows + " ");
- int rows = sheet.getPhysicalNumberOfRows(); // No of rows
- Row firstRow = sheet.getRow(0);
- // below line is important for on-screen logging
- initColIndexVariables(firstRow);
- int cols = firstRow.getPhysicalNumberOfCells(); // No of columns
- int lastColNum = firstRow.getLastCellNum();
-
- out.println("Num Cols = " + cols + " ");
- out.println("Last col num = " + lastColNum + " ");
- out.println("committing = " + committing + " ");
- out.println(" ");
- out.println("Column headings: ");
- out.println("number columns = " + colIndexMap.size() + " ");
- for (String heading : colIndexMap.keySet())
- out.println("" + colIndexMap.get(heading) + ": " + heading + " ");
- out.println(" ");
-
- int printPeriod = 100;
- if (committing) myShepherd.beginDBTransaction();
- out.println("Beginning row loop: ");
- out.println("");
- // one encounter per-row. We keep these running.
- Occurrence occ = null;
- int maxRows = 50000;
- int offset = 0;
- for (int i = 1 + offset; i < rows && i < (maxRows + offset); i++) {
- MarkedIndividual mark = null;
- verbose = ((i % printPeriod) == 0);
- try {
- if (committing) myShepherd.beginDBTransaction();
- Row row = sheet.getRow(i);
- if (isRowEmpty(row)) continue;
- // here's the central logic
- ArrayList annotations = loadAnnotations(row);
- Encounter enc = loadEncounter(row, annotations);
- occ = loadOccurrence(row, occ, enc);
- mark = loadIndividual(row, enc);
- if (committing) {
- for (Annotation ann : annotations) {
- try {
- MediaAsset ma = ann.getMediaAsset();
- if (ma != null) {
- myShepherd.storeNewAnnotation(ann);
- ma.setMetadata();
- ma.updateStandardChildren(myShepherd);
- }
- } catch (Exception e) {
- System.out.println("EXCEPTION on annot/ma persisting!");
- e.printStackTrace();
- }
- }
- myShepherd.storeNewEncounter(enc, enc.getCatalogNumber());
- if (!myShepherd.isOccurrence(occ)) myShepherd.storeNewOccurrence(occ);
- if (!myShepherd.isMarkedIndividual(mark))
- myShepherd.storeNewMarkedIndividual(mark);
- myShepherd.commitDBTransaction();
- }
- if (verbose) {
- out.println("Parsed row (" + i + ")" + " Enc " +
- getEncounterDisplayString(enc) + " " + " individual " + mark +
- " " + " occurrence " + occ + " " + " dateInMillis " +
- enc.getDateInMilliseconds() + " " + " sex " + enc.getSex() +
- " " + " lifeStage " + enc.getLifeStage() + " " + " ");
- }
- } catch (Exception e) {
- out.println("Encountered an error while importing the file.");
- e.printStackTrace(out);
- myShepherd.rollbackDBTransaction();
- }
- }
- out.println(" ");
-
- out.println("UNUSED Column headings (" + unusedColumns.size() + "):");
- for (String heading : unusedColumns) {
- out.println("" + heading + " ");
- }
- out.println(" ");
-
- List usedColumns = new ArrayList();
- for (String colName : colIndexMap.keySet()) {
- if (!unusedColumns.contains(colName)) usedColumns.add(colName);
- }
- out.println("USED Column headings (" + usedColumns.size() + "):");
- for (String heading : usedColumns) {
- out.println("" + heading + " ");
- }
- out.println(" ");
-
- out.println("Missing photos (" + missingPhotos.size() + "):");
- for (String photo : missingPhotos) {
- out.println("" + photo + " ");
- }
- out.println(" ");
-
- out.println("Found photos (" + foundPhotos.size() + "):");
- for (String photo : foundPhotos) {
- out.println("" + photo + " ");
- }
- out.println(" ");
-
- out.println(" " + numFolderRows + " Folder Rows ");
-
- out.println("Import completed successfully ");
- // fs.close();
- }
-
- public Taxonomy loadTaxonomy0(Row row) {
- String sciName = getString(row, "Taxonomy.scientificName");
-
- if (sciName == null) return null;
- Taxonomy taxy = myShepherd.getOrCreateTaxonomy(sciName);
- String commonName = getString(row, "Taxonomy.commonName");
- if (commonName != null) taxy.addCommonName(commonName);
- return taxy;
- }
-
- public Taxonomy loadTaxonomy1(Row row) {
- String sciName = getString(row, "Occurrence.taxonomy1");
-
- if (sciName == null) return null;
- return myShepherd.getOrCreateTaxonomy(sciName);
- }
-
- public static boolean validLatLon(Double lat, Double lon) {
- return ((lat != null) && (lon != null) && ((lat != 0.0) && (lon != 0.0)));
- }
-
- public Occurrence loadOccurrence(Row row, Occurrence oldOcc, Encounter enc) {
- Occurrence occ = getCurrentOccurrence(oldOcc, row);
- // would love to have a more concise way to write following couplets, c'est la vie
- Double seaSurfaceTemp = getDouble(row, "Occurrence.seaSurfaceTemperature");
-
- if (seaSurfaceTemp != null) occ.setSeaSurfaceTemp(seaSurfaceTemp);
- Integer individualCount = getInteger(row, "Occurrence.individualCount");
- if (individualCount != null) occ.setIndividualCount(individualCount);
- Double decimalLatitiude = getDouble(row, "Encounter.decimalLatitiude");
- if (decimalLatitiude != null) occ.setDecimalLatitude(decimalLatitiude);
- Double decimalLatitude = getDouble(row, "Encounter.decimalLatitude");
- Double decimalLongitude = getDouble(row, "Encounter.decimalLongitude");
- if (validLatLon(decimalLatitude, decimalLongitude)) {
- occ.setDecimalLatitude(decimalLatitude);
- occ.setDecimalLongitude(decimalLongitude);
- }
- String fieldStudySite = getString(row, "Occurrence.fieldStudySite");
- if (fieldStudySite != null) occ.setFieldStudySite(fieldStudySite);
- String groupComposition = getString(row, "Occurrence.groupComposition");
- if (groupComposition != null) occ.setGroupComposition(groupComposition);
- String fieldSurveyCode = getString(row, "Survey.id");
- if (fieldSurveyCode == null) fieldSurveyCode = getString(row, "Occurrence.fieldSurveyCode");
- if (fieldSurveyCode != null) occ.setFieldSurveyCode(fieldSurveyCode);
- String sightingPlatform = getString(row, "Survey.vessel");
- if (sightingPlatform == null) sightingPlatform = getString(row, "Platform Designation");
- if (sightingPlatform != null) occ.setSightingPlatform(sightingPlatform);
- String surveyComments = getString(row, "Survey.comments");
- if (surveyComments != null) occ.addComments(surveyComments);
- Integer numAdults = getInteger(row, "Occurrence.numAdults");
- if (numAdults != null) occ.setNumAdults(numAdults);
- Integer minGroupSize = getInteger(row, "Occurrence.minGroupSizeEstimate");
- if (minGroupSize != null) occ.setMinGroupSizeEstimate(minGroupSize);
- Integer maxGroupSize = getInteger(row, "Occurrence.maxGroupSizeEstimate");
- if (maxGroupSize != null) occ.setMaxGroupSizeEstimate(maxGroupSize);
- Double bestGroupSize = getDouble(row, "Occurrence.bestGroupSizeEstimate");
- if (bestGroupSize != null) occ.setBestGroupSizeEstimate(bestGroupSize);
- Integer numCalves = getInteger(row, "Occurrence.numCalves");
- if (numCalves != null) occ.setNumCalves(numCalves);
- Integer numJuveniles = getInteger(row, "Occurrence.numJuveniles");
- if (numJuveniles != null) occ.setNumJuveniles(numJuveniles);
- Double bearing = getDouble(row, "Occurrence.bearing");
- if (bearing != null) occ.setBearing(bearing);
- Double distance = getDouble(row, "Occurrence.distance");
- if (distance != null) occ.setDistance(distance);
- Double swellHeight = getDouble(row, "Occurrence.swellHeight");
- if (swellHeight != null) occ.setSwellHeight(swellHeight);
- String seaState = getString(row, "Occurrence.seaState");
- if (seaState != null) occ.setSeaState(seaState);
- Double visibilityIndex = getDouble(row, "Occurrence.visibilityIndex");
- if (visibilityIndex != null) occ.setVisibilityIndex(visibilityIndex);
- Double transectBearing = getDouble(row, "Occurrence.transectBearing");
- if (transectBearing != null) occ.setTransectBearing(transectBearing);
- String transectName = getString(row, "Occurrence.transectName");
- if (transectName != null) occ.setTransectName(transectName);
- String initialCue = getString(row, "Occurrence.initialCue");
- String humanActivity = getString(row, "Occurrence.humanActivityNearby");
- if (humanActivity != null) occ.setHumanActivityNearby(humanActivity);
- Double effortCode = getDouble(row, "Occurrence.effortCode");
- if (effortCode != null) occ.setEffortCode(effortCode);
- Taxonomy taxy = loadTaxonomy0(row);
- if (taxy != null) occ.addTaxonomy(taxy);
- Taxonomy taxy1 = loadTaxonomy1(row);
- if (taxy1 != null) occ.addTaxonomy(taxy1);
- String surveyTrackVessel = getString(row, "SurveyTrack.vesselID");
- if (surveyTrackVessel != null) occ.setSightingPlatform(surveyTrackVessel);
- Long millis = getLong(row, "Encounter.dateInMilliseconds");
- if (millis == null) millis = getLong(row, "Occurrence.dateInMilliseconds");
- if (millis == null) millis = getLong(row, "Occurrence.millis");
- if (millis != null) occ.setDateTimeLong(millis);
- if (enc != null) {
- occ.addEncounter(enc);
- // overwrite=false on following fromEncs methods
- occ.setLatLonFromEncs(false);
- occ.setSubmitterIDFromEncs(false);
- }
- return occ;
- }
-
- public Encounter loadEncounter(Row row, ArrayList annotations) {
- Encounter enc = new Encounter(annotations);
-
- // since we need access to the encounter ID
- String encID = Util.generateUUID();
-
- enc.setEncounterNumber(encID);
-
- // Time
- Integer year = getInteger(row, "Encounter.year");
- if (year == null) year = getInteger(row, "Occurrence.year");
- if (year != null) enc.setYear(year);
- Integer month = getInteger(row, "Encounter.month");
- if (month == null) month = getInteger(row, "Occurrence.month");
- if (month != null) enc.setMonth(month);
- Integer day = getInteger(row, "Encounter.day");
- if (day == null) day = getInteger(row, "Occurrence.day");
- if (day != null) enc.setDay(day);
- Integer hour = getInteger(row, "Encounter.hour");
- if (hour == null) hour = getInteger(row, "Occurrence.hour");
- if (hour != null) enc.setHour(hour);
- String minutes = getIntAsString(row, "Encounter.minutes");
- if (minutes == null) minutes = getIntAsString(row, "Occurrence.minutes");
- if (minutes != null) enc.setMinutes(minutes);
- // setting milliseconds last means that (if provided) the exif/millis data will always take precedence
- // if we set it before, enc.setMinutes & others would reset millis
- Long millis = getLong(row, "Encounter.dateInMilliseconds");
- if (millis == null) millis = getLong(row, "Occurrence.dateInMilliseconds");
- if (millis == null) millis = getLong(row, "Occurrence.millis");
- boolean hasTimeCategories = (year != null || month != null || day != null || hour != null ||
- minutes != null);
- if (millis != null) {
- if (hasTimeCategories) enc.setDateInMillisOnly(millis); // does not overwrite day/month/etc
- else enc.setDateInMilliseconds(millis);
- }
- // Location
- Double latitude = getDouble(row, "Encounter.latitude");
- if (latitude == null) latitude = getDouble(row, "Encounter.decimalLatitude");
- if (latitude == null) latitude = getDouble(row, "Occurrence.decimalLatitude");
- Double longitude = getDouble(row, "Encounter.longitude");
- if (longitude == null) longitude = getDouble(row, "Encounter.decimalLongitude");
- if (longitude == null) longitude = getDouble(row, "Occurrence.decimalLongitude");
- if (validLatLon(latitude, longitude)) {
- enc.setDecimalLatitude(latitude);
- enc.setDecimalLongitude(longitude);
- }
- String locationID = getString(row, "Encounter.locationID");
- if (locationID != null) enc.setLocationID(locationID);
- String country = getString(row, "Encounter.country");
- if (country != null) enc.setCountry(country);
- // String fields
- String otherCatalogNumbers = getStringOrInt(row, "Encounter.otherCatalogNumbers");
- if (otherCatalogNumbers != null) enc.setOtherCatalogNumbers(otherCatalogNumbers);
- String sex = getString(row, "Encounter.sex");
- if (sex != null) enc.setSex(sex);
- String genus = getString(row, "Encounter.genus");
- if (genus != null) enc.setGenus(genus);
- String specificEpithet = getString(row, "Encounter.specificEpithet");
- if (specificEpithet != null) enc.setSpecificEpithet(specificEpithet);
- String submitterOrganization = getString(row, "Encounter.submitterOrganization");
- if (submitterOrganization != null) enc.setSubmitterOrganization(submitterOrganization);
- String submitterName = getString(row, "Encounter.submitterName");
- if (submitterName != null) enc.setSubmitterName(submitterName);
- Integer patterningCode = getInteger(row, "Encounter.patterningCode");
- if (patterningCode != null) enc.setFlukeType(patterningCode);
- String occurrenceRemarks = getString(row, "Encounter.occurrenceRemarks");
- if (occurrenceRemarks != null) enc.setOccurrenceRemarks(occurrenceRemarks);
- String occurrenceID = getString(row, "Encounter.occurrenceID");
- if (occurrenceID == null) occurrenceID = getString(row, "Occurrence.occurrenceID");
- if (occurrenceID != null) enc.setOccurrenceID(occurrenceID);
- String submitterID = getString(row, "Encounter.submitterID");
- if (submitterID != null) enc.setSubmitterID(submitterID);
- String behavior = getString(row, "Encounter.behavior");
- if (behavior != null) enc.setBehavior(behavior);
- String individualID = getIndividualID(row);
- // DEPRECATED
- // if (individualID!=null) enc.setIndividualID(individualID);
- String lifeStage = getString(row, "Encounter.lifeStage");
- if (lifeStage != null) enc.setLifeStage(lifeStage);
- String groupRole = getString(row, "Encounter.groupRole");
- if (groupRole != null) enc.setGroupRole(groupRole);
- String researcherComments = getString(row, "Encounter.researcherComments");
- if (researcherComments != null) enc.addComments(researcherComments);
- String verbatimLocality = getString(row, "Encounter.verbatimLocality");
- if (verbatimLocality != null) enc.setVerbatimLocality(verbatimLocality);
- String nickname = getString(row, "MarkedIndividual.nickname");
- if (nickname == null) nickname = getString(row, "MarkedIndividual.nickName");
- if (nickname != null) enc.setAlternateID(nickname);
- String alternateID = getString(row, "Encounter.alternateID");
- if (alternateID != null) enc.setAlternateID(alternateID);
- Double length = getDouble(row, "Encounter.measurement.length");
- if (length != null) {
- Measurement lengthMeas = new Measurement(encID, "length", length, "m", "");
- if (committing) enc.setMeasurement(lengthMeas, myShepherd);
- }
- Double weight = getDouble(row, "Encounter.measurement.weight");
- if (weight != null) {
- Measurement weightMeas = new Measurement(encID, "weight", weight, "kg", "");
- if (committing) enc.setMeasurement(weightMeas, myShepherd);
- }
- Double depth = getDouble(row, "Encounter.depth");
- if (depth != null) enc.setDepth(depth);
- String scar = getIntAsString(row, "Encounter.distinguishingScar");
- if (scar != null) enc.setDistinguishingScar(scar);
- // SAMPLES
- TissueSample sample = null;
- String tissueSampleID = getStringOrInt(row, "TissueSample.sampleID");
- // we need to make sure we have a sampleID whenever we have a microsat marker
- if (tissueSampleID == null)
- tissueSampleID = getStringOrInt(row, "MicrosatelliteMarkersAnalysis.analysisID");
- // same for sex analysis
- if (tissueSampleID == null)
- tissueSampleID = getStringOrInt(row, "SexAnalysis.processingLabTaskID");
- if (tissueSampleID != null) {
- sample = myShepherd.getTissueSample(tissueSampleID, encID);
- if (sample == null) sample = new TissueSample(enc.getCatalogNumber(), tissueSampleID);
- }
- String markerAnalysisID = getStringOrInt(row, "MicrosatelliteMarkersAnalysis.analysisID");
- // we need to add uniqueness to the parsed string bc it's a primary key
- // but adding full encID is too long of a string.
- if (markerAnalysisID != null)
- markerAnalysisID = markerAnalysisID + "-enc-" + encID.substring(0,
- Math.min(8, encID.length()));
- if (markerAnalysisID != null && !myShepherd.isGeneticAnalysis(markerAnalysisID)) {
- markerAnalysisID = markerAnalysisID.replaceAll("_", "-");
- MicrosatelliteMarkersAnalysis microMark = myShepherd.getMicrosatelliteMarkersAnalysis(
- markerAnalysisID);
- if (microMark == null) {
- microMark = new MicrosatelliteMarkersAnalysis(markerAnalysisID, tissueSampleID,
- encID);
- if (sample != null) sample.addGeneticAnalysis(microMark);
- } // if microMark was grabbed from Shepherd correctly there is no further data to store.
- }
- String sexAnalID = getStringOrInt(row, "SexAnalysis.processingLabTaskID");
- String sexAnalSex = getString(row, "SexAnalysis.sex");
- if (sexAnalID != null) {
- // we need to add uniqueness to the parsed string bc it's a primary key
- // but adding full encID is too long of a string.
- sexAnalID = sexAnalID + "-enc-" + encID.substring(0, Math.min(8, encID.length()));
- sexAnalID = sexAnalID.replaceAll("_", "-");
- }
- if (sexAnalID != null && sexAnalSex != null && !myShepherd.isGeneticAnalysis(sexAnalID)) {
- SexAnalysis sexAnal = myShepherd.getSexAnalysis(sexAnalID);
- if (sexAnal == null) {
- sexAnal = new SexAnalysis(sexAnalID, sexAnalSex, encID, tissueSampleID);
- if (sample != null) sample.addGeneticAnalysis(sexAnal);
- } else sexAnal.setSex(sexAnalSex);
- }
- if (sample != null) enc.addTissueSample(sample);
- // END SAMPLES
-
- String satelliteTag = getString(row, "SatelliteTag.serialNumber");
- if (satelliteTag != null) {
- SatelliteTag tag = new SatelliteTag("", satelliteTag, ""); // note the empty fields. sat tags are weird.
- enc.setSatelliteTag(tag);
- }
- String caudalType = getIntAsString(row, "Type caudale Mn");
- if (caudalType != null) {
- enc.setDynamicProperty("caudal type", caudalType);
- }
- enc.setState("approved");
- return enc;
- }
-
- public Set getColumnFieldsForClass(String className) {
- Set fieldNames = new HashSet();
-
- try {
- for (String columnHeader : colIndexMap.keySet()) {
- if (columnHeader.contains(className + ".")) {
- fieldNames.add(columnHeader.split(className + ".")[1]); // for Encounter.date returns date
- }
- }
- } catch (Exception e) {}
- return fieldNames;
- }
-
- public ArrayList loadAnnotations(Row row) {
- if (isFolderRow(row)) return loadAnnotationsFolderRow(row);
- ArrayList annots = new ArrayList();
- for (int i = 0; i < getNumMediaAssets(); i++) {
- MediaAsset ma = getMediaAsset(row, i);
- if (ma == null) continue;
- String species = getSpeciesString(row);
- Annotation ann = new Annotation(species, ma);
- ann.setIsExemplar(true);
- annots.add(ann);
- // if (ma!=null && ma.localPath()!=null) foundPhotos.add(ma.localPath().toString());
- }
- if (annots.size() > 0) {
- for (int i = 0; i < annots.size(); i++) {
- String maName = "Encounter.mediaAsset" + i;
- String localPath = getString(row, maName);
- if (localPath != null) foundPhotos.add(photoDirectory + localPath);
- }
- }
- return annots;
- }
-
- // for when the provided image filename is actually a folder of images
- private ArrayList loadAnnotationsFolderRow(Row row) {
- ArrayList annots = new ArrayList();
- String localPath = getString(row, "Encounter.mediaAsset0");
-
- if (localPath == null) return annots;
- localPath = localPath.substring(0, localPath.length() - 1); // removes trailing asterisk
- localPath = fixGlobiceFullPath(localPath) + "/";
-// localPath = localPath.replace(" ","\\ ");
- String fullPath = photoDirectory + localPath;
- // Globice fix!
- // now fix spaces
- File photoDir = new File(fullPath);
- if (!photoDir.exists() || !photoDir.isDirectory() || photoDir.listFiles() == null) {
- boolean itExists = photoDir.exists();
- boolean isDirectory = (itExists) && photoDir.isDirectory();
- boolean hasFiles = isDirectory && photoDir.listFiles() != null;
- System.out.println(
- "StandardImport ERROR: loadAnnotationsFolderRow called on non-directory (or empty?) path "
- + fullPath);
- System.out.println("\t\titExists: " + itExists);
- System.out.println("\t\tisDirectory: " + isDirectory);
- System.out.println("\t\thasFiles: " + hasFiles);
- missingPhotos.add(localPath);
- return annots;
- }
- // if there are keywords we apply to all photos in encounter
- String keyword0 = getString(row, "Encounter.keyword00");
- Keyword key0 = (keyword0 == null) ? null : myShepherd.getOrCreateKeyword(keyword0);
- String keyword1 = getString(row, "Encounter.keyword01");
- Keyword key1 = (keyword1 == null) ? null : myShepherd.getOrCreateKeyword(keyword1);
- String species = getSpeciesString(row);
- for (File f : photoDir.listFiles()) {
- MediaAsset ma = null;
- try {
- JSONObject assetParams = astore.createParameters(f);
- System.out.println("\t\thave assetParams");
- assetParams.put("_localDirect", f.toString());
- System.out.println("\t\tabout to create mediaAsset");
- ma = astore.copyIn(f, assetParams);
- } catch (Exception e) {
- System.out.println("IOException creating MediaAsset for file " + f.getPath());
- missingPhotos.add(f.getPath());
- continue; // skips the rest of loop for this file
- }
- if (ma == null) continue;
- if (key0 != null) ma.addKeyword(key0);
- if (key1 != null) ma.addKeyword(key1);
- Annotation ann = new Annotation(species, ma);
- ann.setIsExemplar(true);
- annots.add(ann);
- }
- if (annots.size() > 0) foundPhotos.add(fullPath);
- return annots;
- }
-
- // capitolizes the final directory in path
- private String fixGlobiceFullPath(String path) {
- String fixed = capitolizeLastFilepart(path);
-
- fixed = removeExtraGlobiceString(fixed);
- return fixed;
- }
-
- private String removeExtraGlobiceString(String path) {
- // we somehow got an extra instance of the word "globice" in the path string, right before a 1
- return (path.replace("Globice1", "1"));
- }
-
- private String capitolizeLastFilepart(String path) {
- String[] parts = path.split("/");
- String lastPart = parts[parts.length - 1];
- String firstPart = path.substring(0, path.indexOf(lastPart));
-
- return firstPart + lastPart.toUpperCase();
- }
-
- // most rows have a single image, but some have an image folder
- private boolean isFolderRow(Row row) {
- String path = getString(row, "Encounter.mediaAsset0");
-
- if (path == null) return false;
- boolean ans = path.endsWith("*");
- if (ans) numFolderRows++;
- return ans;
- }
-
- public String getSpeciesString(Row row) {
- String genus = getString(row, "Encounter.genus");
- String species = getString(row, "Encounter.species");
- String total = genus + " " + species;
-
- if (total == null || total.equals(" ")) total = "unknown";
- return total;
- }
-
- public String getIndividualID(Row row) {
- String indID = getString(row, "Encounter.individualID");
-
- if (indID == null) indID = getString(row, "MarkedIndividual.individualID");
- // Cetamada uses single letter names like A
- if (indID != null && indID.length() == 1) return "Cetamada-" + indID;
- return indID;
- }
-
- public MediaAsset getMediaAsset(Row row, int i) {
- String localPath = getString(row, "Encounter.mediaAsset" + i);
-
- if (localPath == null) return null;
- localPath = Util.windowsFileStringToLinux(localPath);
- String fullPath = photoDirectory + localPath;
- String resolvedPath = resolveHumanEnteredFilename(fullPath);
- if (resolvedPath == null) {
- missingPhotos.add(fullPath);
- return null;
- }
- File f = new File(resolvedPath);
-
- // create MediaAsset and return it
- JSONObject assetParams = astore.createParameters(f);
- assetParams.put("_localDirect", f.toString());
- MediaAsset ma = null;
- try {
- ma = astore.copyIn(f, assetParams);
- } catch (java.io.IOException ioEx) {
- System.out.println("IOException creating MediaAsset for file " + fullPath);
- missingPhotos.add(fullPath);
- }
- // keywording
-
- ArrayList kws = getKeywordsForAsset(row, i);
- ma.setKeywords(kws);
-
- return ma;
- }
-
- private ArrayList getKeywordsForAsset(Row row, int n) {
- ArrayList ans = new ArrayList();
- int maxAssets = getNumAssets(row);
- int maxKeywords = 2;
- int stopAtKeyword = (maxAssets == (n + 1)) ? maxKeywords : n; //
-
- // we have up to two keywords per row.
- for (int i = n; i < stopAtKeyword; i++) {
- String kwColName = "Encounter.keyword0" + i;
- String kwName = getString(row, kwColName);
- if (kwName == null) continue;
- Keyword kw = myShepherd.getOrCreateKeyword(kwName);
- if (kw != null) ans.add(kw);
- }
- return ans;
- }
-
- private int getNumAssets(Row row) {
- int n = 0;
-
- while (getString(row, "Encounter.mediaAsset" + n) != null) { n++; }
- return n;
- }
-
- // Checks common human errors in inputing filenames
- // and returns the most similar filename that actually exists on the server
- // returns null if it cannot find a good string
- private String resolveHumanEnteredFilename(String fullPath) {
- if (Util.fileExists(fullPath)) return fullPath;
- String candidatePath = uppercaseJpg(fullPath);
- if (Util.fileExists(candidatePath)) return candidatePath;
- String candidatePath2 = uppercaseBeforeJpg(candidatePath);
- if (Util.fileExists(candidatePath2)) return candidatePath2;
- candidatePath = lowercaseJpg(fullPath);
- if (Util.fileExists(candidatePath)) return candidatePath;
- candidatePath = fixSpaceBeforeJpg(candidatePath);
- if (Util.fileExists(candidatePath)) return candidatePath;
- candidatePath = fixSpaceBeforeDotJpg(candidatePath);
- if (Util.fileExists(candidatePath)) return candidatePath;
- candidatePath = removeSpaceDashSpaceBeforeDot(candidatePath);
- if (Util.fileExists(candidatePath)) return candidatePath;
- return null;
- }
-
- private String uppercaseBeforeJpg(String filename) {
- // uppercases the section between final slash and .jpg
- if (filename == null) return null;
- int indexOfDotJpg = filename.indexOf(".jpg");
- if (indexOfDotJpg == -1) indexOfDotJpg = filename.indexOf(".JPG");
- int indexOfLastSlash = filename.lastIndexOf("/");
- if (indexOfDotJpg == -1 || indexOfLastSlash == -1) return filename;
- String beforePart = filename.substring(0, indexOfLastSlash + 1);
- String capitolizedPart = filename.substring(indexOfLastSlash + 1,
- indexOfDotJpg).toUpperCase();
- String afterPart = filename.substring(indexOfDotJpg);
-
- return (beforePart + capitolizedPart + afterPart);
- }
-
- private String lowercaseJpg(String filename) {
- if (filename == null) return null;
- return (filename.replace(".JPG", ".jpg"));
- }
-
- private String uppercaseJpg(String filename) {
- if (filename == null) return null;
- return (filename.replace(".jpg", ".JPG"));
- }
-
- private String fixSpaceBeforeJpg(String filename) {
- if (filename == null) return null;
- return (filename.replace(" jpg", ".jpg"));
- }
-
- private String fixSpaceBeforeDotJpg(String filename) {
- if (filename == null) return null;
- return (filename.replace(" .jpg", ".jpg"));
- }
-
- private String removeTailingSpace(String filename) {
- if (filename == null) return null;
- return (filename.replace(" .jpg", ".jpg"));
- }
-
- private String removeSpaceDashSpaceBeforeDot(String filename) {
- if (filename == null) return null;
- return (filename.replace(" - .", "."));
- }
-
- private int getNumMediaAssets() {
- if (numMediaAssets == null) setNumMediaAssets();
- return numMediaAssets.intValue();
- }
-
- private void setNumMediaAssets() {
- int numAssets = 0;
-
- for (String col : colIndexMap.keySet()) {
- if (col.indexOf("mediaAsset") > -1) numAssets++;
- }
- numMediaAssets = numAssets;
- }
-
- public MarkedIndividual loadIndividual(Row row, Encounter enc) {
- boolean newIndividual = false;
- String individualID = getIndividualID(row);
-
- if (individualID == null) return null;
- MarkedIndividual mark = myShepherd.getMarkedIndividualQuiet(individualID);
- if (mark == null) { // new individual
- mark = new MarkedIndividual(individualID, enc);
- newIndividual = true;
- }
- if (mark == null) {
- System.out.println(
- "StandardImport WARNING: weird behavior. Just made an individual but it's still null.");
- return mark;
- }
- if (!newIndividual) mark.addEncounterNoCommit(enc);
- String alternateID = getString(row, "Encounter.alternateID");
- if (alternateID != null) mark.setAlternateID(alternateID);
- String nickname = getString(row, "MarkedIndividual.nickname");
- if (nickname == null) nickname = getString(row, "MarkedIndividual.nickName");
- if (nickname != null) mark.setNickName(nickname);
- return mark;
- }
-
- // check if oldOcc is the same occurrence as the occurrence on this row
- // if so, return oldOcc. If not, return parseOccurrence(row)
- public Occurrence getCurrentOccurrence(Occurrence oldOcc, Row row) {
- String occID = getOccurrenceID(row);
-
- if (oldOcc != null && oldOcc.getOccurrenceID() != null &&
- oldOcc.getOccurrenceID().equals(occID)) return oldOcc;
- Occurrence occ = myShepherd.getOrCreateOccurrence(occID);
-
- return occ;
- // if (isOccurrenceOnRow(oldOcc, row)) return oldOcc;
- // return parseOccurrence(row);
- }
-
- private void initColIndexVariables(Row firstRow) {
- colIndexMap = makeColIndexMap(firstRow);
- unusedColumns = new HashSet();
- // have to manually copy-in like this because keySet returns a POINTER (!!!)
- for (String colName : colIndexMap.keySet()) {
- unusedColumns.add(colName);
- }
- }
-
- // Returns a map from each column header to the integer col number
- public static Map makeColIndexMap(Row firstRow) {
- Map colMap = new HashMap();
-
- for (int i = 0; i < firstRow.getLastCellNum(); i++) {
- String colName = getString(firstRow, i);
- colMap.put(colName, i);
- }
- return colMap;
- }
-
- public String getOccurrenceID(Row row) {
- return (getString(row, "Occurrence.occurrenceID"));
- }
-
- public boolean isOccurrenceOnRow(Occurrence occ, Row row) {
- return (occ != null && !occ.getOccurrenceID().equals(getOccurrenceID(row)));
- }
-
-//// following 'get' functions swallow errors
- public static Integer getInteger(Row row, int i) {
- try {
- double val = row.getCell(i).getNumericCellValue();
- return new Integer((int)val);
- } catch (Exception e) {
- // case for when we have a weird String-Double, which looks like a double in the excel sheet, yet is cast as a String, AND has a leading
- // apostrophe in its stored value that prevents us from parsing it as a number.
- try {
- String str = getString(row, i);
- if (str == null) return null;
- try {
- Integer ans = Integer.parseInt(str);
- return ans;
- } catch (Exception badParse) {
- str = str.substring(1);
- Integer ans2 = Integer.parseInt(str);
- System.out.println(" getInteger SUBSTRINGED and got ans " + ans2);
- return ans2;
- }
- } catch (Exception ex) {}
- }
- return null;
- }
-
- public static Long getLong(Row row, int i) {
- try {
- double val = row.getCell(i).getNumericCellValue();
- return new Long((long)val);
- } catch (Exception e) {
- try {
- String str = getString(row, i);
- if (str == null) return null;
- try {
- Long ans = Long.parseLong(str);
- return ans;
- } catch (Exception badParse) {
- str = str.substring(1);
- Long ans2 = Long.parseLong(str);
- System.out.println(" getLong SUBSTRINGED and got ans " + ans2);
- return ans2;
- }
- } catch (Exception ex) {}
- }
- return null;
- }
-
- public static Double getDouble(Row row, int i) {
- try {
- double val = row.getCell(i).getNumericCellValue();
- return new Double(val);
- } catch (Exception e) {
- // case for when we have a weird String-Double, which looks like a double in the excel sheet, yet is cast as a String, AND has a leading
- // apostrophe in its stored value that prevents us from parsing it as a number.
- try {
- String str = getString(row, i);
- if (str == null) return null;
- System.out.println("EXCEL getDouble string conversion case reached with string " +
- str);
- try {
- Double ans = Double.parseDouble(str);
- System.out.println(" getDouble string conversion got ans " + ans);
- return ans;
- } catch (Exception badParse) {
- str = str.substring(1);
- Double ans2 = Double.parseDouble(str);
- System.out.println(" getDouble SUBSTRINGED and got ans " + ans2);
- return ans2;
- }
- } catch (Exception ex) {}
- }
- return null;
- }
-
- public static String getString(Row row, int i) {
- try {
- String str = row.getCell(i).getStringCellValue();
- if (str.equals("")) return null;
- return str;
- } catch (Exception e) {}
- return null;
- }
-
- public static Boolean getBooleanFromString(Row row, int i) {
- try {
- String boolStr = getString(row, i).trim().toLowerCase();
- if (boolStr == null || boolStr.equals("")) return null;
- else if (boolStr.equals("yes")) return new Boolean(true);
- else if (boolStr.equals("no")) return new Boolean(false);
- } catch (Exception e) {}
- return null;
- }
-
- public static Date getDate(Row row, int i) {
- try {
- Date date = row.getCell(i).getDateCellValue();
- return date;
- } catch (Exception e) {}
- return null;
- }
-
- public static DateTime getDateTime(Row row, int i) {
- Date date = getDate(row, i);
-
- if (date == null) return null;
- return new DateTime(date);
- }
-
- // Below methods are *not* static and work from column names rather than column numbers
- // IMPORTANT: ONLY WORKS IF colIndexMap HAS BEEN INITIALIZED
- public String getString(Row row, String colName) {
- if (!colIndexMap.containsKey(colName)) {
- if (verbose) missingColumns.add(colName);
- return null;
- }
- String ans = getString(row, colIndexMap.get(colName));
- if (ans != null && unusedColumns != null) unusedColumns.remove(colName);
- return ans;
- }
-
- public String getIntAsString(Row row, String colName) {
- Integer i = getInteger(row, colName);
-
- if (i == null) return null;
- return i.toString();
- }
-
- public String getStringOrInt(Row row, String colName) {
- if (!colIndexMap.containsKey(colName)) {
- if (verbose) missingColumns.add(colName);
- return null;
- }
- String ans = getStringOrInt(row, colIndexMap.get(colName));
- if (ans != null && unusedColumns != null) unusedColumns.remove(colName);
- return ans;
- }
-
- public static String getStringOrInt(Row row, int i) {
- String ans = getString(row, i);
-
- if (ans == null) {
- Integer inty = getInteger(row, i);
- if (inty != null) ans = inty.toString();
- }
- return ans;
- }
-
- public Integer getInteger(Row row, String colName) {
- if (!colIndexMap.containsKey(colName)) {
- if (verbose) missingColumns.add(colName);
- return null;
- }
- Integer ans = getInteger(row, colIndexMap.get(colName));
- if (ans != null && unusedColumns != null) unusedColumns.remove(colName);
- return ans;
- }
-
- public Long getLong(Row row, String colName) {
- if (!colIndexMap.containsKey(colName)) {
- if (verbose) missingColumns.add(colName);
- return null;
- }
- Long ans = getLong(row, colIndexMap.get(colName));
- if (ans != null && unusedColumns != null) unusedColumns.remove(colName);
- return ans;
- }
-
- public Double getDouble(Row row, String colName) {
- if (!colIndexMap.containsKey(colName)) {
- if (verbose) missingColumns.add(colName);
- return null;
- }
- Double ans = getDouble(row, colIndexMap.get(colName));
- if (ans != null && unusedColumns != null) unusedColumns.remove(colName);
- return ans;
- }
-
- public Date getDate(Row row, String colName) {
- if (!colIndexMap.containsKey(colName)) {
- if (verbose) missingColumns.add(colName);
- return null;
- }
- Date ans = getDate(row, colIndexMap.get(colName));
- if (ans != null && unusedColumns != null) unusedColumns.remove(colName);
- return ans;
- }
-
- public DateTime getDateTime(Row row, String colName) {
- if (!colIndexMap.containsKey(colName)) {
- if (verbose) missingColumns.add(colName);
- return null;
- }
- DateTime ans = getDateTime(row, colIndexMap.get(colName));
- if (ans != null && unusedColumns != null) unusedColumns.remove(colName);
- return ans;
- }
-
- // Apache POI, shame on you for making me write this. Shame! Shame! Shame! SHAME!
- // (as if I actually wrote this. thanks stackoverflow!)
- public static boolean isRowEmpty(Row row) {
- for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
- Cell cell = row.getCell(c);
- if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK)
- return false;
- }
- return true;
- }
-
- // This would be cool to put in Encounter or something.
- // tho I'm not immediately sure how we'd get the url context, or determine if we want to include /encounters/ or not
- public static String getEncounterURL(Encounter enc) {
- if (enc == null || enc.getCatalogNumber() == null) return null;
- return "/encounters/encounter.jsp?number=" + enc.getCatalogNumber();
- }
-
- // gives us a nice link if we're
- public String getEncounterDisplayString(Encounter enc) {
- if (enc == null) return null;
- if (committing) {
- return "" + enc.getCatalogNumber() + " ";
- }
- return enc.getCatalogNumber();
- }
-
- private AssetStore getAssetStore(Shepherd myShepherd) {
- // return AssetStore.getDefault(myShepherd);
- return AssetStore.get(myShepherd, 5);
-
- }
-}
diff --git a/src/main/java/org/ecocean/servlet/importer/StandardImport.java b/src/main/java/org/ecocean/servlet/importer/StandardImport.java
index b5136f811c..c33bb2fa3e 100644
--- a/src/main/java/org/ecocean/servlet/importer/StandardImport.java
+++ b/src/main/java/org/ecocean/servlet/importer/StandardImport.java
@@ -912,7 +912,8 @@ public Encounter loadEncounter(Row row, ArrayList annotations, Strin
List configuredSpecies = CommonConfiguration.getIndexedPropertyValues(
"genusSpecies", myShepherd.getContext());
if (configuredSpecies != null && configuredSpecies.size() > 0 &&
- configuredSpecies.toString().replaceAll("_"," ").indexOf(enc.getTaxonomyString()) < 0) {
+ configuredSpecies.toString().replaceAll("_",
+ " ").indexOf(enc.getTaxonomyString()) < 0) {
// if bad values
feedback.logParseError(getColIndexFromColName("Encounter.genus", colIndexMap),
genus, row, "UNSUPPORTED VALUE: " + genus);
@@ -2529,27 +2530,12 @@ public String getStringNoLog(Row row, int i) {
// returns file so you can use .getName() or .lastModified() etc
public static File importXlsFile(String rootDir, HttpServletRequest request) {
File dir = new File(rootDir, "import");
- File f = null;
+ File f = new File(dir, "WildbookStandardFormat.xlsx");
- if (ServletUtilities.useCustomStyle(request, "IndoCet")) {
- f = new File(dir, "WildbookStandardFormat_IndoCet.xlsx");
- } else {
- f = new File(dir, "WildbookStandardFormat.xlsx");
- }
if (f != null && f.isFile()) { return f; } else {
System.out.println("ERROR: importXlsFile() rootDir=" + rootDir + ";f is: " + f);
return null;
}
- /*
- try {
- for (final File f : dir.listFiles()) {
- if (f.isFile() && f.getName().matches("WildbookStandardFormat.*\\.xlsx")) return f;
- }
- } catch (Exception ex) {
- System.out.println("ERROR: importXlsFile() rootDir=" + rootDir + " threw " + ex.toString());
- return null;
- }
- */
}
// cannot put this inside CellFeedback bc java inner classes are not allowed static methods or vars (this is stupid).
diff --git a/src/main/resources/bundles/captcha.properties b/src/main/resources/bundles/captcha.properties
new file mode 100644
index 0000000000..0a4e6e154d
--- /dev/null
+++ b/src/main/resources/bundles/captcha.properties
@@ -0,0 +1,3 @@
+procaptchaSiteKey=CHANGEME
+procaptchaSecretKey=CHANGEME
+
diff --git a/src/main/resources/bundles/codexMigration.properties b/src/main/resources/bundles/codexMigration.properties
deleted file mode 100644
index 4722850ea5..0000000000
--- a/src/main/resources/bundles/codexMigration.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-codexDbUrl=jdbc:postgresql://localhost:5432/codex
-codexDbUsername=example
-codexDbPassword=example
diff --git a/src/main/resources/bundles/commonConfiguration.properties b/src/main/resources/bundles/commonConfiguration.properties
index 8b4f4b17cd..a6edbf880c 100755
--- a/src/main/resources/bundles/commonConfiguration.properties
+++ b/src/main/resources/bundles/commonConfiguration.properties
@@ -105,6 +105,9 @@ showEXIF = true
#show taxonomy
showTaxonomy = true
+# show option for "classic" submit page in UI
+showClassicSubmit = true
+
#for multi-species libraries, fill out the genus and species for each supported animal type, starting with genusSpecies0
genusSpecies0 = Balaenoptera acutorostrata
diff --git a/src/main/resources/bundles/de/header.properties b/src/main/resources/bundles/de/header.properties
index c358aa6a3e..c4926bac94 100755
--- a/src/main/resources/bundles/de/header.properties
+++ b/src/main/resources/bundles/de/header.properties
@@ -7,6 +7,7 @@ learn = Lernen
intro = Einf\u00FChrung
participate = Teilnehmen
report = Eine Begegnung melden
+reportClassic = Eine Begegnung melden (Klassisch)
individuals = Einzelpersonen
viewAll = Alle anzeigen
encounters = Begegnungen
diff --git a/src/main/resources/bundles/en/header.properties b/src/main/resources/bundles/en/header.properties
index d91055d021..37c7ac7ad9 100755
--- a/src/main/resources/bundles/en/header.properties
+++ b/src/main/resources/bundles/en/header.properties
@@ -7,6 +7,7 @@ learn = Learn
intro = Introduction
participate = Participate
report = Report an encounter
+reportClassic = Report an encounter (Classic)
individuals = Individuals
viewAll = View All
encounters = Encounters
diff --git a/src/main/resources/bundles/en/indocet/encounter.properties b/src/main/resources/bundles/en/indocet/encounter.properties
deleted file mode 100644
index 6b98527b08..0000000000
--- a/src/main/resources/bundles/en/indocet/encounter.properties
+++ /dev/null
@@ -1 +0,0 @@
-title = IndoCet Encounter
\ No newline at end of file
diff --git a/src/main/resources/bundles/es/header.properties b/src/main/resources/bundles/es/header.properties
index 4d073a4056..2434443002 100755
--- a/src/main/resources/bundles/es/header.properties
+++ b/src/main/resources/bundles/es/header.properties
@@ -7,6 +7,7 @@ learn = Aprender
intro = Introducci\u00f3n
participate = Participar
report = Informar un encuentro
+reportClassic = Informar un encuentro (Cl\u00e1sico)
individuals = Individuos
viewAll = Ver todos
encounters = Encuentros
diff --git a/src/main/resources/bundles/fr/header.properties b/src/main/resources/bundles/fr/header.properties
index 56990dfdd1..a6c54ed594 100644
--- a/src/main/resources/bundles/fr/header.properties
+++ b/src/main/resources/bundles/fr/header.properties
@@ -7,6 +7,7 @@ learn = Apprendre
intro = Introduction
participate = Participer
report = Signaler une rencontre
+reportClassic = Signaler une rencontre (Classique)
individuals = Individus
viewAll = Tout voir
encounters = Rencontres
diff --git a/src/main/resources/bundles/indocet.properties b/src/main/resources/bundles/indocet.properties
deleted file mode 100644
index e1c77ecc96..0000000000
--- a/src/main/resources/bundles/indocet.properties
+++ /dev/null
@@ -1,136 +0,0 @@
-# These are all the fields that IndoCet has defined, which should appear ANYWHERE they are used on the site.
-
-behavior0 = Feeding
-behavior1 = Traveling
-behavior2 = Milling
-behavior3 = Resting
-behavior4 = Socializing
-behavior5 = Probable Feeding
-behavior6 = Mating
-behavior7 = Undetermined
-
-country0 = Comoros
-country1 = France-Mayotte
-country2 = France-Reunion
-country3 = France-Scattered Islands
-country4 = Kenya
-country5 = Madagascar
-country6 = Mauritius-Mauritius
-country7 = Mauritius-Rodrigues
-country8 = Mozambique
-country9 = Seychelles
-country10 = Somalia
-country11 = South Africa
-country12 = Tanzania
-
-locationID0 = Nosy Be
-locationID1 = Nosy Iranja
-locationID2 = Nosy Mitsio
-locationID3 = Antongil Bay
-locationID4 = Sainte Marie
-locationID5 = Fort Dauphin
-locationID6 = Anakao
-locationID7 = Ifaty
-locationID8 = Mahajanga
-locationID9 = Reunion
-locationID10 = Mayotte
-locationID11 = La Perouse
-locationID12 = Glorieuses
-locationID13 = Juan de Nova
-locationID14 = Bassas da India
-locationID15 = Europa
-locationID16 = Tromelin
-locationID17 = Mauritius
-locationID18 = Rodrigues
-locationID19 = Grande Comore
-locationID20 = Moheli
-locationID21 = Anjouan
-
-groupComposition0 = MotherCalf
-groupComposition1 = MotherCalfEscort
-groupComposition2 = MotherCalfMultipleEscort
-groupComposition3 = CompetitiveGroup
-groupComposition4 = Pair
-groupComposition5 = Singleton
-groupComposition6 = Singer
-groupComposition7 = Non-Competitive
-groupComposition8 = AdultsOnly
-groupComposition9 = MixedAgeClasses
-
-groupBehavior0 = Feeding
-groupBehavior1 = Traveling
-groupBehavior2 = Milling
-groupBehavior3 = Resting
-groupBehavior4 = Socializing
-groupBehavior5 = Probable Feeding
-groupBehavior6 = Undetermined
-groupBehavior7 = Mating
-
-initialCue0 = Blow
-initialCue1 = Breach
-initialCue2 = DorsalFin
-initialCue3 = BodyPart
-initialCue4 = FlukeUp
-initialCue5 = Acoustic
-initialCue6 = Splash
-initialCue7 = Birds
-initialCue8 = Boats
-
-seaState0 = 1
-seaState1 = 2
-seaState2 = 3
-seaState3 = 4
-seaState4 = 5
-
-visibilityIndex0 = 0
-visibilityIndex1 = 1
-visibilityIndex2 = 2
-visibilityIndex3 = 3
-visibilityIndex4 = 4
-visibilityIndex5 = 5
-
-groupRole0 = NuclearAnimal
-groupRole1 = PrincipleEscort
-groupRole2 = Challenger
-groupRole3 = SecondaryEscort
-groupRole4 = Mother
-groupRole5 = Escort
-groupRole6 = Singer
-groupRole7 = Undetermined
-
-lifeStage0 = Adult
-lifeStage1 = Juvenile
-lifeStage2 = Calf
-
-
-# Labeled keywords:
-kwLabel0 = feature
-kwLabel1 = flukeType
-kwLabel2 = quality
-kwLabel3 = distinctiveness
-
-feature0 = Fluke
-feature1 = Right Dorsal Fin
-feature2 = Left Dorsal Fin
-feature3 = Right Blaze
-feature4 = Right Chevron
-feature5 = Left Chevron
-
-flukeType0 = 1
-flukeType1 = 2
-flukeType2 = 3
-flukeType3 = 4
-flukeType4 = 5
-
-quality0 = 0
-quality1 = 1
-quality2 = 2
-quality3 = 3
-quality4 = 4
-
-distinctiveness0 = 0
-distinctiveness1 = 1
-distinctiveness2 = 2
-distinctiveness3 = 3
-distinctiveness4 = 4
-
diff --git a/src/main/resources/bundles/it/header.properties b/src/main/resources/bundles/it/header.properties
index ea68d08359..aaa2b4f714 100644
--- a/src/main/resources/bundles/it/header.properties
+++ b/src/main/resources/bundles/it/header.properties
@@ -7,6 +7,7 @@ learn = scopri
intro = introduzione
participate = Partecipa
report = Segnala un incontro
+reportClassic = Segnala un incontro (Classico)
individuals = Gli esemplari
viewAll = Guarda tutto
encounters = Incontri
diff --git a/src/main/resources/bundles/locationID.json b/src/main/resources/bundles/locationID.json
index 76dd0792b0..ab0025dcd3 100644
--- a/src/main/resources/bundles/locationID.json
+++ b/src/main/resources/bundles/locationID.json
@@ -109,6 +109,6 @@
"long": 8.880677
},
"locationID": []
- },
+ }
]
}
\ No newline at end of file
diff --git a/src/main/resources/servletResponseTemplate.htm b/src/main/resources/servletResponseTemplate.htm
index 7ecd8ace8f..1c4a6f9cab 100755
--- a/src/main/resources/servletResponseTemplate.htm
+++ b/src/main/resources/servletResponseTemplate.htm
@@ -66,7 +66,7 @@
@@ -147,7 +147,7 @@
My Accounts
User Management
Library Administration
- Logs
+ Logs
Photo Keywords
Software Documentation
Data Integrity
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index 7a5914bdbd..ebf945b3be 100755
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -457,7 +457,6 @@
/UpdateStandard = authc, roles[researcher]
/WebImport = authc, roles[researcher]
/import/upload = authc, roles[researcher]
- /ResumableUpload = authc, roles[researcher]
/upload = authc, roles[researcher]
@@ -548,6 +547,23 @@
/api/v3/home
+
+ ApiBaseObject
+ org.ecocean.api.BaseObject
+
+
+ ApiBaseObject
+ /api/v3/encounters/*
+
+
+ ApiBaseObject
+ /api/v3/individuals/*
+
+
+ ApiBaseObject
+ /api/v3/occurrences/*
+
+
ApiProjects
@@ -991,6 +1007,12 @@
org.ecocean.servlet.BatchUpload
+
+ BatchUpload
+ /BatchUpload/*
+
+ -->
+
ReCAPTCHA
org.ecocean.servlet.ReCAPTCHA
@@ -1000,12 +1022,6 @@
/ReCAPTCHA
-
- BatchUpload
- /BatchUpload/*
-
- -->
-
IAGateway
/ia
diff --git a/src/main/webapp/appadmin/codexMigrator.jsp b/src/main/webapp/appadmin/codexMigrator.jsp
deleted file mode 100644
index 71dfb3b174..0000000000
--- a/src/main/webapp/appadmin/codexMigrator.jsp
+++ /dev/null
@@ -1,1125 +0,0 @@
-<%@ page contentType="text/html; charset=utf-8" language="java"
-import="org.ecocean.*,
-org.ecocean.tag.MetalTag,
-org.ecocean.social.*,
-org.ecocean.servlet.ServletUtilities,
-org.ecocean.social.Relationship,
-org.joda.time.DateTime,
-java.io.IOException,
-javax.servlet.jsp.JspWriter,
-javax.servlet.http.HttpServletRequest,
-java.nio.file.Files,
-java.sql.Timestamp,
-java.sql.*,
-java.io.File,
-java.util.ArrayList,
-java.util.List,
-java.util.Map,
-java.util.HashMap,
-java.util.Collection,
-java.util.Set,
-java.util.HashSet,
-java.util.Properties,
-java.util.TimeZone,
-javax.jdo.Query,
-org.json.JSONObject,
-org.json.JSONArray,
-org.ecocean.media.*
- "
-%>
-
-<%!
-
-private static String TMP_DIR = "/tmp/migrate";
-
-private static Encounter encounterFromPending(JSONObject edata) {
- Encounter enc = null;
- return enc;
-}
-
-private static boolean stringEmpty(String str) {
- return ((str == null) || str.equals(""));
-}
-
-private static void cfOccurrence(Shepherd myShepherd, Occurrence occ, Map cfMap) {
- for (String key : cfMap.keySet()) {
- String value = cfMap.get(key);
- if (stringEmpty(value)) continue;
- String label = key.replaceAll(" ", "_");
-System.out.println(">>>>>> " + label + " => " + value + " on " + occ);
- occ.addComments("" + key + ": " + value + "
");
- if (occ.getNumberEncounters() < 1) continue;
- LabeledKeyword kw = myShepherd.getOrCreateLabeledKeyword(label, value, false);
- for (Encounter enc : occ.getEncounters()) {
- for (MediaAsset ma : enc.getMedia()) {
- ma.addKeyword(kw);
-System.out.println(">>>>>> ++++++ " + kw + " on " + ma);
- }
- }
- }
-}
-
-private static String cleanJsonString(String json) {
- if (json == null) return null;
- json = json.replaceAll("\\\\", "");
- json = json.substring(1, json.length() - 1);
- return json;
-}
-
-private static JSONObject cleanJSONObject(String data) {
- String clean = cleanJsonString(data);
- if (clean == null) return null;
- try {
- return new JSONObject(clean);
- } catch (Exception ex) {}
- return null;
-}
-
-private static JSONArray cleanJSONArray(String data) {
- String clean = cleanJsonString(data);
- if (clean == null) return null;
- try {
- return new JSONArray(clean);
- } catch (Exception ex) {}
- return null;
-}
-
-private static Object siteSetting(String key, Connection conn) throws SQLException, IOException {
- Statement st = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT * FROM site_setting WHERE key='" + key + "'");
- if (!res.next()) return null;
- String data = cleanJsonString(res.getString("data"));
- if (data == null) return null;
- try {
- return new JSONObject(data);
- } catch (Exception ex) {}
- try {
- return new JSONArray(data);
- } catch (Exception ex) {}
- return data;
-}
-
-private static JSONObject cfDefinitions(String cls, Connection conn) throws SQLException, IOException {
- Statement st = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT data FROM site_setting WHERE key='site.custom.customFields." + cls + "'");
- if (!res.next()) return null;
- JSONObject j = cleanJSONObject(res.getString("data"));
- if (j == null) return null;
- JSONArray darr = j.optJSONArray("definitions");
- if (darr == null) return null;
- JSONObject rtn = new JSONObject();
- for (int i = 0 ; i < darr.length() ; i++) {
- JSONObject defn = darr.optJSONObject(i);
- if (defn == null) continue;
- String id = defn.optString("id", null);
- if (id == null) continue;
- rtn.put(id, defn);
- }
- return rtn;
-}
-
-private static String cfString(JSONObject cfData, String key) {
- if (cfData == null) return null;
- String value = cfData.optString(key, null);
- if ("".equals(value)) return null;
- return value;
-}
-
-private static Integer cfInteger(JSONObject cfData, String key) {
- if (cfData == null) return null;
- if (!cfData.has(key)) return null;
- if (cfData.isNull(key)) return null;
- try {
- return cfData.getInt(key);
- } catch (Exception ex) {}
- return null;
-}
-
-private static Map relationshipMeta(Connection conn) throws SQLException, IOException {
- Object ss = siteSetting("relationship_type_roles", conn);
- Map rtn = new HashMap();
- if (ss == null) return rtn;
- JSONObject rel = (JSONObject)ss;
- for (String key : (Set)rel.keySet()) {
- JSONObject data = rel.optJSONObject(key);
- if (data == null) continue;
- String label = data.optString("label", null);
- if (label != null) rtn.put(key, label);
- JSONArray roles = data.optJSONArray("roles");
- if (roles == null) continue;
- for (int i = 0 ; i < roles.length() ; i++) {
- JSONObject role = roles.optJSONObject(i);
- if (role == null) continue;
- String rid = role.optString("guid", null);
- String rlabel = role.optString("label", null);
- if ((rid != null) && (rlabel != null)) rtn.put(rid, rlabel);
- }
- }
- return rtn;
-}
-
-private static Map socialGroupMeta(Connection conn) throws SQLException, IOException {
- Object ss = siteSetting("social_group_roles", conn);
- Map rtn = new HashMap();
- if (ss == null) return rtn;
- JSONArray sgArr = (JSONArray)ss;
- for (int i = 0 ; i < sgArr.length() ; i++) {
- JSONObject sg = sgArr.optJSONObject(i);
- if (sg == null) continue;
- String guid = sg.optString("guid", null);
- String label = sg.optString("label", null);
- if ((guid == null) || (label == null)) continue;
- rtn.put(guid, label);
- }
- return rtn;
-}
-
-private static Map taxonomyMap(Connection conn) throws SQLException, IOException {
- Object ss = siteSetting("site.species", conn);
- Map rtn = new HashMap();
- if (ss == null) return rtn;
- JSONArray arr = (JSONArray)ss;
- for (int i = 0 ; i < arr.length() ; i++) {
- JSONObject tx = arr.getJSONObject(i);
- rtn.put(tx.optString("id", "_FAIL"), tx.optString("scientificName", "_FAIL"));
- }
- return rtn;
-}
-
-private static JSONObject locationJson(Connection conn) throws SQLException, IOException {
- Object ss = siteSetting("site.custom.regions", conn);
- if (ss == null) return null;
- try {
- return (JSONObject)ss;
- } catch (Exception ex) {}
- return null;
-}
-
-private static Map locationMap(Connection conn) throws SQLException, IOException {
- Map map = new HashMap();
- return locationMap(locationJson(conn), map);
-}
-
-private static Map locationMap(JSONObject data, Map map) {
- if (data == null) return map;
- String id = data.optString("id", null);
- String name = data.optString("name", id);
- if (id != null) map.put(id, name);
- JSONArray sub = data.optJSONArray("locationID");
- if (sub != null) for (int i = 0 ; i < sub.length() ; i++) {
- JSONObject subObj = sub.optJSONObject(i);
- if (subObj == null) continue;
- locationMap(subObj, map);
- }
- return map;
-}
-
-
-private static int batchMax() {
- return 00;
-}
-
-private static void migrateUsers(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- out.println("Users ");
- Statement st = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT * FROM \"user\"");
- int ct = 0;
- while (res.next()) {
- String guid = res.getString("guid");
- int staticRoles = res.getInt("static_roles");
- out.println("" + guid + ": ");
- Set roles = new HashSet();
- if ((staticRoles & 0x04000) > 0) {
- roles.add("admin");
- roles.add("orgAdmin");
- roles.add("researcher");
- roles.add("rest");
- roles.add("machinelearning");
- }
- if ((staticRoles & 0x80000) > 0) roles.add("orgAdmin");
- //if ((staticRoles & 0x10000) > 0) exporter == "N/A"
- if ((staticRoles & 0x20000) > 0) roles.add("researcher");
- if ((staticRoles & 0x40000) > 0) {
- roles.add("rest");
- roles.add("machinelearning");
- }
- User user = myShepherd.getUserByUUID(guid);
- if (user != null) {
- out.println("user exists; skipping ");
- } else {
- user = new User(guid);
- String username = res.getString("email");
- user.setUsername(username);
- user.setAffiliation(res.getString("affiliation"));
- // location seems to often have value in codex
- user.setUserURL(res.getString("website"));
- user.setEmailAddress(res.getString("email"));
- user.setFullName(res.getString("full_name"));
- myShepherd.getPM().makePersistent(user);
-
- for (String roleName : roles) {
- Role role = new Role();
- role.setRolename(roleName);
- role.setUsername(username);
- role.setContext("context0");
- myShepherd.getPM().makePersistent(role);
- }
-
- // TODO: Organizations
-
- String msg = "created user [" + ct + "] [" + String.join(",", roles) + "] " + user;
- out.println("" + msg + " ");
- System.out.println(msg);
- }
- out.println(" ");
- ct++;
- }
- out.println(" ");
-}
-
-
-private static void migrateMediaAssets(JspWriter out, Shepherd myShepherd, Connection conn, HttpServletRequest request, File assetGroupDir) throws SQLException, IOException {
- out.println("MediaAssets ");
- Statement st = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT * FROM asset ORDER BY git_store_guid, guid");
- AssetStore targetStore = AssetStore.getDefault(myShepherd);
- List maIds = new ArrayList();
- int ct = 0;
-
- while (res.next()) {
- ct++;
- if (ct > batchMax()) break;
- String guid = res.getString("guid");
- out.println("" + guid + ": ");
- MediaAsset ma = MediaAssetFactory.loadByUuid(guid, myShepherd);
- if (ma != null) {
- ct--;
- out.println("asset exists; skipping ");
- } else {
- String ext = "unknown";
- String mimeType = res.getString("mime_type");
- if ((mimeType != null) && mimeType.contains("/")) ext = mimeType.split("\\/")[1];
- if ("jpeg".equals(ext)) ext = "jpg";
- String assetGroupGuid = res.getString("git_store_guid");
- File sourceFile = new File(assetGroupDir, assetGroupGuid + "/_assets/" + guid + "." + ext);
- String userFilename = res.getString("path");
- if (stringEmpty(userFilename)) userFilename = guid + "." + ext;
- //out.println(sourceFile.toString());
- if (!sourceFile.exists()) {
- out.println("" + sourceFile + " does not exist ");
- if (ext.equals("unknown")) continue;
- break;
- }
- File tmpFile = new File(TMP_DIR, guid + "." + ext);
- Files.copy(sourceFile.toPath(), tmpFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
- String grouping = Util.hashDirectories(assetGroupGuid, File.separator);
- JSONObject params = targetStore.createParameters(tmpFile, grouping);
- params.put("userFilename", userFilename);
- params.put("_codexMigration", System.currentTimeMillis());
- ma = targetStore.create(params);
- try {
- ma.copyIn(sourceFile);
- } catch (Exception ex) {
- out.println("failed to copyIn " + sourceFile + " => " + ex.toString() + " ");
- break;
- }
- ma.setUUID(guid);
- // TODO: revision from codex?
- ma.setAcmId(res.getString("content_guid"));
- ma.updateMetadata();
- ma.addLabel("_original");
- ma.setAccessControl(request);
- MediaAssetFactory.save(ma, myShepherd);
- maIds.add(ma.getId());
- String msg = "created [" + ct + "] " + ma;
- out.println("" + msg + " ");
- System.out.println(msg);
- }
- out.println(" ");
- }
- myShepherd.commitDBTransaction(); // necessary for backgrounding
- myShepherd.beginDBTransaction();
- MediaAsset.updateStandardChildrenBackground(ServletUtilities.getContext(request), maIds);
- out.println(" ");
-}
-
-
-private static void migrateAnnotations(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- out.println("Annotations ");
- Statement st = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT * FROM annotation ORDER BY guid");
- FeatureType.initAll(myShepherd);
- int ct = 0;
-
- while (res.next()) {
- ct++;
- if (ct > batchMax()) break;
- String guid = res.getString("guid");
- Annotation ann = myShepherd.getAnnotation(guid);
- if (ann != null) {
- ct--;
- out.println("" + guid + ": annotation exists; skipping ");
- } else {
- String maId = res.getString("asset_guid");
- MediaAsset ma = MediaAssetFactory.loadByUuid(maId, myShepherd);
- if (ma == null) {
- //out.println("" + guid + ": failed due to missing MediaAsset id=" + maId + " ");
- //System.out.println(guid + " failed due to missing MediaAsset id=" + maId);
- ct--;
- continue;
- }
- out.println(" " + guid + ": ");
- JSONObject bounds = cleanJSONObject(res.getString("bounds"));
- if (bounds == null) bounds = new JSONObject();
- Feature feat = null;
- JSONArray rect = bounds.optJSONArray("rect");
- if (rect != null) {
- JSONObject params = new JSONObject();
- params.put("theta", bounds.optDouble("theta", 0d));
- params.put("x", rect.optInt(0, 0));
- params.put("y", rect.optInt(1, 0));
- params.put("width", rect.optInt(2, 0));
- params.put("height", rect.optInt(3, 0));
- feat = new Feature("org.ecocean.boundingBox", params);
- } else {
- System.out.println("%%% failed on bbox for bounds=" + bounds);
- feat = new Feature();
- }
- ma.addFeature(feat);
- // 99.9% sure species doesnt matter any more, so setting as null
- ann = new Annotation(null, feat, res.getString("ia_class"));
- ann.setId(guid);
- // TODO: id status?
- ann.setAcmId(res.getString("content_guid"));
- ann.setViewpoint(res.getString("viewpoint"));
- ann.setMatchAgainst(true);
- myShepherd.getPM().makePersistent(ann);
-
- String msg = "created annot [" + ct + "] " + ann;
- out.println("" + msg + " ");
- System.out.println(msg);
- }
- out.println(" ");
- }
- out.println(" ");
-}
-
-private static void migrateEncounters(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- out.println("Encounters ");
- Map txmap = taxonomyMap(conn);
- Statement st = conn.createStatement();
- Statement st2 = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT encounter.*, complex_date_time.datetime, complex_date_time.timezone, complex_date_time.specificity FROM encounter JOIN complex_date_time ON (time_guid = complex_date_time.guid) ORDER BY guid");
- int ct = 0;
-
- while (res.next()) {
- ct++;
- if (ct > batchMax()) break;
- String guid = res.getString("guid");
- out.println("" + guid + ": ");
- Encounter enc = myShepherd.getEncounter(guid);
- if (enc != null) {
- ct--;
- out.println("encounter exists; skipping ");
- } else {
- enc = new Encounter();
- enc.setId(guid);
- Timestamp ts = res.getTimestamp("created");
- if (ts != null) enc.setDWCDateAdded(ts.toString());
- ts = res.getTimestamp("updated");
- if (ts != null) enc.setDWCDateLastModified(ts.toString());
- String txguid = res.getString("taxonomy_guid");
- if (txguid != null) enc.setTaxonomyFromString(txmap.get(txguid));
- User owner = myShepherd.getUserByUUID(res.getString("owner_guid"));
- if (owner != null) {
- enc.addSubmitter(owner);
- enc.setSubmitterID(owner.getUsername());
- }
- Double d = res.getDouble("decimal_latitude");
- if (res.wasNull()) d = null;
- enc.setDecimalLatitude(d);
- d = res.getDouble("decimal_longitude");
- if (res.wasNull()) d = null;
- enc.setDecimalLongitude(d);
- enc.setSex(res.getString("sex"));
- enc.setVerbatimLocality(res.getString("verbatim_locality"));
- enc.setLocationID(res.getString("location_guid"));
-
- // date/time madness
- ts = res.getTimestamp("datetime");
-System.out.println("TIME: ts=" + ts);
- String tz = res.getString("timezone");
- if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone(tz));
- String spec = res.getString("specificity");
- Timestamp adjusted = ts;
- enc.setYear(adjusted.getYear() + 1900);
- if (!"year".equals(spec)) {
- enc.setMonth(adjusted.getMonth() + 1);
- if (!"month".equals(spec)) {
- enc.setDay(adjusted.getDate());
- if (!"day".equals(spec)) {
- enc.setHour(adjusted.getHours());
- enc.setMinutes(Integer.toString(adjusted.getMinutes())); // ygbkm
- }
- }
- }
-
- // custom fields, oof
- // these need to be hard-coded per migration
- JSONObject cfData = cleanJSONObject(res.getString("custom_fields"));
- String lifeStage = cfString(cfData, "344792fc-7910-45cd-867b-cb9c927677e1");
- String livingStatus = cfString(cfData, "b9eb55f4-ebc6-47b7-9991-9339084c8639");
- String occRemarks = cfString(cfData, "0d9a3764-f872-4320-ba03-bde268ce1513");
- String researcherComments = cfString(cfData, "b230a670-ee2e-44c4-89a1-6b1dffe2cda3");
- String unidentIndiv = cfString(cfData, "0f48fdc5-6a5e-4a01-aeff-2f1bebf4864d");
- enc.setLifeStage(lifeStage);
- enc.setLivingStatus(livingStatus);
- enc.setOccurrenceRemarks(occRemarks);
- enc.addComments(researcherComments);
- if (unidentIndiv != null) enc.setDynamicProperty("unidentified_individual", unidentIndiv);
-
- myShepherd.storeNewEncounter(enc, guid);
-
- String msg = "created encounter [" + ct + "] " + enc;
- out.println("" + msg + " ");
- System.out.println(msg);
- }
- out.println(" ");
- }
- out.println(" ");
-
- // annotation joins after
- ct = 0;
- res = st.executeQuery("SELECT guid, encounter_guid FROM annotation ORDER BY encounter_guid, guid");
- while (res.next()) {
- String annGuid = res.getString("guid");
- String encGuid = res.getString("encounter_guid");
- Encounter enc = myShepherd.getEncounter(encGuid);
- Annotation ann = myShepherd.getAnnotation(annGuid);
- if ((enc == null) || (ann == null)) {
- System.out.println("migrateEncounters: cannot join due to null; enc=" + enc + "; ann=" + ann);
- continue;
- }
- ct++;
- enc.addAnnotation(ann);
- }
- out.println("joined " + ct + " enc/ann pairs
");
-}
-
-
-private static void migrateOccurrences(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- out.println("Occurrences ");
- Statement st = conn.createStatement();
- Statement st2 = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT sighting.*, complex_date_time.datetime, complex_date_time.timezone, complex_date_time.specificity FROM sighting JOIN complex_date_time ON (time_guid = complex_date_time.guid) ORDER BY guid");
- int ct = 0;
-
- while (res.next()) {
- ct++;
- if (ct > batchMax()) break;
- String guid = res.getString("guid");
- out.println("" + guid + ": ");
- Occurrence occ = myShepherd.getOccurrence(guid);
- if (occ != null) {
- ct--;
- out.println("occurrence exists; skipping ");
- } else {
- occ = new Occurrence();
- occ.setId(guid);
- Timestamp ts = res.getTimestamp("created");
- if (ts != null) occ.setDateTimeCreated(ts.toString());
- ts = res.getTimestamp("updated");
- if (ts != null) occ.setDWCDateLastModified(ts.toString());
-
- Double d = res.getDouble("decimal_latitude");
- if (res.wasNull()) d = null;
- occ.setDecimalLatitude(d);
- d = res.getDouble("decimal_longitude");
- if (res.wasNull()) d = null;
- occ.setDecimalLongitude(d);
- occ.setComments(res.getString("comments"));
- //occ.setVerbatimLocality(res.getString("verbatim_locality"));
- //occ.setLocationID(res.getString("location_guid"));
-
- // date/time madness
- ts = res.getTimestamp("datetime");
- String tz = res.getString("timezone");
- if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone(tz));
- //String spec = res.getString("specificity");
- // we only store a long for this on occurrences
- if (ts != null) occ.setDateTimeLong(ts.getTime());
-
- // custom fields, oof
- // these need to be hard-coded per migration
- JSONObject cfData = cleanJSONObject(res.getString("custom_fields"));
- Map cfMap = new HashMap();
- cfMap.put("Seen in Artificial Nest", cfString(cfData, "34a8f03e-d282-4fef-b1ed-9eeebaaa887e"));
- cfMap.put("Observation Type", cfString(cfData, "736d8b8f-7abb-404f-9da8-0c1507185baa"));
- cfMap.put("Seen with Unknown Seal", cfString(cfData, "e9a00eab-7ea6-4777-afb3-79d95ebfbf4f"));
- cfMap.put("Photography Type", cfString(cfData, "cf7ed66f-e6c1-4cb1-aadf-0f141ca22316"));
- cfMap.put("Sighting Origin", cfString(cfData, "15b4525a-47e9-4673-ae42-f99ea55f810c"));
- cfMap.put("Seen with Unknown Pup", cfString(cfData, "d0f2cc9e-0845-4608-8754-3d1f70eec699"));
- String photogName = cfString(cfData, "305b50df-7f21-4d8d-aeb6-45ab1869f5ba");
- String photogEmail = cfString(cfData, "ecc6f017-057c-4821-b07a-f82cd60aa31d");
-
- // we have to link encounters here due to customField needs :(
- // this makes the joining code below kinda redundant but leaving it to catch stuff that missed
- ResultSet res2 = st2.executeQuery("SELECT guid FROM encounter WHERE sighting_guid='" + guid + "' ORDER BY guid");
- while (res2.next()) {
- Encounter enc = myShepherd.getEncounter(res2.getString("guid"));
- if (enc == null) continue;
- occ.addEncounter(enc);
- enc.setOccurrenceID(occ.getId());
- if (!stringEmpty(photogName)) enc.setPhotographerName(photogName);
- if (!stringEmpty(photogEmail)) enc.setPhotographerEmail(photogEmail);
- }
-
- // now we can do this, since it needs encs
- cfOccurrence(myShepherd, occ, cfMap);
-
- myShepherd.storeNewOccurrence(occ);
-
- String msg = "created occurrence [" + ct + "] " + occ;
- out.println("" + msg + " ");
- System.out.println(msg);
- }
- out.println(" ");
- }
- out.println(" ");
-
- ct = 0;
- res = st.executeQuery("SELECT guid, sighting_guid FROM encounter ORDER BY sighting_guid");
- while (res.next()) {
- String encGuid = res.getString("guid");
- String occGuid = res.getString("sighting_guid");
- Encounter enc = myShepherd.getEncounter(encGuid);
- Occurrence occ = myShepherd.getOccurrence(occGuid);
- if ((enc == null) || (occ == null)) {
- System.out.println("migrateOccurrences: cannot join due to null; enc=" + enc + "; occ=" + occ);
- continue;
- }
- if (occ.addEncounter(enc)) {
- enc.setOccurrenceID(occ.getId());
- ct++;
- }
- }
- out.println("joined " + ct + " occ/enc pairs
");
-
-}
-
-private static void migrateMarkedIndividuals(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- out.println("MarkedIndividuals ");
- Map txmap = taxonomyMap(conn);
- Statement st = conn.createStatement();
- Statement st2 = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT * FROM individual ORDER BY guid");
- int ct = 0;
-
- while (res.next()) {
- ct++;
- if (ct > batchMax()) break;
- String guid = res.getString("guid");
- out.println("" + guid + ": ");
- MarkedIndividual indiv = myShepherd.getMarkedIndividual(guid);
- if (indiv != null) {
- ct--;
- out.println("indiv exists; skipping ");
- } else {
- indiv = new MarkedIndividual();
- indiv.setId(guid);
- Timestamp ts = res.getTimestamp("created");
- if (ts != null) indiv.setDateTimeCreated(ts.toString());
- //ts = res.getTimestamp("updated");
- //if (ts != null) occ.setDWCDateLastModified(ts.toString());
- String txguid = res.getString("taxonomy_guid");
- if (txguid != null) indiv.setTaxonomyString(txmap.get(txguid));
- ts = res.getTimestamp("time_of_birth");
- if (ts != null) indiv.setTimeOfBirth(ts.getTime());
- ts = res.getTimestamp("time_of_death");
- if (ts != null) indiv.setTimeOfDeath(ts.getTime());
- indiv.setSex(res.getString("sex"));
- indiv.setComments(res.getString("comments"));
-
- ResultSet res2 = st2.executeQuery("SELECT * FROM name WHERE individual_guid='" + guid + "'");
- while (res2.next()) {
- String nameContext = res2.getString("context");
- String nameValue = res2.getString("value");
- if ("FirstName".equals(nameContext)) {
- indiv.addName(nameValue);
- } else {
- indiv.addName(nameContext, nameValue);
- }
- }
-
- // same note as occurrences on needing encs attached first :(
- res2 = st2.executeQuery("SELECT guid FROM encounter WHERE individual_guid='" + guid + "' ORDER BY guid");
- while (res2.next()) {
- Encounter enc = myShepherd.getEncounter(res2.getString("guid"));
- if (enc == null) continue;
- if (!enc.hasMarkedIndividual(indiv)) {
- enc.setIndividual(indiv);
- }
- }
-
- // custom fields, oof
- // these need to be hard-coded per migration
- JSONObject cfData = cleanJSONObject(res.getString("custom_fields"));
-
- String dateOfBirth = cfString(cfData, "87d08929-2133-4053-911a-8740f7fa8dd5");
- if (!stringEmpty(dateOfBirth)) try {
- indiv.setTimeOfBirth(Util.getVersionFromModified(dateOfBirth));
- } catch (Exception ex) {}
- String dateOfDeath = cfString(cfData, "ed537aa9-5d68-45e5-9236-f701d95a8bdd");
- if (!stringEmpty(dateOfDeath)) try {
- indiv.setTimeOfDeath(Util.getVersionFromModified(dateOfDeath));
- } catch (Exception ex) {}
- String notes = cfString(cfData, "8ac7286d-3290-41d3-8497-17b3f7aa5184");
- if (!stringEmpty(notes)) indiv.addComments(notes);
-
- // these require more complex stuff
- String withPup = cfString(cfData, "6428357e-8965-45f6-8f53-d17df08c4316");
- String lifeStatus = cfString(cfData, "854a9755-1909-464b-b024-7608045309a7");
- String flipperTag = cfString(cfData, "7bb54bb8-f148-47b5-91b3-286b8851e461");
- String entanglement = cfString(cfData, "e9ecaaac-54c9-4c94-bf2e-0989f467c1d1");
-
- if (!stringEmpty(withPup)) {
- indiv.addComments("With Pup: " + withPup + "
");
- for (Encounter enc : indiv.getEncounters()) {
-System.out.println(">>>>> ??? " + withPup + " on " + enc);
- enc.setDynamicProperty("with_pup", withPup);
- }
- }
- if (!stringEmpty(flipperTag)) {
- indiv.addComments("Flipper Tag: " + flipperTag + "
");
- MetalTag tag = new MetalTag(flipperTag, "flipper");
- for (Encounter enc : indiv.getEncounters()) {
-System.out.println(">>>>> ??? " + tag + " on " + enc);
- enc.addMetalTag(tag);
- }
- }
- if (!stringEmpty(lifeStatus)) {
- indiv.addComments("Life Status: " + lifeStatus + "
");
- Encounter[] recent = indiv.getDateSortedEncounters(true, 1);
- if ((recent != null) && (recent.length > 0)) recent[0].setLifeStage(lifeStatus);
-System.out.println(">>>>> ??? " + lifeStatus + " on " + indiv);
- }
- if (!stringEmpty(entanglement)) {
- indiv.addComments("Entanglement: " + entanglement + "
");
- LabeledKeyword kw = myShepherd.getOrCreateLabeledKeyword("Entanglement", entanglement, false);
- for (Encounter enc : indiv.getEncounters()) {
- for (MediaAsset ma : enc.getMedia()) {
-System.out.println(">>>>> ??? " + kw + " on " + enc);
- ma.addKeyword(kw);
- }
- }
- }
-
- myShepherd.storeNewMarkedIndividual(indiv);
-
- String msg = "created indiv [" + ct + "] " + indiv;
- out.println("" + msg + " ");
- System.out.println(msg);
- }
- out.println(" ");
- }
- out.println(" ");
-
- ct = 0;
- res = st.executeQuery("SELECT guid, individual_guid FROM encounter WHERE individual_guid IS NOT NULL ORDER BY individual_guid");
- while (res.next()) {
- String encGuid = res.getString("guid");
- String indivGuid = res.getString("individual_guid");
- Encounter enc = myShepherd.getEncounter(encGuid);
- MarkedIndividual indiv = myShepherd.getMarkedIndividual(indivGuid);
- if ((enc == null) || (indiv == null)) {
- System.out.println("migrateMarkedIndividuals: cannot join due to null; enc=" + enc + "; indiv=" + indiv);
- continue;
- }
- ct++;
- enc.setIndividual(indiv);
- }
- out.println("joined " + ct + " enc/indiv pairs
");
-
-}
-
-
-private static void migrateKeywords(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- out.println("Keywords ");
- Statement st = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT keyword.guid, value, STRING_AGG(annotation_guid::text, ',') AS annot_guids FROM keyword JOIN annotation_keywords ON (keyword.guid = keyword_guid) GROUP BY keyword.guid");
- int ct = 0;
-
- while (res.next()) {
- ct++;
- String guid = res.getString("guid");
- String value = res.getString("value");
- if (stringEmpty(value)) continue;
- String annIdList = res.getString("annot_guids");
- if (stringEmpty(annIdList)) continue;
- String[] annIds = annIdList.split(",");
- if (annIds.length < 1) continue;
- Keyword kw = myShepherd.getOrCreateKeyword(value);
- out.println("" + guid + " " + kw + ": ");
- for (String annId : annIds) {
- Annotation ann = myShepherd.getAnnotation(annId);
- if (ann == null) {
- out.println("cannot load Annot " + annId + " ");
- continue;
- }
- MediaAsset ma = ann.getMediaAsset();
- if (ma == null) {
- out.println("cannot load MediaAsset on " + ann + " ");
- continue;
- }
- if (ma.hasKeyword(kw)) {
- out.println("" + ma + " already has " + kw + " ");
- continue;
- }
- ma.addKeyword(kw);
- out.println("Added " + kw + " to " + ma + " ");
- }
- out.println(" ");
- }
- out.println(" ");
-}
-
-private static void migrateRelationships(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- out.println("Relationships ");
- Map relMeta = relationshipMeta(conn);
- Statement st = conn.createStatement();
- Statement st2 = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT * FROM relationship");
- int ct = 0;
-
- while (res.next()) {
- ct++;
- String guid = res.getString("guid");
- String typeGuid = res.getString("type_guid");
- out.println("" + guid + " [" + typeGuid + "]: ");
- String typeLabel = relMeta.get(typeGuid);
- if (typeLabel == null) {
- out.println("unknown label ");
- continue;
- }
- out.println(" typeLabel=" + typeLabel);
- ResultSet res2 = st2.executeQuery("SELECT * FROM relationship_individual_member WHERE relationship_guid='" + guid + "'");
- List indivs = new ArrayList();
- List roles = new ArrayList();
- out.println("");
- while (res2.next()) {
- String indivGuid = res2.getString("individual_guid");
- String roleGuid = res2.getString("individual_role_guid");
- MarkedIndividual indiv = myShepherd.getMarkedIndividual(indivGuid);
- String roleLabel = relMeta.get(roleGuid);
- if ((indiv == null) || (roleLabel == null)) {
- out.println("failed on indivGuid=" + indivGuid + ", roleGuid=" + roleGuid + "[" + roleLabel + "] ");
- } else {
- out.println("" + roleGuid + "[" + roleLabel + "] on " + indiv + " ");
- indivs.add(indiv);
- roles.add(roleLabel);
- }
- }
- out.println(" ");
- if (indivs.size() != 2) {
- out.println("invalid indivs.size=" + indivs.size() + " ");
- continue;
- }
-
- Relationship rel = myShepherd.getRelationship(typeLabel, indivs.get(0).getId(), indivs.get(1).getId(), roles.get(0), roles.get(1));
- if (rel != null) {
- out.println("rel already exists: " + rel + " ");
- continue;
- }
- rel = new Relationship(typeLabel, indivs.get(0), indivs.get(1));
- myShepherd.getPM().makePersistent(rel);
- myShepherd.commitDBTransaction();
- myShepherd.beginDBTransaction();
- rel.setMarkedIndividualRole1(roles.get(0));
- rel.setMarkedIndividualRole2(roles.get(1));
- out.println("created " + rel + " on " + indivs.get(0) + " and " + indivs.get(1) + " ");
- out.println("");
- }
- out.println(" ");
-}
-
-private static void migrateSocialGroups(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- out.println("SocialGroups ");
- Map sgMeta = socialGroupMeta(conn);
- Statement st = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT group_guid, name, individual_guid, roles FROM social_group_individual_membership JOIN social_group ON (group_guid=social_group.guid);");
- int ct = 0;
-
- Map units = new HashMap();
- while (res.next()) {
- ct++;
- String suName = res.getString("name");
- SocialUnit su = units.get(suName);
- if (su == null) su = myShepherd.getSocialUnit(suName);
- if (su == null) su = new SocialUnit(suName);
- units.put(suName, su);
- out.println("" + su + " : ");
-
- String indivID = res.getString("individual_guid");
- MarkedIndividual indiv = myShepherd.getMarkedIndividual(indivID);
- if (indiv == null) {
- out.println("failed to load indivID=" + indivID + " ");
- continue;
- }
- out.println("[" + indiv + "]; ");
- // even tho the code before will import multiple roles per individual, we are
- // going to bail on there already *existing* one meaning this has been done
- // ymmv ???
- Membership exists = su.getMembershipForMarkedIndividual(indiv);
- if (exists != null) {
- out.println("a membership exists for " + indiv + "; skipping ");
- continue;
- }
- myShepherd.getPM().makePersistent(su);
-
- JSONArray rolesArr = cleanJSONArray(res.getString("roles"));
- if ((rolesArr == null) || (rolesArr.length() == 0)) {
- // guess we make it a null role and add it???
- Membership membership = new Membership(indiv);
- membership.setRole(null);
- myShepherd.getPM().makePersistent(membership);
- su.addMember(membership);
- out.println("[null role]");
- } else {
- for (int i = 0 ; i < rolesArr.length() ; i++) {
- String role = rolesArr.optString(i, null);
- if (role == null) continue;
- String roleName = sgMeta.get(role);
- if (roleName == null) {
- out.println("[failed to find roleName for role=" + role + "; skipping] ");
- continue;
- }
- Membership membership = new Membership(indiv);
- membership.setRole(roleName);
- myShepherd.getPM().makePersistent(membership);
- su.addMember(membership);
- out.println("[role=" + role + "; roleName=" + roleName + "]");
- }
- }
-
- out.println("");
- }
- out.println(" ");
-}
-
-private static void migratePendingSightings(JspWriter out, Shepherd myShepherd, Connection conn, HttpServletRequest request) throws SQLException, IOException {
- out.println("PendingSightings ");
- Statement st = conn.createStatement();
- ResultSet res = st.executeQuery("SELECT * FROM asset_group_sighting WHERE stage != 'processed' ORDER BY guid");
- int ct = 0;
-
- while (res.next()) {
- ct++;
- String guid = res.getString("guid");
- out.println("" + guid + ": ");
- Occurrence occ = myShepherd.getOccurrence(guid);
- if (occ != null) {
- ct--;
- out.println("occurrence exists; skipping ");
- } else {
- JSONObject config = cleanJSONObject(res.getString("config"));
- if (config == null) {
- out.println("null config; failing ");
- continue;
- }
- out.println("" + config.toString(4) + " ");
-
- JSONObject sdata = config.optJSONObject("sighting");
- if (sdata == null) {
- out.println("null sighitng data in config; failing ");
- continue;
- }
- JSONArray earr = sdata.optJSONArray("encounters");
- if ((earr == null) || (earr.length() < 1)) {
- out.println("null or empty encounters array in config; failing ");
- continue;
- }
-
- occ = new Occurrence();
- occ.setId(guid);
- // TODO: something with asset_group_guid ?
-
- occ.setEncounters(new ArrayList()); //grrr
- for (int i = 0 ; i < earr.length() ; i++) {
- Encounter enc = encounterFromPending(earr.optJSONObject(i));
- if (enc == null) {
- out.println("failed to create enc " + i + " ");
- continue;
- }
- occ.addEncounter(enc);
- enc.setOccurrenceID(occ.getId());
- }
-
- Timestamp ts = res.getTimestamp("created");
- if (ts != null) occ.setDateTimeCreated(ts.toString());
- ts = res.getTimestamp("updated");
- if (ts != null) occ.setDWCDateLastModified(ts.toString());
-
- Double d = null;
- if (sdata.has("decimal_latitude") && !sdata.isNull("decimal_latitude")) d = sdata.getDouble("decimal_latitude");
- occ.setDecimalLatitude(d);
- d = null;
- if (sdata.has("decimal_longitude") && !sdata.isNull("decimal_longitude")) d = sdata.getDouble("decimal_longitude");
- occ.setDecimalLongitude(d);
- occ.setComments(sdata.optString("comments", null));
- //occ.setVerbatimLocality(res.getString("verbatim_locality"));
- //occ.setLocationID(res.getString("location_guid"));
-
- // date/time madness
- String time = sdata.optString("time", null);
- if (time == null) {
- out.println("null time config; failing ");
- continue;
- }
- //String spec = res.getString("specificity"); n/a
- // we only store a long for this on occurrences
- occ.setDateTimeLong(new DateTime(time).getMillis());
-
- // custom fields, oof
- // these need to be hard-coded per migration
- JSONObject cfData = sdata.optJSONObject("customFields");
- Map cfMap = new HashMap();
- cfMap.put("Seen in Artificial Nest", cfString(cfData, "34a8f03e-d282-4fef-b1ed-9eeebaaa887e"));
- cfMap.put("Observation Type", cfString(cfData, "736d8b8f-7abb-404f-9da8-0c1507185baa"));
- cfMap.put("Seen with Unknown Seal", cfString(cfData, "e9a00eab-7ea6-4777-afb3-79d95ebfbf4f"));
- cfMap.put("Photography Type", cfString(cfData, "cf7ed66f-e6c1-4cb1-aadf-0f141ca22316"));
- cfMap.put("Sighting Origin", cfString(cfData, "15b4525a-47e9-4673-ae42-f99ea55f810c"));
- cfMap.put("Seen with Unknown Pup", cfString(cfData, "d0f2cc9e-0845-4608-8754-3d1f70eec699"));
- String photogName = cfString(cfData, "305b50df-7f21-4d8d-aeb6-45ab1869f5ba");
- String photogEmail = cfString(cfData, "ecc6f017-057c-4821-b07a-f82cd60aa31d");
-
- if (occ.getNumberEncounters() > 0) for (Encounter enc : occ.getEncounters()) {
- if (!stringEmpty(photogName)) enc.setPhotographerName(photogName);
- if (!stringEmpty(photogEmail)) enc.setPhotographerEmail(photogEmail);
- try {
- out.println("" + enc.uiJson(request).toString(4) + " ");
- } catch (Exception ex) {}
- }
-
- // now we can do this, since it needs encs
- cfOccurrence(myShepherd, occ, cfMap);
-
-/*
- myShepherd.storeNewOccurrence(occ);
-
- String msg = "created occurrence [" + ct + "] " + occ;
- out.println("" + msg + " ");
- System.out.println(msg);
-*/
-
-
- out.println("" + occ.getJSONSummary().toString(4) + " ");
- }
-
- out.println("");
- }
- out.println(" ");
-}
-
-
-private static void fixAutogenNames(JspWriter out, Shepherd myShepherd, Connection conn) throws SQLException, IOException {
- Object ss = siteSetting("autogenerated_names", conn);
- if (ss == null) return;
- JSONObject autogenMeta = (JSONObject)ss;
-
- out.println("Autogenerated Names ");
- //Statement st = conn.createStatement();
- Query query = myShepherd.getPM().newQuery("SELECT FROM org.ecocean.MultiValue WHERE valuesAsString.matches('.*autogen-.*')");
- Collection c = (Collection)(query.execute());
- List all = new ArrayList(c);
- query.closeAll();
- for (MultiValue mv : all) {
- JSONObject val = mv.getValues();
- Map replace = new HashMap();
- for (String key : (Set)val.keySet()) {
- if (key.startsWith("autogen-")) {
- JSONArray names = val.optJSONArray(key);
- if ((names == null) || (names.length() < 1)) continue;
- String suffix = names.optString(0, null);
- if (suffix == null) continue;
- String txId = key.substring(8);
- JSONObject meta = autogenMeta.optJSONObject(txId);
- if (meta == null) continue;
- String prefix = meta.optString("prefix", null);
- if (prefix == null) continue;
- replace.put(key, prefix + "-" + suffix);
- }
- }
- for (String kill : replace.keySet()) {
- val.remove(kill);
- JSONArray newNames = new JSONArray();
- newNames.put(replace.get(kill));
- val.put("autogenerated", newNames);
- }
- out.println("" + val + " ");
- mv.setValues(val);
- myShepherd.getPM().makePersistent(mv);
- }
- out.println(" ");
-}
-
-%>
-
-
-<%
-
-File tmp = new File(TMP_DIR);
-if (!tmp.exists()) tmp.mkdir();
-
-String context = ServletUtilities.getContext(request);
-Shepherd myShepherd = new Shepherd(context);
-myShepherd.beginDBTransaction();
-
-Properties props = ShepherdProperties.getProperties("codexMigration.properties", "", context);
-String dbUrl = props.getProperty("codexDbUrl", context);
-String dbUsername = props.getProperty("codexDbUsername", context);
-String dbPassword = props.getProperty("codexDbPassword", context);
-
-// this is under data-dir
-String assetGroupDir = props.getProperty("assetGroupDir", context);
-File dataDir = CommonConfiguration.getDataDirectory(getServletContext(), context);
-
-
-Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
-
-JSONObject locJson = locationJson(conn);
-// hard-coded file path, but life is rough
-if (locJson != null) Util.writeToFile(locJson.toString(4), "/usr/local/tomcat/webapps/wildbook_data_dir/WEB-INF/classes/bundles/locationID.json");
-
-
-/*
-migrateUsers(out, myShepherd, conn);
-
-migrateMediaAssets(out, myShepherd, conn, request, new File(dataDir, assetGroupDir));
-
-migrateAnnotations(out, myShepherd, conn);
-
-migrateEncounters(out, myShepherd, conn);
-
-migrateOccurrences(out, myShepherd, conn);
-
-migrateMarkedIndividuals(out, myShepherd, conn);
-
-migrateKeywords(out, myShepherd, conn);
-
-migrateRelationships(out, myShepherd, conn);
-
-fixAutogenNames(out, myShepherd, conn);
-
-migrateSocialGroups(out, myShepherd, conn);
-*/
-
-migratePendingSightings(out, myShepherd, conn, request);
-
-
-myShepherd.commitDBTransaction();
-myShepherd.closeDBTransaction();
-
-%>
-
-
-
diff --git a/src/main/webapp/appadmin/locationIDTester.jsp b/src/main/webapp/appadmin/locationIDTester.jsp
index 596b998115..0c837bcf6d 100644
--- a/src/main/webapp/appadmin/locationIDTester.jsp
+++ b/src/main/webapp/appadmin/locationIDTester.jsp
@@ -51,25 +51,6 @@ myShepherd.setAction("locationIDTester.jsp");
-Override Indocet tests
-
<%=LocationID.getLocationIDStructure("indocet").toString() %>
-
-The name for locationID 1 is:
<%=LocationID.getNameForLocationID("Moheli","indocet") %>
-
-The name for locationID 6 is:
<%=LocationID.getNameForLocationID("Moheli","indocet") %>
-
-
-
-
-
-Single select and selected:
-
-
-
Get hierarchy for ID
<%
diff --git a/src/main/webapp/cust/indocet/overwrite.css b/src/main/webapp/cust/indocet/overwrite.css
index 181d22e7ea..40b3227493 100644
--- a/src/main/webapp/cust/indocet/overwrite.css
+++ b/src/main/webapp/cust/indocet/overwrite.css
@@ -13,13 +13,6 @@ body {
background-position: center;
}
-.navbar-brand.indocet {
- display: inline !important; /* display: none by default; */
- background: url(indocet-logo-white.png) no-repeat;
- background-position: center;
- background-size: 76%; /* custom value that looks nice next to flukebook logo */
-}
-
.nav-bar-wrapper {
background-color: #075366;
}
@@ -195,9 +188,6 @@ h1, h2, .brand-primary, div #markedIndividualHeader {
color
}
-/*
-Link code copied from indocet's website
-*/
a:hover, .entry-meta span a:hover, .comments-link a:hover, body.coldisplay2 #front-columns a:active {
color: #ffb200;
}
diff --git a/src/main/webapp/encounters/encounter.jsp b/src/main/webapp/encounters/encounter.jsp
index 908023393b..63392d0f3b 100755
--- a/src/main/webapp/encounters/encounter.jsp
+++ b/src/main/webapp/encounters/encounter.jsp
@@ -175,9 +175,7 @@ URLCodec urlCodec = new URLCodec();
//let's load encounters.properties
//Properties encprops = new Properties();
//encprops.load(getClass().getResourceAsStream("/bundles/" + langCode + "/encounter.properties"));
-
- //Properties encprops = ShepherdProperties.getProperties("encounter.properties", langCode, context, "indocet");
-
+
pageContext.setAttribute("num", num);
diff --git a/src/main/webapp/encounters/manualAnnotation.jsp b/src/main/webapp/encounters/manualAnnotation.jsp
index cf6b44daf0..8aa055749b 100644
--- a/src/main/webapp/encounters/manualAnnotation.jsp
+++ b/src/main/webapp/encounters/manualAnnotation.jsp
@@ -16,6 +16,7 @@
java.io.UnsupportedEncodingException,
org.ecocean.identity.IBEISIA,
java.util.ArrayList,
+ java.util.Collections,
org.apache.commons.collections4.CollectionUtils
"
%>
@@ -198,9 +199,11 @@ try{
final String noViewpoint = "----------";
vlist += "" + noViewpoint + " ";
final Set results = new LinkedHashSet<>(Annotation.getAllValidViewpoints());
- Iterator it = results.iterator();
+ List sortedResults = new ArrayList<>(results);
+ Collections.sort(sortedResults);
+ Iterator it = sortedResults.iterator();
while (it.hasNext()) {
- String v = (String)it.next();
+ String v = it.next();
if (!Util.stringExists(v)) continue;
vlist += "" + v + " ";
}
diff --git a/src/main/webapp/header.jsp b/src/main/webapp/header.jsp
index 4a896965fe..0ccad495e4 100755
--- a/src/main/webapp/header.jsp
+++ b/src/main/webapp/header.jsp
@@ -101,7 +101,7 @@ if(request.getUserPrincipal()!=null){
}
}
catch(Exception e){
- System.out.println("Exception on indocetCheck in header.jsp:");
+ System.out.println("Exception in header.jsp:");
e.printStackTrace();
myShepherd.closeDBTransaction();
}
@@ -159,7 +159,7 @@ if(request.getUserPrincipal()!=null){
-
+
@@ -436,7 +436,10 @@ if(request.getUserPrincipal()!=null){
<%=props.getProperty("submit")%>