From d2e568057f3f7f7ccc684da8411e44747d62a154 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 17:53:07 +0000 Subject: [PATCH 01/41] Bump braces from 3.0.2 to 3.0.3 in /frontend Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] --- frontend/package-lock.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 57ec1e3357..a7def6184f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -6259,11 +6259,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -9046,9 +9046,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -24328,11 +24328,11 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "broadcast-channel": { @@ -26345,9 +26345,9 @@ "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "requires": { "to-regex-range": "^5.0.1" } From afc843c5d6adefdddc5c61afb5fd5ff3dcf4a7c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Aug 2024 21:44:46 +0000 Subject: [PATCH 02/41] Bump axios from 1.6.7 to 1.7.4 in /frontend Bumps [axios](https://github.com/axios/axios) from 1.6.7 to 1.7.4. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.6.7...v1.7.4) --- updated-dependencies: - dependency-name: axios dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frontend/package-lock.json | 18 +++++++++--------- frontend/package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d160d2f858..d84e1151c0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,7 +12,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "autoprefixer": "^10.4.18", - "axios": "^1.6.7", + "axios": "^1.7.4", "bootstrap": "^5.3.2", "copy-webpack-plugin": "^12.0.2", "google-map-react": "^2.2.1", @@ -6039,11 +6039,11 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -24592,11 +24592,11 @@ "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==" }, "axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "requires": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" }, diff --git a/frontend/package.json b/frontend/package.json index df28700f0b..69703cd569 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -7,7 +7,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "autoprefixer": "^10.4.18", - "axios": "^1.6.7", + "axios": "^1.7.4", "bootstrap": "^5.3.2", "copy-webpack-plugin": "^12.0.2", "google-map-react": "^2.2.1", From 8eb869ebd55354d6eabef787c6e4e42441f3dae9 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Wed, 21 Aug 2024 16:29:00 -0600 Subject: [PATCH 03/41] drop properties --- src/main/resources/bundles/agent_youtube.properties | 7 ------- src/main/resources/bundles/googleKeys.properties | 3 --- 2 files changed, 10 deletions(-) delete mode 100644 src/main/resources/bundles/agent_youtube.properties diff --git a/src/main/resources/bundles/agent_youtube.properties b/src/main/resources/bundles/agent_youtube.properties deleted file mode 100644 index e763fb0a29..0000000000 --- a/src/main/resources/bundles/agent_youtube.properties +++ /dev/null @@ -1,7 +0,0 @@ -# related to YouTube intelligent agent - -# words which will invalidate a YouTube video (only one need exist) -# these are comma-delimited and case-INsensitive (spaces *around comma* are ignored) - -stop_words=documentary, documental, nemo, octonaut, nickelodeon, aquarium, kids, children - diff --git a/src/main/resources/bundles/googleKeys.properties b/src/main/resources/bundles/googleKeys.properties index b12b088350..bdce3b133e 100644 --- a/src/main/resources/bundles/googleKeys.properties +++ b/src/main/resources/bundles/googleKeys.properties @@ -1,9 +1,6 @@ #Google Service keys for Search, Maps, Translate, youtube, cloud vision googleMapsKey = changme googleSearchKey = changme -youtube_api_key = changeme -youtube_client_id = changme -youtube_client_secret = changme refresh_token= changme translate_key= changme gtm_key= changme From a0bdb19661aa5ee3bcad7ff6ffe6054505107529 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Thu, 22 Aug 2024 15:46:20 -0600 Subject: [PATCH 04/41] utf-8 encoding --- src/main/java/org/ecocean/api/SearchApi.java | 1 + src/main/java/org/ecocean/api/SiteSettings.java | 1 + src/main/java/org/ecocean/api/UserHome.java | 1 + src/main/java/org/ecocean/api/UserInfo.java | 1 + 4 files changed, 4 insertions(+) diff --git a/src/main/java/org/ecocean/api/SearchApi.java b/src/main/java/org/ecocean/api/SearchApi.java index ccf81e1480..b08442f5bb 100644 --- a/src/main/java/org/ecocean/api/SearchApi.java +++ b/src/main/java/org/ecocean/api/SearchApi.java @@ -124,6 +124,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) } } response.setHeader("Content-Type", "application/json"); + response.setCharacterEncoding("UTF-8"); response.getWriter().write(res.toString()); response.getWriter().close(); myShepherd.rollbackAndClose(); diff --git a/src/main/java/org/ecocean/api/SiteSettings.java b/src/main/java/org/ecocean/api/SiteSettings.java index 35da220531..6c704c25ce 100644 --- a/src/main/java/org/ecocean/api/SiteSettings.java +++ b/src/main/java/org/ecocean/api/SiteSettings.java @@ -165,6 +165,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) myShepherd.closeDBTransaction(); response.setStatus(200); response.setHeader("Content-Type", "application/json"); + response.setCharacterEncoding("UTF-8"); response.getWriter().write(settings.toString()); } } diff --git a/src/main/java/org/ecocean/api/UserHome.java b/src/main/java/org/ecocean/api/UserHome.java index 7dc6fe2b48..7b33ea44e8 100644 --- a/src/main/java/org/ecocean/api/UserHome.java +++ b/src/main/java/org/ecocean/api/UserHome.java @@ -115,6 +115,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) home.put("projects", projArr); response.setStatus(200); + response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); response.getWriter().write(home.toString()); myShepherd.rollbackDBTransaction(); diff --git a/src/main/java/org/ecocean/api/UserInfo.java b/src/main/java/org/ecocean/api/UserInfo.java index c12249c888..969e00e0fb 100644 --- a/src/main/java/org/ecocean/api/UserInfo.java +++ b/src/main/java/org/ecocean/api/UserInfo.java @@ -76,6 +76,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) myShepherd.rollbackDBTransaction(); myShepherd.closeDBTransaction(); response.setStatus(200); + response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "application/json"); response.getWriter().write(results.toString()); } From f0f51dbb349efb1cb00dccea4728ad43c233f1d2 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Thu, 22 Aug 2024 16:56:58 -0600 Subject: [PATCH 05/41] add individualNickName and individualFirstEncounterDate/individualLastEncounterDate --- src/main/java/org/ecocean/Encounter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/ecocean/Encounter.java b/src/main/java/org/ecocean/Encounter.java index cf217d46de..cb8e7128b3 100644 --- a/src/main/java/org/ecocean/Encounter.java +++ b/src/main/java/org/ecocean/Encounter.java @@ -4434,11 +4434,19 @@ public void opensearchDocumentSerializer(JsonGenerator jgen) jgen.writeString(name); } jgen.writeEndArray(); + jgen.writeStringField("individualNickName", indiv.getNickName()); if (indiv.getTimeOfBirth() > 0) { String birthTime = Util.getISO8601Date(new DateTime( indiv.getTimeOfBirth()).toString()); jgen.writeStringField("individualTimeOfBirth", birthTime); } + Encounter[] encs = indiv.getDateSortedEncounters(true); + if ((encs != null) && (encs.length > 0)) { + String encDate = Util.getISO8601Date(encs[0].getDate()); + if (encDate != null) jgen.writeStringField("individualFirstEncounterDate", encDate); + encDate = Util.getISO8601Date(encs[encs.length - 1].getDate()); + if (encDate != null) jgen.writeStringField("individualLastEncounterDate", encDate); + } /* this currently is not needed as-is. we instead use just the social unit name as its own property (below) From 285b2311ea18f2a68f81a4edb1a68ae5594dc675 Mon Sep 17 00:00:00 2001 From: holmbergius Date: Fri, 23 Aug 2024 16:56:04 -0700 Subject: [PATCH 06/41] Prevent login from overriding session timeout defined in web.xml --- src/main/java/org/ecocean/api/Login.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/ecocean/api/Login.java b/src/main/java/org/ecocean/api/Login.java index 7f1e26b1e6..46c8715b85 100644 --- a/src/main/java/org/ecocean/api/Login.java +++ b/src/main/java/org/ecocean/api/Login.java @@ -65,7 +65,6 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) // get the user (aka subject) associated with this request. Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); - session.setTimeout(1000 * 60 * 60 * 24 * 30); subject.login(token); user.setLastLogin((new Date()).getTime()); myShepherd.commitDBTransaction(); From e2ea5fe783db652443c2cbf581a544d31c92dd93 Mon Sep 17 00:00:00 2001 From: holmbergius Date: Mon, 26 Aug 2024 08:26:02 -0700 Subject: [PATCH 07/41] Switch welcome.jsp to /react/login/ --- src/main/webapp/header.jsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/header.jsp b/src/main/webapp/header.jsp index 48c6d1faea..67b12965c4 100755 --- a/src/main/webapp/header.jsp +++ b/src/main/webapp/header.jsp @@ -263,7 +263,7 @@ if(request.getUserPrincipal()!=null){ var action = $(element).data('action'); if (action === 'login'){ - window.open('<%=urlLoc %>/welcome.jsp', '_blank'); + window.open('<%=urlLoc %>/react/login/', '_blank'); } else { From 85bf431de0767ad0ef4203748e3864def7f8f640 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 15:34:56 -0600 Subject: [PATCH 08/41] well it compiles --- src/main/java/org/ecocean/YouTube.java | 998 ------------------ .../ai/utilities/ParseDateLocation.java | 7 +- .../java/org/ecocean/identity/IBEISIA.java | 21 +- .../org/ecocean/media/YouTubeAssetStore.java | 31 +- .../servlet/IndividualAddEncounter.java | 66 +- 5 files changed, 20 insertions(+), 1103 deletions(-) delete mode 100644 src/main/java/org/ecocean/YouTube.java diff --git a/src/main/java/org/ecocean/YouTube.java b/src/main/java/org/ecocean/YouTube.java deleted file mode 100644 index 165c55a024..0000000000 --- a/src/main/java/org/ecocean/YouTube.java +++ /dev/null @@ -1,998 +0,0 @@ -package org.ecocean; - -// import javax.servlet.http.HttpServletRequest; -import java.net.URL; -import org.json.JSONObject; -// import org.ecocean.ParseDateLocation.ParseDateLocation; -import org.ecocean.media.AssetStoreType; -// import org.ecocean.servlet.ServletUtilities; -// import org.ecocean.translate.DetectTranslate; - -import java.io.File; -import java.util.List; -import java.util.Properties; -// import java.util.Properties; -// import java.util.ArrayList; -import java.io.IOException; -import java.net.MalformedURLException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; - -import com.google.api.client.auth.oauth2.Credential; -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.googleapis.json.GoogleJsonResponseException; -// import com.google.api.client.http.HttpRequest; -import com.google.api.client.http.HttpRequestInitializer; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.client.json.JsonFactory; - -// import com.google.api.services.samples.youtube.cmdline.Auth; -import com.google.api.services.youtube.model.*; -import com.google.api.services.youtube.YouTube.CommentThreads; - -import org.ecocean.ai.nlp.SUTime; -import org.ecocean.ai.nmt.azure.DetectTranslate; -import org.ecocean.media.*; - -import java.util.ArrayList; - -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; - -import java.text.SimpleDateFormat; - -import java.util.concurrent.atomic.AtomicInteger; - -import javax.jdo.Query; - -// see: https://developers.google.com/youtube/v3/code_samples/java#search_by_keyword - -public class YouTube { - private static String apiKey = null; - private static String refreshToken = null; - private static com.google.api.services.youtube.YouTube youtubeOauthCreds; - private static com.google.api.services.youtube.YouTube youtubeAPIKey; - public static final double EXTRACT_FPS = 0.5; // note: this *must* be synced with value in config/youtube_extract.sh - - // private String storyMediaURL; - // public void setStoryTellerEmail(String email){this.storyTellerEmail=email;} - - public static void init(String context) { - // String context = ServletUtilities.getContext(request); - Properties googleProps = org.ecocean.ShepherdProperties.getProperties( - "googleKeys.properties", ""); - - apiKey = googleProps.getProperty("youtube_api_key"); - - youtubeAPIKey = new com.google.api.services.youtube.YouTube.Builder(new NetHttpTransport(), - new JacksonFactory(), new HttpRequestInitializer() { - public void initialize(com.google.api.client.http.HttpRequest request) - throws IOException {} - }).setApplicationName("wildbook-youtube").build(); - - String CLIENT_ID = googleProps.getProperty("youtube_client_id"); - String CLIENT_SECRET = googleProps.getProperty("youtube_client_secret"); - System.out.println("CLIENT_ID: " + CLIENT_ID); - System.out.println("CLIENT_SECRET: " + CLIENT_SECRET); - refreshToken = googleProps.getProperty("refresh_token"); - System.out.println("refreshToke: " + refreshToken); - HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); - JsonFactory JSON_FACTORY = new JacksonFactory(); - Credential credential = new GoogleCredential.Builder() - .setTransport(HTTP_TRANSPORT) - .setJsonFactory(JSON_FACTORY) - .setClientSecrets(CLIENT_ID, CLIENT_SECRET) - .build(); - credential.setRefreshToken(refreshToken); - - youtubeOauthCreds = new com.google.api.services.youtube.YouTube.Builder(HTTP_TRANSPORT, - JSON_FACTORY, credential) - .setApplicationName("wildbook-youtube") - .build(); - } - - public static boolean isActive() { - return (apiKey != null); - } - - public static boolean isActive2() { - return (refreshToken != null); - } - - public static boolean validId(String id) { - if (id == null) return false; - return id.matches("^[a-zA-Z0-9_-]{11}$"); - } - - public static JSONObject simpleInfo(String id) - throws RuntimeException, MalformedURLException, IOException, NoSuchAlgorithmException, - InvalidKeyException { - if (!validId(id)) return null; - URL url = new URL("https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=" + - id + "&format=json"); - return RestClient.get(url); - // TODO handle 404 for bad ids, etc.... - } - - /* /usr/local/bin/youtube_get.sh ID tempdir will generate: - -rw-rw-r-- 1 jon jon 253156 Sep 8 00:10 V_ozofiGPJo.jpg - -rw------- 1 jon jon 30282 Sep 8 00:10 V_ozofiGPJo.info.json - -rw-rw-r-- 1 jon jon 36398939 Aug 23 08:13 V_ozofiGPJo.mp4 use .json to populate ma.metadata.detailed -- note: set .detailed = { processing: - true } before background grab - */ - - // this fills a directory with grabbed goodies from youtube (synchronously) and returns a list of Files that are its contents - public static List grab(String id, File targetDir) { - if ((id == null) || (targetDir == null)) return null; - if (!targetDir.isDirectory()) throw new RuntimeException(targetDir + " is not a directory"); - String[] cmd = new String[] { "/usr/local/bin/youtube_get.sh", id, targetDir.toString() }; - ProcessBuilder pb = new ProcessBuilder(); - pb.command(cmd); - System.out.println("before .grab() ===["); - - try { - Process proc = pb.start(); - proc.waitFor(); - System.out.println("]=== done with .grab()"); - } catch (Exception ex) { - throw new RuntimeException("YouTube.grab(" + id + ", " + targetDir + ") failed: " + - ex.toString()); - } - File[] flist = targetDir.listFiles(); - if ((flist == null) || (flist.length < 1)) - throw new RuntimeException(targetDir + " is empty; grab failed"); - return Arrays.asList(flist); - } - - // this fills a directory with framegrabs from input video file (synchronously) and returns a list of Files that are its contents - // note: heavy lifting is done by youtube_extract.sh so look there for details (e.g. it will create the dir if needed/possible) - public static List extractFrames(File videoFile, File targetDir) { - if ((videoFile == null) || (targetDir == null)) return null; - if (!videoFile.exists()) throw new RuntimeException(videoFile + " does not exist"); - String[] cmd = new String[] { - "/usr/local/bin/youtube_extract.sh", videoFile.toString(), targetDir.toString() - }; - ProcessBuilder pb = new ProcessBuilder(); - pb.command(cmd); - System.out.println("before .extractFrames() ===["); - - try { - Process proc = pb.start(); - proc.waitFor(); - System.out.println("]=== done with .extractFrames()"); - } catch (Exception ex) { - throw new RuntimeException("YouTube.extractFrames(" + videoFile + ", " + targetDir + - ") failed: " + ex.toString()); - } - File[] flist = targetDir.listFiles(); - if ((flist == null) || (flist.length < 1)) - throw new RuntimeException(targetDir + " is empty; extractFrames failed"); - return Arrays.asList(flist); - } - -/* - public static ((((not sure what it returns)))) commentOnVideo(String ytId, String comment) { - } - */ - public static List searchByKeyword(String keyword, String context) { - return searchByKeyword(keyword, -1, context); - } - - public static List searchByKeyword(String keyword, long pubAfter, - String context) { // pubAfter is ms since epoch - // if (!isActive()) throw new RuntimeException("YouTube API not active (invalid api key?)"); - if (youtubeAPIKey == null) init(context); - try { - // Define the API request for retrieving search results. - com.google.api.services.youtube.YouTube.Search.List search = - youtubeAPIKey.search().list("id,snippet"); - search.setKey(apiKey); - search.setQ(keyword); - if (pubAfter > 0) - search.setPublishedAfter(new com.google.api.client.util.DateTime(pubAfter)); - // Restrict the search results to only include videos. See: - // https://developers.google.com/youtube/v3/docs/search/list#type - search.setType("video"); - - // To increase efficiency, only retrieve the fields that the application uses. - - // TBD - add comments - - search.setFields( - "items(id/kind,id/videoId,snippet/title,snippet/thumbnails/default/url,snippet/description,snippet/publishedAt)"); - search.setMaxResults(50l); - - // Call the API and print results. - SearchListResponse searchResponse = search.execute(); - return searchResponse.getItems(); - } catch (GoogleJsonResponseException e) { - System.err.println("ERROR: YouTube.searchByKeyword() had a service error: " + - e.getDetails().getCode() + " : " + e.getDetails().getMessage()); - } catch (IOException e) { - System.err.println("ERROR: YouTube.searchByKeyword() had an IOException: " + - e.getCause() + " : " + e.getMessage()); - } catch (Throwable t) { - t.printStackTrace(); - } - return null; - } - - public static String postQuestion(String questionToPost, String videoId, Occurrence occur, - String context) { -// if (!isActive2()) throw new RuntimeException("YouTube API refresh token not active (invalid token?)"); - if (!isActive()) init(context); - // if (youtube == null) throw new RuntimeException("YouTube API google credentials 'youtube2' is null"); - if (youtubeOauthCreds == null) init(context); - try { - HashMap parameters = new HashMap<>(); - parameters.put("part", "snippet"); - // The part parameter identifies properties that the API response will include. Set the parameter value to snippet - // The snippet object contains basic details about the comment - - CommentThread commentThread = new CommentThread(); - CommentThreadSnippet snippet = new CommentThreadSnippet(); - Comment topLevelComment = new Comment(); - CommentSnippet commentSnippet = new CommentSnippet(); - // set values for these snippet properties: snippet.videoId and snippet.topLevelComment.snippet.textOriginal - commentSnippet.set("textOriginal", questionToPost); - commentSnippet.set("videoId", videoId); -// commentSnippet.setVideoId(videoId); - - topLevelComment.setSnippet(commentSnippet); - snippet.setTopLevelComment(topLevelComment); - commentThread.setSnippet(snippet); - - com.google.api.services.youtube.YouTube.CommentThreads.Insert - commentThreadsInsertRequest = youtubeOauthCreds.commentThreads().insert( - parameters.get("part").toString(), commentThread); - commentThreadsInsertRequest.setKey(apiKey); - CommentThread response = commentThreadsInsertRequest.execute(); - -// System.out.println(response); - String commentId = response.getSnippet().getTopLevelComment().getId(); - occur.setSocialMediaQueryCommentID(commentId); - return commentId; - } catch (GoogleJsonResponseException e) { - e.printStackTrace(); - System.err.println("There was a service error: " + e.getDetails().getCode() + " : " + - e.getDetails().getMessage()); - } catch (Throwable t) { - t.printStackTrace(); - } - return null; - } - - public static String getReplies(Occurrence occur, String context) { // pubAfter is ms since epoch - // if (!isActive2()) throw new RuntimeException("YouTube API refresh token not active (invalid token?)"); - // if (youtube == null) throw new RuntimeException("YouTube API google credentials 'youtube2' is null"); - if (youtubeOauthCreds == null) init(context); - try { - String commentId = occur.getSocialMediaQueryCommentID(); - CommentListResponse commentsListResponse = youtubeOauthCreds.comments().list("snippet") - .setParentId(commentId).setTextFormat("plainText").setKey(apiKey).execute(); - List comments = commentsListResponse.getItems(); - String replies = ""; - if (comments.isEmpty()) { - System.out.println("Can't get comment replies."); - replies += "none"; - } else { - // Print information from the API response. - System.out.println( - "\n================== Returned Comment Replies ==================\n"); - for (Comment commentReply : comments) { - CommentSnippet snippet = commentReply.getSnippet(); - replies += snippet.getTextDisplay(); - occur.setSocialMediaQueryCommentReplies(replies); - - System.out.println(" - Author: " + snippet.getAuthorDisplayName()); - System.out.println(" - Reply: " + snippet.getTextDisplay()); - System.out.println( - "\n-------------------------------------------------------------\n"); - } - return replies; - } - } catch (GoogleJsonResponseException e) { - e.printStackTrace(); - System.err.println("There was a service error: " + e.getDetails().getCode() + " : " + - e.getDetails().getMessage()); - } catch (Throwable t) { - t.printStackTrace(); - } - return null; - } - - /* public static String sendReply(String commentId, String commentToPost) { //pubAfter is ms since epoch if (!isActive2()) throw new - RuntimeException("YouTube API refresh token not active (invalid token?)"); - if (youtube2 == null) throw new RuntimeException("YouTube API google credentials 'youtube2' is null"); - try { - HashMap parameters = new HashMap<>(); - parameters.put("part", "snippet"); - // CommentThreadListResponse videoCommentsListResponse = youtube.commentThreads() - // .list("snippet").setVideoId(videoId).setTextFormat("plainText").execute(); - // List videoComments = videoCommentsListResponse.getItems(); - - // CommentThread firstComment = videoComments.get(0); - // Will use this thread as parent to new reply. - // String parentId = firstComment.getId(); - - String parentId=commentId; - Comment comment = new Comment(); - CommentSnippet snippet = new CommentSnippet(); - snippet.set("parentId", parentId); - snippet.set("textOriginal", commentToPost); - - comment.setSnippet(snippet); - - com.google.api.services.youtube.YouTube.Comments.Insert commentsInsertRequest = youtube.comments().insert(parameters.get("part").toString(), - comment); - commentsInsertRequest.setKey(apiKey); - Comment response = commentsInsertRequest.execute(); - System.out.println(response); - - - String receipt = response.getSnippet().getTextDisplay(); - return receipt; - }catch (GoogleJsonResponseException e) { - e.printStackTrace(); - System.err.println("There was a service error: " + e.getDetails().getCode() + " : " + e.getDetails().getMessage()); - } catch (Throwable t) { - t.printStackTrace(); - - } - return null; - } - - */ - public static void postOccurrenceMessageToYouTubeIfAppropriate(String message, Occurrence occur, - Shepherd myShepherd, String context) { - System.out.println("--Entering YouTube.postOccurrenceMessageToYouTubeIfAppropriate"); - // validate if we should even be worrying about YouTube mediaassets for this occurrence - if ((occur.getSocialMediaSourceID() != null) && - (occur.hasMediaAssetFromRootStoreType(myShepherd, AssetStoreType.YouTube))) { - if (!isActive()) init(context); - System.out.println( - "This occurrence has a YouTube Media Asset, so let's try to post to the OP the message I was given: " - + message); - // first, does this Occurrence have a commentID? - String videoID = occur.getSocialMediaSourceID().replaceFirst("youtube:", ""); - String concatReplies = getVideoComments(occur, context); - if ((concatReplies == null) || (concatReplies.indexOf(message) == -1)) { - // we ourselves haven't posted this before (i.e., don't harass user with multiple, similar comments) - System.out.println("Replying to a previous YouTube comment"); - - postQuestion(message, videoID, occur, context); - } - } else { - System.out.println("This is not a candidate for YouTube feedback."); - } - System.out.println("--Exiting YouTube.postOccurrenceMessageToYouTubeIfAppropriate"); - } - - /** - * Returns a long String of comments and replies for an Occurrence that was derived from a YouTube video. Use this String for generic NLP - * processing - * - * @param occur The Occurrence that derived from a YouTube video. - * @param context Standard context used in Wildbook. - * @return A long, pretty-print String of comments and replies without hierarchy. - */ - public static String getVideoComments(Occurrence occur, String context) { // pubAfter is ms since epoch - StringBuffer response = new StringBuffer(""); - - if (youtubeOauthCreds == null) init(context); - try { - java.util.List comments = getVideoCommentsList(occur, context); - int numComments = comments.size(); - for (int f = 0; f < numComments; f++) { - CommentThread ct = comments.get(f); - CommentThreadReplies ctr = ct.getReplies(); - List replies = ctr.getComments(); - int numReplies = replies.size(); - CommentThreadSnippet cts = ct.getSnippet(); - Comment topLevelComment = cts.getTopLevelComment(); - response.append(topLevelComment.getSnippet().getTextDisplay()); - for (int g = 0; g < numReplies; g++) { - Comment reply = replies.get(g); - response.append(" " + reply.getSnippet().getTextDisplay()); - } - } - return response.toString(); - } catch (Exception t) { - t.printStackTrace(); - } - return null; - } - - /** - * Returns an array of comments and replies for an Occurrence that was derived from a YouTube video. Use this array for fine-grained NLP - * processing. - * - * @param occur The Occurrence that derived from a YouTube video. - * @param context Standard context used in Wildbook. - * @return An array of comments. You can iterate through each comment looking for replies. - */ - public static List getVideoCommentsList(Occurrence occur, String context) { // pubAfter is ms since epoch - List comments = new ArrayList(); - - if (youtubeOauthCreds == null) init(context); - try { - HashMap parameters = new HashMap<>(); - parameters.put("part", "snippet,replies"); - String videoID = occur.getSocialMediaSourceID().replaceFirst("youtube:", ""); - parameters.put("videoId", videoID); - - CommentThreads.List commentThreadsListByVideoIdRequest = - youtubeOauthCreds.commentThreads().list(parameters.get("part").toString()); - if (parameters.containsKey("videoId") && parameters.get("videoId") != "") { - commentThreadsListByVideoIdRequest.setVideoId(parameters.get("videoId").toString()); - } - CommentThreadListResponse commentsResponse = - commentThreadsListByVideoIdRequest.execute(); - comments = commentsResponse.getItems(); - } catch (GoogleJsonResponseException e) { - e.printStackTrace(); - System.err.println("There was a service error: " + e.getDetails().getCode() + " : " + - e.getDetails().getMessage()); - } catch (Throwable t) { - t.printStackTrace(); - } - return comments; - } - - // Given an Occurrence created from a YouTube video, return the video description - public static String getVideoDescription(Occurrence occur, Shepherd myShepherd) { - String desc = null; - - if ((occur != null) && (occur.hasMediaAssetFromRootStoreType(myShepherd, - AssetStoreType.YouTube))) { - if ((occur.getEncounters() != null) && (occur.getEncounters().size() > 0)) { - Encounter enc = occur.getEncounters().get(0); - ArrayList assets = enc.getMedia(); - if (assets != null) { - MediaAsset ma = assets.get(0); - MediaAsset parentRoot = ma.getParentRoot(myShepherd); - MediaAssetMetadata mdata = ma.getMetadata(); - JSONObject data = mdata.getData(); - if ((parentRoot.getMetadata() != null) && - (parentRoot.getMetadata().getData() != null)) { - if (parentRoot.getMetadata().getData().optJSONObject("detailed") != null) { - desc = parentRoot.getMetadata().getData().getJSONObject( - "detailed").optString("description", "[no description]"); - } - } - } - } - } - return desc; - } - - // Given an Occurrence created from a YouTube video, return the video tags - public static String getVideoTags(Occurrence occur, Shepherd myShepherd) { - String tags = null; - - if ((occur != null) && (occur.hasMediaAssetFromRootStoreType(myShepherd, - AssetStoreType.YouTube))) { - if ((occur.getEncounters() != null) && (occur.getEncounters().size() > 0)) { - Encounter enc = occur.getEncounters().get(0); - ArrayList assets = enc.getMedia(); - if (assets != null) { - MediaAsset ma = assets.get(0); - MediaAsset parentRoot = ma.getParentRoot(myShepherd); - MediaAssetMetadata mdata = ma.getMetadata(); - JSONObject data = mdata.getData(); - if ((parentRoot.getMetadata() != null) && - (parentRoot.getMetadata().getData() != null)) { - if (parentRoot.getMetadata().getData().getJSONObject( - "detailed").optJSONArray("tags") != null) { - tags = parentRoot.getMetadata().getData().getJSONObject( - "detailed").getJSONArray("tags").toString(); - } - } - } - } - } - return tags; - } - - // Given an Occurrence created from a YouTube video, return the video title - public static String getVideoTitle(Occurrence occur, Shepherd myShepherd) { - String title = null; - - if ((occur != null) && (occur.hasMediaAssetFromRootStoreType(myShepherd, - AssetStoreType.YouTube))) { - if ((occur.getEncounters() != null) && (occur.getEncounters().size() > 0)) { - Encounter enc = occur.getEncounters().get(0); - ArrayList assets = enc.getMedia(); - if (assets != null) { - MediaAsset ma = assets.get(0); - MediaAsset parentRoot = ma.getParentRoot(myShepherd); - MediaAssetMetadata mdata = ma.getMetadata(); - JSONObject data = mdata.getData(); - if ((parentRoot.getMetadata() != null) && - (parentRoot.getMetadata().getData() != null)) { - if (parentRoot.getMetadata().getData().optJSONObject("basic") != null) { - title = parentRoot.getMetadata().getData().getJSONObject( - "basic").optString("title", "[unknown]"); - } - } - } - } - } - return title; - } - - public static String getVideoPublishedAt(Occurrence occur, String context) { // pubAfter is ms since epoch - if (!isActive()) init(context); - StringBuffer response = new StringBuffer(""); - if (youtubeOauthCreds == null) init(context); - try { - HashMap parameters = new HashMap<>(); - parameters.put("part", "snippet,replies"); - String videoID = occur.getSocialMediaSourceID().replaceFirst("youtube:", ""); - parameters.put("part", "snippet,contentDetails"); - parameters.put("id", videoID); - - // System.out.println("Trying to get publishedAt for video: "+videoID); - - com.google.api.services.youtube.YouTube.Videos.List listVideosRequest = - youtubeAPIKey.videos().list(parameters.get("part").toString()); - listVideosRequest.setId(videoID); // add list of video IDs here - listVideosRequest.setKey(apiKey); - VideoListResponse listResponse = listVideosRequest.execute(); - Video vid = listResponse.getItems().get(0); - // System.out.println("I have a video!"); - response.append(vid.getSnippet().getPublishedAt().toString()); - - // System.out.println("PublishedAt: "+ response); - - return response.toString(); - } catch (GoogleJsonResponseException e) { - e.printStackTrace(); - System.err.println("There was a service error in publishedAt: " + - e.getDetails().getCode() + " : " + e.getDetails().getMessage()); - } catch (Throwable t) { - t.printStackTrace(); - } - return null; - } - - /* - * Given a MediaAsset from a YouTubeAssetStore, annotate the Encounters of its derived Occurrence with any Encounter.locationID and Encounter date - * information that can be extracted from the title, comments, tags, and descriptions, including replies to our own automated comments. - * - * This is the simple form of the method for calling without megtrics assessment. - * - * - */ - public static void annotateChildrenOfYouTubeMediaAssetWithDateLocation(MediaAsset ma, - String rootDir, Shepherd myShepherd, String context) { - annotateChildrenOfYouTubeMediaAssetWithDateLocation(ma, rootDir, myShepherd, context, - new AtomicInteger(0), new AtomicInteger(0), new AtomicInteger(0), new AtomicInteger(0), - new AtomicInteger(0), new ArrayList(), new ArrayList(), true, - new AtomicInteger(0), new AtomicInteger(0)); - } - - /* - * Given a MediaAsset from a YouTubeAssetStore, annotate the Encounters of its derived Occurrence with any Encounter.locationID and Encounter date - * information that can be extracted from the title, comments, tags, and descriptions, including replies to our own automated comments. - * - * This method includes the ability to pass in variables for counting/statistics purposes and to test the method with the ability to not persist - * changes. - * - * @return An HTML table row of data about the video, Encounter(s), and comemnts posted on YouTube. - * - */ - public static String annotateChildrenOfYouTubeMediaAssetWithDateLocation(MediaAsset ma, - String rootDir, Shepherd myShepherd, String context, AtomicInteger numVideosWithID, - AtomicInteger numVideos, AtomicInteger numUncuratedVideos, AtomicInteger numCommentedVideos, - AtomicInteger numCommentedVideosReplies, ArrayList goodDataVideos, - ArrayList poorDataVideos, boolean persistDifferences, - AtomicInteger numDatesFound, AtomicInteger numLocationIDsFound) { - // if we're going to persist changes, ensure the Shepherd object is ready - if (persistDifferences && !myShepherd.getPM().currentTransaction().isActive()) { - myShepherd.beginDBTransaction(); - } - // the return string of HTML content - String resultsHTML = ""; - - /* - //weka predictor preparation answering the question: does this video description suggest a real world whale shark sighting? - ArrayList attributeList = new ArrayList(2); - ArrayList attributeList2 = new ArrayList(2); - Attribute desc = new Attribute("description", true); - Attribute merged = new Attribute("merged", true); - List classVal2 = myShepherd.getAllLocationIDs(); - classVal2.remove(0); - ArrayList classVal = new ArrayList(); - classVal.add("good"); - classVal.add("poor"); - attributeList2.add(desc); - attributeList2.add(new Attribute("@@class@@",classVal2)); - attributeList.add(merged); - attributeList.add(new Attribute("@@class@@",classVal)); - String locIDpath="/data/whaleshark_data_dirs/shepherd_data_dir/wekaModels/whaleSharkLocationIDClassifier.model"; - String path="/data/whaleshark_data_dirs/shepherd_data_dir/wekaModels/youtubeRandomForest.model"; - */ - boolean videoHasID = false; - boolean hasWildMeComment = false; - boolean hasWildMeCommentReplies = false; - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - // video has metadata for analysis? - if ((ma.getMetadata() != null)) { - numVideos.incrementAndGet(); - MediaAssetMetadata md = ma.getMetadata(); - // video metadata is not null, so proceed - if (md.getData() != null) { - // setup our metadata fields - String videoID = ma.getMetadata().getData().getJSONObject("detailed").optString( - "id"); - String videoTitle = "[unknown]"; - String videoTitleShort = videoTitle; - String videoComments = ""; - String videoCommentsClean = ""; - String locIDWords = ""; - String videoDescription = "[no description]"; - String videoTags = "[no tags]"; - // start capturing metadata about the YouTube video - // video title - if (videoTitle.length() > 1000) { videoTitleShort = videoTitle.substring(0, 1000); } - if (md.getData().optJSONObject("basic") != null) { - videoTitle = md.getData().getJSONObject("basic").optString("title").replaceAll( - ",", " ").replaceAll("\n", " ").replaceAll("'", "").replaceAll("\"", - "").replaceAll("′", "").replaceAll("’", "").toLowerCase(); - } - // video description - String videoDescriptionShort = videoDescription; - if (videoDescription.length() > 1000) { - videoDescriptionShort = videoDescription.substring(0, 1000); - } - // video tags - String videoTagsShort = videoTags; - if (videoTags.length() > 1000) { videoTagsShort = videoTags.substring(0, 1000); } - if (md.getData().getJSONObject("detailed") != null) { - videoDescription = md.getData().getJSONObject("detailed").optString( - "description").replaceAll(",", " ").replaceAll("\n", " ").replaceAll("'", - "").replaceAll("\"", "").replaceAll("’", "").replaceAll("′", - "").toLowerCase(); - videoTags = md.getData().getJSONObject("detailed").getJSONArray( - "tags").toString().replaceAll(",", " ").replaceAll("\n", - " ").replaceAll("'", "").replaceAll("\"", "").replaceAll("′", - "").replaceAll("’", "").toLowerCase(); - } - // Let's get the Encounter objects related to this video - // JDOQL query - String qFilter = - "SELECT FROM org.ecocean.Encounter WHERE (occurrenceRemarks.indexOf('" + - videoID + "') != -1)"; - Query newQ = myShepherd.getPM().newQuery(qFilter); - Collection d = (Collection)newQ.execute(); - ArrayList encresults = new ArrayList(d); - newQ.closeAll(); - int numEncs = encresults.size(); - - // let's iterate our matching Encounters - // first, check if any have been approved (curated) and count them - boolean videoIsCurated = false; - for (int y = 0; y < numEncs; y++) { - Encounter enc = encresults.get(y); - if ((enc.getState() != null) && - ((enc.getState().equals("approved")) || - (enc.getState().equals("unidentifiable")))) { - if (!goodDataVideos.contains(ma)) goodDataVideos.add(ma); - videoIsCurated = true; - } - if ((enc.getIndividualID() != null) && (!enc.getIndividualID().equals(""))) - videoHasID = true; - } - if (!videoIsCurated) numUncuratedVideos.incrementAndGet(); - Occurrence occur = null; - LinkedProperties props = (LinkedProperties)ShepherdProperties.getProperties( - "submitActionClass.properties", "", context); - String chosenStyleDate = ""; - String chosenStyleLocation = ""; - // if we have matching encounters, then the video is either uncurated, or it has been determined to have useful data (curated) - if (numEncs > 0) { - // check for Occurrence - String occurID = ""; - - // grab the first Encounter for analysis - Encounter enc = encresults.get(0); - - // get the current values for date and location ID - String currentDate = ""; - String currentLocationID = ""; - if (enc.getDate() != null) - currentDate = enc.getDate().replaceAll("Unknown", ""); - if (enc.getLocationID() != null) - currentLocationID = enc.getLocationID().replaceAll("None", ""); - // our encounters should all have an Occurrence, one per video - if (enc.getOccurrenceID() != null) { - occur = myShepherd.getOccurrence(enc.getOccurrenceID()); - - // let's get all our YouTube video metadata and comments - List comments = YouTube.getVideoCommentsList(occur, context); - if ((comments == null) || (comments.size() == 0)) { - videoComments = ""; - videoCommentsClean = ""; - } else { - boolean isWildMeComment = false; - int numComments = comments.size(); - videoComments += "
    \n"; - for (int f = 0; f < numComments; f++) { - CommentThread ct = comments.get(f); - CommentThreadSnippet cts = ct.getSnippet(); - Comment topLevelComment = cts.getTopLevelComment(); - CommentSnippet commentSnippet = topLevelComment.getSnippet(); - String authorName = ""; - if ((commentSnippet != null) && - (commentSnippet.getAuthorDisplayName() != null)) { - authorName = commentSnippet.getAuthorDisplayName(); - if (authorName.equals("Wild Me")) isWildMeComment = true; - } - String style = ""; - if (isWildMeComment) { - style = "color: green;font-weight: bold;"; - hasWildMeComment = true; - } - videoComments += "
  • " + authorName + - ": " + - DetectTranslate.translateIfNotEnglish( - topLevelComment.getSnippet().getTextDisplay()); - - videoCommentsClean += DetectTranslate.translateIfNotEnglish( - topLevelComment.getSnippet().getTextDisplay()).toLowerCase() + - " "; - if (ct.getReplies() != null) { - CommentThreadReplies ctr = ct.getReplies(); - List replies = ctr.getComments(); - int numReplies = 0; - if (replies != null) numReplies = replies.size(); - if (numReplies > 0) { - if (isWildMeComment) hasWildMeCommentReplies = true; - videoComments += "
      \n"; - for (int g = 0; g < numReplies; g++) { - Comment reply = replies.get(g); - - videoComments += "
    • " + - DetectTranslate.translateIfNotEnglish( - reply.getSnippet().getTextDisplay()) + "
    • "; - videoCommentsClean += - DetectTranslate.translateIfNotEnglish( - reply.getSnippet().getTextDisplay()).toLowerCase() + - " "; - } - videoComments += "
    \n"; - } - } - videoComments += "
  • \n"; - style = ""; - } - videoComments += "
\n"; - } - occurID = occur.getOccurrenceID(); - - // prep the YouTube video date for SUTimee analysis - String tempRelativeDate = null; - try { - tempRelativeDate = YouTube.getVideoPublishedAt(occur, context); - } catch (Exception e) {} - if ((tempRelativeDate != null) && (tempRelativeDate.indexOf("T") != -1)) { - tempRelativeDate = tempRelativeDate.substring(0, - tempRelativeDate.indexOf("T")); - } - if ((tempRelativeDate != null) && (!tempRelativeDate.equals(""))) { - DateTimeFormatter parser2 = DateTimeFormat.forPattern("yyyy-MM-dd"); - DateTime time = parser2.parseDateTime(tempRelativeDate); - relativeDate = time.toString(parser2); - } - } - StringBuffer sbOriginalText = new StringBuffer(""); - sbOriginalText.append(videoTitle + " " + videoDescription + " " + videoTags + - " " + videoCommentsClean); - - // let's do some translation to English for standardization - videoTitle = DetectTranslate.translateIfNotEnglish(videoTitle); - videoTags = DetectTranslate.translateIfNotEnglish(videoTags); - videoDescription = DetectTranslate.translateIfNotEnglish(videoDescription); - // videoComments=translateIfNotEnglish(videoComments); - - StringBuffer sb = new StringBuffer(""); - - sb.append(videoTitle + " " + videoDescription + " " + videoTags + " " + - videoCommentsClean); - - // get video date with SUTime - String newDetectedDate = ""; - try { - newDetectedDate = SUTime.parseDateStringForBestDate(rootDir, sb.toString(), - relativeDate).replaceAll("null", ""); - } catch (Exception e) {} - if (!newDetectedDate.equals("")) { numDatesFound.incrementAndGet(); } - // determine new LocationID, including comments - String newLocationID = ""; - String lowercaseRemarks = sb.toString().toLowerCase(); - try { - Iterator m_enum = props.orderedKeys().iterator(); - while (m_enum.hasNext()) { - String aLocationSnippet = ((String)m_enum.next()).replaceFirst("\\s++$", - ""); - // System.out.println(" Looking for: "+aLocationSnippet); - if (lowercaseRemarks.indexOf(aLocationSnippet) != -1) { - newLocationID = props.getProperty(aLocationSnippet); - locIDWords += " " + aLocationSnippet; - // System.out.println(".....Building an idea of location: "+location); - } - } - /* - Instances data2 = new Instances("TestInstances",attributeList2,2); - data2.setClassIndex(data2.numAttributes()-1); - Instance pos2 = new DenseInstance(data2.numAttributes()); - pos2.setValue(desc, sbOriginalText.toString().replaceAll("[^A-Za-z0-9 ]", "").replace("\n", "").trim()); - data2.add(pos2); - pos2.setDataset(data2); - - newLocationID=pos2.classAttribute().value(classify(pos2, locIDpath).intValue()); - */ - } catch (Exception e) { - e.printStackTrace(); - } - if (newLocationID == null) newLocationID = ""; - if (!newLocationID.equals("")) { numLocationIDsFound.incrementAndGet(); } - // predict if this is a good video - /* - Instances data = new Instances("TestInstances",attributeList,2); - data.setClassIndex(data.numAttributes()-1); - Instance pos = new DenseInstance(data.numAttributes()); - pos.setValue(merged, lowercaseRemarks.replaceAll("whale shark", "whaleshark")); - data.add(pos); - pos.setDataset(data); - - Double prediction = classify(pos,path); - String rowClass=""; - if(prediction.intValue()==1)rowClass="class=\"rowhighlight\""; - */ - // here is where we would put logic to update encounters if appropriate - if (persistDifferences) { - boolean madeAChange = false; - for (int y = 0; y < numEncs; y++) { - Encounter thisEnc = encresults.get(y); - // chosenStyleDate+="year: "+thisEnc.getYear()+";millis:"+thisEnc.getDateInMilliseconds()+";locationID: - // "+thisEnc.getLocationID()+";"; - // SET LOCATION ID - // first, if we even found a location ID in comments, lets' consider it. - // otherwise, there's no point - if ((newLocationID != null) && (!newLocationID.trim().equals(""))) { - // next, if we have a new locationID and one was not set before, then this is an easy win - if ((thisEnc.getLocationID() == null) || - (thisEnc.getLocationID().trim().equals("")) || - (thisEnc.getLocationID().trim().equals("None"))) { - thisEnc.setLocationID(newLocationID); - madeAChange = true; - } else if (!thisEnc.getLocationID().trim().equals( - newLocationID.trim())) { - // ok, the location IDs are different, now what? - // maybe the newLocationID further specifies the older locationID, that would be a win - if (newLocationID.trim().startsWith( - thisEnc.getLocationID().trim())) { - thisEnc.setLocationID(newLocationID.trim()); - madeAChange = true; - } - // if the Encounter is not yet approved, then we can reset it as well since it's uncurated and may have been - // incorrectly detected with older values - else if ((thisEnc.getState() != null) && - (thisEnc.getState().equals("auto_sourced"))) { - thisEnc.setLocationID(newLocationID.trim()); - madeAChange = true; - } - } - } - // now persist - if (madeAChange) { - myShepherd.commitDBTransaction(); - myShepherd.beginDBTransaction(); - } - if (madeAChange) chosenStyleLocation = "font-style: italic;"; - // reset for date - madeAChange = false; - - chosenStyleDate += "madeit: here;"; - // let's check and fix date - if ((newDetectedDate != null) && (!newDetectedDate.trim().equals(""))) { - // well we have something to analyze at least - // DateTimeFormatter parser3 = DateTimeFormat.forPattern("yyyy-MM-dd"); - DateTimeFormatter parser3 = ISODateTimeFormat.dateParser(); - DateTime dt = parser3.parseDateTime(newDetectedDate); - /* - if((thisEnc.getMonth()==1)&&(newDetectedDate.length()==4)){ - thisEnc.setMonth(-1); - thisEnc.setDay(-1); - madeAChange=true; - thisEnc.setHour(-1); - } - */ - // check for the easy case - if ((thisEnc.getDateInMilliseconds() == null) || - (thisEnc.getYear() <= 0)) { - if (newDetectedDate.length() == 10) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - thisEnc.setDay(dt.getDayOfMonth()); - thisEnc.setHour(-1); - } else if (newDetectedDate.length() == 7) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - thisEnc.setDay(-1); - } else if (newDetectedDate.length() == 4) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(-1); - } - // thisEnc.setDateInMilliseconds(dt.getMillis()); - - chosenStyleDate += "font-style: italic; color: red;"; - madeAChange = true; - } - // if it's unapproved/uncurated, trust the newer value - else if (thisEnc.getState().equals("auto_sourced")) { - if (newDetectedDate.length() == 10) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - thisEnc.setDay(dt.getDayOfMonth()); - } else if (newDetectedDate.length() == 7) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - } else if (newDetectedDate.length() == 4) { - thisEnc.setYear(dt.getYear()); - } - chosenStyleDate += "font-style: italic; color: green;"; - madeAChange = true; - } - } - // now persist - if (madeAChange) { - myShepherd.commitDBTransaction(); - myShepherd.beginDBTransaction(); - } - } - } - resultsHTML = - "" + occurID + - "" + videoID + "" + currentDate + - "

" + newDetectedDate + - "

" + currentLocationID + "

" + newLocationID + "

" + videoTitle + - "" + videoDescription + "" + videoComments + "" + - videoCommentsClean + "

LocID Words: " + locIDWords + - "

" + relativeDate + ""; - } - // this video had no encounters, probably been curated as having no value - else { - if (!poorDataVideos.contains(ma)) { - poorDataVideos.add(ma); - numUncuratedVideos.decrementAndGet(); - } - } - } - // video metadata is null, not much we can do here - else { if (!poorDataVideos.contains(ma)) poorDataVideos.add(ma); } - if (hasWildMeComment) numCommentedVideos.incrementAndGet(); - if (hasWildMeCommentReplies) numCommentedVideosReplies.incrementAndGet(); - } - // video had no metadata, not much we can do here - else { - if (!poorDataVideos.contains(ma)) poorDataVideos.add(ma); - } - if (videoHasID) numVideosWithID.incrementAndGet(); - return resultsHTML; - } -} diff --git a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java b/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java index 10a48031d1..ec0aa562e4 100644 --- a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java +++ b/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java @@ -23,7 +23,6 @@ import org.ecocean.Occurrence; import org.ecocean.Shepherd; import org.ecocean.ShepherdProperties; -import org.ecocean.YouTube; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; @@ -435,7 +434,8 @@ public static String annotateChildrenOfYouTubeMediaAssetWithDateLocation(MediaAs occur = myShepherd.getOccurrence(enc.getOccurrenceID()); // let's get all our YouTube video metadata and comments - List comments = YouTube.getVideoCommentsList(occur, context); + // List comments = YouTube.getVideoCommentsList(occur, context); deprecated, issue 622 + List comments = null; if ((comments == null) || (comments.size() == 0)) { videoComments = ""; videoCommentsClean = ""; @@ -500,7 +500,8 @@ public static String annotateChildrenOfYouTubeMediaAssetWithDateLocation(MediaAs // prep the YouTube video date for SUTimee analysis String tempRelativeDate = null; try { - tempRelativeDate = YouTube.getVideoPublishedAt(occur, context); + // tempRelativeDate = YouTube.getVideoPublishedAt(occur, context); deprecated, issue 622 + tempRelativeDate = null; } catch (Exception e) {} if ((tempRelativeDate != null) && (tempRelativeDate.indexOf("T") != -1)) { tempRelativeDate = tempRelativeDate.substring(0, diff --git a/src/main/java/org/ecocean/identity/IBEISIA.java b/src/main/java/org/ecocean/identity/IBEISIA.java index ee623a66a0..9b12921b83 100644 --- a/src/main/java/org/ecocean/identity/IBEISIA.java +++ b/src/main/java/org/ecocean/identity/IBEISIA.java @@ -26,7 +26,6 @@ import org.ecocean.TwitterBot; import org.ecocean.TwitterUtil; import org.ecocean.Util; -import org.ecocean.YouTube; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -4076,7 +4075,8 @@ public static void fromDetection(Occurrence occ, Shepherd myShepherd, String con String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); String tempRelativeDate = null; try { - tempRelativeDate = YouTube.getVideoPublishedAt(occ, context); + // tempRelativeDate = YouTube.getVideoPublishedAt(occ, context); deprecated, issue 622 + tempRelativeDate = null; } catch (Exception e) {} if ((tempRelativeDate != null) && (tempRelativeDate.indexOf("T") != -1)) { tempRelativeDate = tempRelativeDate.substring(0, tempRelativeDate.indexOf("T")); @@ -4096,11 +4096,10 @@ public static void fromDetection(Occurrence occ, Shepherd myShepherd, String con List encounters = occ.getEncounters(); int numEncounters = encounters.size(); Encounter enc = encounters.get(0); - String ytRemarks = ""; + String ytRemarks = null; // GET AND TRANSLATE VIDEO COMMENTS - if (YouTube.getVideoDescription(occ, myShepherd) != null) { - ytRemarks = YouTube.getVideoDescription(occ, myShepherd); - } + // deprecated, issue 622 + // ytRemarks = YouTube.getVideoDescription(occ, myShepherd); String detectedLanguage = "en"; try { detectedLanguage = DetectTranslate.detectLanguage(ytRemarks); @@ -4113,10 +4112,9 @@ public static void fromDetection(Occurrence occ, Shepherd myShepherd, String con e.printStackTrace(); } // GET AND TRANSLATE VIDEO TITLE - String videoTitle = ""; - if (YouTube.getVideoTitle(occ, myShepherd) != null) { - videoTitle = YouTube.getVideoTitle(occ, myShepherd); - } + String videoTitle = null; + // deprecated, issue 622 + // videoTitle = YouTube.getVideoTitle(occ, myShepherd); try { String titleLanguage = "en"; titleLanguage = DetectTranslate.detectLanguage(videoTitle); @@ -4321,7 +4319,8 @@ public static void fromDetection(Occurrence occ, Shepherd myShepherd, String con if (questionToPost != null) { String videoId = enc.getEventID().replaceAll("youtube:", ""); try { - YouTube.postQuestion(questionToPost, videoId, occ, context); + throw new Exception("YouTube agent has been deprecated"); + // YouTube.postQuestion(questionToPost, videoId, occ, context); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception yet) { diff --git a/src/main/java/org/ecocean/media/YouTubeAssetStore.java b/src/main/java/org/ecocean/media/YouTubeAssetStore.java index d010ca5535..506c0c8262 100644 --- a/src/main/java/org/ecocean/media/YouTubeAssetStore.java +++ b/src/main/java/org/ecocean/media/YouTubeAssetStore.java @@ -14,7 +14,6 @@ import org.ecocean.servlet.ServletUtilities; import org.ecocean.Shepherd; import org.ecocean.Util; -import org.ecocean.YouTube; import org.joda.time.DateTime; import org.json.JSONException; import org.json.JSONObject; @@ -124,13 +123,7 @@ private static String idFromParameters(JSONObject params) { // how should we thread in bkgd??? ... probably this should by synchrous, but stuff can bg when needed (e.g. extractMetadata) public static List grab(MediaAsset ma) throws IOException { - if (ma == null) return null; - String id = idFromParameters(ma.getParameters()); - if (id == null) return null; - // when fetched: (1) parse .json and set metadata.detailed; (2) create child assets (using default store!) for video & thumb - File dir = Files.createTempDirectory("youtube_get_" + id + "_" + ma.getId() + "_").toFile(); - System.out.println("YouTubeAssetStore.grab(" + ma + ") tempdir = " + dir); - return YouTube.grab(id, dir); + throw new IOException("deprecated"); } // returns success (stuff grabbed and parsed) @@ -194,23 +187,7 @@ public static boolean grabAndParse(Shepherd myShepherd, MediaAsset ma, boolean w // here, ma must be a video file! public static List extractFrames(MediaAsset ma) throws IOException { - if ((ma == null) || (ma.getStore() == null)) return null; - if (!ma.isMimeTypeMajor("video")) - throw new IOException(ma + - " does not appear to be a video file, extractFrames() aborted"); - Path locP = ma.localPath(); - if (locP == null) - throw new IOException(ma + " failed to get .localPath(); extractFrames() aborted"); - // we attempt to create the final resting place for these files (which only works for LocalAssetStore) - // but this will work for any (writable, duh) AssetStore (since this will get us a temp dir basically) - File fakeFile = new File(Util.hashDirectories(Util.generateUUID(), File.separator)); - JSONObject params = ma.getStore().createParameters(fakeFile); - MediaAsset tmpMA = ma.getStore().create(params); - Path dirP = tmpMA.localPath(); - if (dirP == null) dirP = Files.createTempDirectory("youtube_extract_" + ma.getId()); // fallback to tmp - - System.out.println(ma + " --> " + locP + " extract to " + dirP); - return YouTube.extractFrames(locP.toFile(), dirP.toFile()); + throw new IOException("deprecated"); } // returns success (frames extracted) -- passed in parent/_original MA ... maybe later we would want to also allow _video child option? TODO @@ -335,7 +312,7 @@ private static MediaAsset _createFrameChild(Shepherd myShepherd, MediaAsset pare } JSONObject sp = astore.createParameters(f); sp.put("key", parent.getUUID() + "/" + f.getName()); - sp.put("extractFPS", YouTube.EXTRACT_FPS); + //sp.put("extractFPS", YouTube.EXTRACT_FPS); sp.put("extractOffset", offset); MediaAsset kid = new MediaAsset(astore, sp); kid.copyIn(f); @@ -352,11 +329,13 @@ public MediaAssetMetadata extractMetadata(MediaAsset ma, boolean minimal) JSONObject data = new JSONObject(); // we (attempt to) let the basic stuff finish synchronously, so we have a populated data chunk to save (hopefully)before the detailed one does +/* deprecated due to issue 622, retirement of YouTube agent try { data.put("basic", YouTube.simpleInfo(idFromParameters(ma.getParameters()))); } catch (Exception ex) { System.out.println(ma + " failed simpleInfo(): " + ex.toString()); } +*/ if (!minimal) { data.put("detailed", new JSONObject("{\"_processing\": true, \"timestamp\": " + diff --git a/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java b/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java index 7dc94f7820..338cbb55e2 100644 --- a/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java +++ b/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java @@ -306,71 +306,7 @@ public static void executeEmails(Shepherd myShepherd, HttpServletRequest request } private void youTubePostback(Encounter enc2add, Shepherd myShepherd, String context) { - /* - * START YouTube PostBack check - * - */ - try { - System.out.println("In IndividualAddEncounter trying to fire YouTube.."); - if (enc2add.getOccurrenceID() != null) { - if (myShepherd.isOccurrence(enc2add.getOccurrenceID())) { - System.out.println("...In IndividualAddEncounter found an occurrence.."); - Occurrence occur = myShepherd.getOccurrence(enc2add.getOccurrenceID()); - // TBD-support more than just en language - - // determine language for response - String ytRemarks = enc2add.getOccurrenceRemarks().trim().toLowerCase(); - int commentEnd = ytRemarks.indexOf("from youtube video:"); - if (commentEnd > 0) { - ytRemarks = ytRemarks.substring(commentEnd); - } - String detectedLanguage = "en"; - try { - detectedLanguage = DetectTranslate.detectLanguage(ytRemarks); - if (!detectedLanguage.toLowerCase().startsWith("en")) { - ytRemarks = DetectTranslate.translateToEnglish(ytRemarks); - } - if (detectedLanguage.startsWith("es")) { detectedLanguage = "es"; } else { - detectedLanguage = "en"; - } - } catch (Exception e) { - System.out.println("I hit an exception trying to detect language."); - e.printStackTrace(); - } - // end determine language for response - - Properties ytProps = null; - try { - ytProps = ShepherdProperties.getProperties("quest.properties", - detectedLanguage); - } catch (NullPointerException npe) { - System.out.println( - "Exception: Could not find quest.properties for langCode=" + - detectedLanguage + ". Falling back to en."); - } - if (ytProps == null) { - try { - ytProps = ShepherdProperties.getProperties("quest.properties", "en"); - } catch (NullPointerException npe2) { - System.out.println( - "Exception: Could not find quest.properties for en."); - } - } - if (ytProps != null) { - String message = ytProps.getProperty("individualAddEncounter").replaceAll( - "%INDIVIDUAL%", enc2add.getIndividualID()); - System.out.println( - "Will post back to YouTube OP this message if appropriate: " + message); - YouTube.postOccurrenceMessageToYouTubeIfAppropriate(message, occur, - myShepherd, context); - } - } - } - } catch (Exception e) { e.printStackTrace(); } - /* - * END YouTube PostBack check - * - */ + System.out.println("youTubePostback(): YouTube agent support has been deprecated"); } private void setDateLastModified(Encounter enc) { From 9cba0e6707c8454497363832a84a49f682a8d379 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 15:51:13 -0600 Subject: [PATCH 09/41] long overdue utility method --- src/main/java/org/ecocean/Util.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/ecocean/Util.java b/src/main/java/org/ecocean/Util.java index c74e1696e7..a74b2cb9fb 100644 --- a/src/main/java/org/ecocean/Util.java +++ b/src/main/java/org/ecocean/Util.java @@ -826,6 +826,9 @@ public static boolean stringExists(String str) { return (str != null && !str.trim().equals("") && !str.toLowerCase().equals("none") && !str.toLowerCase().equals("unknown")); } + public static boolean stringIsEmptyOrNull(String str) { + return ((str == null) || str.equals("")); + } public static boolean stringsEqualish(String s1, String s2) { if (!stringExists(s1)) { From 3eaa89fca58b7ccb9ab70e58efcb3518a844eba2 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 15:51:35 -0600 Subject: [PATCH 10/41] drop stanford NLP for simple utility --- src/main/java/org/ecocean/servlet/ProjectCreate.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/ecocean/servlet/ProjectCreate.java b/src/main/java/org/ecocean/servlet/ProjectCreate.java index 6ac6174e0b..18826b9c2f 100644 --- a/src/main/java/org/ecocean/servlet/ProjectCreate.java +++ b/src/main/java/org/ecocean/servlet/ProjectCreate.java @@ -9,8 +9,6 @@ import javax.servlet.ServletException; import org.json.JSONObject; -import edu.stanford.nlp.util.StringUtils; - import org.json.JSONArray; import org.json.JSONException; @@ -116,7 +114,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) if (projectUserIds != null && projectUserIds.length() > 0) { for (int i = 0; i < projectUserIds.length(); i++) { String userIdentifier = projectUserIds.getString(i); - if (!StringUtils.isNullOrEmpty(userIdentifier)) { + if (!Util.stringIsEmptyOrNull(userIdentifier)) { User user = null; if (Util.isUUID(userIdentifier)) { user = myShepherd.getUserByUUID(userIdentifier); From d0d3286e9d5448ca0f893919906d882f20657306 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 16:13:27 -0600 Subject: [PATCH 11/41] remove SUTime cruft (continued?") --- .../org/ecocean/servlet/SUTimeServlet.java | 246 - src/main/webapp/WEB-INF/web.xml | 14 - src/main/webapp/sutime/calendarview.css | 82 - src/main/webapp/sutime/calendarview.js | 839 ---- src/main/webapp/sutime/prototype.js | 4221 ----------------- src/main/webapp/sutime/su-footer.jsp | 7 - src/main/webapp/sutime/su-header.jsp | 142 - src/main/webapp/sutime/sutime.css | 25 - 8 files changed, 5576 deletions(-) delete mode 100644 src/main/java/org/ecocean/servlet/SUTimeServlet.java delete mode 100644 src/main/webapp/sutime/calendarview.css delete mode 100644 src/main/webapp/sutime/calendarview.js delete mode 100644 src/main/webapp/sutime/prototype.js delete mode 100644 src/main/webapp/sutime/su-footer.jsp delete mode 100644 src/main/webapp/sutime/su-header.jsp delete mode 100644 src/main/webapp/sutime/sutime.css diff --git a/src/main/java/org/ecocean/servlet/SUTimeServlet.java b/src/main/java/org/ecocean/servlet/SUTimeServlet.java deleted file mode 100644 index 3d584ec787..0000000000 --- a/src/main/java/org/ecocean/servlet/SUTimeServlet.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.ecocean.servlet; - -import javax.servlet.*; -import javax.servlet.http.*; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import edu.stanford.nlp.ling.CoreAnnotations; -import edu.stanford.nlp.ling.CoreLabel; -import edu.stanford.nlp.pipeline.Annotation; -import edu.stanford.nlp.pipeline.Annotator; -import edu.stanford.nlp.time.Options; -import edu.stanford.nlp.time.TimeAnnotations; -import edu.stanford.nlp.time.Timex; -import edu.stanford.nlp.util.CoreMap; - -import edu.stanford.nlp.util.StringUtils; -import org.apache.commons.lang3.StringEscapeUtils; - -public class SUTimeServlet extends HttpServlet { - private SUTimePipeline pipeline; // = null; - - @Override public void init() - throws ServletException { - String dataDir = getServletContext().getRealPath("/WEB-INF/data"); - String taggerFilename = dataDir + "/english-left3words-distsim.tagger"; - Properties pipelineProps = new Properties(); - - pipelineProps.setProperty("pos.model", taggerFilename); - pipeline = new SUTimePipeline(pipelineProps); - System.setProperty("de.jollyday.config", - getServletContext().getRealPath("/WEB-INF/classes/holidays/jollyday.properties")); - } - - public static boolean parseBoolean(String value) { - if (StringUtils.isNullOrEmpty(value)) { - return false; - } - if (value.equalsIgnoreCase("on")) { - return true; - } - return Boolean.parseBoolean(value); - } - - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - if (request.getCharacterEncoding() == null) { - request.setCharacterEncoding("utf-8"); - } - response.setContentType("text/html; charset=UTF-8"); - - this.getServletContext().getRequestDispatcher("/sutime/su-header.jsp").include(request, - response); - addResults(request, response); - this.getServletContext().getRequestDispatcher("/sutime/su-footer.jsp").include(request, - response); - } - - @Override public void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - doGet(request, response); - } - - private String getRuleFilepaths(String... files) { - String rulesDir = getServletContext().getRealPath("/WEB-INF/data/sutime/rules"); - StringBuilder sb = new StringBuilder(); - - for (String file : files) { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(rulesDir + "/" + file); - } - return sb.toString(); - } - - private Properties getTimeAnnotatorProperties(HttpServletRequest request) { - // Parses request and set up properties for time annotators - boolean markTimeRanges = parseBoolean(request.getParameter("markTimeRanges")); - boolean includeNested = parseBoolean(request.getParameter("includeNested")); - boolean includeRange = parseBoolean(request.getParameter("includeRange")); - boolean readRules = true; - String heuristicLevel = request.getParameter("relativeHeuristicLevel"); - - Options.RelativeHeuristicLevel relativeHeuristicLevel = Options.RelativeHeuristicLevel.NONE; - if (!StringUtils.isNullOrEmpty(heuristicLevel)) { - relativeHeuristicLevel = Options.RelativeHeuristicLevel.valueOf(heuristicLevel); - } - String ruleFile = null; - if (readRules) { - String rules = request.getParameter("rules"); - if ("English".equalsIgnoreCase(rules)) { - ruleFile = getRuleFilepaths("defs.sutime.txt", "english.sutime.txt", - "english.holidays.sutime.txt"); - } - } - // Create properties - Properties props = new Properties(); - if (markTimeRanges) { - props.setProperty("sutime.markTimeRanges", "true"); - } - if (includeNested) { - props.setProperty("sutime.includeNested", "true"); - } - if (includeRange) { - props.setProperty("sutime.includeRange", "true"); - } - if (ruleFile != null) { - props.setProperty("sutime.rules", ruleFile); - props.setProperty("sutime.binders", "1"); - props.setProperty("sutime.binder.1", "edu.stanford.nlp.time.JollyDayHolidays"); - props.setProperty("sutime.binder.1.xml", - getServletContext().getRealPath("/WEB-INF/data/holidays/Holidays_sutime.xml")); - props.setProperty("sutime.binder.1.pathtype", "file"); - } - props.setProperty("sutime.teRelHeurLevel", relativeHeuristicLevel.toString()); -// props.setProperty("sutime.verbose", "true"); - -// props.setProperty("heideltime.path", getServletContext().getRealPath("/packages/heideltime")); -// props.setProperty("gutime.path", getServletContext().getRealPath("/packages/gutime")); - return props; - } - - private static void displayAnnotation(PrintWriter out, String query, Annotation anno, - boolean includeOffsets) { - List timexAnns = anno.get(TimeAnnotations.TimexAnnotations.class); - List pieces = new ArrayList<>(); - List tagged = new ArrayList<>(); - int previousEnd = 0; - - for (CoreMap timexAnn : timexAnns) { - int begin = timexAnn.get(CoreAnnotations.CharacterOffsetBeginAnnotation.class); - int end = timexAnn.get(CoreAnnotations.CharacterOffsetEndAnnotation.class); - if (begin >= previousEnd) { - pieces.add(query.substring(previousEnd, begin)); - tagged.add(false); - pieces.add(query.substring(begin, end)); - tagged.add(true); - previousEnd = end; - } - } - if (previousEnd < query.length()) { - pieces.add(query.substring(previousEnd)); - tagged.add(false); - } - out.println("
"); - for (int i = 0; i < pieces.size(); ++i) { - if (tagged.get(i)) { - out.print(""); - out.print(StringEscapeUtils.escapeHtml4(pieces.get(i))); - out.print(""); - } else { - out.print(StringEscapeUtils.escapeHtml4(pieces.get(i))); - } - } - out.println("
"); - - out.println("

Temporal Expressions

"); - if (timexAnns.size() > 0) { - out.println(""); - out.println(""); - if (includeOffsets) { - out.println( - ""); - } - out.println(""); - for (CoreMap timexAnn : timexAnns) { - out.println(""); - Timex timex = timexAnn.get(TimeAnnotations.TimexAnnotation.class); - int begin = timexAnn.get(CoreAnnotations.CharacterOffsetBeginAnnotation.class); - int end = timexAnn.get(CoreAnnotations.CharacterOffsetEndAnnotation.class); - out.print(""); - out.print(""); - if (includeOffsets) { - out.print(""); - out.print(""); - out.print(""); - out.print(""); - } - out.print(""); - out.println(""); - } - out.println("
TextValueChar BeginChar EndToken BeginToken EndTimex3 Tag
" + StringEscapeUtils.escapeHtml4(query.substring(begin, - end)) + "" + ((timex.value() != - null) ? StringEscapeUtils.escapeHtml4(timex.value()) : "") + "" + begin + "" + end + "" + timexAnn.get(CoreAnnotations.TokenBeginAnnotation.class) + - "" + timexAnn.get(CoreAnnotations.TokenEndAnnotation.class) + - "" + StringEscapeUtils.escapeHtml4(timex.toString()) + "
"); - } else { - out.println("No temporal expressions."); - } - out.println("

POS Tags

"); - out.println("
"); - for (CoreMap sentence : anno.get(CoreAnnotations.SentencesAnnotation.class)) { - List tokens = sentence.get(CoreAnnotations.TokensAnnotation.class); - for (CoreLabel token : tokens) { - String tokenOutput = StringEscapeUtils.escapeHtml4(token.word() + "/" + - token.tag()); - out.print(tokenOutput + " "); - } - out.println("
"); - } - out.println("
"); - } - - private void addResults(HttpServletRequest request, HttpServletResponse response) - throws IOException { - // if we can't handle UTF-8, need to do something like this... - // String originalQuery = request.getParameter("q"); - // String query = WebappUtil.convertString(originalQuery); - - String query = request.getParameter("q"); - String dateString = request.getParameter("d"); - // TODO: this always returns true... - boolean dateError = !pipeline.isDateOkay(dateString); - boolean includeOffsets = parseBoolean(request.getParameter("includeOffsets")); - PrintWriter out = response.getWriter(); - - if (dateError) { - out.println("

Warning: unparseable date " + - StringEscapeUtils.escapeHtml4(dateString)); - } - if (!StringUtils.isNullOrEmpty(query)) { - Properties props = getTimeAnnotatorProperties(request); - String annotatorType = request.getParameter("annotator"); - if (annotatorType == null) { - annotatorType = "sutime"; - } - Annotator timeAnnotator = pipeline.getTimeAnnotator(annotatorType, props); - if (timeAnnotator != null) { - Annotation anno = pipeline.process(query, dateString, timeAnnotator); - out.println("

Annotated Text

(tagged using " + annotatorType + - ")"); - displayAnnotation(out, query, anno, includeOffsets); - } else { - out.println("

Error creating annotator for " + - StringEscapeUtils.escapeHtml4(annotatorType)); - } - } - } - - private static final long serialVersionUID = 1L; -} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 10f2f56a4e..85c5981d27 100755 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -336,8 +336,6 @@ /OccurrenceSearchExportMetadataExcel = authc, roles[researcher] /OccurrenceSearchExportGtm = authc, roles[researcher] - /SUTimeServlet = authc, roles[admin] - #lockdown Keyword handling /appadmin/kwAdmin.jsp = authc, roles[admin] /KeywordHandler = authc, roles[admin] @@ -1864,18 +1862,6 @@ /TranslationsGet - - - SUTimeServlet - org.ecocean.servlet.SUTimeServlet - - - - SUTimeServlet - /SUTimeServlet - - - OccurrenceSearchExportGtm /OccurrenceSearchExportGtm diff --git a/src/main/webapp/sutime/calendarview.css b/src/main/webapp/sutime/calendarview.css deleted file mode 100644 index 9e2c90455e..0000000000 --- a/src/main/webapp/sutime/calendarview.css +++ /dev/null @@ -1,82 +0,0 @@ - -div.calendar -{ - font-size: smaller; - color: #000; -} - -div.calendar.popup -{ - margin-left: -40px; - margin-top: -100px; -} - -div.calendar table -{ - background-color: #eee; - border: 1px solid #aaa; - border-collapse: collapse; -} - -div.calendar thead { - background-color: white; -} - -div.calendar td, -div.calendar th -{ - padding: 3px; - text-align: center; -} - -div.calendar td.title -{ - font-weight: bold; -} - -div.calendar th -{ - background: #ddd; - border-bottom: 1px solid #ccc; - border-top: 1px solid #ccc; - font-weight: bold; - color: #555; -} - -div.calendar tr.days td { - width: 2em; - color: #555; - text-align: center; - cursor: pointer; -} - -div.calendar tr.days td:hover, -div.calendar td.button:hover -{ - background-color: #34ABFA; - cursor: pointer; -} - -div.calendar tr.days td:active -div.calendar td.button:active -{ - background-color: #cde; -} - -div.calendar tr.days td.selected -{ - font-weight: bold; - background-color: #fff; - color: #000; -} - -div.calendar tr.days td.today -{ - font-weight: bold; - color: #D50000; -} - -div.calendar tr.days td.otherDay -{ - color: #bbb; -} diff --git a/src/main/webapp/sutime/calendarview.js b/src/main/webapp/sutime/calendarview.js deleted file mode 100644 index f4be8f7581..0000000000 --- a/src/main/webapp/sutime/calendarview.js +++ /dev/null @@ -1,839 +0,0 @@ -// -// CalendarView (for Prototype) -// calendarview.org -// -// Maintained by Justin Mecham -// -// Portions Copyright 2002-2005 Mihai Bazon -// -// This calendar is based very loosely on the Dynarch Calendar in that it was -// used as a base, but completely gutted and more or less rewritten in place -// to use the Prototype JavaScript library. -// -// As such, CalendarView is licensed under the terms of the GNU Lesser General -// Public License (LGPL). More information on the Dynarch Calendar can be -// found at: -// -// www.dynarch.com/projects/calendar -// - -var Calendar = Class.create() - -//------------------------------------------------------------------------------ -// Constants -//------------------------------------------------------------------------------ - -Calendar.VERSION = '1.2' - -Calendar.DAY_NAMES = new Array( - 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', - 'Sunday' -) - -Calendar.SHORT_DAY_NAMES = new Array( - 'S', 'M', 'T', 'W', 'T', 'F', 'S', 'S' -) - -Calendar.MONTH_NAMES = new Array( - 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', - 'September', 'October', 'November', 'December' -) - -Calendar.SHORT_MONTH_NAMES = new Array( - 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', - 'Dec' -) - -Calendar.NAV_PREVIOUS_YEAR = -2 -Calendar.NAV_PREVIOUS_MONTH = -1 -Calendar.NAV_TODAY = 0 -Calendar.NAV_NEXT_MONTH = 1 -Calendar.NAV_NEXT_YEAR = 2 - -//------------------------------------------------------------------------------ -// Static Methods -//------------------------------------------------------------------------------ - -// This gets called when the user presses a mouse button anywhere in the -// document, if the calendar is shown. If the click was outside the open -// calendar this function closes it. -Calendar._checkCalendar = function(event) { - if (!window._popupCalendar) - return false - if (Element.descendantOf(Event.element(event), window._popupCalendar.container)) - return - window._popupCalendar.callCloseHandler() - return Event.stop(event) -} - -//------------------------------------------------------------------------------ -// Event Handlers -//------------------------------------------------------------------------------ - -Calendar.handleMouseDownEvent = function(event) -{ - Event.observe(document, 'mouseup', Calendar.handleMouseUpEvent) - Event.stop(event) -} - -// XXX I am not happy with how clicks of different actions are handled. Need to -// clean this up! -Calendar.handleMouseUpEvent = function(event) -{ - var el = Event.element(event) - var calendar = el.calendar - var isNewDate = false - - // If the element that was clicked on does not have an associated Calendar - // object, return as we have nothing to do. - if (!calendar) return false - - // Clicked on a day - if (typeof el.navAction == 'undefined') - { - if (calendar.currentDateElement) { - Element.removeClassName(calendar.currentDateElement, 'selected') - Element.addClassName(el, 'selected') - calendar.shouldClose = (calendar.currentDateElement == el) - if (!calendar.shouldClose) calendar.currentDateElement = el - } - calendar.date.setDateOnly(el.date) - isNewDate = true - calendar.shouldClose = !el.hasClassName('otherDay') - var isOtherMonth = !calendar.shouldClose - if (isOtherMonth) calendar.update(calendar.date) - } - - // Clicked on an action button - else - { - var date = new Date(calendar.date) - - if (el.navAction == Calendar.NAV_TODAY) - date.setDateOnly(new Date()) - - var year = date.getFullYear() - var mon = date.getMonth() - function setMonth(m) { - var day = date.getDate() - var max = date.getMonthDays(m) - if (day > max) date.setDate(max) - date.setMonth(m) - } - switch (el.navAction) { - - // Previous Year - case Calendar.NAV_PREVIOUS_YEAR: - if (year > calendar.minYear) - date.setFullYear(year - 1) - break - - // Previous Month - case Calendar.NAV_PREVIOUS_MONTH: - if (mon > 0) { - setMonth(mon - 1) - } - else if (year-- > calendar.minYear) { - date.setFullYear(year) - setMonth(11) - } - break - - // Today - case Calendar.NAV_TODAY: - break - - // Next Month - case Calendar.NAV_NEXT_MONTH: - if (mon < 11) { - setMonth(mon + 1) - } - else if (year < calendar.maxYear) { - date.setFullYear(year + 1) - setMonth(0) - } - break - - // Next Year - case Calendar.NAV_NEXT_YEAR: - if (year < calendar.maxYear) - date.setFullYear(year + 1) - break - - } - - if (!date.equalsTo(calendar.date)) { - calendar.setDate(date) - isNewDate = true - } else if (el.navAction == 0) { - isNewDate = (calendar.shouldClose = true) - } - } - - if (isNewDate) event && calendar.callSelectHandler() - if (calendar.shouldClose) event && calendar.callCloseHandler() - - Event.stopObserving(document, 'mouseup', Calendar.handleMouseUpEvent) - - return Event.stop(event) -} - -Calendar.defaultSelectHandler = function(calendar) -{ - if (!calendar.dateField) return false - - // Update dateField value - if (calendar.dateField.tagName == 'DIV') - Element.update(calendar.dateField, calendar.date.print(calendar.dateFormat)) - else if (calendar.dateField.tagName == 'INPUT') { - calendar.dateField.value = calendar.date.print(calendar.dateFormat) } - - // Trigger the onchange callback on the dateField, if one has been defined - if (typeof calendar.dateField.onchange == 'function') - calendar.dateField.onchange() - - // Call the close handler, if necessary - if (calendar.shouldClose) calendar.callCloseHandler() -} - -Calendar.defaultCloseHandler = function(calendar) -{ - calendar.hide() -} - - -//------------------------------------------------------------------------------ -// Calendar Setup -//------------------------------------------------------------------------------ - -Calendar.setup = function(params) -{ - - function param_default(name, def) { - if (!params[name]) params[name] = def - } - - param_default('dateField', null) - param_default('triggerElement', null) - param_default('parentElement', null) - param_default('selectHandler', null) - param_default('closeHandler', null) - - // In-Page Calendar - if (params.parentElement) - { - var calendar = new Calendar(params.parentElement) - calendar.setSelectHandler(params.selectHandler || Calendar.defaultSelectHandler) - if (params.dateFormat) - calendar.setDateFormat(params.dateFormat) - if (params.dateField) { - calendar.setDateField(params.dateField) - calendar.parseDate(calendar.dateField.innerHTML || calendar.dateField.value) - } - calendar.show() - return calendar - } - - // Popup Calendars - // - // XXX There is significant optimization to be had here by creating the - // calendar and storing it on the page, but then you will have issues with - // multiple calendars on the same page. - else - { - var triggerElement = $(params.triggerElement || params.dateField) - triggerElement.onclick = function() { - var calendar = new Calendar() - calendar.setSelectHandler(params.selectHandler || Calendar.defaultSelectHandler) - calendar.setCloseHandler(params.closeHandler || Calendar.defaultCloseHandler) - if (params.dateFormat) - calendar.setDateFormat(params.dateFormat) - if (params.dateField) { - calendar.setDateField(params.dateField) - calendar.parseDate(calendar.dateField.innerHTML || calendar.dateField.value) - } - if (params.dateField) - Date.parseDate(calendar.dateField.value || calendar.dateField.innerHTML, calendar.dateFormat) - calendar.showAtElement(triggerElement) - return calendar - } - } - -} - - - -//------------------------------------------------------------------------------ -// Calendar Instance -//------------------------------------------------------------------------------ - -Calendar.prototype = { - - // The HTML Container Element - container: null, - - // Callbacks - selectHandler: null, - closeHandler: null, - - // Configuration - minYear: 1900, - maxYear: 2100, - dateFormat: '%Y-%m-%d', - - // Dates - date: new Date(), - currentDateElement: null, - - // Status - shouldClose: false, - isPopup: true, - - dateField: null, - - - //---------------------------------------------------------------------------- - // Initialize - //---------------------------------------------------------------------------- - - initialize: function(parent) - { - if (parent) - this.create($(parent)) - else - this.create() - }, - - - - //---------------------------------------------------------------------------- - // Update / (Re)initialize Calendar - //---------------------------------------------------------------------------- - - update: function(date) - { - var calendar = this - var today = new Date() - var thisYear = today.getFullYear() - var thisMonth = today.getMonth() - var thisDay = today.getDate() - var month = date.getMonth(); - var dayOfMonth = date.getDate(); - - // Ensure date is within the defined range - if (date.getFullYear() < this.minYear) - date.setFullYear(this.minYear) - else if (date.getFullYear() > this.maxYear) - date.setFullYear(this.maxYear) - - this.date = new Date(date) - - // Calculate the first day to display (including the previous month) - date.setDate(1) - date.setDate(-(date.getDay()) + 1) - - // Fill in the days of the month - Element.getElementsBySelector(this.container, 'tbody tr').each( - function(row, i) { - var rowHasDays = false - row.immediateDescendants().each( - function(cell, j) { - var day = date.getDate() - var dayOfWeek = date.getDay() - var isCurrentMonth = (date.getMonth() == month) - - // Reset classes on the cell - cell.className = '' - cell.date = new Date(date) - cell.update(day) - - // Account for days of the month other than the current month - if (!isCurrentMonth) - cell.addClassName('otherDay') - else - rowHasDays = true - - // Ensure the current day is selected - if (isCurrentMonth && day == dayOfMonth) { - cell.addClassName('selected') - calendar.currentDateElement = cell - } - - // Today - if (date.getFullYear() == thisYear && date.getMonth() == thisMonth && day == thisDay) - cell.addClassName('today') - - // Weekend - if ([0, 6].indexOf(dayOfWeek) != -1) - cell.addClassName('weekend') - - // Set the date to tommorrow - date.setDate(day + 1) - } - ) - // Hide the extra row if it contains only days from another month - !rowHasDays ? row.hide() : row.show() - } - ) - - this.container.getElementsBySelector('td.title')[0].update( - Calendar.MONTH_NAMES[month] + ' ' + this.date.getFullYear() - ) - }, - - - - //---------------------------------------------------------------------------- - // Create/Draw the Calendar HTML Elements - //---------------------------------------------------------------------------- - - create: function(parent) - { - - // If no parent was specified, assume that we are creating a popup calendar. - if (!parent) { - parent = document.getElementsByTagName('body')[0] - this.isPopup = true - } else { - this.isPopup = false - } - - // Calendar Table - var table = new Element('table') - - // Calendar Header - var thead = new Element('thead') - table.appendChild(thead) - - // Title Placeholder - var row = new Element('tr') - var cell = new Element('td', { colSpan: 7 } ) - cell.addClassName('title') - row.appendChild(cell) - thead.appendChild(row) - - // Calendar Navigation - row = new Element('tr') - this._drawButtonCell(row, '«', 1, Calendar.NAV_PREVIOUS_YEAR) - this._drawButtonCell(row, '‹', 1, Calendar.NAV_PREVIOUS_MONTH) - this._drawButtonCell(row, 'Today', 3, Calendar.NAV_TODAY) - this._drawButtonCell(row, '›', 1, Calendar.NAV_NEXT_MONTH) - this._drawButtonCell(row, '»', 1, Calendar.NAV_NEXT_YEAR) - thead.appendChild(row) - - // Day Names - row = new Element('tr') - for (var i = 0; i < 7; ++i) { - cell = new Element('th').update(Calendar.SHORT_DAY_NAMES[i]) - if (i == 0 || i == 6) - cell.addClassName('weekend') - row.appendChild(cell) - } - thead.appendChild(row) - - // Calendar Days - var tbody = table.appendChild(new Element('tbody')) - for (i = 6; i > 0; --i) { - row = tbody.appendChild(new Element('tr')) - row.addClassName('days') - for (var j = 7; j > 0; --j) { - cell = row.appendChild(new Element('td')) - cell.calendar = this - } - } - - // Calendar Container (div) - this.container = new Element('div') - this.container.addClassName('calendar') - if (this.isPopup) { - this.container.setStyle({ position: 'absolute', display: 'none' }) - this.container.addClassName('popup') - } - this.container.appendChild(table) - - // Initialize Calendar - this.update(this.date) - - // Observe the container for mousedown events - Event.observe(this.container, 'mousedown', Calendar.handleMouseDownEvent) - - // Append to parent element - parent.appendChild(this.container) - - }, - - _drawButtonCell: function(parent, text, colSpan, navAction) - { - var cell = new Element('td') - if (colSpan > 1) cell.colSpan = colSpan - cell.className = 'button' - cell.calendar = this - cell.navAction = navAction - cell.innerHTML = text - cell.unselectable = 'on' // IE - parent.appendChild(cell) - return cell - }, - - - - //------------------------------------------------------------------------------ - // Callbacks - //------------------------------------------------------------------------------ - - // Calls the Select Handler (if defined) - callSelectHandler: function() - { - if (this.selectHandler) - this.selectHandler(this, this.date.print(this.dateFormat)) - }, - - // Calls the Close Handler (if defined) - callCloseHandler: function() - { - if (this.closeHandler) - this.closeHandler(this) - }, - - - - //------------------------------------------------------------------------------ - // Calendar Display Functions - //------------------------------------------------------------------------------ - - // Shows the Calendar - show: function() - { - this.container.show() - if (this.isPopup) { - window._popupCalendar = this - Event.observe(document, 'mousedown', Calendar._checkCalendar) - } - }, - - // Shows the calendar at the given absolute position - showAt: function (x, y) - { - this.container.setStyle({ left: x + 'px', top: y + 'px' }) - this.show() - }, - - // Shows the Calendar at the coordinates of the provided element - showAtElement: function(element) - { - var pos = Position.cumulativeOffset(element) - this.showAt(pos[0], pos[1]) - }, - - // Hides the Calendar - hide: function() - { - if (this.isPopup) - Event.stopObserving(document, 'mousedown', Calendar._checkCalendar) - this.container.hide() - }, - - - - //------------------------------------------------------------------------------ - // Miscellaneous - //------------------------------------------------------------------------------ - - // Tries to identify the date represented in a string. If successful it also - // calls this.setDate which moves the calendar to the given date. - parseDate: function(str, format) - { - if (!format) - format = this.dateFormat - this.setDate(Date.parseDate(str, format)) - }, - - - - //------------------------------------------------------------------------------ - // Getters/Setters - //------------------------------------------------------------------------------ - - setSelectHandler: function(selectHandler) - { - this.selectHandler = selectHandler - }, - - setCloseHandler: function(closeHandler) - { - this.closeHandler = closeHandler - }, - - setDate: function(date) - { - if (!date.equalsTo(this.date)) - this.update(date) - }, - - setDateFormat: function(format) - { - this.dateFormat = format - }, - - setDateField: function(field) - { - this.dateField = $(field) - }, - - setRange: function(minYear, maxYear) - { - this.minYear = minYear - this.maxYear = maxYear - } - -} - -// global object that remembers the calendar -window._popupCalendar = null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//============================================================================== -// -// Date Object Patches -// -// This is pretty much untouched from the original. I really would like to get -// rid of these patches if at all possible and find a cleaner way of -// accomplishing the same things. It's a shame Prototype doesn't extend Date at -// all. -// -//============================================================================== - -Date.DAYS_IN_MONTH = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) -Date.SECOND = 1000 /* milliseconds */ -Date.MINUTE = 60 * Date.SECOND -Date.HOUR = 60 * Date.MINUTE -Date.DAY = 24 * Date.HOUR -Date.WEEK = 7 * Date.DAY - -// Parses Date -Date.parseDate = function(str, fmt) { - var today = new Date(); - var y = 0; - var m = -1; - var d = 0; - var a = str.split(/\W+/); - var b = fmt.match(/%./g); - var i = 0, j = 0; - var hr = 0; - var min = 0; - - for (i = 0; i < a.length; ++i) { - if (!a[i]) continue; - switch (b[i]) { - case "%d": - case "%e": - d = parseInt(a[i], 10); - break; - case "%m": - m = parseInt(a[i], 10) - 1; - break; - case "%Y": - case "%y": - y = parseInt(a[i], 10); - (y < 100) && (y += (y > 29) ? 1900 : 2000); - break; - case "%b": - case "%B": - for (j = 0; j < 12; ++j) { - if (Calendar.MONTH_NAMES[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { - m = j; - break; - } - } - break; - case "%H": - case "%I": - case "%k": - case "%l": - hr = parseInt(a[i], 10); - break; - case "%P": - case "%p": - if (/pm/i.test(a[i]) && hr < 12) - hr += 12; - else if (/am/i.test(a[i]) && hr >= 12) - hr -= 12; - break; - case "%M": - min = parseInt(a[i], 10); - break; - } - } - if (isNaN(y)) y = today.getFullYear(); - if (isNaN(m)) m = today.getMonth(); - if (isNaN(d)) d = today.getDate(); - if (isNaN(hr)) hr = today.getHours(); - if (isNaN(min)) min = today.getMinutes(); - if (y != 0 && m != -1 && d != 0) - return new Date(y, m, d, hr, min, 0); - y = 0; m = -1; d = 0; - for (i = 0; i < a.length; ++i) { - if (a[i].search(/[a-zA-Z]+/) != -1) { - var t = -1; - for (j = 0; j < 12; ++j) { - if (Calendar.MONTH_NAMES[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } - } - if (t != -1) { - if (m != -1) { - d = m+1; - } - m = t; - } - } else if (parseInt(a[i], 10) <= 12 && m == -1) { - m = a[i]-1; - } else if (parseInt(a[i], 10) > 31 && y == 0) { - y = parseInt(a[i], 10); - (y < 100) && (y += (y > 29) ? 1900 : 2000); - } else if (d == 0) { - d = a[i]; - } - } - if (y == 0) - y = today.getFullYear(); - if (m != -1 && d != 0) - return new Date(y, m, d, hr, min, 0); - return today; -}; - -// Returns the number of days in the current month -Date.prototype.getMonthDays = function(month) { - var year = this.getFullYear() - if (typeof month == "undefined") - month = this.getMonth() - if (((0 == (year % 4)) && ( (0 != (year % 100)) || (0 == (year % 400)))) && month == 1) - return 29 - else - return Date.DAYS_IN_MONTH[month] -}; - -// Returns the number of day in the year -Date.prototype.getDayOfYear = function() { - var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); - var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0); - var time = now - then; - return Math.floor(time / Date.DAY); -}; - -/** Returns the number of the week in year, as defined in ISO 8601. */ -Date.prototype.getWeekNumber = function() { - var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); - var DoW = d.getDay(); - d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu - var ms = d.valueOf(); // GMT - d.setMonth(0); - d.setDate(4); // Thu in Week 1 - return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1; -}; - -/** Checks date and time equality */ -Date.prototype.equalsTo = function(date) { - return ((this.getFullYear() == date.getFullYear()) && - (this.getMonth() == date.getMonth()) && - (this.getDate() == date.getDate()) && - (this.getHours() == date.getHours()) && - (this.getMinutes() == date.getMinutes())); -}; - -/** Set only the year, month, date parts (keep existing time) */ -Date.prototype.setDateOnly = function(date) { - var tmp = new Date(date); - this.setDate(1); - this.setFullYear(tmp.getFullYear()); - this.setMonth(tmp.getMonth()); - this.setDate(tmp.getDate()); -}; - -/** Prints the date in a string according to the given format. */ -Date.prototype.print = function (str) { - var m = this.getMonth(); - var d = this.getDate(); - var y = this.getFullYear(); - var wn = this.getWeekNumber(); - var w = this.getDay(); - var s = {}; - var hr = this.getHours(); - var pm = (hr >= 12); - var ir = (pm) ? (hr - 12) : hr; - var dy = this.getDayOfYear(); - if (ir == 0) - ir = 12; - var min = this.getMinutes(); - var sec = this.getSeconds(); - s["%a"] = Calendar.SHORT_DAY_NAMES[w]; // abbreviated weekday name [FIXME: I18N] - s["%A"] = Calendar.DAY_NAMES[w]; // full weekday name - s["%b"] = Calendar.SHORT_MONTH_NAMES[m]; // abbreviated month name [FIXME: I18N] - s["%B"] = Calendar.MONTH_NAMES[m]; // full month name - // FIXME: %c : preferred date and time representation for the current locale - s["%C"] = 1 + Math.floor(y / 100); // the century number - s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31) - s["%e"] = d; // the day of the month (range 1 to 31) - // FIXME: %D : american date style: %m/%d/%y - // FIXME: %E, %F, %G, %g, %h (man strftime) - s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format) - s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format) - s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366) - s["%k"] = hr; // hour, range 0 to 23 (24h format) - s["%l"] = ir; // hour, range 1 to 12 (12h format) - s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12 - s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59 - s["%n"] = "\n"; // a newline character - s["%p"] = pm ? "PM" : "AM"; - s["%P"] = pm ? "pm" : "am"; - // FIXME: %r : the time in am/pm notation %I:%M:%S %p - // FIXME: %R : the time in 24-hour notation %H:%M - s["%s"] = Math.floor(this.getTime() / 1000); - s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59 - s["%t"] = "\t"; // a tab character - // FIXME: %T : the time in 24-hour notation (%H:%M:%S) - s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn; - s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON) - s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN) - // FIXME: %x : preferred date representation for the current locale without the time - // FIXME: %X : preferred time representation for the current locale without the date - s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99) - s["%Y"] = y; // year with the century - s["%%"] = "%"; // a literal '%' character - - return str.gsub(/%./, function(match) { return s[match] || match }); -}; - -Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; -Date.prototype.setFullYear = function(y) { - var d = new Date(this); - d.__msh_oldSetFullYear(y); - if (d.getMonth() != this.getMonth()) - this.setDate(28); - this.__msh_oldSetFullYear(y); -} diff --git a/src/main/webapp/sutime/prototype.js b/src/main/webapp/sutime/prototype.js deleted file mode 100644 index 6385503a1c..0000000000 --- a/src/main/webapp/sutime/prototype.js +++ /dev/null @@ -1,4221 +0,0 @@ -/* Prototype JavaScript framework, version 1.6.0.2 - * (c) 2005-2008 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://www.prototypejs.org/ - * - *--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.6.0.2', - - Browser: { - IE: !!(window.attachEvent && !window.opera), - Opera: !!window.opera, - WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, - Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, - MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) - }, - - BrowserFeatures: { - XPath: !!document.evaluate, - ElementExtensions: !!window.HTMLElement, - SpecificElementExtensions: - document.createElement('div').__proto__ && - document.createElement('div').__proto__ !== - document.createElement('form').__proto__ - }, - - ScriptFragment: ']*>([\\S\\s]*?)<\/script>', - JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, - - emptyFunction: function() { }, - K: function(x) { return x } -}; - -if (Prototype.Browser.MobileSafari) - Prototype.BrowserFeatures.SpecificElementExtensions = false; - - -/* Based on Alex Arnell's inheritance implementation. */ -var Class = { - create: function() { - var parent = null, properties = $A(arguments); - if (Object.isFunction(properties[0])) - parent = properties.shift(); - - function klass() { - this.initialize.apply(this, arguments); - } - - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - var subclass = function() { }; - subclass.prototype = parent.prototype; - klass.prototype = new subclass; - parent.subclasses.push(klass); - } - - for (var i = 0; i < properties.length; i++) - klass.addMethods(properties[i]); - - if (!klass.prototype.initialize) - klass.prototype.initialize = Prototype.emptyFunction; - - klass.prototype.constructor = klass; - - return klass; - } -}; - -Class.Methods = { - addMethods: function(source) { - var ancestor = this.superclass && this.superclass.prototype; - var properties = Object.keys(source); - - if (!Object.keys({ toString: true }).length) - properties.push("toString", "valueOf"); - - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i], value = source[property]; - if (ancestor && Object.isFunction(value) && - value.argumentNames().first() == "$super") { - var method = value, value = Object.extend((function(m) { - return function() { return ancestor[m].apply(this, arguments) }; - })(property).wrap(method), { - valueOf: function() { return method }, - toString: function() { return method.toString() } - }); - } - this.prototype[property] = value; - } - - return this; - } -}; - -var Abstract = { }; - -Object.extend = function(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; -}; - -Object.extend(Object, { - inspect: function(object) { - try { - if (Object.isUndefined(object)) return 'undefined'; - if (object === null) return 'null'; - return object.inspect ? object.inspect() : String(object); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } - }, - - toJSON: function(object) { - var type = typeof object; - switch (type) { - case 'undefined': - case 'function': - case 'unknown': return; - case 'boolean': return object.toString(); - } - - if (object === null) return 'null'; - if (object.toJSON) return object.toJSON(); - if (Object.isElement(object)) return; - - var results = []; - for (var property in object) { - var value = Object.toJSON(object[property]); - if (!Object.isUndefined(value)) - results.push(property.toJSON() + ': ' + value); - } - - return '{' + results.join(', ') + '}'; - }, - - toQueryString: function(object) { - return $H(object).toQueryString(); - }, - - toHTML: function(object) { - return object && object.toHTML ? object.toHTML() : String.interpret(object); - }, - - keys: function(object) { - var keys = []; - for (var property in object) - keys.push(property); - return keys; - }, - - values: function(object) { - var values = []; - for (var property in object) - values.push(object[property]); - return values; - }, - - clone: function(object) { - return Object.extend({ }, object); - }, - - isElement: function(object) { - return object && object.nodeType == 1; - }, - - isArray: function(object) { - return object != null && typeof object == "object" && - 'splice' in object && 'join' in object; - }, - - isHash: function(object) { - return object instanceof Hash; - }, - - isFunction: function(object) { - return typeof object == "function"; - }, - - isString: function(object) { - return typeof object == "string"; - }, - - isNumber: function(object) { - return typeof object == "number"; - }, - - isUndefined: function(object) { - return typeof object == "undefined"; - } -}); - -Object.extend(Function.prototype, { - argumentNames: function() { - var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); - return names.length == 1 && !names[0] ? [] : names; - }, - - bind: function() { - if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } - }, - - bindAsEventListener: function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function(event) { - return __method.apply(object, [event || window.event].concat(args)); - } - }, - - curry: function() { - if (!arguments.length) return this; - var __method = this, args = $A(arguments); - return function() { - return __method.apply(this, args.concat($A(arguments))); - } - }, - - delay: function() { - var __method = this, args = $A(arguments), timeout = args.shift() * 1000; - return window.setTimeout(function() { - return __method.apply(__method, args); - }, timeout); - }, - - wrap: function(wrapper) { - var __method = this; - return function() { - return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); - } - }, - - methodize: function() { - if (this._methodized) return this._methodized; - var __method = this; - return this._methodized = function() { - return __method.apply(null, [this].concat($A(arguments))); - }; - } -}); - -Function.prototype.defer = Function.prototype.delay.curry(0.01); - -Date.prototype.toJSON = function() { - return '"' + this.getUTCFullYear() + '-' + - (this.getUTCMonth() + 1).toPaddedString(2) + '-' + - this.getUTCDate().toPaddedString(2) + 'T' + - this.getUTCHours().toPaddedString(2) + ':' + - this.getUTCMinutes().toPaddedString(2) + ':' + - this.getUTCSeconds().toPaddedString(2) + 'Z"'; -}; - -var Try = { - these: function() { - var returnValue; - - for (var i = 0, length = arguments.length; i < length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) { } - } - - return returnValue; - } -}; - -RegExp.prototype.match = RegExp.prototype.test; - -RegExp.escape = function(str) { - return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); -}; - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create({ - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - execute: function() { - this.callback(this); - }, - - stop: function() { - if (!this.timer) return; - clearInterval(this.timer); - this.timer = null; - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.execute(); - } finally { - this.currentlyExecuting = false; - } - } - } -}); -Object.extend(String, { - interpret: function(value) { - return value == null ? '' : String(value); - }, - specialChar: { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '\\': '\\\\' - } -}); - -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { - var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += String.interpret(replacement(match)); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - }, - - sub: function(pattern, replacement, count) { - replacement = this.gsub.prepareReplacement(replacement); - count = Object.isUndefined(count) ? 1 : count; - - return this.gsub(pattern, function(match) { - if (--count < 0) return match[0]; - return replacement(match); - }); - }, - - scan: function(pattern, iterator) { - this.gsub(pattern, iterator); - return String(this); - }, - - truncate: function(length, truncation) { - length = length || 30; - truncation = Object.isUndefined(truncation) ? '...' : truncation; - return this.length > length ? - this.slice(0, length - truncation.length) + truncation : String(this); - }, - - strip: function() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, - - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(function(script) { return eval(script) }); - }, - - escapeHTML: function() { - var self = arguments.callee; - self.text.data = this; - return self.div.innerHTML; - }, - - unescapeHTML: function() { - var div = new Element('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? (div.childNodes.length > 1 ? - $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : - div.childNodes[0].nodeValue) : ''; - }, - - toQueryParams: function(separator) { - var match = this.strip().match(/([^?#]*)(#.*)?$/); - if (!match) return { }; - - return match[1].split(separator || '&').inject({ }, function(hash, pair) { - if ((pair = pair.split('='))[0]) { - var key = decodeURIComponent(pair.shift()); - var value = pair.length > 1 ? pair.join('=') : pair[0]; - if (value != undefined) value = decodeURIComponent(value); - - if (key in hash) { - if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; - hash[key].push(value); - } - else hash[key] = value; - } - return hash; - }); - }, - - toArray: function() { - return this.split(''); - }, - - succ: function() { - return this.slice(0, this.length - 1) + - String.fromCharCode(this.charCodeAt(this.length - 1) + 1); - }, - - times: function(count) { - return count < 1 ? '' : new Array(count + 1).join(this); - }, - - camelize: function() { - var parts = this.split('-'), len = parts.length; - if (len == 1) return parts[0]; - - var camelized = this.charAt(0) == '-' - ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) - : parts[0]; - - for (var i = 1; i < len; i++) - camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); - - return camelized; - }, - - capitalize: function() { - return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); - }, - - underscore: function() { - return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); - }, - - dasherize: function() { - return this.gsub(/_/,'-'); - }, - - inspect: function(useDoubleQuotes) { - var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { - var character = String.specialChar[match[0]]; - return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); - }); - if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; - return "'" + escapedString.replace(/'/g, '\\\'') + "'"; - }, - - toJSON: function() { - return this.inspect(true); - }, - - unfilterJSON: function(filter) { - return this.sub(filter || Prototype.JSONFilter, '#{1}'); - }, - - isJSON: function() { - var str = this; - if (str.blank()) return false; - str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); - return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); - }, - - evalJSON: function(sanitize) { - var json = this.unfilterJSON(); - try { - if (!sanitize || json.isJSON()) return eval('(' + json + ')'); - } catch (e) { } - throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); - }, - - include: function(pattern) { - return this.indexOf(pattern) > -1; - }, - - startsWith: function(pattern) { - return this.indexOf(pattern) === 0; - }, - - endsWith: function(pattern) { - var d = this.length - pattern.length; - return d >= 0 && this.lastIndexOf(pattern) === d; - }, - - empty: function() { - return this == ''; - }, - - blank: function() { - return /^\s*$/.test(this); - }, - - interpolate: function(object, pattern) { - return new Template(this, pattern).evaluate(object); - } -}); - -if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { - escapeHTML: function() { - return this.replace(/&/g,'&').replace(//g,'>'); - }, - unescapeHTML: function() { - return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); - } -}); - -String.prototype.gsub.prepareReplacement = function(replacement) { - if (Object.isFunction(replacement)) return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -}; - -String.prototype.parseQuery = String.prototype.toQueryParams; - -Object.extend(String.prototype.escapeHTML, { - div: document.createElement('div'), - text: document.createTextNode('') -}); - -with (String.prototype.escapeHTML) div.appendChild(text); - -var Template = Class.create({ - initialize: function(template, pattern) { - this.template = template.toString(); - this.pattern = pattern || Template.Pattern; - }, - - evaluate: function(object) { - if (Object.isFunction(object.toTemplateReplacements)) - object = object.toTemplateReplacements(); - - return this.template.gsub(this.pattern, function(match) { - if (object == null) return ''; - - var before = match[1] || ''; - if (before == '\\') return match[2]; - - var ctx = object, expr = match[3]; - var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; - match = pattern.exec(expr); - if (match == null) return before; - - while (match != null) { - var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; - ctx = ctx[comp]; - if (null == ctx || '' == match[3]) break; - expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); - match = pattern.exec(expr); - } - - return before + String.interpret(ctx); - }); - } -}); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; - -var $break = { }; - -var Enumerable = { - each: function(iterator, context) { - var index = 0; - iterator = iterator.bind(context); - try { - this._each(function(value) { - iterator(value, index++); - }); - } catch (e) { - if (e != $break) throw e; - } - return this; - }, - - eachSlice: function(number, iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var index = -number, slices = [], array = this.toArray(); - while ((index += number) < array.length) - slices.push(array.slice(index, index+number)); - return slices.collect(iterator, context); - }, - - all: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result = true; - this.each(function(value, index) { - result = result && !!iterator(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result = false; - this.each(function(value, index) { - if (result = !!iterator(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function(iterator, context) { - iterator = iterator.bind(context); - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator, context) { - iterator = iterator.bind(context); - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(filter, iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var results = []; - - if (Object.isString(filter)) - filter = new RegExp(filter); - - this.each(function(value, index) { - if (filter.match(value)) - results.push(iterator(value, index)); - }); - return results; - }, - - include: function(object) { - if (Object.isFunction(this.indexOf)) - if (this.indexOf(object) != -1) return true; - - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inGroupsOf: function(number, fillWith) { - fillWith = Object.isUndefined(fillWith) ? null : fillWith; - return this.eachSlice(number, function(slice) { - while(slice.length < number) slice.push(fillWith); - return slice; - }); - }, - - inject: function(memo, iterator, context) { - iterator = iterator.bind(context); - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.map(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result; - this.each(function(value, index) { - value = iterator(value, index); - if (result == null || value >= result) - result = value; - }); - return result; - }, - - min: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result; - this.each(function(value, index) { - value = iterator(value, index); - if (result == null || value < result) - result = value; - }); - return result; - }, - - partition: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var trues = [], falses = []; - this.each(function(value, index) { - (iterator(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator, context) { - iterator = iterator.bind(context); - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator, context) { - iterator = iterator.bind(context); - return this.map(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.map(); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (Object.isFunction(args.last())) - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - return iterator(collections.pluck(index)); - }); - }, - - size: function() { - return this.toArray().length; - }, - - inspect: function() { - return '#'; - } -}; - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - filter: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray, - every: Enumerable.all, - some: Enumerable.any -}); -function $A(iterable) { - if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; -} - -if (Prototype.Browser.WebKit) { - $A = function(iterable) { - if (!iterable) return []; - if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && - iterable.toArray) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; - }; -} - -Array.from = $A; - -Object.extend(Array.prototype, Enumerable); - -if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0, length = this.length; i < length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(Object.isArray(value) ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - reduce: function() { - return this.length > 1 ? this : this[0]; - }, - - uniq: function(sorted) { - return this.inject([], function(array, value, index) { - if (0 == index || (sorted ? array.last() != value : !array.include(value))) - array.push(value); - return array; - }); - }, - - intersect: function(array) { - return this.uniq().findAll(function(item) { - return array.detect(function(value) { return item === value }); - }); - }, - - clone: function() { - return [].concat(this); - }, - - size: function() { - return this.length; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - }, - - toJSON: function() { - var results = []; - this.each(function(object) { - var value = Object.toJSON(object); - if (!Object.isUndefined(value)) results.push(value); - }); - return '[' + results.join(', ') + ']'; - } -}); - -// use native browser JS 1.6 implementation if available -if (Object.isFunction(Array.prototype.forEach)) - Array.prototype._each = Array.prototype.forEach; - -if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { - i || (i = 0); - var length = this.length; - if (i < 0) i = length + i; - for (; i < length; i++) - if (this[i] === item) return i; - return -1; -}; - -if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { - i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; - var n = this.slice(0, i).reverse().indexOf(item); - return (n < 0) ? n : i - n - 1; -}; - -Array.prototype.toArray = Array.prototype.clone; - -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} - -if (Prototype.Browser.Opera){ - Array.prototype.concat = function() { - var array = []; - for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); - for (var i = 0, length = arguments.length; i < length; i++) { - if (Object.isArray(arguments[i])) { - for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) - array.push(arguments[i][j]); - } else { - array.push(arguments[i]); - } - } - return array; - }; -} -Object.extend(Number.prototype, { - toColorPart: function() { - return this.toPaddedString(2, 16); - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - }, - - toPaddedString: function(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - }, - - toJSON: function() { - return isFinite(this) ? this.toString() : 'null'; - } -}); - -$w('abs round ceil floor').each(function(method){ - Number.prototype[method] = Math[method].methodize(); -}); -function $H(object) { - return new Hash(object); -}; - -var Hash = Class.create(Enumerable, (function() { - - function toQueryPair(key, value) { - if (Object.isUndefined(value)) return key; - return key + '=' + encodeURIComponent(String.interpret(value)); - } - - return { - initialize: function(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - }, - - _each: function(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - set: function(key, value) { - return this._object[key] = value; - }, - - get: function(key) { - return this._object[key]; - }, - - unset: function(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - }, - - toObject: function() { - return Object.clone(this._object); - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - index: function(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - }, - - merge: function(object) { - return this.clone().update(object); - }, - - update: function(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return values.map(toQueryPair.curry(key)).join('&'); - } - return toQueryPair(key, values); - }).join('&'); - }, - - inspect: function() { - return '#'; - }, - - toJSON: function() { - return Object.toJSON(this.toObject()); - }, - - clone: function() { - return new Hash(this); - } - } -})()); - -Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; -Hash.from = $H; -var ObjectRange = Class.create(Enumerable, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - while (this.include(value)) { - iterator(value); - value = value.succ(); - } - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -}; - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new XMLHttpRequest()}, - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')} - ) || false; - }, - - activeRequestCount: 0 -}; - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responder) { - if (!this.include(responder)) - this.responders.push(responder); - }, - - unregister: function(responder) { - this.responders = this.responders.without(responder); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (Object.isFunction(responder[callback])) { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) { } - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { Ajax.activeRequestCount++ }, - onComplete: function() { Ajax.activeRequestCount-- } -}); - -Ajax.Base = Class.create({ - initialize: function(options) { - this.options = { - method: 'post', - asynchronous: true, - contentType: 'application/x-www-form-urlencoded', - encoding: 'UTF-8', - parameters: '', - evalJSON: true, - evalJS: true - }; - Object.extend(this.options, options || { }); - - this.options.method = this.options.method.toLowerCase(); - - if (Object.isString(this.options.parameters)) - this.options.parameters = this.options.parameters.toQueryParams(); - else if (Object.isHash(this.options.parameters)) - this.options.parameters = this.options.parameters.toObject(); - } -}); - -Ajax.Request = Class.create(Ajax.Base, { - _complete: false, - - initialize: function($super, url, options) { - $super(options); - this.transport = Ajax.getTransport(); - this.request(url); - }, - - request: function(url) { - this.url = url; - this.method = this.options.method; - var params = Object.clone(this.options.parameters); - - if (!['get', 'post'].include(this.method)) { - // simulate other verbs over post - params['_method'] = this.method; - this.method = 'post'; - } - - this.parameters = params; - - if (params = Object.toQueryString(params)) { - // when GET, append parameters to URL - if (this.method == 'get') - this.url += (this.url.include('?') ? '&' : '?') + params; - else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - params += '&_='; - } - - try { - var response = new Ajax.Response(this); - if (this.options.onCreate) this.options.onCreate(response); - Ajax.Responders.dispatch('onCreate', this, response); - - this.transport.open(this.method.toUpperCase(), this.url, - this.options.asynchronous); - - if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); - - this.transport.onreadystatechange = this.onStateChange.bind(this); - this.setRequestHeaders(); - - this.body = this.method == 'post' ? (this.options.postBody || params) : null; - this.transport.send(this.body); - - /* Force Firefox to handle ready state 4 for synchronous requests */ - if (!this.options.asynchronous && this.transport.overrideMimeType) - this.onStateChange(); - - } - catch (e) { - this.dispatchException(e); - } - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState > 1 && !((readyState == 4) && this._complete)) - this.respondToReadyState(this.transport.readyState); - }, - - setRequestHeaders: function() { - var headers = { - 'X-Requested-With': 'XMLHttpRequest', - 'X-Prototype-Version': Prototype.Version, - 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' - }; - - if (this.method == 'post') { - headers['Content-type'] = this.options.contentType + - (this.options.encoding ? '; charset=' + this.options.encoding : ''); - - /* Force "Connection: close" for older Mozilla browsers to work - * around a bug where XMLHttpRequest sends an incorrect - * Content-length header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType && - (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) - headers['Connection'] = 'close'; - } - - // user-defined headers - if (typeof this.options.requestHeaders == 'object') { - var extras = this.options.requestHeaders; - - if (Object.isFunction(extras.push)) - for (var i = 0, length = extras.length; i < length; i += 2) - headers[extras[i]] = extras[i+1]; - else - $H(extras).each(function(pair) { headers[pair.key] = pair.value }); - } - - for (var name in headers) - this.transport.setRequestHeader(name, headers[name]); - }, - - success: function() { - var status = this.getStatus(); - return !status || (status >= 200 && status < 300); - }, - - getStatus: function() { - try { - return this.transport.status || 0; - } catch (e) { return 0 } - }, - - respondToReadyState: function(readyState) { - var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); - - if (state == 'Complete') { - try { - this._complete = true; - (this.options['on' + response.status] - || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - var contentType = response.getHeader('Content-type'); - if (this.options.evalJS == 'force' - || (this.options.evalJS && this.isSameOrigin() && contentType - && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) - this.evalResponse(); - } - - try { - (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); - Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - if (state == 'Complete') { - // avoid memory leak in MSIE: clean up - this.transport.onreadystatechange = Prototype.emptyFunction; - } - }, - - isSameOrigin: function() { - var m = this.url.match(/^\s*https?:\/\/[^\/]*/); - return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ - protocol: location.protocol, - domain: document.domain, - port: location.port ? ':' + location.port : '' - })); - }, - - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name) || null; - } catch (e) { return null } - }, - - evalResponse: function() { - try { - return eval((this.transport.responseText || '').unfilterJSON()); - } catch (e) { - this.dispatchException(e); - } - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Response = Class.create({ - initialize: function(request){ - this.request = request; - var transport = this.transport = request.transport, - readyState = this.readyState = transport.readyState; - - if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { - this.status = this.getStatus(); - this.statusText = this.getStatusText(); - this.responseText = String.interpret(transport.responseText); - this.headerJSON = this._getHeaderJSON(); - } - - if(readyState == 4) { - var xml = transport.responseXML; - this.responseXML = Object.isUndefined(xml) ? null : xml; - this.responseJSON = this._getResponseJSON(); - } - }, - - status: 0, - statusText: '', - - getStatus: Ajax.Request.prototype.getStatus, - - getStatusText: function() { - try { - return this.transport.statusText || ''; - } catch (e) { return '' } - }, - - getHeader: Ajax.Request.prototype.getHeader, - - getAllHeaders: function() { - try { - return this.getAllResponseHeaders(); - } catch (e) { return null } - }, - - getResponseHeader: function(name) { - return this.transport.getResponseHeader(name); - }, - - getAllResponseHeaders: function() { - return this.transport.getAllResponseHeaders(); - }, - - _getHeaderJSON: function() { - var json = this.getHeader('X-JSON'); - if (!json) return null; - json = decodeURIComponent(escape(json)); - try { - return json.evalJSON(this.request.options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - }, - - _getResponseJSON: function() { - var options = this.request.options; - if (!options.evalJSON || (options.evalJSON != 'force' && - !(this.getHeader('Content-type') || '').include('application/json')) || - this.responseText.blank()) - return null; - try { - return this.responseText.evalJSON(options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - } -}); - -Ajax.Updater = Class.create(Ajax.Request, { - initialize: function($super, container, url, options) { - this.container = { - success: (container.success || container), - failure: (container.failure || (container.success ? null : container)) - }; - - options = Object.clone(options); - var onComplete = options.onComplete; - options.onComplete = (function(response, json) { - this.updateContent(response.responseText); - if (Object.isFunction(onComplete)) onComplete(response, json); - }).bind(this); - - $super(url, options); - }, - - updateContent: function(responseText) { - var receiver = this.container[this.success() ? 'success' : 'failure'], - options = this.options; - - if (!options.evalScripts) responseText = responseText.stripScripts(); - - if (receiver = $(receiver)) { - if (options.insertion) { - if (Object.isString(options.insertion)) { - var insertion = { }; insertion[options.insertion] = responseText; - receiver.insert(insertion); - } - else options.insertion(receiver, responseText); - } - else receiver.update(responseText); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { - initialize: function($super, container, url, options) { - $super(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = { }; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.options.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(response) { - if (this.options.decay) { - this.decay = (response.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = response.responseText; - } - this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -function $(element) { - if (arguments.length > 1) { - for (var i = 0, elements = [], length = arguments.length; i < length; i++) - elements.push($(arguments[i])); - return elements; - } - if (Object.isString(element)) - element = document.getElementById(element); - return Element.extend(element); -} - -if (Prototype.BrowserFeatures.XPath) { - document._getElementsByXPath = function(expression, parentElement) { - var results = []; - var query = document.evaluate(expression, $(parentElement) || document, - null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - for (var i = 0, length = query.snapshotLength; i < length; i++) - results.push(Element.extend(query.snapshotItem(i))); - return results; - }; -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Node) var Node = { }; - -if (!Node.ELEMENT_NODE) { - // DOM level 2 ECMAScript Language Binding - Object.extend(Node, { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE: 12 - }); -} - -(function() { - var element = this.Element; - this.Element = function(tagName, attributes) { - attributes = attributes || { }; - tagName = tagName.toLowerCase(); - var cache = Element.cache; - if (Prototype.Browser.IE && attributes.name) { - tagName = '<' + tagName + ' name="' + attributes.name + '">'; - delete attributes.name; - return Element.writeAttribute(document.createElement(tagName), attributes); - } - if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); - return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); - }; - Object.extend(this.Element, element || { }); -}).call(window); - -Element.cache = { }; - -Element.Methods = { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function(element) { - element = $(element); - Element[Element.visible(element) ? 'hide' : 'show'](element); - return element; - }, - - hide: function(element) { - $(element).style.display = 'none'; - return element; - }, - - show: function(element) { - $(element).style.display = ''; - return element; - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - return element; - }, - - update: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - content = Object.toHTML(content); - element.innerHTML = content.stripScripts(); - content.evalScripts.bind(content).defer(); - return element; - }, - - replace: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - else if (!Object.isElement(content)) { - content = Object.toHTML(content); - var range = element.ownerDocument.createRange(); - range.selectNode(element); - content.evalScripts.bind(content).defer(); - content = range.createContextualFragment(content.stripScripts()); - } - element.parentNode.replaceChild(content, element); - return element; - }, - - insert: function(element, insertions) { - element = $(element); - - if (Object.isString(insertions) || Object.isNumber(insertions) || - Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = {bottom:insertions}; - - var content, insert, tagName, childNodes; - - for (var position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - insert = Element._insertionTranslations[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - insert(element, content); - continue; - } - - content = Object.toHTML(content); - - tagName = ((position == 'before' || position == 'after') - ? element.parentNode : element).tagName.toUpperCase(); - - childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - - if (position == 'top' || position == 'after') childNodes.reverse(); - childNodes.each(insert.curry(element)); - - content.evalScripts.bind(content).defer(); - } - - return element; - }, - - wrap: function(element, wrapper, attributes) { - element = $(element); - if (Object.isElement(wrapper)) - $(wrapper).writeAttribute(attributes || { }); - else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); - else wrapper = new Element('div', wrapper); - if (element.parentNode) - element.parentNode.replaceChild(wrapper, element); - wrapper.appendChild(element); - return wrapper; - }, - - inspect: function(element) { - element = $(element); - var result = '<' + element.tagName.toLowerCase(); - $H({'id': 'id', 'className': 'class'}).each(function(pair) { - var property = pair.first(), attribute = pair.last(); - var value = (element[property] || '').toString(); - if (value) result += ' ' + attribute + '=' + value.inspect(true); - }); - return result + '>'; - }, - - recursivelyCollect: function(element, property) { - element = $(element); - var elements = []; - while (element = element[property]) - if (element.nodeType == 1) - elements.push(Element.extend(element)); - return elements; - }, - - ancestors: function(element) { - return $(element).recursivelyCollect('parentNode'); - }, - - descendants: function(element) { - return $(element).select("*"); - }, - - firstDescendant: function(element) { - element = $(element).firstChild; - while (element && element.nodeType != 1) element = element.nextSibling; - return $(element); - }, - - immediateDescendants: function(element) { - if (!(element = $(element).firstChild)) return []; - while (element && element.nodeType != 1) element = element.nextSibling; - if (element) return [element].concat($(element).nextSiblings()); - return []; - }, - - previousSiblings: function(element) { - return $(element).recursivelyCollect('previousSibling'); - }, - - nextSiblings: function(element) { - return $(element).recursivelyCollect('nextSibling'); - }, - - siblings: function(element) { - element = $(element); - return element.previousSiblings().reverse().concat(element.nextSiblings()); - }, - - match: function(element, selector) { - if (Object.isString(selector)) - selector = new Selector(selector); - return selector.match($(element)); - }, - - up: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(element.parentNode); - var ancestors = element.ancestors(); - return Object.isNumber(expression) ? ancestors[expression] : - Selector.findElement(ancestors, expression, index); - }, - - down: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - return Object.isNumber(expression) ? element.descendants()[expression] : - element.select(expression)[index || 0]; - }, - - previous: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); - var previousSiblings = element.previousSiblings(); - return Object.isNumber(expression) ? previousSiblings[expression] : - Selector.findElement(previousSiblings, expression, index); - }, - - next: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); - var nextSiblings = element.nextSiblings(); - return Object.isNumber(expression) ? nextSiblings[expression] : - Selector.findElement(nextSiblings, expression, index); - }, - - select: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element, args); - }, - - adjacent: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element.parentNode, args).without(element); - }, - - identify: function(element) { - element = $(element); - var id = element.readAttribute('id'), self = arguments.callee; - if (id) return id; - do { id = 'anonymous_element_' + self.counter++ } while ($(id)); - element.writeAttribute('id', id); - return id; - }, - - readAttribute: function(element, name) { - element = $(element); - if (Prototype.Browser.IE) { - var t = Element._attributeTranslations.read; - if (t.values[name]) return t.values[name](element, name); - if (t.names[name]) name = t.names[name]; - if (name.include(':')) { - return (!element.attributes || !element.attributes[name]) ? null : - element.attributes[name].value; - } - } - return element.getAttribute(name); - }, - - writeAttribute: function(element, name, value) { - element = $(element); - var attributes = { }, t = Element._attributeTranslations.write; - - if (typeof name == 'object') attributes = name; - else attributes[name] = Object.isUndefined(value) ? true : value; - - for (var attr in attributes) { - name = t.names[attr] || attr; - value = attributes[attr]; - if (t.values[attr]) name = t.values[attr](element, value); - if (value === false || value === null) - element.removeAttribute(name); - else if (value === true) - element.setAttribute(name, name); - else element.setAttribute(name, value); - } - return element; - }, - - getHeight: function(element) { - return $(element).getDimensions().height; - }, - - getWidth: function(element) { - return $(element).getDimensions().width; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - var elementClassName = element.className; - return (elementClassName.length > 0 && (elementClassName == className || - new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - if (!element.hasClassName(className)) - element.className += (element.className ? ' ' : '') + className; - return element; - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - element.className = element.className.replace( - new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); - return element; - }, - - toggleClassName: function(element, className) { - if (!(element = $(element))) return; - return element[element.hasClassName(className) ? - 'removeClassName' : 'addClassName'](className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - var node = element.firstChild; - while (node) { - var nextNode = node.nextSibling; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - element.removeChild(node); - node = nextNode; - } - return element; - }, - - empty: function(element) { - return $(element).innerHTML.blank(); - }, - - descendantOf: function(element, ancestor) { - element = $(element), ancestor = $(ancestor); - var originalAncestor = ancestor; - - if (element.compareDocumentPosition) - return (element.compareDocumentPosition(ancestor) & 8) === 8; - - if (element.sourceIndex && !Prototype.Browser.Opera) { - var e = element.sourceIndex, a = ancestor.sourceIndex, - nextAncestor = ancestor.nextSibling; - if (!nextAncestor) { - do { ancestor = ancestor.parentNode; } - while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); - } - if (nextAncestor && nextAncestor.sourceIndex) - return (e > a && e < nextAncestor.sourceIndex); - } - - while (element = element.parentNode) - if (element == originalAncestor) return true; - return false; - }, - - scrollTo: function(element) { - element = $(element); - var pos = element.cumulativeOffset(); - window.scrollTo(pos[0], pos[1]); - return element; - }, - - getStyle: function(element, style) { - element = $(element); - style = style == 'float' ? 'cssFloat' : style.camelize(); - var value = element.style[style]; - if (!value) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css[style] : null; - } - if (style == 'opacity') return value ? parseFloat(value) : 1.0; - return value == 'auto' ? null : value; - }, - - getOpacity: function(element) { - return $(element).getStyle('opacity'); - }, - - setStyle: function(element, styles) { - element = $(element); - var elementStyle = element.style, match; - if (Object.isString(styles)) { - element.style.cssText += ';' + styles; - return styles.include('opacity') ? - element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; - } - for (var property in styles) - if (property == 'opacity') element.setOpacity(styles[property]); - else - elementStyle[(property == 'float' || property == 'cssFloat') ? - (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : - property] = styles[property]; - - return element; - }, - - setOpacity: function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - return element; - }, - - getDimensions: function(element) { - element = $(element); - var display = $(element).getStyle('display'); - if (display != 'none' && display != null) // Safari bug - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - var originalDisplay = els.display; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = 'block'; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = originalDisplay; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - return element; - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - return element; - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return element; - element._overflow = Element.getStyle(element, 'overflow') || 'auto'; - if (element._overflow !== 'hidden') - element.style.overflow = 'hidden'; - return element; - }, - - undoClipping: function(element) { - element = $(element); - if (!element._overflow) return element; - element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; - element._overflow = null; - return element; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - if (element.tagName == 'BODY') break; - var p = Element.getStyle(element, 'position'); - if (p !== 'static') break; - } - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - absolutize: function(element) { - element = $(element); - if (element.getStyle('position') == 'absolute') return; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - var offsets = element.positionedOffset(); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.width = width + 'px'; - element.style.height = height + 'px'; - return element; - }, - - relativize: function(element) { - element = $(element); - if (element.getStyle('position') == 'relative') return; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - return element; - }, - - cumulativeScrollOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - getOffsetParent: function(element) { - if (element.offsetParent) return $(element.offsetParent); - if (element == document.body) return $(element); - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return $(element); - - return $(document.body); - }, - - viewportOffset: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent == document.body && - Element.getStyle(element, 'position') == 'absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - if (!Prototype.Browser.Opera || element.tagName == 'BODY') { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } - } while (element = element.parentNode); - - return Element._returnOffset(valueL, valueT); - }, - - clonePosition: function(element, source) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || { }); - - // find page position of source - source = $(source); - var p = source.viewportOffset(); - - // find coordinate system to use - element = $(element); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(element, 'position') == 'absolute') { - parent = element.getOffsetParent(); - delta = parent.viewportOffset(); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if (options.setWidth) element.style.width = source.offsetWidth + 'px'; - if (options.setHeight) element.style.height = source.offsetHeight + 'px'; - return element; - } -}; - -Element.Methods.identify.counter = 1; - -Object.extend(Element.Methods, { - getElementsBySelector: Element.Methods.select, - childElements: Element.Methods.immediateDescendants -}); - -Element._attributeTranslations = { - write: { - names: { - className: 'class', - htmlFor: 'for' - }, - values: { } - } -}; - -if (Prototype.Browser.Opera) { - Element.Methods.getStyle = Element.Methods.getStyle.wrap( - function(proceed, element, style) { - switch (style) { - case 'left': case 'top': case 'right': case 'bottom': - if (proceed(element, 'position') === 'static') return null; - case 'height': case 'width': - // returns '0px' for hidden elements; we want it to return null - if (!Element.visible(element)) return null; - - // returns the border-box dimensions rather than the content-box - // dimensions, so we subtract padding and borders from the value - var dim = parseInt(proceed(element, style), 10); - - if (dim !== element['offset' + style.capitalize()]) - return dim + 'px'; - - var properties; - if (style === 'height') { - properties = ['border-top-width', 'padding-top', - 'padding-bottom', 'border-bottom-width']; - } - else { - properties = ['border-left-width', 'padding-left', - 'padding-right', 'border-right-width']; - } - return properties.inject(dim, function(memo, property) { - var val = proceed(element, property); - return val === null ? memo : memo - parseInt(val, 10); - }) + 'px'; - default: return proceed(element, style); - } - } - ); - - Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( - function(proceed, element, attribute) { - if (attribute === 'title') return element.title; - return proceed(element, attribute); - } - ); -} - -else if (Prototype.Browser.IE) { - // IE doesn't report offsets correctly for static elements, so we change them - // to "relative" to get the values, then change them back. - Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( - function(proceed, element) { - element = $(element); - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - - $w('positionedOffset viewportOffset').each(function(method) { - Element.Methods[method] = Element.Methods[method].wrap( - function(proceed, element) { - element = $(element); - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - // Trigger hasLayout on the offset parent so that IE6 reports - // accurate offsetTop and offsetLeft values for position: fixed. - var offsetParent = element.getOffsetParent(); - if (offsetParent && offsetParent.getStyle('position') === 'fixed') - offsetParent.setStyle({ zoom: 1 }); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - }); - - Element.Methods.getStyle = function(element, style) { - element = $(element); - style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); - var value = element.style[style]; - if (!value && element.currentStyle) value = element.currentStyle[style]; - - if (style == 'opacity') { - if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) - if (value[1]) return parseFloat(value[1]) / 100; - return 1.0; - } - - if (value == 'auto') { - if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) - return element['offset' + style.capitalize()] + 'px'; - return null; - } - return value; - }; - - Element.Methods.setOpacity = function(element, value) { - function stripAlpha(filter){ - return filter.replace(/alpha\([^\)]*\)/gi,''); - } - element = $(element); - var currentStyle = element.currentStyle; - if ((currentStyle && !currentStyle.hasLayout) || - (!currentStyle && element.style.zoom == 'normal')) - element.style.zoom = 1; - - var filter = element.getStyle('filter'), style = element.style; - if (value == 1 || value === '') { - (filter = stripAlpha(filter)) ? - style.filter = filter : style.removeAttribute('filter'); - return element; - } else if (value < 0.00001) value = 0; - style.filter = stripAlpha(filter) + - 'alpha(opacity=' + (value * 100) + ')'; - return element; - }; - - Element._attributeTranslations = { - read: { - names: { - 'class': 'className', - 'for': 'htmlFor' - }, - values: { - _getAttr: function(element, attribute) { - return element.getAttribute(attribute, 2); - }, - _getAttrNode: function(element, attribute) { - var node = element.getAttributeNode(attribute); - return node ? node.value : ""; - }, - _getEv: function(element, attribute) { - attribute = element.getAttribute(attribute); - return attribute ? attribute.toString().slice(23, -2) : null; - }, - _flag: function(element, attribute) { - return $(element).hasAttribute(attribute) ? attribute : null; - }, - style: function(element) { - return element.style.cssText.toLowerCase(); - }, - title: function(element) { - return element.title; - } - } - } - }; - - Element._attributeTranslations.write = { - names: Object.extend({ - cellpadding: 'cellPadding', - cellspacing: 'cellSpacing' - }, Element._attributeTranslations.read.names), - values: { - checked: function(element, value) { - element.checked = !!value; - }, - - style: function(element, value) { - element.style.cssText = value ? value : ''; - } - } - }; - - Element._attributeTranslations.has = {}; - - $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + - 'encType maxLength readOnly longDesc').each(function(attr) { - Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; - Element._attributeTranslations.has[attr.toLowerCase()] = attr; - }); - - (function(v) { - Object.extend(v, { - href: v._getAttr, - src: v._getAttr, - type: v._getAttr, - action: v._getAttrNode, - disabled: v._flag, - checked: v._flag, - readonly: v._flag, - multiple: v._flag, - onload: v._getEv, - onunload: v._getEv, - onclick: v._getEv, - ondblclick: v._getEv, - onmousedown: v._getEv, - onmouseup: v._getEv, - onmouseover: v._getEv, - onmousemove: v._getEv, - onmouseout: v._getEv, - onfocus: v._getEv, - onblur: v._getEv, - onkeypress: v._getEv, - onkeydown: v._getEv, - onkeyup: v._getEv, - onsubmit: v._getEv, - onreset: v._getEv, - onselect: v._getEv, - onchange: v._getEv - }); - })(Element._attributeTranslations.read.values); -} - -else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1) ? 0.999999 : - (value === '') ? '' : (value < 0.00001) ? 0 : value; - return element; - }; -} - -else if (Prototype.Browser.WebKit) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - - if (value == 1) - if(element.tagName == 'IMG' && element.width) { - element.width++; element.width--; - } else try { - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch (e) { } - - return element; - }; - - // Safari returns margins on body which is incorrect if the child is absolutely - // positioned. For performance reasons, redefine Element#cumulativeOffset for - // KHTML/WebKit only. - Element.Methods.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return Element._returnOffset(valueL, valueT); - }; -} - -if (Prototype.Browser.IE || Prototype.Browser.Opera) { - // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements - Element.Methods.update = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - - content = Object.toHTML(content); - var tagName = element.tagName.toUpperCase(); - - if (tagName in Element._insertionTranslations.tags) { - $A(element.childNodes).each(function(node) { element.removeChild(node) }); - Element._getContentFromAnonymousElement(tagName, content.stripScripts()) - .each(function(node) { element.appendChild(node) }); - } - else element.innerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -if ('outerHTML' in document.createElement('div')) { - Element.Methods.replace = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - element.parentNode.replaceChild(content, element); - return element; - } - - content = Object.toHTML(content); - var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); - - if (Element._insertionTranslations.tags[tagName]) { - var nextSibling = element.next(); - var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - parent.removeChild(element); - if (nextSibling) - fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); - else - fragments.each(function(node) { parent.appendChild(node) }); - } - else element.outerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -Element._returnOffset = function(l, t) { - var result = [l, t]; - result.left = l; - result.top = t; - return result; -}; - -Element._getContentFromAnonymousElement = function(tagName, html) { - var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; - if (t) { - div.innerHTML = t[0] + html + t[1]; - t[2].times(function() { div = div.firstChild }); - } else div.innerHTML = html; - return $A(div.childNodes); -}; - -Element._insertionTranslations = { - before: function(element, node) { - element.parentNode.insertBefore(node, element); - }, - top: function(element, node) { - element.insertBefore(node, element.firstChild); - }, - bottom: function(element, node) { - element.appendChild(node); - }, - after: function(element, node) { - element.parentNode.insertBefore(node, element.nextSibling); - }, - tags: { - TABLE: ['', '
', 1], - TBODY: ['', '
', 2], - TR: ['', '
', 3], - TD: ['
', '
', 4], - SELECT: ['', 1] - } -}; - -(function() { - Object.extend(this.tags, { - THEAD: this.tags.TBODY, - TFOOT: this.tags.TBODY, - TH: this.tags.TD - }); -}).call(Element._insertionTranslations); - -Element.Methods.Simulated = { - hasAttribute: function(element, attribute) { - attribute = Element._attributeTranslations.has[attribute] || attribute; - var node = $(element).getAttributeNode(attribute); - return node && node.specified; - } -}; - -Element.Methods.ByTag = { }; - -Object.extend(Element, Element.Methods); - -if (!Prototype.BrowserFeatures.ElementExtensions && - document.createElement('div').__proto__) { - window.HTMLElement = { }; - window.HTMLElement.prototype = document.createElement('div').__proto__; - Prototype.BrowserFeatures.ElementExtensions = true; -} - -Element.extend = (function() { - if (Prototype.BrowserFeatures.SpecificElementExtensions) - return Prototype.K; - - var Methods = { }, ByTag = Element.Methods.ByTag; - - var extend = Object.extend(function(element) { - if (!element || element._extendedByPrototype || - element.nodeType != 1 || element == window) return element; - - var methods = Object.clone(Methods), - tagName = element.tagName, property, value; - - // extend methods for specific tags - if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); - - for (property in methods) { - value = methods[property]; - if (Object.isFunction(value) && !(property in element)) - element[property] = value.methodize(); - } - - element._extendedByPrototype = Prototype.emptyFunction; - return element; - - }, { - refresh: function() { - // extend methods for all tags (Safari doesn't need this) - if (!Prototype.BrowserFeatures.ElementExtensions) { - Object.extend(Methods, Element.Methods); - Object.extend(Methods, Element.Methods.Simulated); - } - } - }); - - extend.refresh(); - return extend; -})(); - -Element.hasAttribute = function(element, attribute) { - if (element.hasAttribute) return element.hasAttribute(attribute); - return Element.Methods.Simulated.hasAttribute(element, attribute); -}; - -Element.addMethods = function(methods) { - var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; - - if (!methods) { - Object.extend(Form, Form.Methods); - Object.extend(Form.Element, Form.Element.Methods); - Object.extend(Element.Methods.ByTag, { - "FORM": Object.clone(Form.Methods), - "INPUT": Object.clone(Form.Element.Methods), - "SELECT": Object.clone(Form.Element.Methods), - "TEXTAREA": Object.clone(Form.Element.Methods) - }); - } - - if (arguments.length == 2) { - var tagName = methods; - methods = arguments[1]; - } - - if (!tagName) Object.extend(Element.Methods, methods || { }); - else { - if (Object.isArray(tagName)) tagName.each(extend); - else extend(tagName); - } - - function extend(tagName) { - tagName = tagName.toUpperCase(); - if (!Element.Methods.ByTag[tagName]) - Element.Methods.ByTag[tagName] = { }; - Object.extend(Element.Methods.ByTag[tagName], methods); - } - - function copy(methods, destination, onlyIfAbsent) { - onlyIfAbsent = onlyIfAbsent || false; - for (var property in methods) { - var value = methods[property]; - if (!Object.isFunction(value)) continue; - if (!onlyIfAbsent || !(property in destination)) - destination[property] = value.methodize(); - } - } - - function findDOMClass(tagName) { - var klass; - var trans = { - "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", - "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", - "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", - "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", - "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": - "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": - "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": - "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": - "FrameSet", "IFRAME": "IFrame" - }; - if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName.capitalize() + 'Element'; - if (window[klass]) return window[klass]; - - window[klass] = { }; - window[klass].prototype = document.createElement(tagName).__proto__; - return window[klass]; - } - - if (F.ElementExtensions) { - copy(Element.Methods, HTMLElement.prototype); - copy(Element.Methods.Simulated, HTMLElement.prototype, true); - } - - if (F.SpecificElementExtensions) { - for (var tag in Element.Methods.ByTag) { - var klass = findDOMClass(tag); - if (Object.isUndefined(klass)) continue; - copy(T[tag], klass.prototype); - } - } - - Object.extend(Element, Element.Methods); - delete Element.ByTag; - - if (Element.extend.refresh) Element.extend.refresh(); - Element.cache = { }; -}; - -document.viewport = { - getDimensions: function() { - var dimensions = { }; - var B = Prototype.Browser; - $w('width height').each(function(d) { - var D = d.capitalize(); - dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] : - (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D]; - }); - return dimensions; - }, - - getWidth: function() { - return this.getDimensions().width; - }, - - getHeight: function() { - return this.getDimensions().height; - }, - - getScrollOffsets: function() { - return Element._returnOffset( - window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, - window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); - } -}; -/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, - * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style - * license. Please see http://www.yui-ext.com/ for more information. */ - -var Selector = Class.create({ - initialize: function(expression) { - this.expression = expression.strip(); - this.compileMatcher(); - }, - - shouldUseXPath: function() { - if (!Prototype.BrowserFeatures.XPath) return false; - - var e = this.expression; - - // Safari 3 chokes on :*-of-type and :empty - if (Prototype.Browser.WebKit && - (e.include("-of-type") || e.include(":empty"))) - return false; - - // XPath can't do namespaced attributes, nor can it read - // the "checked" property from DOM nodes - if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) - return false; - - return true; - }, - - compileMatcher: function() { - if (this.shouldUseXPath()) - return this.compileXPathMatcher(); - - var e = this.expression, ps = Selector.patterns, h = Selector.handlers, - c = Selector.criteria, le, p, m; - - if (Selector._cache[e]) { - this.matcher = Selector._cache[e]; - return; - } - - this.matcher = ["this.matcher = function(root) {", - "var r = root, h = Selector.handlers, c = false, n;"]; - - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : - new Template(c[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.matcher.push("return h.unique(n);\n}"); - eval(this.matcher.join('\n')); - Selector._cache[this.expression] = this.matcher; - }, - - compileXPathMatcher: function() { - var e = this.expression, ps = Selector.patterns, - x = Selector.xpath, le, m; - - if (Selector._cache[e]) { - this.xpath = Selector._cache[e]; return; - } - - this.matcher = ['.//*']; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - if (m = e.match(ps[i])) { - this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : - new Template(x[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.xpath = this.matcher.join(''); - Selector._cache[this.expression] = this.xpath; - }, - - findElements: function(root) { - root = root || document; - if (this.xpath) return document._getElementsByXPath(this.xpath, root); - return this.matcher(root); - }, - - match: function(element) { - this.tokens = []; - - var e = this.expression, ps = Selector.patterns, as = Selector.assertions; - var le, p, m; - - while (e && le !== e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - // use the Selector.assertions methods unless the selector - // is too complex. - if (as[i]) { - this.tokens.push([i, Object.clone(m)]); - e = e.replace(m[0], ''); - } else { - // reluctantly do a document-wide search - // and look for a match in the array - return this.findElements(document).include(element); - } - } - } - } - - var match = true, name, matches; - for (var i = 0, token; token = this.tokens[i]; i++) { - name = token[0], matches = token[1]; - if (!Selector.assertions[name](element, matches)) { - match = false; break; - } - } - - return match; - }, - - toString: function() { - return this.expression; - }, - - inspect: function() { - return "#"; - } -}); - -Object.extend(Selector, { - _cache: { }, - - xpath: { - descendant: "//*", - child: "/*", - adjacent: "/following-sibling::*[1]", - laterSibling: '/following-sibling::*', - tagName: function(m) { - if (m[1] == '*') return ''; - return "[local-name()='" + m[1].toLowerCase() + - "' or local-name()='" + m[1].toUpperCase() + "']"; - }, - className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", - id: "[@id='#{1}']", - attrPresence: function(m) { - m[1] = m[1].toLowerCase(); - return new Template("[@#{1}]").evaluate(m); - }, - attr: function(m) { - m[1] = m[1].toLowerCase(); - m[3] = m[5] || m[6]; - return new Template(Selector.xpath.operators[m[2]]).evaluate(m); - }, - pseudo: function(m) { - var h = Selector.xpath.pseudos[m[1]]; - if (!h) return ''; - if (Object.isFunction(h)) return h(m); - return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); - }, - operators: { - '=': "[@#{1}='#{3}']", - '!=': "[@#{1}!='#{3}']", - '^=': "[starts-with(@#{1}, '#{3}')]", - '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", - '*=': "[contains(@#{1}, '#{3}')]", - '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", - '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" - }, - pseudos: { - 'first-child': '[not(preceding-sibling::*)]', - 'last-child': '[not(following-sibling::*)]', - 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', - 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", - 'checked': "[@checked]", - 'disabled': "[@disabled]", - 'enabled': "[not(@disabled)]", - 'not': function(m) { - var e = m[6], p = Selector.patterns, - x = Selector.xpath, le, v; - - var exclusion = []; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in p) { - if (m = e.match(p[i])) { - v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); - exclusion.push("(" + v.substring(1, v.length - 1) + ")"); - e = e.replace(m[0], ''); - break; - } - } - } - return "[not(" + exclusion.join(" and ") + ")]"; - }, - 'nth-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); - }, - 'nth-last-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); - }, - 'nth-of-type': function(m) { - return Selector.xpath.pseudos.nth("position() ", m); - }, - 'nth-last-of-type': function(m) { - return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); - }, - 'first-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); - }, - 'last-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); - }, - 'only-of-type': function(m) { - var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); - }, - nth: function(fragment, m) { - var mm, formula = m[6], predicate; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - if (mm = formula.match(/^(\d+)$/)) // digit only - return '[' + fragment + "= " + mm[1] + ']'; - if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (mm[1] == "-") mm[1] = -1; - var a = mm[1] ? Number(mm[1]) : 1; - var b = mm[2] ? Number(mm[2]) : 0; - predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + - "((#{fragment} - #{b}) div #{a} >= 0)]"; - return new Template(predicate).evaluate({ - fragment: fragment, a: a, b: b }); - } - } - } - }, - - criteria: { - tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', - className: 'n = h.className(n, r, "#{1}", c); c = false;', - id: 'n = h.id(n, r, "#{1}", c); c = false;', - attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', - attr: function(m) { - m[3] = (m[5] || m[6]); - return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); - }, - pseudo: function(m) { - if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); - return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); - }, - descendant: 'c = "descendant";', - child: 'c = "child";', - adjacent: 'c = "adjacent";', - laterSibling: 'c = "laterSibling";' - }, - - patterns: { - // combinators must be listed first - // (and descendant needs to be last combinator) - laterSibling: /^\s*~\s*/, - child: /^\s*>\s*/, - adjacent: /^\s*\+\s*/, - descendant: /^\s/, - - // selectors follow - tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, - id: /^#([\w\-\*]+)(\b|$)/, - className: /^\.([\w\-\*]+)(\b|$)/, - pseudo: -/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, - attrPresence: /^\[([\w]+)\]/, - attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ - }, - - // for Selector.match and Element#match - assertions: { - tagName: function(element, matches) { - return matches[1].toUpperCase() == element.tagName.toUpperCase(); - }, - - className: function(element, matches) { - return Element.hasClassName(element, matches[1]); - }, - - id: function(element, matches) { - return element.id === matches[1]; - }, - - attrPresence: function(element, matches) { - return Element.hasAttribute(element, matches[1]); - }, - - attr: function(element, matches) { - var nodeValue = Element.readAttribute(element, matches[1]); - return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); - } - }, - - handlers: { - // UTILITY FUNCTIONS - // joins two collections - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - a.push(node); - return a; - }, - - // marks an array of nodes for counting - mark: function(nodes) { - var _true = Prototype.emptyFunction; - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = _true; - return nodes; - }, - - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = undefined; - return nodes; - }, - - // mark each child node with its position (for nth calls) - // "ofType" flag indicates whether we're indexing for nth-of-type - // rather than nth-child - index: function(parentNode, reverse, ofType) { - parentNode._countedByPrototype = Prototype.emptyFunction; - if (reverse) { - for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { - var node = nodes[i]; - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; - } - } else { - for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; - } - }, - - // filters out duplicates and extends all nodes - unique: function(nodes) { - if (nodes.length == 0) return nodes; - var results = [], n; - for (var i = 0, l = nodes.length; i < l; i++) - if (!(n = nodes[i])._countedByPrototype) { - n._countedByPrototype = Prototype.emptyFunction; - results.push(Element.extend(n)); - } - return Selector.handlers.unmark(results); - }, - - // COMBINATOR FUNCTIONS - descendant: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName('*')); - return results; - }, - - child: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) { - for (var j = 0, child; child = node.childNodes[j]; j++) - if (child.nodeType == 1 && child.tagName != '!') results.push(child); - } - return results; - }, - - adjacent: function(nodes) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - var next = this.nextElementSibling(node); - if (next) results.push(next); - } - return results; - }, - - laterSibling: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, Element.nextSiblings(node)); - return results; - }, - - nextElementSibling: function(node) { - while (node = node.nextSibling) - if (node.nodeType == 1) return node; - return null; - }, - - previousElementSibling: function(node) { - while (node = node.previousSibling) - if (node.nodeType == 1) return node; - return null; - }, - - // TOKEN FUNCTIONS - tagName: function(nodes, root, tagName, combinator) { - var uTagName = tagName.toUpperCase(); - var results = [], h = Selector.handlers; - if (nodes) { - if (combinator) { - // fastlane for ordinary descendant combinators - if (combinator == "descendant") { - for (var i = 0, node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName(tagName)); - return results; - } else nodes = this[combinator](nodes); - if (tagName == "*") return nodes; - } - for (var i = 0, node; node = nodes[i]; i++) - if (node.tagName.toUpperCase() === uTagName) results.push(node); - return results; - } else return root.getElementsByTagName(tagName); - }, - - id: function(nodes, root, id, combinator) { - var targetNode = $(id), h = Selector.handlers; - if (!targetNode) return []; - if (!nodes && root == document) return [targetNode]; - if (nodes) { - if (combinator) { - if (combinator == 'child') { - for (var i = 0, node; node = nodes[i]; i++) - if (targetNode.parentNode == node) return [targetNode]; - } else if (combinator == 'descendant') { - for (var i = 0, node; node = nodes[i]; i++) - if (Element.descendantOf(targetNode, node)) return [targetNode]; - } else if (combinator == 'adjacent') { - for (var i = 0, node; node = nodes[i]; i++) - if (Selector.handlers.previousElementSibling(targetNode) == node) - return [targetNode]; - } else nodes = h[combinator](nodes); - } - for (var i = 0, node; node = nodes[i]; i++) - if (node == targetNode) return [targetNode]; - return []; - } - return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; - }, - - className: function(nodes, root, className, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - return Selector.handlers.byClassName(nodes, root, className); - }, - - byClassName: function(nodes, root, className) { - if (!nodes) nodes = Selector.handlers.descendant([root]); - var needle = ' ' + className + ' '; - for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { - nodeClassName = node.className; - if (nodeClassName.length == 0) continue; - if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) - results.push(node); - } - return results; - }, - - attrPresence: function(nodes, root, attr, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - var results = []; - for (var i = 0, node; node = nodes[i]; i++) - if (Element.hasAttribute(node, attr)) results.push(node); - return results; - }, - - attr: function(nodes, root, attr, value, operator, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - var handler = Selector.operators[operator], results = []; - for (var i = 0, node; node = nodes[i]; i++) { - var nodeValue = Element.readAttribute(node, attr); - if (nodeValue === null) continue; - if (handler(nodeValue, value)) results.push(node); - } - return results; - }, - - pseudo: function(nodes, name, value, root, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - if (!nodes) nodes = root.getElementsByTagName("*"); - return Selector.pseudos[name](nodes, value, root); - } - }, - - pseudos: { - 'first-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.previousElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'last-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.nextElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'only-child': function(nodes, value, root) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) - results.push(node); - return results; - }, - 'nth-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root); - }, - 'nth-last-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true); - }, - 'nth-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, false, true); - }, - 'nth-last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true, true); - }, - 'first-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, false, true); - }, - 'last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, true, true); - }, - 'only-of-type': function(nodes, formula, root) { - var p = Selector.pseudos; - return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); - }, - - // handles the an+b logic - getIndices: function(a, b, total) { - if (a == 0) return b > 0 ? [b] : []; - return $R(1, total).inject([], function(memo, i) { - if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); - return memo; - }); - }, - - // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type - nth: function(nodes, formula, root, reverse, ofType) { - if (nodes.length == 0) return []; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - var h = Selector.handlers, results = [], indexed = [], m; - h.mark(nodes); - for (var i = 0, node; node = nodes[i]; i++) { - if (!node.parentNode._countedByPrototype) { - h.index(node.parentNode, reverse, ofType); - indexed.push(node.parentNode); - } - } - if (formula.match(/^\d+$/)) { // just a number - formula = Number(formula); - for (var i = 0, node; node = nodes[i]; i++) - if (node.nodeIndex == formula) results.push(node); - } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (m[1] == "-") m[1] = -1; - var a = m[1] ? Number(m[1]) : 1; - var b = m[2] ? Number(m[2]) : 0; - var indices = Selector.pseudos.getIndices(a, b, nodes.length); - for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { - for (var j = 0; j < l; j++) - if (node.nodeIndex == indices[j]) results.push(node); - } - } - h.unmark(nodes); - h.unmark(indexed); - return results; - }, - - 'empty': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - // IE treats comments as element nodes - if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; - results.push(node); - } - return results; - }, - - 'not': function(nodes, selector, root) { - var h = Selector.handlers, selectorType, m; - var exclusions = new Selector(selector).findElements(root); - h.mark(exclusions); - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node._countedByPrototype) results.push(node); - h.unmark(exclusions); - return results; - }, - - 'enabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node.disabled) results.push(node); - return results; - }, - - 'disabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.disabled) results.push(node); - return results; - }, - - 'checked': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.checked) results.push(node); - return results; - } - }, - - operators: { - '=': function(nv, v) { return nv == v; }, - '!=': function(nv, v) { return nv != v; }, - '^=': function(nv, v) { return nv.startsWith(v); }, - '$=': function(nv, v) { return nv.endsWith(v); }, - '*=': function(nv, v) { return nv.include(v); }, - '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, - '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } - }, - - split: function(expression) { - var expressions = []; - expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { - expressions.push(m[1].strip()); - }); - return expressions; - }, - - matchElements: function(elements, expression) { - var matches = $$(expression), h = Selector.handlers; - h.mark(matches); - for (var i = 0, results = [], element; element = elements[i]; i++) - if (element._countedByPrototype) results.push(element); - h.unmark(matches); - return results; - }, - - findElement: function(elements, expression, index) { - if (Object.isNumber(expression)) { - index = expression; expression = false; - } - return Selector.matchElements(elements, expression || '*')[index || 0]; - }, - - findChildElements: function(element, expressions) { - expressions = Selector.split(expressions.join(',')); - var results = [], h = Selector.handlers; - for (var i = 0, l = expressions.length, selector; i < l; i++) { - selector = new Selector(expressions[i].strip()); - h.concat(results, selector.findElements(element)); - } - return (l > 1) ? h.unique(results) : results; - } -}); - -if (Prototype.Browser.IE) { - Object.extend(Selector.handlers, { - // IE returns comment nodes on getElementsByTagName("*"). - // Filter them out. - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - if (node.tagName !== "!") a.push(node); - return a; - }, - - // IE improperly serializes _countedByPrototype in (inner|outer)HTML. - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node.removeAttribute('_countedByPrototype'); - return nodes; - } - }); -} - -function $$() { - return Selector.findChildElements(document, $A(arguments)); -} -var Form = { - reset: function(form) { - $(form).reset(); - return form; - }, - - serializeElements: function(elements, options) { - if (typeof options != 'object') options = { hash: !!options }; - else if (Object.isUndefined(options.hash)) options.hash = true; - var key, value, submitted = false, submit = options.submit; - - var data = elements.inject({ }, function(result, element) { - if (!element.disabled && element.name) { - key = element.name; value = $(element).getValue(); - if (value != null && (element.type != 'submit' || (!submitted && - submit !== false && (!submit || key == submit) && (submitted = true)))) { - if (key in result) { - // a key is already present; construct an array of values - if (!Object.isArray(result[key])) result[key] = [result[key]]; - result[key].push(value); - } - else result[key] = value; - } - } - return result; - }); - - return options.hash ? data : Object.toQueryString(data); - } -}; - -Form.Methods = { - serialize: function(form, options) { - return Form.serializeElements(Form.getElements(form), options); - }, - - getElements: function(form) { - return $A($(form).getElementsByTagName('*')).inject([], - function(elements, child) { - if (Form.Element.Serializers[child.tagName.toLowerCase()]) - elements.push(Element.extend(child)); - return elements; - } - ); - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) return $A(inputs).map(Element.extend); - - for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || (name && input.name != name)) - continue; - matchingInputs.push(Element.extend(input)); - } - - return matchingInputs; - }, - - disable: function(form) { - form = $(form); - Form.getElements(form).invoke('disable'); - return form; - }, - - enable: function(form) { - form = $(form); - Form.getElements(form).invoke('enable'); - return form; - }, - - findFirstElement: function(form) { - var elements = $(form).getElements().findAll(function(element) { - return 'hidden' != element.type && !element.disabled; - }); - var firstByIndex = elements.findAll(function(element) { - return element.hasAttribute('tabIndex') && element.tabIndex >= 0; - }).sortBy(function(element) { return element.tabIndex }).first(); - - return firstByIndex ? firstByIndex : elements.find(function(element) { - return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - form = $(form); - form.findFirstElement().activate(); - return form; - }, - - request: function(form, options) { - form = $(form), options = Object.clone(options || { }); - - var params = options.parameters, action = form.readAttribute('action') || ''; - if (action.blank()) action = window.location.href; - options.parameters = form.serialize(true); - - if (params) { - if (Object.isString(params)) params = params.toQueryParams(); - Object.extend(options.parameters, params); - } - - if (form.hasAttribute('method') && !options.method) - options.method = form.method; - - return new Ajax.Request(action, options); - } -}; - -/*--------------------------------------------------------------------------*/ - -Form.Element = { - focus: function(element) { - $(element).focus(); - return element; - }, - - select: function(element) { - $(element).select(); - return element; - } -}; - -Form.Element.Methods = { - serialize: function(element) { - element = $(element); - if (!element.disabled && element.name) { - var value = element.getValue(); - if (value != undefined) { - var pair = { }; - pair[element.name] = value; - return Object.toQueryString(pair); - } - } - return ''; - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - return Form.Element.Serializers[method](element); - }, - - setValue: function(element, value) { - element = $(element); - var method = element.tagName.toLowerCase(); - Form.Element.Serializers[method](element, value); - return element; - }, - - clear: function(element) { - $(element).value = ''; - return element; - }, - - present: function(element) { - return $(element).value != ''; - }, - - activate: function(element) { - element = $(element); - try { - element.focus(); - if (element.select && (element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type))) - element.select(); - } catch (e) { } - return element; - }, - - disable: function(element) { - element = $(element); - element.blur(); - element.disabled = true; - return element; - }, - - enable: function(element) { - element = $(element); - element.disabled = false; - return element; - } -}; - -/*--------------------------------------------------------------------------*/ - -var Field = Form.Element; -var $F = Form.Element.Methods.getValue; - -/*--------------------------------------------------------------------------*/ - -Form.Element.Serializers = { - input: function(element, value) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element, value); - default: - return Form.Element.Serializers.textarea(element, value); - } - }, - - inputSelector: function(element, value) { - if (Object.isUndefined(value)) return element.checked ? element.value : null; - else element.checked = !!value; - }, - - textarea: function(element, value) { - if (Object.isUndefined(value)) return element.value; - else element.value = value; - }, - - select: function(element, index) { - if (Object.isUndefined(index)) - return this[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - else { - var opt, value, single = !Object.isArray(index); - for (var i = 0, length = element.length; i < length; i++) { - opt = element.options[i]; - value = this.optionValue(opt); - if (single) { - if (value == index) { - opt.selected = true; - return; - } - } - else opt.selected = index.include(value); - } - } - }, - - selectOne: function(element) { - var index = element.selectedIndex; - return index >= 0 ? this.optionValue(element.options[index]) : null; - }, - - selectMany: function(element) { - var values, length = element.length; - if (!length) return null; - - for (var i = 0, values = []; i < length; i++) { - var opt = element.options[i]; - if (opt.selected) values.push(this.optionValue(opt)); - } - return values; - }, - - optionValue: function(opt) { - // extend element because hasAttribute may not be native - return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; - } -}; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = Class.create(PeriodicalExecuter, { - initialize: function($super, element, frequency, callback) { - $super(callback, frequency); - this.element = $(element); - this.lastValue = this.getValue(); - }, - - execute: function() { - var value = this.getValue(); - if (Object.isString(this.lastValue) && Object.isString(value) ? - this.lastValue != value : String(this.lastValue) != String(value)) { - this.callback(this.element, value); - this.lastValue = value; - } - } -}); - -Form.Element.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = Class.create({ - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - Form.getElements(this.element).each(this.registerCallback, this); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - default: - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -}); - -Form.Element.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) var Event = { }; - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - KEY_HOME: 36, - KEY_END: 35, - KEY_PAGEUP: 33, - KEY_PAGEDOWN: 34, - KEY_INSERT: 45, - - cache: { }, - - relatedTarget: function(event) { - var element; - switch(event.type) { - case 'mouseover': element = event.fromElement; break; - case 'mouseout': element = event.toElement; break; - default: return null; - } - return Element.extend(element); - } -}); - -Event.Methods = (function() { - var isButton; - - if (Prototype.Browser.IE) { - var buttonMap = { 0: 1, 1: 4, 2: 2 }; - isButton = function(event, code) { - return event.button == buttonMap[code]; - }; - - } else if (Prototype.Browser.WebKit) { - isButton = function(event, code) { - switch (code) { - case 0: return event.which == 1 && !event.metaKey; - case 1: return event.which == 1 && event.metaKey; - default: return false; - } - }; - - } else { - isButton = function(event, code) { - return event.which ? (event.which === code + 1) : (event.button === code); - }; - } - - return { - isLeftClick: function(event) { return isButton(event, 0) }, - isMiddleClick: function(event) { return isButton(event, 1) }, - isRightClick: function(event) { return isButton(event, 2) }, - - element: function(event) { - var node = Event.extend(event).target; - return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); - }, - - findElement: function(event, expression) { - var element = Event.element(event); - if (!expression) return element; - var elements = [element].concat(element.ancestors()); - return Selector.findElement(elements, expression, 0); - }, - - pointer: function(event) { - return { - x: event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)), - y: event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)) - }; - }, - - pointerX: function(event) { return Event.pointer(event).x }, - pointerY: function(event) { return Event.pointer(event).y }, - - stop: function(event) { - Event.extend(event); - event.preventDefault(); - event.stopPropagation(); - event.stopped = true; - } - }; -})(); - -Event.extend = (function() { - var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { - m[name] = Event.Methods[name].methodize(); - return m; - }); - - if (Prototype.Browser.IE) { - Object.extend(methods, { - stopPropagation: function() { this.cancelBubble = true }, - preventDefault: function() { this.returnValue = false }, - inspect: function() { return "[object Event]" } - }); - - return function(event) { - if (!event) return false; - if (event._extendedByPrototype) return event; - - event._extendedByPrototype = Prototype.emptyFunction; - var pointer = Event.pointer(event); - Object.extend(event, { - target: event.srcElement, - relatedTarget: Event.relatedTarget(event), - pageX: pointer.x, - pageY: pointer.y - }); - return Object.extend(event, methods); - }; - - } else { - Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; - Object.extend(Event.prototype, methods); - return Prototype.K; - } -})(); - -Object.extend(Event, (function() { - var cache = Event.cache; - - function getEventID(element) { - if (element._prototypeEventID) return element._prototypeEventID[0]; - arguments.callee.id = arguments.callee.id || 1; - return element._prototypeEventID = [++arguments.callee.id]; - } - - function getDOMEventName(eventName) { - if (eventName && eventName.include(':')) return "dataavailable"; - return eventName; - } - - function getCacheForID(id) { - return cache[id] = cache[id] || { }; - } - - function getWrappersForEventName(id, eventName) { - var c = getCacheForID(id); - return c[eventName] = c[eventName] || []; - } - - function createWrapper(element, eventName, handler) { - var id = getEventID(element); - var c = getWrappersForEventName(id, eventName); - if (c.pluck("handler").include(handler)) return false; - - var wrapper = function(event) { - if (!Event || !Event.extend || - (event.eventName && event.eventName != eventName)) - return false; - - Event.extend(event); - handler.call(element, event); - }; - - wrapper.handler = handler; - c.push(wrapper); - return wrapper; - } - - function findWrapper(id, eventName, handler) { - var c = getWrappersForEventName(id, eventName); - return c.find(function(wrapper) { return wrapper.handler == handler }); - } - - function destroyWrapper(id, eventName, handler) { - var c = getCacheForID(id); - if (!c[eventName]) return false; - c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); - } - - function destroyCache() { - for (var id in cache) - for (var eventName in cache[id]) - cache[id][eventName] = null; - } - - if (window.attachEvent) { - window.attachEvent("onunload", destroyCache); - } - - return { - observe: function(element, eventName, handler) { - element = $(element); - var name = getDOMEventName(eventName); - - var wrapper = createWrapper(element, eventName, handler); - if (!wrapper) return element; - - if (element.addEventListener) { - element.addEventListener(name, wrapper, false); - } else { - element.attachEvent("on" + name, wrapper); - } - - return element; - }, - - stopObserving: function(element, eventName, handler) { - element = $(element); - var id = getEventID(element), name = getDOMEventName(eventName); - - if (!handler && eventName) { - getWrappersForEventName(id, eventName).each(function(wrapper) { - element.stopObserving(eventName, wrapper.handler); - }); - return element; - - } else if (!eventName) { - Object.keys(getCacheForID(id)).each(function(eventName) { - element.stopObserving(eventName); - }); - return element; - } - - var wrapper = findWrapper(id, eventName, handler); - if (!wrapper) return element; - - if (element.removeEventListener) { - element.removeEventListener(name, wrapper, false); - } else { - element.detachEvent("on" + name, wrapper); - } - - destroyWrapper(id, eventName, handler); - - return element; - }, - - fire: function(element, eventName, memo) { - element = $(element); - if (element == document && document.createEvent && !element.dispatchEvent) - element = document.documentElement; - - var event; - if (document.createEvent) { - event = document.createEvent("HTMLEvents"); - event.initEvent("dataavailable", true, true); - } else { - event = document.createEventObject(); - event.eventType = "ondataavailable"; - } - - event.eventName = eventName; - event.memo = memo || { }; - - if (document.createEvent) { - element.dispatchEvent(event); - } else { - element.fireEvent(event.eventType, event); - } - - return Event.extend(event); - } - }; -})()); - -Object.extend(Event, Event.Methods); - -Element.addMethods({ - fire: Event.fire, - observe: Event.observe, - stopObserving: Event.stopObserving -}); - -Object.extend(document, { - fire: Element.Methods.fire.methodize(), - observe: Element.Methods.observe.methodize(), - stopObserving: Element.Methods.stopObserving.methodize(), - loaded: false -}); - -(function() { - /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards and John Resig. */ - - var timer; - - function fireContentLoadedEvent() { - if (document.loaded) return; - if (timer) window.clearInterval(timer); - document.fire("dom:loaded"); - document.loaded = true; - } - - if (document.addEventListener) { - if (Prototype.Browser.WebKit) { - timer = window.setInterval(function() { - if (/loaded|complete/.test(document.readyState)) - fireContentLoadedEvent(); - }, 0); - - Event.observe(window, "load", fireContentLoadedEvent); - - } else { - document.addEventListener("DOMContentLoaded", - fireContentLoadedEvent, false); - } - - } else { - document.write(" - - - - -

Stanford Temporal Tagger: SUTime

-
- - - - - -
-Please enter a reference date (format must be YYYY-MM-DD): -

-Date: -value="<%=StringEscapeUtils.escapeHtml4(dateString)%>"<% - }%> /> - -
- -
-Please enter your text here (sample sentence): -

- -
- - -
- -
-
- diff --git a/src/main/webapp/sutime/sutime.css b/src/main/webapp/sutime/sutime.css deleted file mode 100644 index 8dc66607a6..0000000000 --- a/src/main/webapp/sutime/sutime.css +++ /dev/null @@ -1,25 +0,0 @@ -#Footer { - position: relative; - bottom: 0px; -} -#Main td -{ - padding:15px; - vertical-align:top; -} -#Main table -{ - margin:15px; -} -td -{ - padding:5px; -} -table -{ - margin:15px; -} -#Annotated td -{ - font-size: 14px; -} From 75f4731f880fcfdf55b9312e9c80e64cb49c3da2 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 16:30:28 -0600 Subject: [PATCH 12/41] big youtube handling --- .../java/org/ecocean/identity/IBEISIA.java | 259 ------------------ 1 file changed, 259 deletions(-) diff --git a/src/main/java/org/ecocean/identity/IBEISIA.java b/src/main/java/org/ecocean/identity/IBEISIA.java index 9b12921b83..cbfff645a0 100644 --- a/src/main/java/org/ecocean/identity/IBEISIA.java +++ b/src/main/java/org/ecocean/identity/IBEISIA.java @@ -4070,265 +4070,6 @@ public static String IAIntake(List anns, Shepherd myShepherd, HttpSe public static void fromDetection(Occurrence occ, Shepherd myShepherd, String context, String rootDir) { System.out.println(">>>>>> detection created " + occ.toString()); - - // prep the YouTube video date for SUTimee analysis - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - String tempRelativeDate = null; - try { - // tempRelativeDate = YouTube.getVideoPublishedAt(occ, context); deprecated, issue 622 - tempRelativeDate = null; - } catch (Exception e) {} - if ((tempRelativeDate != null) && (tempRelativeDate.indexOf("T") != -1)) { - tempRelativeDate = tempRelativeDate.substring(0, tempRelativeDate.indexOf("T")); - } - if ((tempRelativeDate != null) && (!tempRelativeDate.equals(""))) { - DateTimeFormatter parser2 = DateTimeFormat.forPattern("yyyy-MM-dd"); - DateTime time = parser2.parseDateTime(tempRelativeDate); - relativeDate = time.toString(parser2); - } - // set the locationID/location/date on all encounters by inspecting detected comments on the first encounter - if ((occ.getEncounters() != null) && (occ.getEncounters().get(0) != null)) { - String locCode = null; - String location = ""; - int year = -1; - int month = -1; - int day = -1; - List encounters = occ.getEncounters(); - int numEncounters = encounters.size(); - Encounter enc = encounters.get(0); - String ytRemarks = null; - // GET AND TRANSLATE VIDEO COMMENTS - // deprecated, issue 622 - // ytRemarks = YouTube.getVideoDescription(occ, myShepherd); - String detectedLanguage = "en"; - try { - detectedLanguage = DetectTranslate.detectLanguage(ytRemarks); - System.out.println("Video description suggests language: " + detectedLanguage); - if (!detectedLanguage.toLowerCase().startsWith("en")) { - ytRemarks = DetectTranslate.translateToEnglish(ytRemarks); - } - } catch (Exception e) { - System.out.println("I hit an exception trying to detect language."); - e.printStackTrace(); - } - // GET AND TRANSLATE VIDEO TITLE - String videoTitle = null; - // deprecated, issue 622 - // videoTitle = YouTube.getVideoTitle(occ, myShepherd); - try { - String titleLanguage = "en"; - titleLanguage = DetectTranslate.detectLanguage(videoTitle); - System.out.println("Video title " + videoTitle + " suggests language: " + - titleLanguage); - // use the title language if there were no comments - if (ytRemarks.equals("")) { - detectedLanguage = titleLanguage; - } - if (!titleLanguage.toLowerCase().startsWith("en")) { - videoTitle = DetectTranslate.translateToEnglish(videoTitle); - } - } catch (Exception e) { - System.out.println( - "I hit an exception trying to detect language in the video title."); - e.printStackTrace(); - } - System.out.println("Final detectedLanguage: " + detectedLanguage); - - // GET AND TRANSLATE OCR TEXT EMBEDDED IN VIDEO FRAMES - // grab texts from yt videos through OCR (before we parse for location/ID and Date) and add it to remarks variable. - String ocrRemarks = ""; - try { - if ((occ.getEncounters() != null) && (occ.getEncounters().size() > 0)) { - Encounter myEnc = occ.getEncounters().get(0); - List assets = myEnc.getMedia(); - if ((assets != null) && (assets.size() > 0)) { - MediaAsset myAsset = assets.get(0); - MediaAsset parent = myAsset.getParent(myShepherd); - if (parent != null) { - ArrayList frames = YouTubeAssetStore.findFrames(parent, - myShepherd); - if ((frames != null) && (frames.size() > 0)) { - // Google OCR - // ArrayList bytesFrames= new ArrayList(GoogleOcr.makeBytesFrames(frames)); - // ocrRemarks = GoogleOcr.detectText(bytesFrames); - // if(ocrRemarks==null)ocrRemarks=""; - // System.out.println("I found Google OCR remarks: "+ocrRemarks); - - // Azure OCR - ocrRemarks = AzureOcr.detectText(frames, detectedLanguage); - if (ocrRemarks == null) ocrRemarks = ""; - System.out.println("I found Azure OCR remarks: " + ocrRemarks); - } - } else { - System.out.println( - "I could not find any frames from YouTubeAssetStore.findFrames for asset:" - + myAsset.getId() + " from Encounter " + myEnc.getCatalogNumber()); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - System.out.println("I hit an exception trying to find ocrRemarks."); - } - try { - String ocrDetectedLanguage = "en"; - ocrDetectedLanguage = DetectTranslate.detectLanguage(ocrRemarks); - - System.out.println("OCR suggests language: " + ocrDetectedLanguage); - if (!ocrDetectedLanguage.toLowerCase().startsWith("en")) { - ocrRemarks = DetectTranslate.translateToEnglish(ocrRemarks); - } - } catch (Exception e) { - System.out.println( - "I hit an exception trying to detect language for OCR comments."); - e.printStackTrace(); - } - String remarks = ytRemarks + " " + ocrRemarks + " " + videoTitle; - - System.out.println("Let's parse these remarks for date and location: " + remarks); - - LinkedProperties props = (LinkedProperties)ShepherdProperties.getProperties( - "submitActionClass.properties", "", context); - - // OK, let's check the comments and tags for retrievable metadata - try { - // first parse for location and locationID - String lowercaseRemarks = remarks.toLowerCase(); - try { - Iterator m_enum = props.orderedKeys().iterator(); - while (m_enum.hasNext()) { - String aLocationSnippet = ((String)m_enum.next()).replaceFirst("\\s++$", - ""); - // System.out.println(" Looking for: "+aLocationSnippet); - if (lowercaseRemarks.indexOf(aLocationSnippet) != -1) { - locCode = props.getProperty(aLocationSnippet); - location += " " + aLocationSnippet; - // System.out.println(".....Building an idea of location: "+location); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - boolean setDate = true; - if (enc.getDateInMilliseconds() != null) { setDate = false; } - // next use natural language processing for date - if (setDate) { - // boolean NLPsuccess=false; - try { - System.out.println(">>>>>> looking for date with NLP"); - // call Stanford NLP function to find and select a date from ytRemarks - // String myDate= ServletUtilities.nlpDateParse(remarks); - String myDate = SUTime.parseDateStringForBestDate(rootDir, remarks, - relativeDate).replaceAll("null", ""); - System.out.println("Finished SUTime.parseDateStringForBestDate: " + myDate); - // parse through the selected date to grab year, month and day separately.Remove cero from month and day with intValue. - if (myDate != null) { - System.out.println(">>>>>> NLP found date: " + myDate); - - // current datetime just for quality comparison - LocalDateTime dt = new LocalDateTime(); - DateTimeFormatter parser1 = ISODateTimeFormat.dateOptionalTimeParser(); - LocalDateTime reportedDateTime = new LocalDateTime( - parser1.parseLocalDateTime(myDate)); - // System.out.println(" reportedDateTime is: "+reportedDateTime.toString(parser1)); - StringTokenizer str = new StringTokenizer(myDate, "-"); - int numTokens = str.countTokens(); - System.out.println(" StringTokenizer for date has " + numTokens + - " tokens for String input " + str.toString()); - if (numTokens >= 1) { - year = reportedDateTime.getYear(); - if (year > (dt.getYear() + 1)) { - year = -1; - } - } - if (numTokens >= 2) { - try { - month = reportedDateTime.getMonthOfYear(); - } catch (Exception e) { month = -1; } - } else { month = -1; } - // see if we can get a day, because we do want to support only yyy-MM too - if (numTokens >= 3) { - try { - day = reportedDateTime.getDayOfMonth(); - } catch (Exception e) { - day = 0; - } - } else { day = -1; } - } - } catch (Exception e) { - System.out.println("Exception in NLP in IBEISIA.class"); - e.printStackTrace(); - } - // if we found a date via NLP or brute force, let's use it here - if (year > -1) { - for (int i = 0; i < numEncounters; i++) { - Encounter enctemp = encounters.get(i); - enctemp.setYear(year); - if (month > -1) { - enctemp.setMonth(month); - if (day > -1) { enctemp.setDay(day); } - } - } - } - } // end if set date - } catch (Exception props_e) { - props_e.printStackTrace(); - } - // if we found a locationID, iterate and set it on every Encounter - if (locCode != null) { - for (int i = 0; i < numEncounters; i++) { - Encounter enctemp = encounters.get(i); - enctemp.setLocationID(locCode); - System.out.println("Setting locationID for detected Encounter to: " + locCode); - if (!location.equals("")) { - enctemp.setLocation(location.trim()); - System.out.println("Setting location for detected Encounter to: " + - location); - } - } - } - // set the Wildbook A.I. user if it exists - if (myShepherd.getUser("wildbookai") != null) { - for (int i = 0; i < numEncounters; i++) { - Encounter enctemp = encounters.get(i); - enctemp.setSubmitterID("wildbookai"); - } - } - // if date and/or location not found, ask youtube poster through comment section. - // cred= ShepherdProperties.getProperties("youtubeCredentials.properties", ""); - try { - // YouTube.init(request); - Properties quest = new Properties(); - // Properties questEs = new Properties(); - - // TBD-simplify to one set of files - System.out.println("Getting quest.properties for language code: " + - detectedLanguage); - quest = ShepherdProperties.getProperties("quest.properties", - detectedLanguage.substring(0, 2)); - // questEs= ShepherdProperties.getProperties("questEs.properties"); - - String questionToPost = null; - if ((enc.getDateInMilliseconds() == null) && (locCode == null)) { - questionToPost = quest.getProperty("whenWhere"); - } else if (enc.getDateInMilliseconds() == null) { - questionToPost = quest.getProperty("when"); - } else if (locCode == null) { - questionToPost = quest.getProperty("where"); - } - if (questionToPost != null) { - String videoId = enc.getEventID().replaceAll("youtube:", ""); - try { - throw new Exception("YouTube agent has been deprecated"); - // YouTube.postQuestion(questionToPost, videoId, occ, context); - } catch (Exception e) { e.printStackTrace(); } - } - } catch (Exception yet) { - System.out.println("Caught exception trying to post a YouTube question."); - yet.printStackTrace(); - } - } - // end set date/location/locationID on Encounters } //// TOTAL HACK... buy jon a drink and he will tell you about these..... From bada9f9e291675f1a4830aed0f31189f4fc47bb6 Mon Sep 17 00:00:00 2001 From: Tanya Date: Mon, 26 Aug 2024 16:29:59 -0700 Subject: [PATCH 13/41] missing german from react update --- frontend/src/constants/locales.js | 4 +- frontend/src/locale/de.json | 231 ++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 frontend/src/locale/de.json diff --git a/frontend/src/constants/locales.js b/frontend/src/constants/locales.js index 3449d29c13..0435361d87 100644 --- a/frontend/src/constants/locales.js +++ b/frontend/src/constants/locales.js @@ -1,5 +1,6 @@ -const locales = ["en", "es", "fr", "it"]; +const locales = ["de", "en", "es", "fr", "it"]; const localeMap = { + de: "de", en: "en", es: "es", fr: "fr", @@ -7,6 +8,7 @@ const localeMap = { }; const languageMap = { + de: "Deutsch", en: "English", es: "Español", fr: "Français", diff --git a/frontend/src/locale/de.json b/frontend/src/locale/de.json new file mode 100644 index 0000000000..b9d9f73c5e --- /dev/null +++ b/frontend/src/locale/de.json @@ -0,0 +1,231 @@ +{ + "ENCOUNTERS": "Begegnungen", + "ANNOTATIONS": "Annotationen", + "LOGIN_USERNAME": "Benutzername", + "LOGIN_PASSWORD": "Kennwort", + "LOGIN_SIGN_IN": "Anmelden", + "LOGIN_REMEMBER_ME": "An mich erinnern", + "LOGIN_FORGOT_PASSWORD": "Passwort vergessen?", + "LOGIN_NEW_TO_WILDBOOK": "Neu bei Wildbook?", + "LOGIN_REQUEST_ACCOUNT": "Konto anfordern", + "LOGIN_INVALID_EMAIL_OR_PASSWORD": "Ungültige E-Mail oder ungültiges Passwort", + "LOGIN_LOGIN": "Anmelden", + "LOGIN_LOGOUT": "Abmelden", + "menu.learn.aboutWildbook": "Über Wildbook", + "menu.learn.contactUs": "Kontaktieren Sie uns", + "menu.learn.citingWildbook": "Wildbuch zitieren", + "menu.learn.howToPhotograph": "Wie man fotografiert", + "menu.learn.privacyPolicy": "Datenschutzrichtlinie", + "menu.learn.termsOfUse": "Nutzungsbedingungen", + "menu.learn.learnMore": "Erfahren Sie mehr über Wildbook", + "menu.submit.reportSighting": "Eine Begegnung melden", + "menu.submit.bulkImport": "Massenimport", + "menu.myData.myEncounters": "Meine Begegnungen", + "menu.myData.approvedAnimals": "Meine genehmigten Begegnungen", + "menu.myData.unapprovedAnimals": "Meine nicht genehmigten Begegnungen", + "menu.myData.unidentifiableAnimals": "Meine nicht identifizierbaren Begegnungen", + "menu.myData.myIndividuals": "Meine Individuen", + "menu.myData.mySightings": "Meine Sichtungen", + "menu.myData.myBulkImports": "Meine Bulk-Importe", + "menu.myData.myProjects": "Meine Projekte", + "menu.search.encounters": "Begegnungen", + "menu.search.individuals": "Individuen", + "menu.search.sightings": "Sichtungen", + "menu.animals.individualGallery": "Individuelle Galerie", + "menu.animals.animalCalendar": "Tierkalender", + "menu.administer.myAccount": "Mein Konto", + "menu.administer.manageAccounts": "Meine Konten verwalten", + "menu.administer.userManagement": "Benutzerverwaltung", + "menu.administer.libraryAdmin": "Bibliotheksverwaltung", + "menu.administer.logs": "Protokolle", + "menu.administer.photoKeywords": "Foto-Schlüsselwörter", + "menu.administer.softwareDocs": "Software-Dokumentation", + "menu.administer.dataIntegrity": "Datenintegrität", + "menu.administer.bulkImportLogs": "Bulk-Import-Protokolle", + "USER_PROFILE": "Benutzerprofil", + "LEARN": "Lernen", + "SUBMIT": "Einreichen", + "ANIMALS": "Tiere", + "MY_DATA": "Meine Daten", + "SEARCH": "Suche", + "ADMINISTER": "Verwalten", + "FOOTER_DESC": "KI-Tools für den kollaborativen, internationalen Schutz von Wildtieren", + "FOOTER_COPYRIGHT": "2024 © Conservation X Labs | Alle Rechte vorbehalten", + "HOME": "Zuhause", + "FOOTER_DOCUMENTATION": "Dokumentation", + "FOOTER_COMMUNITY_FORUM": "Gemeinschaftsforum", + "FOOTER_TERM_OF_USE": "Nutzungsbedingungen", + "REPORT_SIGHTINGS": "Eine Begegnung melden", + "FOOTER_DONATE": "Spende", + "FOOTER_DISCORD": "Discord", + "FOOTER_GITHUB": "GitHub", + "FOOTER_TWITTER": "X (Twitter)", + "FOOTER_FACEBOOK": "Facebook", + "FOOTER_INSTAGRAM": "Instagram", + "FOOTER_LINKEDIN": "LinkedIn", + "HOME_LATEST_DATA": "Neueste Daten", + "HOME_PICK_UP_1": "Abholen wo ", + "HOME_PICK_UP_2": "Sie sind gegangen", + "HOME_LATEST_BULK_REPORT": "Letzter Bulk-Bericht", + "HOME_LATEST_INDIVIDUAL": "Letzte Einzelperson", + "HOME_LATEST_MATCHING_ACTION": "Letzte Abgleichsaktion", + "HOME_FILES_LOADED": "{num} geladene Dateien", + "HOME_VIEW_PROJECT_1": "Ihre Ansicht", + "HOME_VIEW_PROJECT_2": "Projekte", + "HOME_NO_PROJECT": "Kein Projekt", + "SEE_ALL": "Alle sehen", + "VIEW": "Ansicht", + "NONE": "Keine", + "REPORT_AN_ENCOUNTER": "Eine Begegnung melden", + "SUBMIT_NEW_DATA": "Neue Daten einreichen", + "BULK_REPORT": "Massenimport", + "LANDING_PAGE": "Landing Page", + "NO_NEW_MESSAGE": "Keine neue Nachricht", + "INDIVIDUAL_MERGE_NOTIFICATIONS": "Individuelle Zusammenführungsbenachrichtigungen", + "INITIATED_BY_USER": "Initiiert von Benutzer {user}", + "IGNORE": "Ignorieren", + "DENY": "Ablehnen", + "MERGE_PENDING_MESSAGE": "Die Zusammenführung von {indv2} in {indv1} wurde eingeleitet. Auto Datum der Fertigstellung: {mergeDate}, 2 Wochen verzögerte Ausführung.", + "MERGE_DENIED_MESSAGE": "Eine Zusammenführung von {indv2} in {indv1} wurde abgelehnt. Initiated by {initiator}. Verweigert durch Benutzer: {deniedBy} ", + "DISMISS": "Dismiss", + "MERGE_COMPLETE_MESSAGE": "Eine Zusammenführung von {indv2} in {indv1} wurde abgeschlossen. Initiiert von {initiator}. Datum der Fertigstellung: {mergeDate}", + "BANNER_ALERT": "Wildbook bekommt ein neues Aussehen! Wir danken Ihnen für Ihre Geduld, während wir diese Änderungen vornehmen.", + "ERROR_PAGE_NOT_FOUND": "Seite nicht gefunden", + "ERROR_PAGE_NOT_FOUND_DESC": "Die Seite, die Sie suchen, existiert nicht. Sie wurde möglicherweise verschoben oder gelöscht. Gehen Sie zurück zur Startseite.", + "ERROR_BACK_HOME": "Zurück nach Hause", + "ERROR_PAGE_SERVER_ERROR": "Interner Serverfehler", + "ERROR_PAGE_SERVER_ERROR_DESC": "Oops! Bei uns ist etwas schief gelaufen. Wir arbeiten daran, das Problem zu beheben. Versuchen Sie, die Seite in ein paar Minuten zu aktualisieren.", + "ERROR_PAGE_UNAUTHORIZED": "Nicht autorisiert", + "ERROR_PAGE_UNAUTHORIZED_DESC": "Sie müssen sich einloggen, um diese Seite zu sehen. Bitte melden Sie sich an oder kontaktieren Sie den Support, wenn Sie Probleme haben.", + "ERROR_PAGE_FORBIDDEN": "Verboten", + "ERROR_PAGE_FORBIDDEN_DESC": "Sie haben keine Berechtigung, auf diese Seite zuzugreifen. Wenn Sie glauben, dass dies ein Fehler ist, wenden Sie sich an den Support.", + "ERROR_PAGE_BAD_REQUEST": "Schlechte Anfrage", + "ERROR_PAGE_BAD_REQUEST_DESC": "Ihr Browser hat eine Anfrage gesendet, die dieser Server nicht verstehen konnte. Bitte überprüfen Sie die URL oder kontaktieren Sie uns.", + "FILTER": "Filter", + "RESULTS_TABLE": "Ergebnistabelle", + "CLEAR": "Löschen", + "TOTAL_ITEMS": "Posten insgesamt", + "PER_PAGE": "Pro Seite", + "PAGE": "Seite", + "GO_TO": "Gehe zu", + "GO": "Gehe", + "ENCOUNTER_SEARCH_RESULTS": "Ergebnisse der Begegnungssuche", + "APPLY": "Anwenden", + "RESET": "Zurücksetzen", + "APPLIED_FILTERS": "Angewendete Filter", + "FILTER_EDIT_FILTER": "Bearbeiten", + "FILTER_COPY": "Kopieren", + "FILTER_RESET_FILTER": "Zurücksetzen", + "FILTER_LOCATION": "Standort", + "FILTER_LOCATION_DESC": "Verwenden Sie die folgenden Felder, um Ihre Suche nach dem Standort zu filtern", + "FILTER_GPS_COORDINATES": "GPS-Koordinaten", + "Northeast_Latitude": "Nordöstlicher Breitengrad", + "Northeast_Longitude": "Nordöstlicher Längengrad", + "Southwest_Latitude": "Südwestlicher Breitengrad", + "Southwest_Longitude": "Südwestlicher Längengrad", + "FILTER_VERBATIM_LOCATION": "Verbatim-Standort", + "FILTER_VERBATIM_LOCATION_DESC": "Geben Sie eine genaue oder teilweise Suche ein", + "FILTER_COUNTRY": "Land", + "FILTER_LOCATION_ID": "Standort-ID", + "FILTER_DATE": "Datum", + "FILTER_DATE_DESC": "Verwenden Sie die nachstehenden Felder, um den Zeitrahmen Ihrer Suche einzuschränken", + "FILTER_SIGHTING_DATE": "Sichtungsdatum", + "FILTER_FROM": "Von", + "FILTER_TO": "Bis", + "FILTER_VERBATIM_EVENT_DATE": "Verbatim-Ereignisdatum", + "FILTER_ENCOUNTER_SUBMISSION_DATE": "Datum der Einreichung", + "FILTER_OBSERVATION_ATTRIBUTE": "Beobachtungsattribut", + "FILTER_OBSERVATION_ATTRIBUTE_DESC": "Verwenden Sie die folgenden Felder, um Ihre Suche nach beobachteten Attributen zu filtern", + "FILTER_SEX": "Geschlecht", + "FILTER_LIFE_STATUS": "Lebensstatus", + "FILTER_GENUS_AND_SPECIES": "Gattung und Art", + "FILTER_SIGHTING_ID": "Sichtung ID", + "FILTER_OBSERVATION_SEARCH": "Suche nach Beobachtungen", + "FILTER_OBSERVATION_NAME": "Beobachtungsname", + "FILTER_OBSERVATION_VALUE": "Beobachtungswert", + "FILTER_ADD_OBSERVATION_SEARCH": "Beobachtung hinzufügen Suche", + "FILTER_OBSERVATION_COMMENTS": "Kommentare zur Beobachtung", + "FILTER_OBSERVATION_COMMENTS_DESC": "Geben Sie eine genaue oder teilweise Übereinstimmung ein. Groß- und Kleinschreibung wird nicht beachtet", + "FILTER_BEHAVIOUR": "Verhalten", + "FILTER_PATTERNING_CODE": "Musterungscode", + "FILTER_MEASUREMENTS": "Messungen", + "FILTER_IMAGE_LABEL": "Bildbezeichnung", + "FILTER_IMAGE_LABEL_DESC": "Verwenden Sie die folgenden Felder, um Ihre Suche auf der Grundlage von Metadaten zu Fotos einzuschränken", + "FILTER_KEYWORDS": "Schlüsselwörter", + "USE_AND_OPERATOR": "Verwenden Sie AND Operator", + "FILTER_HAS_AT_LEAST_ONE_ASSOCIATED_PHOTO_OR_VIDEO": "Hat mindestens ein zugehöriges Foto oder Video", + "FILTER_KEYWORDS_DESC": "Wählen Sie ein oder mehrere Schlüsselwörter aus. Um alle ausgewählten Schlüsselwörter zu verlangen, markieren Sie Use AND operator", + "FILTER_LABELLED_KEYWORDS": "Bezeichnete Schlüsselwörter", + "FILTER_LABELLED_KEYWORDS_DESC": "Wählen Sie einen oder mehrere Werte für gelabelte Schlüsselwörter aus. Um alle ausgewählten Schlüsselwörter zu verlangen, markieren Sie Use AND operator", + "FILTER_LABEL": "Bezeichnung", + "FILTER_VALUE": "Wert", + "FILTER_VIEWPOINT": "Aussichtspunkt", + "FILTER_IA_CLASS": "IA-Klasse", + "FILTER_IDENTITY": "Identität", + "FILTER_IDENTITY_DESC": "Verwenden Sie die nachstehenden Felder, um Ihre Suche auf der Grundlage der zugehörigen Person einzuschränken", + "FILTER_MINIMUM_TIMES_SIGHTED": "Mindestzeiten gesichtet", + "FILTER_SIGHTED_AT_LEAST": "Mindestens gesichtet", + "FILTER_TIMES": "Zeiten", + "FILTER_NO_INDIVIDUAL_ID": "Nur Begegnungen ohne zugewiesene individuelle ID einbeziehen", + "FILTER_ALTERNATIVE_ID": "Alternative ID", + "FILTER_INDIVIDUAL_NAME": "Name der Person", + "FILTER_INDIVIDUAL_NAME_DESC": "Name der Person einschließlich aller Kontexte", + "FILTER_TAGS": "Tags", + "FILTER_TAGS_DESC": "Verwenden Sie die folgenden Felder, um Ihre Suche auf bestimmte Tags zu beschränken", + "FILTER_METAL_TAGS": "Metall-Tags", + "FILTER_ACOUSTIC_TAGS": "Akustische Tags", + "FILTER_ACOUSTIC_TAG_SERIAL_NUMBER": "Seriennummer", + "FILTER_ACOUSTIC_TAG_ID": "ID", + "FILTER_SATELLITE_TAGS": "Satelliten-Tags", + "FILTER_NAME": "Name", + "FILTER_SERIAL_NUMBER": "Seriennummer", + "FILTER_ARGOS_PPT_NUMBER": "Argos PPT-Number", + "FILTER_BIOLOGICAL_SAMPLE": "Biologische Probe", + "FILTER_BIOLOGICAL_SAMPLE_DESC": "Verwenden Sie die nachstehenden Felder, um Ihre Suche auf der Grundlage biologischer Proben und der daraus resultierenden Analysen einzuschränken", + "FILTER_HAS_BIOLOGICAL_SAMPLE": "Hat eine biologische Probe", + "FILTER_BIOLOGICAL_SAMPLE_ID": "Biologische Probe ID", + "FILTER_HAPLO_TYPE": "Haplo-Typ", + "FILTER_GENETIC_SEX": "Genetisches Geschlecht", + "FILTER_BIOLOGICAL_MEASUREMENTS": "Biologische Messungen", + "FILTER_MARKER_LOCI": "Mikrosatelliten-Marker-Loci", + "FILTER_RELAX_ALLELE_LENGTH": "Relax-Allel-Länge (+/-)", + "FILTER_ALLELE1": "Allel 1", + "FILTER_ALLELE2": "Allel 2", + "FILTER_SOCIAL": "Sozial", + "FILTER_SOCIAL_DESC": "Verwenden Sie die folgenden Felder, um Ihre Suche auf der Grundlage sozialer Verbindungen einzuschränken", + "FILTER_SOCIAL_UNIT": "Einheit der sozialen Gruppe", + "FILTER_RELATIONSHIP_ROLE": "Soziale Beziehungsrolle", + "FILTER_METADATA": "Metadaten", + "FILTER_METADATA_DESC": "Verwenden Sie die nachstehenden Felder, um Ihre Suche auf der Grundlage plattformbezogener Daten einzuschränken", + "FILTER_ENCOUNTERS_STATUS": "Begegnungsstatus", + "FILTER_SUBMITTER": "Einreicher, Fotograf oder E-Mail Adresse. Dieses Feld unterscheidet NICHT zwischen Groß- und Kleinschreibung", + "FILTER_ORGANIZATION_ID": "Organisations-ID", + "FILTER_PROJECT_NAME": "Projektname", + "FILTER_ASSIGNED_USER": "Zugewiesener Benutzer", + "ENCOUNTER_SEARCH_FILTERS": "Suchfilter für Begegnungen", + "DRAW": "Zeichnen", + "CANCEL": "Abbrechen", + "FILTERS": "Filter", + "TYPE_HERE": "Hier eingeben", + "SELECT_ONE_OR_MORE": "Wählen Sie einen oder mehrere", + "TYPE_NUMBER": "###", + "ENCOUNTER_PROJECT_MANAGEMENT": "Projektleitung", + "ENCOUNTER_MATCHING_IMAGES_VIDEOS": "Passende Bilder/Videos", + "ENCOUNTER_MAPPED_RESULTS": "Zugeordnete Ergebnisse", + "ENCOUNTER_RESULTS_CALENDAR": "Ergebniskalender", + "ENCOUNTER_ANALYSIS": "Analyse", + "ENCOUNTER_EXPORT": "Exportieren", + "SEARCH_ENCOUNTERS": "Suchbegegnungen", + "INDIVIDUAL_ID": "Individuelle ID", + "SIGHTING_ID": "Sichtungs ID", + "ALTERNATIVE_ID": "Alternative ID", + "CREATED_DATE": "Erstellungsdatum", + "LOCATION_ID": "Standort-ID", + "SPECIES": "Spezies", + "SUBMITTER": "Einreicher", + "DATE_SUBMITTED": "Datum der Einreichung", + "NUMBER_ANNOTATIONS": "Anzahl der Anmerkungen", + "ADD_LABELLED_KEYWORD_SEARCH": "Beschriftete Schlagwortsuche hinzufügen", + "APPLY_SEARCH_ID": "Such-ID anwenden", + "APPLY_SEARCH_ID_DESC": "Diese Funktion ermöglicht es Benutzern, ihre Suchkriterien auf einfache Weise mit anderen zu teilen. Nachdem er eine Suche durchgeführt hat, kann ein Benutzer seine eindeutige Such-ID kopieren und sie mit einem anderen Benutzer teilen. Der Empfänger kann dann diese Such-ID in den Abschnitt „Such-ID anwenden“ einfügen und auf „Anwenden“ klicken, um die genauen Suchkriterien zu replizieren und die gleichen Ergebnisse wie der ursprüngliche Benutzer zu erhalten." +} \ No newline at end of file From 57d10cf5264c94ce999cb8e49e12e68d1374d4d8 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 17:39:44 -0600 Subject: [PATCH 14/41] cleanup --- .../ai/utilities/ParseDateLocation.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java b/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java index ec0aa562e4..b2da0c3a02 100644 --- a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java +++ b/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java @@ -183,17 +183,6 @@ public static String parseDate(String rootDir, String context, Status tweet) { return null; } - /* - TODO FIXME this is made by jon as a desired set of arguments to call from IBEISIA.fromDetection() - - note: rootDir is base path for context, i.e. request.getSession().getServletContext().getRealPath("/") suitable for, e.g. baseDir = - ServletUtilities.dataDir(context, rootDir); - */ - /* - public static String parseDate(String textInput, String context, String rootDir){ - return null; - } - */ // NOTE: parseDate method WITHOUT tweet4j status object as a parameter. There is another parseDate method! public static String parseDate(String rootDir, String textInput, String context) { @@ -226,36 +215,6 @@ public static String parseDate(String rootDir, String textInput, String context) return myDate; } - /* - public static ArrayList nlpLocationParse(String text) throws RuntimeException { - ArrayList locations = new ArrayList<>(); - Properties props = new Properties(); - props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner"); //TODO adding truecase before ner doesn't seem to be making a difference - here. If this doesn't change with some tweaking, you may want to remove the stanford-corenlp class:model-english dependency. Update: the - stanford-corenlp class:model-english dependency seems essential even when truecase is excluded. Very weird. StanfordCoreNLP pipeline = new - StanfordCoreNLP(props); - edu.stanford.nlp.pipeline.Annotation document = new edu.stanford.nlp.pipeline.Annotation(text); - pipeline.annotate(document); - List sentences = document.get(SentencesAnnotation.class); - for(CoreMap sentence: sentences) { - for (CoreLabel token: sentence.get(TokensAnnotation.class)) { - String ne = token.get(NamedEntityTagAnnotation.class); - if(ne.equals("LOCATION")){ - String word = token.get(TextAnnotation.class); - System.out.println("Location captured: " + word); - locations.add(word); - } - } - } - - if (locations.size() > 0){ - return locations; - } else{ - throw new RuntimeException("no locations found"); - } - - } - */ /** * Pass in a MediaAsset that derives from a YouTube video, and this method will go check for any additional info, such as response comments, that From ec23a0672cde20bbeb5e08a497e04fa1c0eeaf34 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Tue, 27 Aug 2024 14:35:15 -0600 Subject: [PATCH 15/41] unused import --- src/main/java/org/ecocean/identity/IBEISIA.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/org/ecocean/identity/IBEISIA.java b/src/main/java/org/ecocean/identity/IBEISIA.java index cbfff645a0..a33c10b376 100644 --- a/src/main/java/org/ecocean/identity/IBEISIA.java +++ b/src/main/java/org/ecocean/identity/IBEISIA.java @@ -1,8 +1,5 @@ package org.ecocean.identity; -import org.ecocean.ai.nlp.SUTime; -import org.ecocean.ai.nmt.azure.DetectTranslate; -import org.ecocean.ai.ocr.azure.AzureOcr; import org.ecocean.Annotation; import org.ecocean.AnnotationLite; import org.ecocean.CommonConfiguration; From 14d6da9e9781363c7ad23f3b5cc03b5812db8ea3 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Tue, 27 Aug 2024 15:19:03 -0600 Subject: [PATCH 16/41] clean house re: SUTime --- src/main/java/org/ecocean/TwitterBot.java | 7 +- src/main/java/org/ecocean/ai/nlp/SUTime.java | 549 -------------- .../ai/utilities/ParseDateLocation.java | 673 ------------------ .../org/ecocean/servlet/SUTimePipeline.java | 94 --- 4 files changed, 4 insertions(+), 1319 deletions(-) delete mode 100644 src/main/java/org/ecocean/ai/nlp/SUTime.java delete mode 100644 src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java delete mode 100644 src/main/java/org/ecocean/servlet/SUTimePipeline.java diff --git a/src/main/java/org/ecocean/TwitterBot.java b/src/main/java/org/ecocean/TwitterBot.java index 8a85d3c75c..55afe7b15d 100644 --- a/src/main/java/org/ecocean/TwitterBot.java +++ b/src/main/java/org/ecocean/TwitterBot.java @@ -18,7 +18,6 @@ import java.util.ArrayList; import java.util.List; import org.ecocean.ai.nmt.azure.DetectTranslate; -import org.ecocean.ai.utilities.ParseDateLocation; import org.ecocean.ia.IA; import org.ecocean.ia.Task; import org.ecocean.media.MediaAsset; @@ -562,9 +561,11 @@ private static void updateEncounter(MediaAsset tweetMA, ArrayList an if ((originTweet == null) || (anns == null)) return; String tx = taxonomyStringFromTweet(originTweet, myShepherd.getContext()); + // ParseDateLocation has been deprecated // use NLP to get Date/Location if available in Tweet - String newDetectedDate = ParseDateLocation.parseDate(rootDir, myShepherd.getContext(), - originTweet); + // String newDetectedDate = ParseDateLocation.parseDate(rootDir, myShepherd.getContext(), originTweet); + String newDetectedDate = null; + for (Annotation ann : anns) { Encounter enc = ann.findEncounter(myShepherd); if (enc == null) continue; diff --git a/src/main/java/org/ecocean/ai/nlp/SUTime.java b/src/main/java/org/ecocean/ai/nlp/SUTime.java deleted file mode 100644 index 9099f63a02..0000000000 --- a/src/main/java/org/ecocean/ai/nlp/SUTime.java +++ /dev/null @@ -1,549 +0,0 @@ -package org.ecocean.ai.nlp; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -import org.ecocean.servlet.*; -import org.ecocean.TwitterUtil; - -import java.io.IOException; - -import edu.stanford.nlp.ling.CoreAnnotations; -import edu.stanford.nlp.pipeline.Annotation; -import edu.stanford.nlp.pipeline.Annotator; -import edu.stanford.nlp.time.Options; -import edu.stanford.nlp.time.SUTime.Temporal; -import edu.stanford.nlp.time.TimeAnnotations; -import edu.stanford.nlp.time.TimeExpression; -import edu.stanford.nlp.util.CoreMap; -import edu.stanford.nlp.util.StringUtils; -import twitter4j.Status; - -import org.apache.commons.lang3.StringEscapeUtils; - -public class SUTime { - public static boolean parseBoolean(String value) { - if (StringUtils.isNullOrEmpty(value)) { - return false; - } - if (value.equalsIgnoreCase("on")) { - return true; - } - return Boolean.parseBoolean(value); - } - - private static String getRuleFilepaths(String rootDir, String... files) { - String rulesDir = ""; - - try { - rulesDir = rootDir + "/WEB-INF/data/sutime/rules"; - } catch (Exception npe) { - // OK, we couldn't find a servlet context, so let's try to get the files from a hardcoded override directory - rulesDir = "/data/wildbook_data_dir/WEB-INF/data/sutime/rules"; - } - StringBuilder sb = new StringBuilder(); - for (String file : files) { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(rulesDir + "/" + file); - System.out.println("Loading SUTime rules file: " + rulesDir + "/" + file); - } - return sb.toString(); - } - - private static Properties getTimeAnnotatorProperties(String rootDir) { - // Parses request and set up properties for time annotators - - System.out.println("Entering " + "SUTime.getTimeAnnotatorProperties"); - - boolean markTimeRanges = false; - // parseBoolean(request.getParameter("markTimeRanges")); - boolean includeNested = false; - // parseBoolean(request.getParameter("includeNested")); - boolean includeRange = false; - // parseBoolean(request.getParameter("includeRange")); - String heuristicLevel = null; - // request.getParameter("relativeHeuristicLevel"); - Options.RelativeHeuristicLevel relativeHeuristicLevel = Options.RelativeHeuristicLevel.NONE; - if (!StringUtils.isNullOrEmpty(heuristicLevel)) { - relativeHeuristicLevel = Options.RelativeHeuristicLevel.valueOf(heuristicLevel); - } - String ruleFile = null; - ruleFile = getRuleFilepaths(rootDir, "defs.sutime.txt", "english.sutime.txt", - "english.holidays.sutime.txt"); - - // Create properties - Properties props = new Properties(); - if (markTimeRanges) { - props.setProperty("sutime.markTimeRanges", "true"); - } - if (includeNested) { - props.setProperty("sutime.includeNested", "true"); - } - if (includeRange) { - props.setProperty("sutime.includeRange", "true"); - } - if (ruleFile != null) { - props.setProperty("sutime.rules", ruleFile); - props.setProperty("sutime.binders", "1"); - props.setProperty("sutime.binder.1", "edu.stanford.nlp.time.JollyDayHolidays"); - - try { - props.setProperty("sutime.binder.1.xml", - (rootDir + "/WEB-INF/data/holidays/Holidays_sutime.xml")); - } catch (Exception npe) { - props.setProperty("sutime.binder.1.xml", - "/data/wildbook_data_dir/WEB-INF/data/holidays/Holidays_sutime.xml"); - npe.printStackTrace(); - } - props.setProperty("sutime.binder.1.pathtype", "file"); - } - props.setProperty("sutime.teRelHeurLevel", relativeHeuristicLevel.toString()); - props.setProperty("sutime.verbose", "true"); - -// props.setProperty("heideltime.path", getServletContext().getRealPath("/packages/heideltime")); -// props.setProperty("gutime.path", getServletContext().getRealPath("/packages/gutime")); - return props; - } - - private static List getTimeAnnotations(String query, Annotation anno, - boolean includeOffsets) { - List timexAnns = anno.get(TimeAnnotations.TimexAnnotations.class); - List pieces = new ArrayList(); - List tagged = new ArrayList(); - int previousEnd = 0; - - for (CoreMap timexAnn : timexAnns) { - int begin = timexAnn.get(CoreAnnotations.CharacterOffsetBeginAnnotation.class); - int end = timexAnn.get(CoreAnnotations.CharacterOffsetEndAnnotation.class); - if (begin >= previousEnd) { - pieces.add(query.substring(previousEnd, begin)); - tagged.add(false); - pieces.add(query.substring(begin, end)); - tagged.add(true); - previousEnd = end; - } - } - if (previousEnd < query.length()) { - pieces.add(query.substring(previousEnd)); - tagged.add(false); - } - return timexAnns; - } - - // use the current date as the reference date - private static List getDates(String query, String rootDir, SUTimePipeline pipeline) - throws IOException { - String dateString = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - - return getDates(query, rootDir, pipeline, dateString); - } - - // use a provided date as a reference date - private static List getDates(String query, String rootDir, SUTimePipeline pipeline, - String dateString) - throws IOException { - System.out.println("Entering SUTime.getDates!"); - - boolean includeOffsets = false; - // boolean includeOffsets = parseBoolean(request.getParameter("includeOffsets")); - if (!StringUtils.isNullOrEmpty(query)) { - Properties props = getTimeAnnotatorProperties(rootDir); - System.out.println(("Found props: " + props.toString())); - // String annotatorType = request.getParameter("annotator"); - // if (annotatorType == null) { - String annotatorType = "sutime"; - // } - Annotator timeAnnotator = pipeline.getTimeAnnotator(annotatorType, props); - if (timeAnnotator != null) { - Annotation anno = pipeline.process(query, dateString, timeAnnotator); - // out.println("

Annotated Text

(tagged using " + annotatorType + ")"); - List timexAnns = getTimeAnnotations(query, anno, includeOffsets); - - return timexAnns; - } else { - System.out.println("

Error creating annotator for " + - StringEscapeUtils.escapeHtml4(annotatorType)); - } - } - return null; - } - - public static SUTimePipeline createPipeline(String rootDir) { - System.out.println("Creating the SUTimePipeline!"); - SUTimePipeline pipeline; // = null; - String dataDir = ""; - - // check if we're calling this from a servlet context, which we should be - try { - dataDir = rootDir + "/WEB-INF/data"; - System.setProperty("de.jollyday.config", - (rootDir + "/WEB-INF/classes/holidays/jollyday.properties")); - } catch (Exception npe) { - // OK, we couldn't find a servlet context, so let's try to get the files from a hardcoded override directory - dataDir = "/data/wildbook_data_dir/WEB-INF/data"; - System.setProperty("de.jollyday.config", - ("/data/wildbook_data_dir/WEB-INF/classes/holidays/jollyday.properties")); - npe.printStackTrace(); - } - String taggerFilename = dataDir + "/english-left3words-distsim.tagger"; - Properties pipelineProps = new Properties(); - System.out.println("pos.model set to " + taggerFilename); - pipelineProps.setProperty("pos.model", taggerFilename); - pipeline = new SUTimePipeline(pipelineProps); - return pipeline; - } - - public static ArrayList parseStringForDates(String rootDir, String text) { - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - - return parseStringForDates(rootDir, text, relativeDate); - } - - public static ArrayList parseStringForDates(String rootDir, String text, - String relativeDate) { - ArrayList arrayListDates = new ArrayList(); - SUTimePipeline pipeline = createPipeline(rootDir); - - // clean up the text - System.out.println("parseDates with text " + text); - - // text = text.replaceAll("[,.!?;:]", "$0 "); - // System.out.println("text: " + text); - // String[] text1 = text.replaceAll("[^A-Za-z0-9 ]", " ").toLowerCase().split("\\s+"); //TODO I think this does a better version of what the - // above (text = text.replaceAll("[,.!?;:]", "$0 ");) does?? -Mark Fisher - // String text2 = String.join(" ", text1); - - // System.out.println("Cleaned up text to text2: " + text2); - - /* - try { - if (request.getCharacterEncoding() == null) { - request.setCharacterEncoding("utf-8"); - } - } - catch(Exception e) { - e.printStackTrace(); - } - */ - - try { - List timexAnnsAll = getDates(text, rootDir, pipeline, relativeDate); - for (CoreMap cm : timexAnnsAll) { - Temporal myDate = cm.get(TimeExpression.Annotation.class).getTemporal(); - // TimeExpression.Annotation:The CoreMap key for storing a TimeExpression annotation. - String dateStr = myDate.toString(); - System.out.println(".....found date: " + dateStr); - arrayListDates.add(dateStr.replaceAll("-XX", "")); - } - System.out.println("NLP dates found+:" + arrayListDates); - - // if (!arrayListDates.isEmpty()) { - // turn arrayList into an array to be able to use the old For loop and compare dates. - - // return arrayListDates; - // } - } catch (Exception ioe) { - ioe.printStackTrace(); - } - return arrayListDates; - } - - // - public static String parseDateStringForBestDate(String rootDir, String text) { - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - - return parseDateStringForBestDate(rootDir, text, relativeDate); - } - - public static String parseDateStringForBestDate(String rootDir, String text, - String relativeDate) { - ArrayList arrayListDates = parseStringForDates(rootDir, text, relativeDate); - String selectedDate = ""; - - try { - selectedDate = selectBestDateFromCandidates(arrayListDates); - } catch (Exception e) { - e.printStackTrace(); - } - if (selectedDate == null || selectedDate.equals("")) { - return null; - } else { - return selectedDate; - } - } - - public static String selectBestDateFromCandidates(ArrayList candidates) - throws Exception { - String selectedDate = ""; - - if (candidates.size() < 1) { - throw new Exception("list of candidate dates was empty"); - } else if (candidates.size() >= 1) { - // filter by options that are valid dates - ArrayList validDates = new ArrayList(); - try { - validDates = removeInvalidDates(candidates); - } catch (Exception e) { - // e.printStackTrace(); - } - try { - System.out.println(validDates); - } catch (Exception e) { - System.out.println("couldn't print validDates"); - // e.printStackTrace(); - } - // filter by options that are not in the future - ArrayList validDatesWithFutureDatesRemoved = new ArrayList(); - try { - validDatesWithFutureDatesRemoved = removeFutureDates(validDates); - System.out.println("Before future removal:"); - System.out.println(validDates); - System.out.println("After future removal:"); - System.out.println(validDatesWithFutureDatesRemoved); - } catch (Exception e) { - System.out.println("couldn't run removeFutureDates"); - // e.printStackTrace(); - } - // remove excessive past dates - ArrayList validDatesWithExcessiveDatesRemoved = new ArrayList(); - try { - validDatesWithExcessiveDatesRemoved = removeExcessivePastDates( - validDatesWithFutureDatesRemoved); - System.out.println("Before excessive past removal:"); - System.out.println(validDatesWithFutureDatesRemoved); - System.out.println("After excessive past removal:"); - System.out.println(validDatesWithExcessiveDatesRemoved); - } catch (Exception e) { - System.out.println("couldn't run removeExcessivePastDates"); - // e.printStackTrace(); - } - // if non-yesterday dates exist as well as yesterday ones, prefer the non-yesterdays. Otherwise, just get the yesterday. - ArrayList validDatesFilteredByYesterday = new ArrayList(); - try { - validDatesFilteredByYesterday = removeYesterdayDatesIfTheyAreNotTheOnlyDates( - validDatesWithExcessiveDatesRemoved); - System.out.println(validDatesFilteredByYesterday); - } catch (Exception e) { - System.out.println("couldn't print validDatesFilteredByYesterday"); - // e.printStackTrace(); - } - // Now select the longest one? - if (validDatesFilteredByYesterday == null || validDatesFilteredByYesterday.size() < 1) { - throw new Exception( - "validDatesFilteredByYesterday is null or empty before selecting the longest string"); - } - if (validDatesFilteredByYesterday.size() > 1) { - for (int j = 0; j < validDatesFilteredByYesterday.size(); j++) { - for (int k = j + 1; k < validDatesFilteredByYesterday.size(); k++) { - if (validDatesFilteredByYesterday.get(j).length() > - validDatesFilteredByYesterday.get(k).length()) { - selectedDate = validDatesFilteredByYesterday.get(j); - } else if (validDatesFilteredByYesterday.get(j).length() < - validDatesFilteredByYesterday.get(k).length()) { - selectedDate = validDatesFilteredByYesterday.get(k); - } else { - selectedDate = validDatesFilteredByYesterday.get(0); - } - } - } - } else if (validDatesFilteredByYesterday.size() == 1) { - selectedDate = validDatesFilteredByYesterday.get(0); - } - } - if (selectedDate == null || selectedDate.equals("")) { - throw new Exception( - "selectedDate either null or empty after selecting for longest one"); - } else { - return selectedDate; - } - } - - public static ArrayList removeInvalidDates(ArrayList candidates) - throws Exception { - ArrayList validDates = new ArrayList(); - DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); - DateFormat df2 = new SimpleDateFormat("yyyy-MM"); - DateFormat df3 = new SimpleDateFormat("yyyy"); - String newDateString = null; - - java.util.Date candiDate; - for (int i = 0; i < candidates.size(); i++) { - String candidateString = candidates.get(i); - try { - candiDate = df.parse(candidateString); - newDateString = df.format(candiDate); - validDates.add(newDateString); - } catch (ParseException e) { - try { - candiDate = df2.parse(candidateString); - newDateString = df2.format(candiDate); - validDates.add(newDateString); - } catch (Exception f) { - try { - candiDate = df3.parse(candidateString); - newDateString = df3.format(candiDate); - validDates.add(newDateString); - } catch (Exception g) { - g.printStackTrace(); - continue; - } - } - } - } - if (validDates == null | validDates.size() < 1) { - throw new Exception( - "validDates arrayList is empty or null in removeInvalidDates method"); - } else { - return validDates; - } - } - - public static ArrayList removeFutureDates(ArrayList candidates) - throws Exception { - // TODO add handling for tweets coming from future in datelines - ArrayList returnCandidates = new ArrayList(); - - java.util.Date today = getToday(); - for (int i = 0; i < candidates.size(); i++) { - String currentDateString = candidates.get(i); - try { - java.util.Date currentDateObj = convertStringToDate(currentDateString); - if (currentDateObj == null) { - System.out.println("currentDateObj in removeFutureDates is null"); - } - if (!currentDateObj.after(today)) { - returnCandidates.add(currentDateString); - } - } catch (Exception e) { - e.printStackTrace(); - continue; - } - } - if (returnCandidates == null | returnCandidates.size() < 1) { - throw new Exception("return list is null or empty after removeFutureDates runs"); - } else { - return returnCandidates; - } - } - - public static java.util.Date convertStringToDate(String dateString) - throws Exception { - DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); - DateFormat df2 = new SimpleDateFormat("yyyy-MM"); - DateFormat df3 = new SimpleDateFormat("yyyy"); - - java.util.Date returnDate = null; - try { - returnDate = df.parse(dateString); - } catch (Exception e) { - try { - returnDate = df2.parse(dateString); - } catch (Exception f) { - try { - returnDate = df3.parse(dateString); - } catch (Exception g) { - g.printStackTrace(); - } - } - } - if (returnDate == null) { - throw new Exception("date in convertStringToDate is null"); - } else { - return returnDate; - } - } - - public static java.util.Date getToday() { - final Calendar cal = Calendar.getInstance(); - - return cal.getTime(); - } - - public static ArrayList removeYesterdayDatesIfTheyAreNotTheOnlyDates( - ArrayList candidates) - throws Exception { - String yesterday = getYesterdayDateString(); - ArrayList returnCandidates = new ArrayList(); - int yesterdayCounter = 0; - - for (int i = 0; i < candidates.size(); i++) { - if (candidates.get(i).equals(yesterday)) { - yesterdayCounter++; - } else { - returnCandidates.add(candidates.get(i)); - } - } - if (yesterdayCounter == candidates.size() | yesterdayCounter == 0) { - // yesterday is the only date or yesterday doesn't occur at all - returnCandidates = candidates; - } else if (yesterdayCounter != 0 && yesterdayCounter < candidates.size()) { - // keep returnCandidates as it is from the for loop above - } - if (returnCandidates == null | returnCandidates.size() < 1) { - throw new Exception( - "removeYesterdayDatesIfTheyAreNotTheOnlyDates method returned null or empty arrayList"); - } else { - return returnCandidates; - } - } - -// use this function to remove false positive from NLP that are clearly before the project started, such as "1492" - public static ArrayList removeExcessivePastDates(ArrayList candidates) - throws Exception { -// TODO add handling for tweets coming from future in datelines - ArrayList returnCandidates = new ArrayList(); - - for (int i = 0; i < candidates.size(); i++) { - String currentDateString = candidates.get(i); - try { - java.util.Date currentDateObj = convertStringToDate(currentDateString); - if (currentDateObj == null) { - System.out.println("currentDateObj in removeFutureDates is null"); - } - if (!currentDateObj.before(convertStringToDate("1930-01-01"))) { - returnCandidates.add(currentDateString); - } - } catch (Exception e) { - e.printStackTrace(); - continue; - } - } - if (returnCandidates == null | returnCandidates.size() < 1) { - throw new Exception("return list is null or empty after removeExcessivePastDates runs"); - } else { - return returnCandidates; - } - } - - public static String getYesterdayDateString() { - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - - return dateFormat.format(getYesterday()); - } - - public static java.util.Date getYesterday() { - final Calendar cal = Calendar.getInstance(); - - cal.add(Calendar.DATE, -1); - return cal.getTime(); - } - -// overloaded version to deal with tweets - public static String parseDateStringForBestDate(String rootDir, Status tweet) - throws Exception { - String text = TwitterUtil.getText(tweet); - - System.out.println("Entering nlpDateParse twitter version with text " + text); -// create my pipeline with the help of the annotators I added. - - // Date tweetDate=tweet.getCreatedAt(); - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - String selectedDate = parseDateStringForBestDate(rootDir, text, relativeDate); - System.out.println("Best guess for referenced Tweet date from NLP: " + selectedDate); - return selectedDate; - } -} diff --git a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java b/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java deleted file mode 100644 index b2da0c3a02..0000000000 --- a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java +++ /dev/null @@ -1,673 +0,0 @@ -package org.ecocean.ai.utilities; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.Collection; -import java.util.Date; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; -import java.util.regex.*; - -import javax.jdo.Query; -import org.ecocean.ai.nlp.SUTime; -import org.ecocean.ai.nmt.azure.DetectTranslate; -import org.ecocean.Encounter; -import org.ecocean.identity.IBEISIA; -import org.ecocean.LinkedProperties; -import org.ecocean.media.MediaAsset; -import org.ecocean.media.MediaAssetMetadata; -import org.ecocean.media.YouTubeAssetStore; -import org.ecocean.Occurrence; -import org.ecocean.Shepherd; -import org.ecocean.ShepherdProperties; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; -import org.json.JSONObject; - -import com.google.api.services.youtube.model.Comment; -import com.google.api.services.youtube.model.CommentSnippet; -import com.google.api.services.youtube.model.CommentThread; -import com.google.api.services.youtube.model.CommentThreadReplies; -import com.google.api.services.youtube.model.CommentThreadSnippet; - -import twitter4j.Status; - -public class ParseDateLocation { - public static ArrayList parseLocation(String text, String context) { - ArrayList locations = new ArrayList<>(); - - // translate to English if not English - try { - text = detectLanguageAndTranslateToEnglish(text, context); - } catch (RuntimeException e) { - e.printStackTrace(); - } - // check for obvious Encounter.locationIDs - try { - locations.add(getLocationCodeKey(text, context)); - } catch (RuntimeException e) { - e.printStackTrace(); - } - /* - //use NLP - TO DO try{ - ArrayList nlpLocations = nlpLocationParse(text); - for (int i = 0; i>>>>> looking for date with NLP"); - // call Stanford NLP function to find and select a date from ytRemarks - myDate = org.ecocean.ai.nlp.SUTime.parseDateStringForBestDate(rootDir, tweet); - // parse through the selected date to grab year, month and day separately.Remove cero from month and day with intValue. - System.out.println(">>>>>> NLP found date: " + myDate); - } catch (Exception e) { - System.out.println("Exception in NLP in IBEISIA.class"); - e.printStackTrace(); - } - return myDate; - } - return null; - } - - - // NOTE: parseDate method WITHOUT tweet4j status object as a parameter. There is another parseDate method! - public static String parseDate(String rootDir, String textInput, String context) { - // int year=-1; - // int month=-1; - // int day=-1; - - try { - String detectedLanguage = DetectTranslate.detectLanguage(textInput); - if (!detectedLanguage.toLowerCase().startsWith("en")) { - textInput = DetectTranslate.translateToEnglish(textInput); - System.out.println("Translated text for parseLocation is " + textInput); - } - } catch (Exception e) { - System.out.println("Exception trying to detect language."); - e.printStackTrace(); - } - String myDate = null; - - // boolean NLPsuccess=false; - try { - System.out.println(">>>>>> looking for date with NLP"); - // call Stanford NLP function to find and select a date from ytRemarks - myDate = org.ecocean.ai.nlp.SUTime.parseDateStringForBestDate(rootDir, textInput); - System.out.println(">>>>>> NLP found date: " + myDate); - } catch (Exception e) { - System.out.println("Exception in NLP in IBEISIA.class"); - e.printStackTrace(); - } - return myDate; - } - - -/** - * Pass in a MediaAsset that derives from a YouTube video, and this method will go check for any additional info, such as response comments, that - * might help refine or populate derived Encounter dates and locations - * - * @param ma - * @param suDirPath - * @param myShepherd a Shepherd object - * @param context The context that WIldbook is running in. A null value will assume context0. - * @param numVideosWithID Allows you to keep a running, thread-safe tabulation of videos that have resulted in individualIDs. Can be null. - * @param numVideos Allows you to keep a running, thread-safe tabulation of a total number of videos as a result of running this method repeatedly. - * Can be null. - * @param numUncuratedVideos Allows you to keep a running, thread-safe tabulation of videos that have NOT been curated (Encounter.state != approved or - * unidentifiable). Can be null. - * @param numCommentedVideos Allows you to keep a running, thread-safe tabulation of videos that the IntelligentAgent has commented upon. Can be null. - * @param numCommentedVideosReplies Allows you to keep a running, thread-safe tabulation of videos that the IntelligentAgent has commented upon AND - * that have replies. Can be null. - * @param goodDataVideos Allows you to keep a running tab of appropriate videos processed outside this method. Can be null. - * @param poorDataVideos Allows you to keep a running tab of inappropriate videos processed outside this method. Can be null. - * @param persistDifferences Whether to save the updated date and location values found by the Intelligent Agent during executing this method. - * @param numDatesFound Allows you to keep a running, thread-safe tabulation of a total number of video-derived date updates made as a result of - * running this method repeatedly. Can be null. - * @param numLocationIDsFound Allows you to keep a running, thread-safe tabulation of a total number of video-derived location updates made as a - * result of running this method repeatedly. Can be null. - * @return String an HTML table row of found text and changes - */ - public static String annotateChildrenOfYouTubeMediaAssetWithDateLocation(MediaAsset ma, - String suDirPath, Shepherd myShepherd, String context, AtomicInteger numVideosWithID, - AtomicInteger numVideos, AtomicInteger numUncuratedVideos, AtomicInteger numCommentedVideos, - AtomicInteger numCommentedVideosReplies, ArrayList goodDataVideos, - ArrayList poorDataVideos, boolean persistDifferences, - AtomicInteger numDatesFound, AtomicInteger numLocationIDsFound) { - // if we're going to persist changes, ensure the Shepherd object is ready - if (persistDifferences && !myShepherd.getPM().currentTransaction().isActive()) { - myShepherd.beginDBTransaction(); - } - // allow context to be NULL but assume context0 if it is set as null - if (context == null) context = "context0"; - // the return string of HTML content - String resultsHTML = ""; - - // whether the video has resulted in an Encounter assigned to a MarkedIndividual - boolean videoHasID = false; - - // whether we found a Wild Me comment on the video - boolean hasWildMeComment = false; - - // whether any found Wild Me comment has a reply - boolean hasWildMeCommentReplies = false; - - // the date of the video, allowing for relative evaluation of the true date via SUTime - // to start with, we assume today's dat but will process this later. - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - // video has metadata for analysis? - if ((ma.getMetadata() != null)) { - if (numVideos != null) numVideos.incrementAndGet(); - MediaAssetMetadata md = ma.getMetadata(); - // video metadata is not null, so proceed - if (md.getData() != null) { - // setup our metadata fields - String videoID = ma.getMetadata().getData().getJSONObject("detailed").optString( - "id"); - String videoTitle = ""; - // just to save money on language detection, reduce number of characters sent - String videoTitleShort = videoTitle; - String videoComments = ""; - String videoCommentsClean = ""; - String locIDWords = ""; - String videoDescription = ""; - String videoTags = ""; - // start capturing metadata about the YouTube video - // video title short form just to save $$$ on language detection by sending fewer characters - if (videoTitle.length() > 500) { videoTitleShort = videoTitle.substring(0, 500); } - if (md.getData().optJSONObject("basic") != null) { - videoTitle = AIUtilities.youtubePredictorPrepareString( - md.getData().getJSONObject("basic").optString("title")); - } - if (md.getData().optJSONObject("detailed") != null) { - videoDescription = AIUtilities.youtubePredictorPrepareString( - md.getData().getJSONObject("detailed").optString("description")); - videoTags = AIUtilities.youtubePredictorPrepareString( - md.getData().getJSONObject("detailed").getJSONArray("tags").toString()); - } - // video description short form just to save $$$ on language detection by sending fewer characters - String videoDescriptionShort = videoDescription; - if (videoDescription.length() > 1000) { - videoDescriptionShort = videoDescription.substring(0, 1000); - } - // video tags short form just to save $$$ on language detection by sending fewer characters - String videoTagsShort = videoTags; - if (videoTags.length() > 500) { videoTagsShort = videoTags.substring(0, 500); } - String ytRemarks = videoTitle + " " + videoDescription + " " + videoTags; - String storedLanguage = "null"; - String detectedLanguage = "en"; - boolean languageIsStored = false; - // first, set metadata lanuage on the mediaasset - if (md.getData().optJSONObject("detected") != null) { - if (md.getData().getJSONObject("detected").optString("langCode") != null) { - String storedData = md.getData().getJSONObject("detected").optString( - "langCode"); - if ((!storedData.trim().equals("")) && - (storedData.toLowerCase().indexOf("unknown") == -1)) { - // if(!detectedLanguage.equals(storedData))changedDetectedLanguage=true; - detectedLanguage = storedData; - languageIsStored = true; - } - } - } - if (!languageIsStored) { - try { - detectedLanguage = DetectTranslate.detectLanguage(videoTitleShort + " " + - videoDescriptionShort + " " + videoTagsShort); - JSONObject json = md.getData(); - JSONObject jsonDetected = new JSONObject(); - jsonDetected.put("langCode", detectedLanguage); - json.put("detected", jsonDetected); - md.setData(json); - ma.setMetadata(new MediaAssetMetadata(json)); - // ma.setMetadata(md); - myShepherd.commitDBTransaction(); - myShepherd.beginDBTransaction(); - } catch (Exception e) { - e.printStackTrace(); - } - } - // Let's get the Encounter objects related to this video - // JDOQL query - String qFilter = - "SELECT FROM org.ecocean.Encounter WHERE (occurrenceRemarks.indexOf('" + - videoID + "') != -1)"; - Query newQ = myShepherd.getPM().newQuery(qFilter); - Collection d = (Collection)newQ.execute(); - ArrayList encresults = new ArrayList(d); - newQ.closeAll(); - int numEncs = encresults.size(); - - // let's iterate our matching Encounters - // first, check if any have been approved (curated) and count them - boolean videoIsCurated = false; - for (int y = 0; y < numEncs; y++) { - Encounter enc = encresults.get(y); - if ((enc.getState() != null) && - ((enc.getState().equals("approved")) || - (enc.getState().equals("unidentifiable")))) { - if ((goodDataVideos != null) && !goodDataVideos.contains(ma)) - goodDataVideos.add(ma); - videoIsCurated = true; - } - if ((enc.getIndividualID() != null) && (!enc.getIndividualID().equals(""))) - videoHasID = true; - } - if (!videoIsCurated && (numUncuratedVideos != null)) - numUncuratedVideos.incrementAndGet(); - Occurrence occur = null; - LinkedProperties props = (LinkedProperties)ShepherdProperties.getProperties( - "submitActionClass.properties", "", context); - String chosenStyleDate = ""; - String chosenStyleLocation = ""; - // if we have matching encounters, then the video is either uncurated, or it has been determined to have useful data (curated) - if (numEncs > 0) { - // check for Occurrence - String occurID = ""; - - // grab the first Encounter for analysis - Encounter enc = encresults.get(0); - - // get the current values for date and location ID - String currentDate = ""; - String currentLocationID = ""; - if (enc.getDate() != null) - currentDate = enc.getDate().replaceAll("Unknown", ""); - if (enc.getLocationID() != null) - currentLocationID = enc.getLocationID().replaceAll("None", ""); - // our encounters should all have an Occurrence, one per video - if (enc.getOccurrenceID() != null) { - occur = myShepherd.getOccurrence(enc.getOccurrenceID()); - - // let's get all our YouTube video metadata and comments - // List comments = YouTube.getVideoCommentsList(occur, context); deprecated, issue 622 - List comments = null; - if ((comments == null) || (comments.size() == 0)) { - videoComments = ""; - videoCommentsClean = ""; - } else { - boolean isWildMeComment = false; - int numComments = comments.size(); - videoComments += "
    \n"; - for (int f = 0; f < numComments; f++) { - CommentThread ct = comments.get(f); - CommentThreadSnippet cts = ct.getSnippet(); - Comment topLevelComment = cts.getTopLevelComment(); - CommentSnippet commentSnippet = topLevelComment.getSnippet(); - String authorName = ""; - if ((commentSnippet != null) && - (commentSnippet.getAuthorDisplayName() != null)) { - authorName = commentSnippet.getAuthorDisplayName(); - // TO DO: set this aside to a Properties file for the agent - if (authorName.equals("Wild Me")) isWildMeComment = true; - } - String style = ""; - if (isWildMeComment) { - style = "color: green;font-weight: bold;"; - hasWildMeComment = true; - } - videoComments += "
  • " + authorName + - ": " + - DetectTranslate.translateIfNotEnglish( - topLevelComment.getSnippet().getTextDisplay()); - - videoCommentsClean += DetectTranslate.translateIfNotEnglish( - topLevelComment.getSnippet().getTextDisplay()).toLowerCase() + - " "; - if (ct.getReplies() != null) { - CommentThreadReplies ctr = ct.getReplies(); - List replies = ctr.getComments(); - int numReplies = 0; - if (replies != null) numReplies = replies.size(); - if (numReplies > 0) { - if (isWildMeComment) hasWildMeCommentReplies = true; - videoComments += "
      \n"; - for (int g = 0; g < numReplies; g++) { - Comment reply = replies.get(g); - - videoComments += "
    • " + - DetectTranslate.translateIfNotEnglish( - reply.getSnippet().getTextDisplay()) + "
    • "; - videoCommentsClean += - DetectTranslate.translateIfNotEnglish( - reply.getSnippet().getTextDisplay()).toLowerCase() + - " "; - } - videoComments += "
    \n"; - } - } - videoComments += "
  • \n"; - style = ""; - } - videoComments += "
\n"; - } - occurID = occur.getOccurrenceID(); - - // prep the YouTube video date for SUTimee analysis - String tempRelativeDate = null; - try { - // tempRelativeDate = YouTube.getVideoPublishedAt(occur, context); deprecated, issue 622 - tempRelativeDate = null; - } catch (Exception e) {} - if ((tempRelativeDate != null) && (tempRelativeDate.indexOf("T") != -1)) { - tempRelativeDate = tempRelativeDate.substring(0, - tempRelativeDate.indexOf("T")); - } - if ((tempRelativeDate != null) && (!tempRelativeDate.equals(""))) { - DateTimeFormatter parser2 = DateTimeFormat.forPattern("yyyy-MM-dd"); - DateTime time = parser2.parseDateTime(tempRelativeDate); - relativeDate = time.toString(parser2); - } - } - StringBuffer sbOriginalText = new StringBuffer(""); - sbOriginalText.append(videoTitle + " " + videoDescription + " " + videoTags + - " " + videoCommentsClean); - - // let's do some translation to English for standardization - videoTitle = DetectTranslate.translateIfNotEnglish(videoTitleShort); - videoTags = DetectTranslate.translateIfNotEnglish(videoTagsShort); - videoDescription = DetectTranslate.translateIfNotEnglish(videoDescriptionShort); - - StringBuffer sb = new StringBuffer(""); - - sb.append(videoTitle + " " + videoDescription + " " + videoTags + " " + - videoCommentsClean); - - // get video date with SUTime - String newDetectedDate = ""; - try { - newDetectedDate = SUTime.parseDateStringForBestDate(suDirPath, - sb.toString(), relativeDate).replaceAll("null", ""); - } catch (Exception e) { - e.printStackTrace(); - } - if ((numDatesFound != null) && (goodDataVideos != null) && - goodDataVideos.contains(ma) && !newDetectedDate.equals("")) { - numDatesFound.incrementAndGet(); - } - // determine new LocationID, including comments - String newLocationID = ""; - String lowercaseRemarks = sb.toString().toLowerCase(); - try { - Iterator m_enum = props.orderedKeys().iterator(); - while (m_enum.hasNext()) { - String aLocationSnippet = ((String)m_enum.next()).replaceFirst("\\s++$", - ""); - // System.out.println(" Looking for: "+aLocationSnippet); - if (lowercaseRemarks.indexOf(aLocationSnippet) != -1) { - newLocationID = props.getProperty(aLocationSnippet); - locIDWords += " " + aLocationSnippet; - // System.out.println(".....Building an idea of location: "+location); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - if (newLocationID == null) newLocationID = ""; - if ((numLocationIDsFound != null) && (goodDataVideos != null) && - goodDataVideos.contains(ma) && !newLocationID.equals("")) { - numLocationIDsFound.incrementAndGet(); - } - // here is where we would put logic to update encounters if appropriate - if (persistDifferences) { - boolean madeAChange = false; - for (int y = 0; y < numEncs; y++) { - Encounter thisEnc = encresults.get(y); - // SET LOCATION ID - // first, if we even found a location ID in comments, lets' consider it. - // otherwise, there's no point - if ((newLocationID != null) && (!newLocationID.trim().equals(""))) { - // next, if we have a new locationID and one was not set before, then this is an easy win - if ((thisEnc.getLocationID() == null) || - (thisEnc.getLocationID().trim().equals("")) || - (thisEnc.getLocationID().trim().equals("None"))) { - thisEnc.setLocationID(newLocationID); - madeAChange = true; - } else if (!thisEnc.getLocationID().trim().equals( - newLocationID.trim())) { - // ok, the location IDs are different, now what? - // maybe the newLocationID further specifies the older locationID, that would be a win - if (newLocationID.trim().startsWith( - thisEnc.getLocationID().trim())) { - thisEnc.setLocationID(newLocationID.trim()); - madeAChange = true; - } - // if the Encounter is not yet approved, then we can reset it as well since it's uncurated and may have been - // incorrectly detected with older values - else if ((thisEnc.getState() != null) && - (thisEnc.getState().equals("auto_sourced"))) { - thisEnc.setLocationID(newLocationID.trim()); - madeAChange = true; - } - } - } - // now persist - if (madeAChange) { - myShepherd.commitDBTransaction(); - myShepherd.beginDBTransaction(); - } - if (madeAChange) chosenStyleLocation = "font-style: italic;"; - // END SET LOCATION ID - - // SET THE DATE - madeAChange = false; - chosenStyleDate += "year: " + thisEnc.getYear() + ";millis:" + - thisEnc.getDateInMilliseconds() + ";locationID: " + - thisEnc.getLocationID() + ";"; - // let's check and fix date - if ((newDetectedDate != null) && (!newDetectedDate.trim().equals(""))) { - // well we have something to analyze at least - // DateTimeFormatter parser3 = DateTimeFormat.forPattern("yyyy-MM-dd"); - DateTimeFormatter parser3 = ISODateTimeFormat.dateParser(); - DateTime dt = parser3.parseDateTime(newDetectedDate); - // check for the easy case - if ((thisEnc.getDateInMilliseconds() == null) || - (thisEnc.getYear() <= 0)) { - if (newDetectedDate.length() == 10) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - thisEnc.setDay(dt.getDayOfMonth()); - } else if (newDetectedDate.length() == 7) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - } else if (newDetectedDate.length() == 4) { - thisEnc.setYear(dt.getYear()); - } - // thisEnc.setDateInMilliseconds(dt.getMillis()); - - chosenStyleDate += "font-style: italic; color: red;"; - madeAChange = true; - } - // if it's unapproved/uncurated, trust the newer value - else if (thisEnc.getState().equals("auto_sourced")) { - if (newDetectedDate.length() == 10) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - thisEnc.setDay(dt.getDayOfMonth()); - } else if (newDetectedDate.length() == 7) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - } else if (newDetectedDate.length() == 4) { - thisEnc.setYear(dt.getYear()); - } - chosenStyleDate += "font-style: italic; color: green;"; - madeAChange = true; - } - } - // now persist - if (madeAChange) { - myShepherd.commitDBTransaction(); - myShepherd.beginDBTransaction(); - } - // END SET DATE - } - } - resultsHTML = - "" + occurID + - "" + videoID + "" + currentDate + - "

" + newDetectedDate + - "

" + currentLocationID + "

" + newLocationID + "

" + videoTitle + - "" + videoDescription + "" + videoComments + "" + - videoCommentsClean + "

LocID Words: " + locIDWords + - "

" + relativeDate + "" + storedLanguage + "/" + - detectedLanguage + ""; - } - // this video had no encounters, probably been curated as having no value - else { - if ((poorDataVideos != null) && !poorDataVideos.contains(ma)) { - poorDataVideos.add(ma); - if (numUncuratedVideos != null) numUncuratedVideos.decrementAndGet(); - } - } - } - // video metadata is null, not much we can do here - else { - if ((poorDataVideos != null) && !poorDataVideos.contains(ma)) - poorDataVideos.add(ma); - } - } - // video had no metadata, not much we can do here - // add to poorDataVideos because there's nothing we can with it - else { - if ((poorDataVideos != null) && !poorDataVideos.contains(ma)) poorDataVideos.add(ma); - } - // increment our counters as needed - if (hasWildMeComment && (numCommentedVideos != null)) numCommentedVideos.incrementAndGet(); - if (hasWildMeCommentReplies && (numCommentedVideosReplies != null)) - numCommentedVideosReplies.incrementAndGet(); - if (videoHasID && (numVideosWithID != null)) numVideosWithID.incrementAndGet(); - return resultsHTML; - } - - public static boolean hasRunDetection(MediaAsset ma, Shepherd myShepherd) { - List children = YouTubeAssetStore.findFrames(ma, myShepherd); - - if (children != null) { - int numChildren = children.size(); - for (int i = 0; i < numChildren; i++) { - MediaAsset child = children.get(i); - if ((child.getDetectionStatus() != null) && - (child.getDetectionStatus().equals(IBEISIA.STATUS_COMPLETE))) { - return true; - } - } - } - return false; - } -} diff --git a/src/main/java/org/ecocean/servlet/SUTimePipeline.java b/src/main/java/org/ecocean/servlet/SUTimePipeline.java deleted file mode 100644 index 832bf558ec..0000000000 --- a/src/main/java/org/ecocean/servlet/SUTimePipeline.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.ecocean.servlet; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.IOException; -import java.util.Properties; - -import edu.stanford.nlp.ling.CoreAnnotations; -import edu.stanford.nlp.pipeline.Annotation; -import edu.stanford.nlp.pipeline.Annotator; -import edu.stanford.nlp.pipeline.StanfordCoreNLP; -import edu.stanford.nlp.time.GUTimeAnnotator; -import edu.stanford.nlp.time.HeidelTimeAnnotator; -import edu.stanford.nlp.time.TimeAnnotations; -import edu.stanford.nlp.time.TimeAnnotator; - -public class SUTimePipeline { - /** A logger for this class */ - // private static Redwood.RedwoodChannels log = Redwood.channels(SUTimePipeline.class); - final StanfordCoreNLP pipeline; - - public SUTimePipeline() { - this(new Properties()); - } - - public SUTimePipeline(Properties props) { - // By default, we want to tokenize the text, split it into - // sentences, and then put it through the sutime annotator. - // We also want to pos tag it and put it through the number and - // qen annotators. - // Since there will be different options for the sutime annotator, - // we will actually create a new sutime annotator for each query. - // This should be inexpensive. - if (props.getProperty("annotators") == null) { - props.setProperty("annotators", "tokenize, ssplit, pos"); -// "tokenize, ssplit, pos, number, qen"); - } -/* if (props.getProperty("customAnnotatorClass.number") == null) { - props.setProperty("customAnnotatorClass.number", - "edu.stanford.nlp.pipeline.NumberAnnotator"); - } - if (props.getProperty("customAnnotatorClass.qen") == null) { - props.setProperty("customAnnotatorClass.qen", - "edu.stanford.nlp.pipeline.QuantifiableEntityNormalizingAnnotator"); - } */ - // this replicates the tokenizer behavior in StanfordCoreNLP - props.setProperty("tokenize.options", "invertible,ptb3Escaping=true"); - this.pipeline = new StanfordCoreNLP(props); - } - - public boolean isDateOkay(String dateString) { - return true; // TODO: can we predict which ones it won't like? - } - - public Annotator getTimeAnnotator(String annotatorType, Properties props) { - switch (annotatorType) { - case "sutime": - return new TimeAnnotator("sutime", props); - case "gutime": - return new GUTimeAnnotator("gutime", props); - case "heideltime": - return new HeidelTimeAnnotator("heidelTime", props); - default: - return null; - } - } - - public Annotation process(String sentence, String dateString, Annotator timeAnnotator) { - // log.info("Processing text \"" + sentence + "\" with dateString = " + dateString); - Annotation anno = new Annotation(sentence); - - if (dateString != null && !dateString.isEmpty()) { - anno.set(CoreAnnotations.DocDateAnnotation.class, dateString); - } - pipeline.annotate(anno); - - timeAnnotator.annotate(anno); - return anno; - } - - public static void main(String[] args) - throws IOException { - SUTimePipeline pipeline = new SUTimePipeline(); - Annotator timeAnnotator = pipeline.getTimeAnnotator("sutime", new Properties()); - BufferedReader is = new BufferedReader(new InputStreamReader(System.in)); - - System.out.print("> "); - for (String line; (line = is.readLine()) != null;) { - Annotation ann = pipeline.process(line, null, timeAnnotator); - System.out.println(ann.get(TimeAnnotations.TimexAnnotations.class)); - System.out.print("> "); - } - } -} From a292a7172f9daf69b6dd267083924e5825b8f334 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Tue, 27 Aug 2024 16:10:39 -0600 Subject: [PATCH 17/41] remove pom dependencies, and some misc --- pom.xml | 27 ------------------- .../org/ecocean/media/YouTubeAssetStore.java | 3 +++ src/main/webapp/WEB-INF/web.xml | 1 - 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index f36c2b1d74..3a3339bd31 100644 --- a/pom.xml +++ b/pom.xml @@ -515,33 +515,6 @@ 0.6.1 - - - edu.stanford.nlp - stanford-corenlp - 3.9.1 - - - com.google.protobuf - protobuf-java - - - - - - - sutime-stanford-corenlp-models - sutime-stanford-corenlp-models - 3.6.0 - - - - - edu.stanford.nlp - stanford-parser - 3.9.1 - - nz.ac.waikato.cms.weka diff --git a/src/main/java/org/ecocean/media/YouTubeAssetStore.java b/src/main/java/org/ecocean/media/YouTubeAssetStore.java index 506c0c8262..2085c0a737 100644 --- a/src/main/java/org/ecocean/media/YouTubeAssetStore.java +++ b/src/main/java/org/ecocean/media/YouTubeAssetStore.java @@ -18,6 +18,9 @@ import org.json.JSONException; import org.json.JSONObject; + +// soon to be deprecated: https://github.com/WildMeOrg/Wildbook/issues/694 + /** * YouTubeAssetStore references MediaAssets that reside on YouTube. * currently this is read-only but later could be writable with an API key if needed? diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 85c5981d27..8a643f2a9b 100755 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -404,7 +404,6 @@ /SimpleCMRSpecifySessions.jsp = authc, roles[researcher] /occurrenceExportSearchResults.jsp = authc, roles[researcher] - /sutime/** = authc /EncounterRemoveUser = authc, roles[researcher] /EncounterAddUser = authc, roles[researcher] From 477ff77382797b019559cd8bd95dfd4d0b851cc3 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Wed, 28 Aug 2024 14:27:23 -0600 Subject: [PATCH 18/41] rm commented deprecated call --- src/main/java/org/ecocean/media/YouTubeAssetStore.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/org/ecocean/media/YouTubeAssetStore.java b/src/main/java/org/ecocean/media/YouTubeAssetStore.java index 2085c0a737..f94138a9fb 100644 --- a/src/main/java/org/ecocean/media/YouTubeAssetStore.java +++ b/src/main/java/org/ecocean/media/YouTubeAssetStore.java @@ -332,13 +332,6 @@ public MediaAssetMetadata extractMetadata(MediaAsset ma, boolean minimal) JSONObject data = new JSONObject(); // we (attempt to) let the basic stuff finish synchronously, so we have a populated data chunk to save (hopefully)before the detailed one does -/* deprecated due to issue 622, retirement of YouTube agent - try { - data.put("basic", YouTube.simpleInfo(idFromParameters(ma.getParameters()))); - } catch (Exception ex) { - System.out.println(ma + " failed simpleInfo(): " + ex.toString()); - } -*/ if (!minimal) { data.put("detailed", new JSONObject("{\"_processing\": true, \"timestamp\": " + From 280ec0389574fbf67603d3f992e287e070244292 Mon Sep 17 00:00:00 2001 From: Tanya <62726866+TanyaStere42@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:41:39 -0700 Subject: [PATCH 19/41] upgraded from alpha to beta usability: no red text otherwise, we refer to bulk import as in beta, not in alpha, everywhere except for the actual bulk import page. Unified messaging is important --- src/main/webapp/import/instructions.jsp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/import/instructions.jsp b/src/main/webapp/import/instructions.jsp index a8a702b326..1a21685546 100644 --- a/src/main/webapp/import/instructions.jsp +++ b/src/main/webapp/import/instructions.jsp @@ -37,8 +37,7 @@ String wbName = ContextConfiguration.getNameForContext(context); } .warning { border-radius: 5px; - background-color: lightgrey; - color: red; + background-color: #f0e130; padding: 5px; } @@ -49,7 +48,7 @@ String wbName = ContextConfiguration.getNameForContext(context);

Bulk Import: Instructions

- This feature is in Alpha. This means it is untested and unreleased. Please only use this tool if you are willing to help us test the UI and report bugs. Your data might not be imported correctly until we have done further testing and development. + This feature is in Beta. This means has been updated and tested, but is still under active development. Please only use this tool if you are willing to help us test the UI and report bugs. Your data might not be imported correctly until we have done further testing and development.

The goal of this tool is to allow scientists to add large amounts of data to <%=wbName%> at once, such as an entire season's observations, while performing the data-blending and data-integrity checks themselves.

From 0e6a95d96c0347d096dc7a46f49cb0207907fd5b Mon Sep 17 00:00:00 2001 From: erinz2020 Date: Thu, 29 Aug 2024 14:04:38 +0000 Subject: [PATCH 20/41] add de flag, adjust language order in dropdown menu --- frontend/public/flags/de.png | Bin 0 -> 6021 bytes frontend/src/App.jsx | 2 ++ frontend/src/constants/locales.js | 10 +++++----- 3 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 frontend/public/flags/de.png diff --git a/frontend/public/flags/de.png b/frontend/public/flags/de.png new file mode 100644 index 0000000000000000000000000000000000000000..92b1f1fdca06d2aa5775c9edae56da421ea8bee8 GIT binary patch literal 6021 zcmex=ctd(A&7xhQ(;Tmtd^ZOV3$#nZy@&#Ww7UKhB zgjDFOI=;7_AIf!c&ek8cha;xd&aZcyV<|T8lg#pkJv(N?7%M)+c{SfFw_7E;*fRS= zb=yXr-**3cEsAt)pIG`kOBNcz7=aJ=Ol9Bmt~Ny5t?2rL@4QKo-)jF#6+DTmK2bEU z&FE1IjIsD&r51nXonI@$dY-O7_)hA`<~P58nLIqP<@gO)%d`o{n$6 zW7?U1^ZS>~!xJ;#E1s&7INb?jboH}7Sz-IU_|?KF<7xZZcVr8l-~9f?<#t%OAO#Tj z$$;u}&#yXdN!P98FSw>UKmGp2<$SKo_q1!iNY+z>F|=&NCoT9s_x!5XjB}&Gh?&kt zgK;!9j%Ml|qh;gZs$w*-)m1%=;_C~jUHgujH(Wx1X~s+G-o4#kRkG>@CcVe*9bIb6 zH+hFr_iNXWL5^n)YUAhcHCy!iw);mb*E1h_gVMQ@m*km!)75-YGWWnGbLncaDPOGo z9>hoKcTM8UY<~6U@5?QFx6}(Si8;@4Rjpu|mD}U|q)YSKJ@4=;7jEB}>F>Pc9qZRc zKUOL{n_;*9{Jq)UqehPg$Y=@~%`&59$Y`NDTFX$qZe;p(u_k0fv5$QC^Y^|>-!A?! dSLs=W+sf@0JZy;;!=({3>W^U>0`~uJ0st;s2E+gW literal 0 HcmV?d00001 diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 56f5ea2ea9..c1abbac6b2 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -4,6 +4,7 @@ import messagesEn from "./locale/en.json"; import messagesEs from "./locale/es.json"; import messagesFr from "./locale/fr.json"; import messagesIt from "./locale/it.json"; +import messagesDe from "./locale/de.json"; import "bootstrap/dist/css/bootstrap.min.css"; import "bootstrap-icons/font/bootstrap-icons.css"; import { QueryClient, QueryClientProvider } from "react-query"; @@ -20,6 +21,7 @@ function App() { es: messagesEs, fr: messagesFr, it: messagesIt, + de: messagesDe, }; const initialLocale = Cookies.get("wildbookLangCode") || "en"; const [locale, setLocale] = useState(initialLocale); diff --git a/frontend/src/constants/locales.js b/frontend/src/constants/locales.js index 0435361d87..faac826dbf 100644 --- a/frontend/src/constants/locales.js +++ b/frontend/src/constants/locales.js @@ -1,18 +1,18 @@ -const locales = ["de", "en", "es", "fr", "it"]; -const localeMap = { - de: "de", +const locales = ["en", "es", "fr", "it", "de"]; +const localeMap = { en: "en", es: "es", fr: "fr", it: "it", + de: "de", }; -const languageMap = { - de: "Deutsch", +const languageMap = { en: "English", es: "Español", fr: "Français", it: "Italiano", + de: "Deutsch", }; export { locales, localeMap, languageMap }; From 29345858a69a40046363bd71b614fc745f550d6e Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Thu, 29 Aug 2024 12:14:01 -0600 Subject: [PATCH 21/41] more cruft gone --- .../servlet/IndividualAddEncounter.java | 7 - .../WEB-INF/data/holidays/Holidays_sutime.xml | 44 - .../WEB-INF/data/sutime/rules/defs.sutime.txt | 201 ---- .../sutime/rules/english.holidays.sutime.txt | 29 - .../data/sutime/rules/english.sutime.txt | 964 ------------------ 5 files changed, 1245 deletions(-) delete mode 100644 src/main/webapp/WEB-INF/data/holidays/Holidays_sutime.xml delete mode 100644 src/main/webapp/WEB-INF/data/sutime/rules/defs.sutime.txt delete mode 100644 src/main/webapp/WEB-INF/data/sutime/rules/english.holidays.sutime.txt delete mode 100644 src/main/webapp/WEB-INF/data/sutime/rules/english.sutime.txt diff --git a/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java b/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java index 338cbb55e2..ccd629a6df 100644 --- a/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java +++ b/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java @@ -130,9 +130,6 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) // responseJSON=RESTUtils.getJSONObjectFromPOJO(addToMe, // ((JDOPersistenceManager)myShepherd.getPM()).getExecutionContext()).toString(); responseJSON = addToMe.uiJson(request, false).toString(); - - // youTube postback check - youTubePostback(enc2add, myShepherd, context); } catch (RuntimeException e) { e.printStackTrace(); myShepherd.rollbackDBTransaction(); @@ -305,10 +302,6 @@ public static void executeEmails(Shepherd myShepherd, HttpServletRequest request es.shutdown(); } - private void youTubePostback(Encounter enc2add, Shepherd myShepherd, String context) { - System.out.println("youTubePostback(): YouTube agent support has been deprecated"); - } - private void setDateLastModified(Encounter enc) { String strOutputDateTime = ServletUtilities.getDate(); diff --git a/src/main/webapp/WEB-INF/data/holidays/Holidays_sutime.xml b/src/main/webapp/WEB-INF/data/holidays/Holidays_sutime.xml deleted file mode 100644 index 3523b42b13..0000000000 --- a/src/main/webapp/WEB-INF/data/holidays/Holidays_sutime.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/data/sutime/rules/defs.sutime.txt b/src/main/webapp/WEB-INF/data/sutime/rules/defs.sutime.txt deleted file mode 100644 index 28afa933af..0000000000 --- a/src/main/webapp/WEB-INF/data/sutime/rules/defs.sutime.txt +++ /dev/null @@ -1,201 +0,0 @@ - RefTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$RefTime" } - SimpleTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$SimpleTime" } - InexactTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$InexactTime" } - InexactDuration = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$InexactDuration" } - DurationWithFields = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$DurationWithFields" } - //Duration = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$Duration" } - IsoDate = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$IsoDate" } - IsoTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$IsoTime" } - TimeRange = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$Range" } - TimeWithRange = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$TimeWithRange" } - RelativeTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$RelativeTime" } - OrdinalTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$OrdinalTime" } - PeriodicTemporalSet = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$PeriodicTemporalSet" } - ExplicitTemporalSet = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$ExplicitTemporalSet" } - - ANY = -1; - NONE = -1; - NON_TEMPORAL = "NON_TEMPORAL"; - - DURATION_UNKNOWN = DurationWithFields(); - DURATION_NONE = DurationWithFields(); - - TIME_NOW = { - type: REFTIME, - label: "PRESENT_REF", - value: RefTime("NOW") - } - TIME_PRESENT = { - type: REFDATE, - label: "PRESENT_REF", - value: InexactTime( TimeRange(TIME_NOW, TIME_NOW) ) - } - TIME_PAST = { - type: REFDATE, - label: "PAST_REF", - value: InexactTime( TimeRange(TIME_UNKNOWN, TIME_NOW) ) - } - TIME_FUTURE = { - type: REFDATE, - label: "FUTURE_REF", - value: InexactTime( TimeRange(TIME_NOW, TIME_UNKNOWN) ) - } - - // Predefined durations: YEAR, MONTH, DAY, WEEK, HOUR, MINUTE, SECOND - FORTNIGHT = { type: "TIMEUNIT", value: Duration(WEEK, 2) }; - HALFHOUR = Duration(MINUTE, 30); - QUARTERHOUR = Duration(MINUTE, 15); - - // Basic dates/times - MONDAY = DayOfWeek(1); - TUESDAY = DayOfWeek(2); - WEDNESDAY = DayOfWeek(3); - THURSDAY = DayOfWeek(4); - FRIDAY = DayOfWeek(5); - SATURDAY = DayOfWeek(6); - SUNDAY = DayOfWeek(7); - - WEEKEND = { - type: DAYS_OF_WEEK, - label: "WE", - value: TimeWithRange(TimeRange(SATURDAY, SUNDAY, Duration(DAY, 2))) - } - - JANUARY = MonthOfYear(1); - FEBRUARY = MonthOfYear(2); - MARCH = MonthOfYear(3); - APRIL = MonthOfYear(4); - MAY = MonthOfYear(5); - JUNE = MonthOfYear(6); - JULY = MonthOfYear(7); - AUGUST = MonthOfYear(8); - SEPTEMBER = MonthOfYear(9); - OCTOBER = MonthOfYear(10); - NOVEMBER = MonthOfYear(11); - DECEMBER = MonthOfYear(12); - - // Dates are rough with respect to northern hemisphere (actual - // solstice/equinox days depend on the year) - SPRING_EQUINOX = { - type: DAY_OF_YEAR, - value: InexactTime( TimeRange( IsoDate(ANY, 3, 20), IsoDate(ANY, 3, 21) ) ) - } - SUMMER_SOLSTICE = { - type: DAY_OF_YEAR, - value: InexactTime( TimeRange( IsoDate(ANY, 6, 20), IsoDate(ANY, 6, 21) ) ) - } - FALL_EQUINOX = { - type: DAY_OF_YEAR, - value: InexactTime( TimeRange( IsoDate(ANY, 9, 22), IsoDate(ANY, 9, 23) ) ) - } - WINTER_SOLSTICE = { - type: DAY_OF_YEAR, - value: InexactTime( TimeRange( IsoDate(ANY, 12, 21), IsoDate(ANY, 12, 22) ) ) - } - - // Dates for seasons are rough with respect to northern hemisphere - SPRING = { - type: SEASON_OF_YEAR, - label: "SP", - value: InexactTime( SPRING_EQUINOX, QUARTER, TimeRange( MARCH, JUNE, QUARTER ) ) } - SUMMER = { - type: SEASON_OF_YEAR, - label: "SU", - value: InexactTime( SUMMER_SOLSTICE, QUARTER, TimeRange( JUNE, SEPTEMBER, QUARTER ) ) - } - FALL = { - type: SEASON_OF_YEAR, - label: "FA", - value: InexactTime( FALL_EQUINOX, QUARTER, TimeRange( SEPTEMBER, DECEMBER, QUARTER ) ) - } - WINTER = { - type: SEASON_OF_YEAR, - label: "WI", - value: InexactTime( WINTER_SOLSTICE, QUARTER, TimeRange( DECEMBER, MARCH, QUARTER ) ) - } - - // Time of day - NOON = IsoTime( 12, 0, NONE ) - MIDNIGHT = IsoTime( 0, 0, NONE ) - MORNING = { - type: TIME_OF_DAY, - label: "MO", - value: InexactTime( TimeRange ( IsoTime( 6, NONE, NONE), NOON ) ) - } - AM = IsoTime(NIL, NIL, NIL, NIL, HALFDAY_AM) - PM = IsoTime(NIL, NIL, NIL, NIL, HALFDAY_PM) - AFTERNOON = { - type: TIME_OF_DAY, - label: "AF", - value: InexactTime( TimeRange ( NOON, IsoTime( 18, NONE, NONE) ) ) - } - EVENING = { - type: TIME_OF_DAY, - label: "EV", - value: InexactTime( TimeRange ( IsoTime( 18, NONE, NONE), IsoTime ( 20, NONE, NONE) ) ) - } - NIGHT = { - type: TIME_OF_DAY, - label: "NI", - value: InexactTime( MIDNIGHT, TimeRange ( IsoTime( 19, NONE, NONE), Duration(HOUR, 10) ) ) - } - - SUNRISE = { - type: TIME_OF_DAY, - label: "MO", - modifier: "EARLY" - } - - SUNSET = { - type: TIME_OF_DAY, - label: "EV", - modifier: "EARLY" - } - - DAWN = { - type: TIME_OF_DAY, - label: "MO", - modifier: "EARLY" - } - - DUSK = { - type: TIME_OF_DAY, - label: "EV", - modifier: "EARLY" - } - - LUNCHTIME = InexactTime( TimeRange( IsoTime(12, NONE, NONE), IsoTime(14, NONE, NONE) )) - TEATIME = InexactTime( TimeRange( IsoTime(15, NONE, NONE), IsoTime(17, NONE, NONE) )) - DINNERTIME = InexactTime( TimeRange( IsoTime(18, NONE, NONE), IsoTime(20, NONE, NONE) )) - - DAYTIME = { - type: TIME_OF_DAY, - label: "DT", - value: InexactTime( TimeRange(DAWN, SUNSET) ) - } - MORNING_TWILIGHT = { - type: TIME_OF_DAY, - label: "MO", - value: InexactTime( TimeRange(DAWN, SUNRISE) ) - } - EVENING_TWILIGHT = { - type: TIME_OF_DAY, - label: "EV", - value: InexactTime( TimeRange(SUNSET, DUSK) ) - } - // For now, just have TWILIGHT be same as EVENING_TWILIGHT (could possibly be MORNING_TWILIGHT || EVENING_TWILIGHT) - TWILIGHT = EVENING_TWILIGHT - - // Relative days - YESTERDAY = RelativeTime( Duration(DAY, -1) ); - TOMORROW = RelativeTime( Duration(DAY, +1) ); - TODAY = RelativeTime( THIS, DAY ); - TONIGHT = RelativeTime( THIS, NIGHT ); - - HOURLY = PeriodicTemporalSet(NIL, HOUR, "EVERY", "P1X"); - NIGHTLY = PeriodicTemporalSet(NIGHT, DAY, "EVERY", "P1X"); - DAILY = PeriodicTemporalSet(NIL, DAY, "EVERY", "P1X"); - MONTHLY = PeriodicTemporalSet(NIL, MONTH, "EVERY", "P1X"); - QUARTERLY = PeriodicTemporalSet(NIL, QUARTER, "EVERY", "P1X"); - YEARLY = PeriodicTemporalSet(NIL, YEAR, "EVERY", "P1X"); - WEEKLY = PeriodicTemporalSet(NIL, WEEK, "EVERY", "P1X"); \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/data/sutime/rules/english.holidays.sutime.txt b/src/main/webapp/WEB-INF/data/sutime/rules/english.holidays.sutime.txt deleted file mode 100644 index e513dfcdd6..0000000000 --- a/src/main/webapp/WEB-INF/data/sutime/rules/english.holidays.sutime.txt +++ /dev/null @@ -1,29 +0,0 @@ - ENV.defaults["stage"] = 1 - ENV.defaults["ruleType"] = "tokens" - - $POSS = "( /'s/ | /'/ /s/ )" - { (/new/ /year/ $POSS? /eve/ ) => IsoDate(NIL, 12, 31) } - { (/new/ /year/ $POSS? /day/? ) => IsoDate(NIL, 1, 1) } - { (/inauguration/ /day/ ) => IsoDate(NIL, 1, 20) } - { (/groundhog/ /day/ ) => IsoDate(NIL, 2, 2) } - { (/st.?|saint/? /valentine/ $POSS? /day/ ) => IsoDate(NIL, 2, 14) } - { (/st.?|saint/ /patrick/ $POSS? /day/ ) => IsoDate(NIL, 3, 17) } - { (/april/ /fools/ /day/? ) => IsoDate(NIL, 4, 1) } - { (/cinco/ /de/ /mayo/ ) => IsoDate(NIL, 5, 5) } - { (/halloween/ ) => IsoDate(NIL, 10, 31) } - { (/x-?mas|christmas/ /eve/ ) => IsoDate(NIL, 12, 24) } - { (/x-?mas|christmas/ /day/? ) => IsoDate(NIL, 12, 25) } - - - { (/martin/ /luther/ /king/ /day/ | /mlk/ /day/) => JH_MARTIN_LUTHER_KING } - { (/memorial/ /day/) => JH_MEMORIAL } - { (/mother/ $POSS /day/) => JH_MOTHERS_DAY } - { (/father/ $POSS /day/) => JH_FATHERS_DAY } - { (/labou?r/ /day/) => JH_LABOUR_DAY } - { (/columbus/ /day/) => JH_COLUMBUS_DAY } - { (/thanksgiving/) => JH_THANKSGIVING } - - { (/easter/ (/day/|/sunday/)?) => JH_EASTER } - { (/clean/ /monday/) => JH_CLEAN_MONDAY } - { (/good/ /friday/) => JH_GOOD_FRIDAY } - { (/ash/ /wednesday/) => JH_ASH_WEDNESDAY } diff --git a/src/main/webapp/WEB-INF/data/sutime/rules/english.sutime.txt b/src/main/webapp/WEB-INF/data/sutime/rules/english.sutime.txt deleted file mode 100644 index 1783cd4a8e..0000000000 --- a/src/main/webapp/WEB-INF/data/sutime/rules/english.sutime.txt +++ /dev/null @@ -1,964 +0,0 @@ - ENV.defaults["stage.limitIters"] = 50 - - tokens = { type: "CLASS", value: "edu.stanford.nlp.ling.CoreAnnotations$TokensAnnotation" } - numtokens = { type: "CLASS", value: "edu.stanford.nlp.ling.CoreAnnotations$NumerizedTokensAnnotation" } - - $TIMEOFDAY = "/morning|afternoon|evening|night|noon|midnight|teatime|lunchtime|dinnertime|suppertime|afternoon|midday|dusk|dawn|sunup|sunrise|sundown|twilight|daybreak/"; - - $NUM = ( [ { numcomptype:NUMBER } ] ); - $INT = ( [ { numcomptype:NUMBER } & !{ word:/.*\.\d+.*/} & !{ word:/.*,.*/ } ] ); - $INTORD = ( [ ({ numcomptype:NUMBER } | { numcomptype:ORDINAL }) & !{ word:/.*\.\d+.*/} & !{ word:/.*,.*/ } ] ); - $INT1000TO3000 = ( [ $INT & !{ word:/\+.*/} & { numcompvalue>1000 } & { numcompvalue<3000 } ] ); - $INT1TO31 = ( [ $INTORD & !{ word:/\+.*/} & { numcompvalue>=1 } & { numcompvalue<=31 } ] ); - $NUM_ORD = ( [ { numcomptype:ORDINAL } ] ); - - $INT_TIMES = ( $INT /times/ | once | twice | thrice ); - $REL_MOD = ( /the/? /next|following|last|previous/ | /this/ /coming|past/? | /the/ /coming|past/ ); - $FREQ_MOD = ( /each/ | /every/ $NUM_ORD | /every/ /other|alternate|alternating/? | /alternate|alternating/ ); - $EARLY_LATE_MOD = ( /late|early|mid-?/ | /the/? /beginning|start|dawn|middle|end/ /of/ ); - $APPROX_MOD = ( /about|around|some|exactly|precisely/ ); - $YEAR = ( /[012]\d\d\d/ | /'\d\d/ | /'/ /\d\d/ | /\w+teen|twenty/ [ { numcompvalue<100 } & { numcompvalue>0 } & $INT ] ); - $POSSIBLE_YEAR = ( $YEAR /a\.?d\.?|b\.?c\.?/? | $INT /a\.?d\.?|b\.?c\.?/ | $INT1000TO3000 ); - $hasTemporal = "( { temporal::EXISTS } & {{ temporal.value != NON_TEMPORAL }} & !{{ tags[\"TIMEZONE\"] }} )" - - # Decades - DECADES_MAP = { - "twenties": "2X", - "thirties": "3X", - "forties": "4X", - "fifties": "5X", - "sixties": "6X", - "seventies": "7X", - "eighties": "8X", - "nineties": "9X" - } - $Decades = CreateRegex(Keys(DECADES_MAP)) - - # Durations - TIMEUNIT_MAP = { - "year": YEAR, - "yr": YEAR, - "month": MONTH, - "mo": MONTH, - "day": DAY, - "hour": HOUR, - "hr": HOUR, - "minute": MINUTE, - "min": MINUTE, - "second": SECOND, - "sec": SECOND, - "millisecond": MILLIS, - "millisec": MILLIS, - "week": WEEK, - "wk": WEEK, - "fortnight": FORTNIGHT, - "quarter": QUARTER, - "century": CENTURY, - "centuries": CENTURY, - "millennia": MILLENNIUM, - "millennium": MILLENNIUM, - "millenia": MILLENNIUM, - "millenium": MILLENNIUM - } - $TEUnits = CreateRegex(Keys(TIMEUNIT_MAP)) - BASIC_NUMBER_MAP = { - "one": 1, - "two": 2, - "three": 3, - "four": 4, - "five": 5, - "six": 6, - "seven": 7, - "eight": 8, - "nine": 9, - "ten": 10, - "eleven": 11, - "twelve": 12, - "thirteen": 13, - "fourteen": 14, - "fifteen": 15, - "sixteen": 16, - "seventeen": 17, - "eighteen": 18, - "nineteen": 19, - "twenty": 20, - "thirty": 30, - "forty": 40, - "fifty": 50, - "sixty": 60, - "seventy": 70, - "eighty": 80, - "ninety": 90, - "hundred": 100 - } - $BasicNumTerm = CreateRegex(Keys(BASIC_NUMBER_MAP)) - BASIC_ORDINAL_MAP = { - "first": 1, - "second": 2, - "third": 3, - "fourth": 4, - "fifth": 5, - "sixth": 6, - "seventh": 7, - "eighth": 8, - "ninth": 9, - "tenth": 10, - "eleventh": 11, - "twelfth": 12, - "thirteenth": 13, - "fourteenth": 14, - "fifteenth": 15, - "sixteenth": 16, - "seventeenth": 17, - "eighteenth": 18, - "nineteenth": 19, - "twentieth": 20, - "thirtieth": 30, - "fortieth": 40, - "fiftieth": 50, - "sixtieth": 60, - "seventieth": 70, - "eightieth": 80, - "ninetieth": 90, - "hundredth": 100 - } - $BasicOrdTerm = CreateRegex(Keys(BASIC_ORDINAL_MAP)) - - ######################################################################################################################## - - ENV.defaults["stage"] = 0 - ENV.defaults["ruleType"] = "tokens" - - { pattern: ( $POSSIBLE_YEAR ), - action: ( - Tag($0, "YEAR", - :case { - $0 =~ ( /\w+teen|twenty/ [ $INT ] ) => Add(Multiply($0[0].numcompvalue, 100), $0[1].numcompvalue), - $0 =~ ( /'/ /\d\d/ ) => Concat("XX", $0[1].word), - $0 =~ ( /'\d\d/ ) => Concat("XX", $0[0].word.substring(1)), - :else => $0[0].numcompvalue - } - ), - Tag($0, "YEAR_ERA", - :case { - $0 =~ ( $INT /a\.?d\.?/ ) => ERA_AD, - $0 =~ ( $INT /b\.?c\.?/ ) => ERA_BC, - :else => ERA_UNKNOWN - } - ) - ) - } - - # Operators - { pattern: ( /this/ ), - action: Tag($0, "TemporalOp", THIS) } - { pattern: ( /next/ ), - action: Tag($0, "TemporalOp", NEXT) } - { pattern: ( /following/ ), - action: Tag($0, "TemporalOp", NEXT) } - { pattern: ( /previous/ ), - action: Tag($0, "TemporalOp", PREV) } - { pattern: ( /last/ ), - action: Tag($0, "TemporalOp", PREV) } - { pattern: ( /this|the/ /coming|following|next/ ), - action: Tag($0, "TemporalOp", NEXT_IMMEDIATE) } - { pattern: ( /this|the/ /past|previous|last/ ), - action: Tag($0, "TemporalOp", PREV_IMMEDIATE) } - - # Modifiers - - # Early late modifiers - { pattern: ( /late/ | /end/ ), - action: Tag($0, "Modifier", "LATE") } - { pattern: ( /early/ | /beginning|start|dawn/ ), - action: Tag($0, "Modifier", "EARLY") } - { pattern: ( /mid-?/ | /middle/ ), - action: Tag($0, "Modifier", "MID") } - - # Frequency modifiers - { pattern: ( /each/ | /every/ ), - action: ( Tag($0, "PTS.quant", $0), Tag($0, "PTS.multiple", 1 ) ) } - { pattern: ( /every/ ($NUM_ORD|$INT) ), - action: ( Tag($0, "PTS.quant", $0), Tag($0, "PTS.multiple", $1[0].numcompvalue ) ) } - { pattern: ( /every/ /other|alternate|alternating/ | /alternate|alternating/ ), - action: ( Tag($0, "PTS.quant", $0), Tag($0, "PTS.multiple", 2 ) ) } - - # Approximate modifiers - { pattern: ( /about|around|some/ ), - action: Tag($0, "Modifier", "APPROX") } - { pattern: ( /exactly|precisely/ ), - action: Tag($0, "Modifier", "EXACT") } - - # Periodic Set - PERIODIC_SET = { - "centennial": TemporalCompose(MULTIPLY, YEARLY, 100), - "yearly": YEARLY, - "annually": YEARLY, - "annual": YEARLY, - "hourly": HOURLY, - "nightly": NIGHTLY, - "daily": DAILY, - "weekly": WEEKLY, - "monthly": MONTHLY, - "quarterly": QUARTERLY - } - $PeriodicSetRegex = CreateRegex(Keys(PERIODIC_SET)) - { pattern: ( /.*($PeriodicSetRegex)/ ), - matchWithResults: TRUE, - action: Tag($0, "PeriodicSet", PERIODIC_SET[Lowercase($$0.matchResults[0].word.group(1))]) } - - ######################################################################################################################## - - ENV.defaults["stage"] = 1 - ENV.defaults["ruleType"] = "text" - - # Durations: 3-months old or three-months old - { text: /(\d+)[-]($TEUnits)(s)?([-\s]old)?/ => Duration( TIMEUNIT_MAP[Lowercase($2)], $1 ) } - { text: /($BasicNumTerm)[-]($TEUnits)(s)?([-\s]old)?/ => - Duration( TIMEUNIT_MAP[Lowercase($2)], BASIC_NUMBER_MAP[Lowercase($1)] ) } - - # Durations - ENV.defaults["ruleType"] = "tokens" - { (/years?|yrs?/) => YEAR } - { (/months?|mos?/) => MONTH } - { (/days?/) => DAY } - { (/hours?|hrs?/) => HOUR } - { (/minutes?|mins?/) => MINUTE } - { (/seconds?|secs?/) => SECOND } - { (/milliseconds?|millisecs?/) => MILLIS } - { (/weeks?|wks?/) => WEEK } - { (/fortnights?/) => FORTNIGHT } - { (/quarters?/) => QUARTER } - { (/decades?/) => DECADE } - { (/centurys?|centuries?/) => CENTURY } - { (/millenn?ias?|millenn?iums?/) => MILLENNIUM } - - # Time of Day - { (/mornings?/) => MORNING } - { (/afternoons?/) => AFTERNOON } - { (/evenings?/) => EVENING } - { (/dusks?/) => DUSK } - { (/twilights?/) => TWILIGHT } - { (/dawns?|daybreaks?/) => DAWN } - { (/sunrises?|sunups?/) => SUNRISE } - { (/sundowns?|sunsets?/) => SUNSET } - { (/middays?|noons?/) => NOON } - { (/midnights?/) => MIDNIGHT } - { (/teatimes?/) => TEATIME } - { (/lunchtimes?/) => LUNCHTIME } - { (/dinnertimes?/) => DINNERTIME } - { (/suppertimes?/) => SUPPERTIME } - { (/daylights?|days?|daytimes?/) => DAYTIME } - { (/nighttimes?|nights?|overnights?/) => NIGHT } - - # Seasons - { (/summers?/) => SUMMER } - { (/winters?/) => WINTER } - { (/falls?|autumns?/) => FALL } - { (/springs?/) => SPRING } - - # Relative times - { (/yesterdays?/) => YESTERDAY } - { (/todays?/) => TODAY } - { (/tomorrows?/) => TOMORROW } - { (/tonights?|tonites?/) => TONIGHT } - - # Day of Week - { (/mondays?/) => MONDAY } - { (/tuesdays?/) => TUESDAY } - { (/wednesdays?/) => WEDNESDAY } - { (/thursdays?/) => THURSDAY } - { (/fridays?/) => FRIDAY } - { (/saturdays?/) => SATURDAY } - { (/sundays?/) => SUNDAY } - { (/mons?/) => MONDAY } - { (/tues?/) => TUESDAY } - { (/weds?/) => WEDNESDAY } - { (/thurs?/) => THURSDAY } - { (/fris?/) => FRIDAY } - { (/sats?/) => SATURDAY } - { (/suns?/) => SUNDAY } - - { (/weekends?/) => WEEKEND } - { (/weekdays?/) => WEEKDAY } - - # Month - { (/januarys?/) => JANUARY } - { (/februarys?/) => FEBRUARY } - { (/marchs?/) => MARCH } - { (/aprils?/) => APRIL } - { (/mays?/) => MAY } - { (/junes?/) => JUNE } - { (/julys?/) => JULY } - { (/augusts?/) => AUGUST } - { (/septembers?/) => SEPTEMBER } - { (/octobers?/) => OCTOBER } - { (/novembers?/) => NOVEMBER } - { (/decembers?/) => DECEMBER } - { (/jan\.?/) => JANUARY } - { (/feb?/) => FEBRUARY } - { (/mar\.?/) => MARCH } - { (/apr\.?/) => APRIL } - { (/jun\.?/) => JUNE } - { (/jul\.?/) => JULY } - { (/aug\.?/) => AUGUST } - { (/sept?\.?/) => SEPTEMBER } - { (/oct\.?/) => OCTOBER } - { (/nov\.?/) => NOVEMBER } - { (/dec\.?/) => DECEMBER } - - { ruleType: "filter", - over: NIL, - pattern: ( [ { temporal::IS_TIMEX_DATE } & {{ tokens[0].tag =~ /NN.*S/ }} ] ), - result: MakePeriodicTemporalSet($0[0].temporal.value) - } - - ######################################################################################################################## - - ENV.defaults["ruleType"] = "tokens" - ENV.defaults["priority"] = 0 - ENV.defaults["locale"] = "en" - - // Military times with time zones from http://www.timeanddate.com/library/abbreviations/timezones/military/ - MILITARY_TIME_ZONE_MAP = { - "A": 1, - "B": 2, - "C": 3, - "D": 4, - "E": 5, - "F": 6, - "G": 7, - "H": 8, - "I": 9, - "K": 10, - "L": 11, - "M": 12, - "N": -1, - "O": -2, - "P": -3, - "Q": -4, - "R": -5, - "S": -6, - "T": -7, - "U": -8, - "V": -9, - "W": -10, - "X": -11, - "Y": -12, - "Z": 0 - } - - { - ruleType: "tokens", - pattern: ( (/(\d\d)(\d\d)([A-Z])/) ), - matchWithResults: TRUE, - result: { type: "Temporal", - value: IsoTime($$1.matchResults[0].word.group(1), $$1.matchResults[0].word.group(2), NIL).setTimeZone( - MILITARY_TIME_ZONE_MAP[$$1.matchResults[0].word.group(3)] ) }, - // Change to TRUE to support military time zones - active: FALSE - } - - # ISO date/times - # TODO: Support other timezone formats - { ruleType: "time", pattern: /yyyy-?MM-?dd-?'T'HH(:?mm(:?ss([.,]S{1,3})?)?)?(Z)?/ } - { ruleType: "time", pattern: /yyyy-MM-dd/ } - { ruleType: "time", pattern: /'T'HH(:?mm(:?ss([.,](S{1,3}))?)?)?(Z)?/ } - # Tokenizer "sometimes adds extra slash - { ruleType: "time", pattern: /yyyy\\?\/MM\\?\/dd/ } - { ruleType: "time", pattern: /MM?\\?\/dd?\\?\/(yyyy|yy)/ } - { ruleType: "time", pattern: /MM?-dd?-(yyyy|yy)/ } - { ruleType: "time", pattern: /HH?:mm(:ss)?(Z)?/ } - { ruleType: "time", pattern: /yyyy-MM/ } - - #WildMe added - { ruleType: "time", pattern: /yyyy\.MM\.dd/ } - - # Euro - Ambiguous pattern - interpret as dd.MM.yy(yy) - { ruleType: "time", pattern: /dd?\.MM?\.(yyyy|yy)/ } - { ruleType: "time", pattern: /HH?''hmm/ } - - # Timezones - { ruleType: "time", pattern: /zzz/, action: Tag(_, "TIMEZONE", TRUE) } - { ruleType: "time", pattern: /ZZZ/, action: Tag(_, "TIMEZONE", TRUE) } - - # Birthdays - { ( [ { tag:NNP } ]+ [ { tag:POS } ] /birthday/ ) => SimpleTime($0) } - - # Generic decade - { ( /the/? ( /\w+teen/ /$Decades/ ) ) - => IsoDate( Concat( Format("%02d", $0[0].numcompvalue), DECADES_MAP[Lowercase($0[1].word)]), NIL, NIL) - } - { ( /the/? ( /$Decades/ ) ) - => IsoDate( Concat("XX", DECADES_MAP[Lowercase($0[0].word)]) , NIL, NIL) - } - { (/the/? /'/ /\d\d/ ) => IsoDate( Format( "XX%02d", $0[-1].numcompvalue), NIL, NIL) } - { (/the/? /'/ /\d0s/ | /the/? /'\d0s/ ) => IsoDate( Replace($0[-1].word, /'?(\d)0s/, "XX$1X"), NIL, NIL) } - { (/the/? /\d\d\d0s/) => IsoDate( Replace($0[-1].word, /(\d\d\d)0s/, "$1X"), NIL, NIL) } - { (/the/? /\d\d00s/) => IsoDate( Replace($0[-1].word, /(\d\d)00s/, "$1XX"), NIL, NIL) } - { (/the/? /mid-\d\d\d0s/) => IsoDate( Replace($0[-1].word, /mid-(\d\d\d)0s/, "$1X"), NIL, NIL) } - { (/the/? /mid-\d\d00s/) => IsoDate( Replace($0[-1].word, /mid-(\d\d)00s/, "$1XX"), NIL, NIL) } - - # some century expressions - { ( (/every/ $NUM_ORD) (/centurys?|ies/) ) => - MakePeriodicTemporalSet(CENTURY, GetTag($1[0], "PTS.quant"), GetTag($1[0], "PTS.multiple") ) } - - { ( /the/? ($NUM_ORD) /-/? /century/ (/b\.?c\.?/) ) - => IsoDate( - Format("-%02dXX", Subtract($1[0].numcompvalue, 1)), - NIL, NIL) - } - { pattern: ( /the/? (/($BasicOrdTerm)-century/) (/b\.?c\.?/) ), - matchWithResults: TRUE, - result: IsoDate( - Format("-%02dXX", Subtract(BASIC_ORDINAL_MAP[Lowercase($$1.matchResults[0].word.group(1))], 1)), - NIL, NIL) - } - { pattern: ( /the/? (/(\d+)(st|nd|rd|th)-century/) (/b\.?c\.?/) ), - matchWithResults: TRUE, - result: IsoDate( - Format("-%02dXX", Subtract( { type: "NUMBER", value: $$1.matchResults[0].word.group(1) }, 1)), - NIL, NIL) - } - - { ( /the/? ($NUM_ORD) /-/? /century/ (/a\.?d\.?/)? ) - => IsoDate( - Format("%02dXX", Subtract($1[0].numcompvalue, 1)), - NIL, NIL) - } - - { pattern: ( /the/? (/($BasicOrdTerm)-century/) (/a\.?d\.?/)? ), - matchWithResults: TRUE, - result: IsoDate( - Format("%02dXX", Subtract(BASIC_ORDINAL_MAP[Lowercase($$1.matchResults[0].word.group(1))], 1)), - NIL, NIL) - } - { pattern: ( /the/? (/(\d+)(st|nd|rd|th)-century/) (/a\.?d\.?/)? ), - matchWithResults: TRUE, - result: IsoDate( - Format("%02dXX", Subtract( { type: "NUMBER", value: $$1.matchResults[0].word.group(1) }, 1)), - NIL, NIL) - } - - # some quarter expressions - need to add year refs - { ( /the/? [{tag:JJ}]? ($NUM_ORD) /-/? [{tag:JJ}]? /quarter/ ) => - TemporalCompose(CREATE, QUARTER_OF_YEAR, $1[0].numcompvalue) } - { text: /(\d+)(st|nd|rd|th)-quarter/ => - TemporalCompose(CREATE, QUARTER_OF_YEAR, $1 ) - } - { text: /($BasicOrdTerm)-quarter/ => - TemporalCompose(CREATE, QUARTER_OF_YEAR, BASIC_ORDINAL_MAP[Lowercase($1)]) - } - - # (unit)ly - { ruleType: "tokens", -# pattern: ( (?m){1,3} /((bi|semi)\s*-?\s*)?((annual|year|month|week|dai|hour|night|quarter)ly|annual)/ ), - pattern: ( (?m){1,3} /((bi|semi)\s*-?\s*)?($PeriodicSetRegex)/ ), - result: :case { - $0[0].word =~ /bi.*/ => TemporalCompose(MULTIPLY, GetTag($0[-1], "PeriodicSet"), 2), - $0[0].word =~ /semi.*/ => TemporalCompose(DIVIDE, GetTag($0[-1], "PeriodicSet"), 2), - :else => GetTag($0[-1], "PeriodicSet") } - } - - # some interval expressions - { text: /\b(\d{4})\s*(?:-)\s*(\d{4})\b/ => - TimeRange( IsoDate($1, NIL, NIL), IsoDate($2, NIL, NIL) ) } - { ( /the/ /weekend/ ) => WEEKEND } - - # Now a few time expressions - { ( (/\d\d\d\d/) /hours?/? (/universal|zulu/ | /[a-z]+/ /standard|daylight/) /time/ ) => IsoTime($1[0].word, NIL, NIL) } - { ( (/\d\d?/) /hours?/ (?: (/\d\d?/) /minutes?/?)? (/universal|zulu/ | /[a-z]+/ /standard|daylight/) /time/ ) - => IsoTime($1[0].word, $1[0].word, NIL) } - { text: /(\d\d):?(\d\d)(:?(\d\d))?\s*h(ou)rs?/ => IsoTime($1,$2,$3) } - { text: /(\d\d?)(:?(\d\d))(:\d\d)?a\.?m\.?/ => TemporalCompose(INTERSECT, IsoTime($1,$3,$4), AM) } - { text: /(\d\d?)(:?(\d\d))(:\d\d)?p\.?m\.?/ => TemporalCompose(INTERSECT, IsoTime($1,$3,$4), PM) } - { text: /(\d\d?)a\.?m\.?/ => TemporalCompose(INTERSECT, IsoTime($1,"0",NIL), AM) } - { text: /(\d\d?)p\.?m\.?/ => TemporalCompose(INTERSECT, IsoTime($1,"0",NIL), PM) } - - { ( /the/ /hour/ /of/ ([ $INT & { numcompvalue<=24 } ]) )=> IsoTime($1[0].numcompvalue, 0, NIL) } - { ( (?: /the/ /hour/ /of/?)? ([ $INT & { numcompvalue<=24 } ]) /o'?clock/ ) => IsoTime($1[0].numcompvalue, 0, NIL) } - - # Year - { ( /the/? /year/ ($POSSIBLE_YEAR) ) - => :case { - $1[0].word =~ /'.*/ => IsoDate( GetTag($1[0], "YEAR"), NIL, NIL ), - :else => IsoDate( GetTag($1[0], "YEAR"), NIL, NIL, GetTag($1[0], "YEAR_ERA"), TRUE) - } - } - - { ( ($POSSIBLE_YEAR) & [ { ner::IS_NIL } | { ner:DATE } | { ner:O } | { ner:NUMBER } ]+ ) - => :case { - $1[0].word =~ /'.*/ => IsoDate( GetTag($1[0], "YEAR"), NIL, NIL ), - :else => IsoDate( GetTag($1[0], "YEAR"), NIL, NIL, GetTag($1[0], "YEAR_ERA"), TRUE) - } - } - - { ( /the/ ($TIMEOFDAY) ) => $1[0].temporal.value } - - { ( /good/ /morning|evening|day|afternoon|night/ ) => NON_TEMPORAL } - - ######################################################################################################################## - # Compositional rules - - ENV.defaults["ruleType"] = "composite" - - { name: "temporal-composite-6b", - priority: 20, - pattern: ( ( $REL_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: RelativeTime( GetTag($1[0], "TemporalOp"), $2[0].temporal.value ) - } - - ######################################################################################################################## - # Composite Duration rules - - ENV.defaults["priority"] = 10 - ENV.defaults["stage"] = 2 - - # Duration (start, end, unit, range_start, range_end) - # Duration rules - # i.e. "the past twenty four years" - { pattern: ( /the/ /past|last|previous/ (?: ($NUM) /to|-/ )? ($NUM)? ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration($1,$2,$3,TIME_UNKNOWN,TIME_REF) - } - - { pattern: ( /the/ /next|following/ (?: ($NUM) /to|-/ )? ($NUM)? ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration($1,$2,$3,TIME_REF,TIME_UNKNOWN) - } - - # i.e. "another 3 years", "another thirteen months" - { pattern: ( /another/ (?: ($NUM) /to|-/ )? ($NUM)? ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration($1, $2, $3, TIME_REF, TIME_UNKNOWN) } - - # i.e. "the 2 months following the crash", "for ten days before leaving" - # TODO: NEED TO FIX THIS, right now it doesn't include "the crash" or "leaving" - # ...need to be able to recognize NPs and VPs using POS tags - { pattern: ( /the/ (?: ($NUM) /to|-/ )? ($NUM) ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration($1, $2, $3) } - - # i.e. "the first 9 months of 1997" - { pattern: ( /the/ /first|initial|last|final|latest/ (?: ($NUM) /to|-/ )? ($NUM)? ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration( $1, $2, $3 ) } - { pattern: ( /the/ /first|initial|last|final|latest/ /half/ /of/ ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration( $1, $2, $3 ) } - - # i.e. "the fifth straight year", "the third straight month in a row", "the ninth day consecutively" - # i.e. "the eighth consecutive day in a row" - # i.e. "the twenty ninth day straight" - { pattern: ( /the/ ($NUM_ORD) /straight|consecutive/ ([ { temporal::IS_TIME_UNIT } ]) (?: /in/ /a/ /row/ | /consecutively/ )? ), - result: Duration (NIL, $1, $2, TIME_UNKNOWN, TIME_REF) } - { pattern: ( /the/ ($NUM_ORD) /straight|consecutive/? ([ { temporal::IS_TIME_UNIT } ]) (?: /in/ /a/ /row/ | /consecutively/ ) ), - result: Duration (NIL, $1, $2, TIME_UNKNOWN, TIME_REF) } - - # hundreds of years - { pattern: ( (/(ten|hundred|thousand|million|billion|trillion)s/) /of/ ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration ( NIL, $1, $2) } - - # i.e. "recent weeks", "several days" - { pattern: ( (/recent|several/) /-/? ([ { temporal::IS_TIME_UNIT } ]) ), - result: InexactDuration( Duration(NIL, NIL, $2) ) } - - # i.e. 3-months old, "four years", "four minutes" - { pattern: ( ($NUM) /to|-/ ($NUM) [ "-" ]? ([ { temporal::IS_TIME_UNIT } ]) (?: [ "-" ]? /old/ )? ), - result: Duration( $1, $2, $3) } - { pattern: ( ($NUM) [ "-" ]? ([ { temporal::IS_TIME_UNIT } ]) (?: [ "-" ]? /old/ )? ), - result: Duration( NIL, $1, $2 ) } - - # i.e. "a decade", "a few decades", NOT "a few hundred decades" - { pattern: ( (?: /the/ /past|next|following|coming|last|first|final/ | /a|an/ )? (/couple/ /of/? ) ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration ( Duration( NIL, NIL, $2 ), 2 ) } - { pattern: ( (?: /the/ /past|next|following|coming|last|first|final/ /half/ /of/ ) ([ { temporal::IS_TIME_UNIT } ]) ), - result: InexactDuration ( Duration( NIL, NIL, $2 ) ) } - { pattern: ( (?: /the/ /past|next|following|coming|last|first|final/ | /a|an/ )? (/few/) ([ { temporal::IS_TIME_UNIT } ]) ), - result: InexactDuration ( Duration( NIL, NIL, $2 ) ) } - - { pattern: ( /the/ [ { tag:JJ } ]? ([ { temporal::IS_TIME_UNIT } & { word:/.*s/ } ]) ), - priority: -1, - result: InexactDuration( $1[0].temporal.value ) } - - { pattern: ( /a|an/ ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration( $1[0].temporal.value, 1) } - - ###################################################################################################################### - # Compositional date rules - - ENV.defaults["priority"] = 0 - - { ( ($FREQ_MOD|/the/)? ($NUM_ORD) ([ { temporal::IS_TIME_UNIT } | { temporal::DAYOFWEEK } ]) ) => - :case{ - # Only attach ordinal to time if not prefixed by frequency modifier (e.g. every) - ($1 == NIL || $1 =~ ( /the/ ) ) => OrdinalTime($3[0].temporal.value, $2[0].numcompvalue), - # Return NIL otherwise - we have other patterns that handle sets (every 3rd months) later - :else => NIL - } - } - - { name: "composite-date-expression-1a", - priority: 1, - pattern: ( (/every/ $NUM_ORD) (?$month [ { temporal::MONTH }]) ), - result: MakePeriodicTemporalSet( - $month[0].temporal, - GetTag($1[0], "PTS.quant"), GetTag($1[0], "PTS.multiple") ) } - - { name: "composite-date-expression-1", - priority: 1, - pattern: ( ( /the/? (?$day $NUM_ORD & $INT1TO31) /of/? | (?$day /\d\d?/ & $INT1TO31) )? - (?$month [ { temporal::MONTH } ]) - (?$day $NUM_ORD|/\d\d?/ & $INT1TO31)? - (?: /of|,/? (?$year $POSSIBLE_YEAR))? ), - result: TemporalCompose(INTERSECT, - $year[0].temporal, - IsoDate(NIL, $month[0].temporal.value.month, $day[0].numcompvalue)) - } - - { name: "composite-date-expression-1b", - pattern: ( /the/? /ides/ /of|in/? (?$month [ { temporal::MONTH } ]) (?: /of|,/? (?$year $POSSIBLE_YEAR))? ), - result: TemporalCompose(INTERSECT, - $year[0].temporal, - IsoDate(NIL, - $month[0].temporal.value.month, - :case { - $month[0].temporal.value.month == 3 => 15, - $month[0].temporal.value.month == 5 => 15, - $month[0].temporal.value.month == 7 => 15, - $month[0].temporal.value.month == 10 => 15, - :else => 13 - } - )) - } - - { name: "composite-date-expression-1c", - pattern: ( /the/? /nones/ /of|in/? (?$month [ { temporal::MONTH } ]) (?: /of|,/? (?$year $POSSIBLE_YEAR))? ), - result: IsoDate( - GetTag($year[0].numtokens[0], "YEAR"), - $month[0].temporal.value.month, - :case { - $month[0].temporal.value.month == 3 => 7, - $month[0].temporal.value.month == 5 => 7, - $month[0].temporal.value.month == 7 => 7, - $month[0].temporal.value.month == 10 => 7, - :else => 5 - } - ) - } - - { name: "composite-date-expression-2", - pattern: ( /the/? (?$mod /beginning|start|middle|mid-?|end/ ) /of|in/? (?$date [ { temporal::IS_TIMEX_DATE } ]) ), - result: TemporalCompose(ADD_MODIFIER, $date[0].temporal, GetTag($mod[0], "Modifier") ) } - - { name: "composite-date-expression-2a1", - pattern: ( /the/? (?$mod /first/ /half/) /of/ (?$date [ { temporal::IS_TIMEX_DATE } ]) ), - result: TemporalCompose(ADD_MODIFIER, $date[0].temporal, "EARLY" ) } - - { name: "composite-date-expression-2a2", - pattern: ( /the/? (?$mod /second|last|latter/ /half/) /of/ (?$date [ { temporal::IS_TIMEX_DATE } ]) ), - result: TemporalCompose(ADD_MODIFIER, $date[0].temporal, "LATE" ) } - - { name: "composite-date-expression-2b", - pattern: ( /the/? (?$date [ { temporal::IS_TIMEX_DATE } ]) (/'/ /s/ | /'s/ )? (?$mod /beginning|end/) ), - result: TemporalCompose(ADD_MODIFIER, $date[0].temporal, GetTag($mod[0], "Modifier") ) } - - { name: "composite-date-expression-3", - pattern: ( /the/? (?$weeknum ($NUM_ORD|last)) (?$week /week(end)?/ ) /of|in/? [ { temporal::IS_TIMEX_DATE } ] ), - result: TemporalCompose( - IN, - $0[-1].temporal, - TemporalCompose( - CREATE, - $week[0].temporal, - :case { - $weeknum =~ (/last/) => -1, - :else => $weeknum[0].numcompvalue - } )) - } - - { name: "composite-date-expression-3b", - pattern: ( /the/? (?$week /week(end)?/ ) /of|in/? [ { temporal::IS_TIMEX_DATE } ] ), - result: TemporalCompose( - INTERSECT, - $0[-1].temporal, - $week[0].temporal) - } - - { name: "composite-date-expression-3c", - pattern: ( ( [ { temporal::DAYOFWEEK } ] ) /the/? (?$day $NUM_ORD) ), - result: TemporalCompose( - INTERSECT, - $1[0].temporal, - IsoDate(NIL, NIL, $day[0].numcompvalue)) - } - - { name: "composite-date-expression-6", - pattern: ( ([ { temporal::IS_TIMEX_DATE } ]) (morning|afternoon|evening|night) ), - result: TemporalCompose(INTERSECT, $1[0].temporal, $2[0].temporal) - } - - { name: "composite-date-expression-7a", - pattern: ( (?: /the/? /day/ (/before/|/prior/ /to/) ([ { temporal::IS_TIMEX_DATE } ]) ) ), - result: TemporalCompose( - PLUS, - $2[0].temporal, - TemporalCompose( - MULTIPLY, - DAY, - -1)) - } - - { name: "composite-date-expression-7b", - pattern: ( (?: /the/? /day/ (/after/) ([ { temporal::IS_TIMEX_DATE } ]) ) ), - result: TemporalCompose( - PLUS, - $2[0].temporal, - DAY) - } - - { name: "composite-date-expression-8", - pattern: ( /the/ [ { tag:JJ } ]* ([ { temporal::IS_TIME_UNIT } - & !{ word:/.*s/ } ] )), - result: RelativeTime( THIS, $1[0].temporal.value ) - } - - ######################################################################################################################## - # Composite time expressions - - { name: "composite-time-expression-1a", - active: TRUE, - pattern: ( (?: (?$time [ { temporal::IS_TIMEX_TIME } ]) | (?$hour [ $INT & { numcompvalue<=24 } ])) - (?$context /in/ /the/ /morning/ | /a\.?m\.?/) - ), - result: :case { - $time => TemporalCompose(INTERSECT, $time[0].temporal.value, AM), - $hour[0].numcompvalue == 12 => IsoTime(0, 0, NIL), - :else => IsoTime($hour[0].numcompvalue, 0, NIL) - } - } - - { name: "composite-time-expression-1b", - active: TRUE, - pattern: ( (?: (?$time [ { temporal::IS_TIMEX_TIME } ]) | (?$hour [ $INT & { numcompvalue<=24 } ])) - (?$context /in/ /the/ /afternoon|evening/| /at/ /night/| /p\.?m\.?/) - ), - result: :case { - $time => TemporalCompose(INTERSECT, $time[0].temporal.value, PM), - $hour[0].numcompvalue < 12 => IsoTime(Add($hour[0].numcompvalue, 12), 0, NIL), - ( ($hour[0].numcompvalue == 12) && ($context =~ ( []* /evening|night/)) ) - => TemporalCompose(OFFSET_EXACT, IsoTime(0, 0, NIL), DAY), - :else => IsoTime($hour[0].numcompvalue, 0, NIL) - } - } - - { name: "composite-time-expression-1c", - active: TRUE, - pattern: ( (?: (?$time [ { temporal::IS_TIMEX_TIME } ]) | (?$hour [ $INT & { numcompvalue==12 } ])) - (?$context /midnight/) - ), - result: :case { - $time[0].temporal.value.hour == 12 => MIDNIGHT, - $hour[0].numcompvalue == 12 => MIDNIGHT, - :else => NIL - } - } - - { name: "composite-time-expression-2", - pattern: ( (?$minute /a/? /quarter/ | /a/? /half/ | [ $INT & { numcompvalue<=60 } ] /minutes?/? ) - (?$rel /past|after|before|to|until/) - (?: (?$time [ { temporal::IS_TIMEX_TIME } ]) | (?$hour [ $INT & { numcompvalue<=24 } ])) - ), - result: TemporalCompose( - :case { - $rel[0].word =~ /past|after/ => PLUS, - :else => MINUS - }, - :case { - $time => $time[0].temporal, - :else => IsoTime($hour[0].numcompvalue, 0, NIL) - }, - Duration( - MINUTE, - :case { - $minute =~ ( /a/? /quarter/ ) => 15, - $minute =~ ( /a/? /half/ ) => 30, - :else => $0[0].numcompvalue - } - ) - ) } - - { pattern: ( ( /\d\d\d\d/ | $NUM ) [ {tag:/RB/} ] [ {tag:/JJ/} ]+ [ {tag:/NNS/} & !($hasTemporal) ] ), - result: NON_TEMPORAL, - priority: -1 } - { pattern: ( ( /\d\d\d\d/ | $NUM ) [ {tag:/JJ/} ]* [ {tag:/NNS/} & !($hasTemporal) ] ), - result: NON_TEMPORAL, - priority: -1 } - - ######################################################################################################################## - # General compositional rules - ENV.defaults["stage"] = 3 - - { name: "temporal-composite-timezone1", - pattern: ( (?$time [ { temporal::IS_TIMEX_TIME } ]) (?$timezone [ {{ tags["TIMEZONE"] }} ]) ), - result: TemporalCompose(INTERSECT, $time[0].temporal, $timezone[0].temporal) - } - - { name: "temporal-composite-timezone2", - pattern: ( (?$time [ { temporal::IS_TIMEX_TIME } ]) "-LRB-" (?$timezone [ {{ tags["TIMEZONE"] }} ]) "-RRB-" ), - result: TemporalCompose(INTERSECT, $time[0].temporal, $timezone[0].temporal) - } - - { name: "temporal-composite-1", - pattern: ( /the/? - (( [ $hasTemporal ] ) /,|of|in/? ( [ { temporal::IS_TIMEX_DATE } | { temporal::IS_TIMEX_TIME } ] ) | - ( [ { temporal::IS_TIMEX_DATE } ] ) /at/ ( [ { temporal::IS_TIMEX_TIME } ] ) | - ( [ { temporal::IS_TIMEX_TIME } | { temporal::IS_TIMEX_DURATION } ] ) /on/ ( [ { temporal::IS_TIMEX_DATE } ] | [ { temporal::IS_TIMEX_SET } ]) | - ( [ { temporal::IS_TIMEX_DATE } | { temporal::IS_TIMEX_TIME } ] ) (/'s/ | /'/ /s/) ( [ $hasTemporal ] )) ), - result: TemporalCompose(INTERSECT, $1[0].temporal, $1[-1].temporal) - } - - { name: "temporal-composite-2", - pattern: ( ( [ { temporal::IS_TIMEX_DATE } | { temporal::IS_TIMEX_TIME } ] ) (/today|tonight/) ), - result: $0[0].temporal.value - } - - { name: "temporal-composite-3", - pattern: ( ( [ { temporal::IS_TIMEX_DURATION } ] ) (/before|from|since|after/ | /prior/ /to/) - ( [ ({ temporal::IS_TIMEX_TIME } | { temporal::IS_TIMEX_DATE }) ] ) ), - result: TemporalCompose( - OFFSET, $0[-1].temporal, - TemporalCompose( - MULTIPLY, - $0[0].temporal, - :case { - $2 =~ (/before/|/prior/ /to/) => -1, - :else => 1 - } )) - } - - # expand: timex later|earlier|late => one timex - { name: "temporal-composite-4", - pattern: ( ( [ { temporal::IS_TIMEX_DURATION } ] ) (/earlier|later|ago|hence/ | /from/ /now/) ), - result: TemporalCompose(OFFSET, TIME_REF, - TemporalCompose( MULTIPLY, $0[0].temporal, - :case { - $2 =~ (/earlier/|/ago/) => -1, - :else => 1 - })) - } - - # expand: timex later|earlier|late => one timex - { name: "temporal-composite-5", - pattern: ( ( [ $hasTemporal & !{ temporal::IS_TIMEX_DURATION } ] ) - (/before|earlier|later|late|ago|hence/ | /from/ /now/) ), - result: $0[0].temporal.value } - - { name: "temporal-composite-6a", - pattern: ( /the/? ( $EARLY_LATE_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: TemporalCompose( ADD_MODIFIER, $2[0].temporal.value, GetTag($1[0], "Modifier") ) - } - - { name: "temporal-composite-6b", - priority: 4, - pattern: ( ( $REL_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: RelativeTime( GetTag($1[0], "TemporalOp"), $2[0].temporal.value ) - } - - { name: "temporal-composite-6b1", - priority: 4, - pattern: ( ( /no/ /more/ /than/ | /at/ /most/ | /up/ /to/ ) - ( [ { temporal::IS_TIMEX_DURATION } & !{{ temporal.value.mod }} ] ) ), - result: TemporalCompose( ADD_MODIFIER, $0[-1].temporal.value, "EQUAL_OR_LESS" ) - } - { name: "temporal-composite-6b2", - priority: 4, - pattern: ( ( /more/ /than/ ) - ( [ { temporal::IS_TIMEX_DURATION } & !{{ temporal.value.mod }} ] ) ), - result: TemporalCompose( ADD_MODIFIER, $0[-1].temporal.value, "MORE_THAN" ) - } - { name: "temporal-composite-6b3", - priority: 4, - pattern: ( ( /no/ /less/ /than/ | /at/ /least/ ) - ( [ { temporal::IS_TIMEX_DURATION } & !{{ temporal.value.mod }} ] ) ), - result: TemporalCompose( ADD_MODIFIER, $0[-1].temporal.value, "EQUAL_OR_MORE" ) - } - { name: "temporal-composite-6b4", - priority: 4, - pattern: ( ( /less/ /than/ ) - ( [ { temporal::IS_TIMEX_DURATION } & !{{ temporal.value.mod }} ] ) ), - result: TemporalCompose( ADD_MODIFIER, $0[-1].temporal.value, "LESS_THAN" ) - } - - # expand: (the|this|about|nearly|early|later|earlier|late) timex => one timex - # expand: more than| up to| less than timex => one timex - { name: "temporal-composite-6c", - pattern: ( ( /this|about|nearly|early|later|earlier|late/ ) - ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: $0[-1].temporal.value - } - - { name: "temporal-composite-7a", - pattern: ( /every/ ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: MakePeriodicTemporalSet($1[0].temporal, "every", 1 ) - } - - { name: "temporal-composite-7b", -# pattern: ( ( $FREQ_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - pattern: ( ( $FREQ_MOD ) ( [ $hasTemporal ] ) ), - result: MakePeriodicTemporalSet($2[0].temporal, GetTag($1[0], "PTS.quant"), GetTag($1[0], "PTS.multiple") ) - } - - { name: "temporal-composite-8:ranges", - active: options."markTimeRanges", - pattern: ( /from/? ( [ { temporal::IS_TIMEX_TIME } | { temporal::IS_TIMEX_DATE } ] ) /to|-/ ( [ { temporal::IS_TIMEX_TIME } | { temporal::IS_TIMEX_DATE } ] ) ), - result: TimeRange( $1[0].temporal.value, $2[0].temporal.value ) } - - { name: "temporal-composite-9", - pattern: ( [{ temporal::IS_TIMEX_TIME }] (?: /sharp/|/exactly/|/precisely/|/on/ /the/ /dot/) ), - result: $0[0].temporal.value } - - ######################################################################################################################## - - ENV.defaults["stage"] = 4 - ENV.defaults["ruleType"] = "tokens" - - # Vague times - { ( /the/ /past/ | /recently/ ) => TIME_PAST } - { pattern: ( /at/ /the/ (/time/) ), matchedExpressionGroup: 1, result: TIME_PAST } - { ( /past|once|medieval|previously/ ) => TIME_PAST } - { ( /present|current|currently/ | /right/? /now/ ) => TIME_PRESENT } - { ( /the/? /near/? /future/ ) => TIME_FUTURE } - - # Final rules to determine how to resolve date - ENV.defaults["ruleType"] = "composite" - ENV.defaults["stage.limitIters"] = 1 - { pattern: ( [ { temporal::IS_TIMEX_DURATION } & {{ tokens =~ ( /.*s/ ) }} ] ), - result: InexactDuration( $0[0].temporal.value ) } - - { pattern: ( [ { tag:/VBD/ } | /have/ ] []{0,2} [ $hasTemporal ] ), - action: VTag( $0[-1].temporal.value, "resolveTo", RESOLVE_TO_PAST ) - } - { pattern: ( [ $hasTemporal ] []{0,2} [ { tag:/VBD/ } | /have/ ] ), - action: VTag( $0[0].temporal.value, "resolveTo", RESOLVE_TO_PAST ) - } - { pattern: ( (/would/ | /could/ | /should/ | /will/ | /going/ /to/ | /'/ /ll/ | /'ll/ ) - []{0,2} [ $hasTemporal ] - ), - action: VTag( $0[-1].temporal.value, "resolveTo", RESOLVE_TO_FUTURE ) - } - { pattern: ( [ $hasTemporal ] []{0,2} - (/would/ | /could/ | /should/ | /will/ | /going/ /to/ | /'/ /ll/ | /'ll/ ) ), - action: VTag( $0[0].temporal.value, "resolveTo", RESOLVE_TO_FUTURE ) - } - - ######################################################################################################################## - # Final filtering rules - - ENV.defaults["ruleType"] = "filter" - ENV.defaultTokensAnnotationKey = tokens - - { pattern: ( $NUM /to/ $NUM) } - { pattern: ( /(quarter|sun)s?/ ) } - { pattern: ( [ { word:/(fall|spring|second|march|may|sat|sun|min)s?/ } & !{ tag:/NN.*/ } ] ) } - { pattern: ( /the/ [ { word:/second/ } & !{ tag:/NN.*/ } ] ) } - { pattern: ( [ { word:/((twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety)-)?second/ } ] ) } - { pattern: ( [ {{ temporal.value == NON_TEMPORAL }} ] ), over: NIL } - - # Reject anything that is just a timezone - { pattern: ( [ {{ tags["TIMEZONE"] }} ] ), over: NIL } - From 7e5edf2bc7b75e623fb46413cdb5a4cdac54eaa0 Mon Sep 17 00:00:00 2001 From: erinz2020 Date: Fri, 30 Aug 2024 19:05:01 +0000 Subject: [PATCH 22/41] fix lint issues --- frontend/config-overrides.js | 23 +- frontend/config/webpack/webpack.dev.js | 16 +- frontend/config/webpack/webpack.prod.js | 26 +- frontend/package-lock.json | 1720 ++++++++++------- frontend/package.json | 4 + frontend/src/About.jsx | 5 +- frontend/src/App.jsx | 22 +- frontend/src/App.test.js | 10 +- frontend/src/AuthenticatedSwitch.jsx | 7 +- frontend/src/FrontDesk.jsx | 8 +- frontend/src/GoogleTagManager.jsx | 2 +- frontend/src/ThemeColorProvider.jsx | 264 ++- frontend/src/UnAuthenticatedSwitch.jsx | 24 +- frontend/src/components/AlertBanner.jsx | 5 +- frontend/src/components/AndSelector.jsx | 170 +- .../src/components/AuthenticatedAppHeader.jsx | 134 +- frontend/src/components/Chip.jsx | 230 +-- frontend/src/components/CircledMoreButton.jsx | 47 +- frontend/src/components/DataTable.jsx | 210 +- frontend/src/components/DiamondCard.jsx | 180 +- frontend/src/components/FilterPanel.jsx | 287 +-- frontend/src/components/Form/Description.jsx | 27 +- .../components/Form/FormGroupMultiSelect.jsx | 81 +- .../src/components/Form/FormGroupText.jsx | 89 +- .../src/components/Form/FormMeasurements.jsx | 233 +-- .../components/Form/LabelledKeywordFilter.jsx | 352 ++-- frontend/src/components/Map.jsx | 201 +- frontend/src/components/MultiSelect.jsx | 169 +- frontend/src/components/OrSelector.jsx | 119 +- .../components/UnAuthenticatedAppHeader.jsx | 67 +- .../src/components/fields/filters/AreaMap.jsx | 10 +- .../filterFields/ApplyQueryFilter.jsx | 118 +- .../BiologicalSamplesAndAnalysesFilter.jsx | 526 ++--- .../components/filterFields/DateFilter.jsx | 292 +-- .../filterFields/IdentityFilter.jsx | 50 +- .../filterFields/ImageLabelFilter.jsx | 303 ++- .../filterFields/LocationFilterMap.jsx | 281 +-- .../filterFields/LocationFilterText.jsx | 77 +- .../ObservationAttributeFilter.jsx | 261 +-- .../filterFields/OptionTermFilter.jsx | 95 - .../filterFields/PointDistanceFilter.jsx | 173 -- .../src/components/filterFields/SideBar.jsx | 172 +- .../components/filterFields/SocialFilter.jsx | 69 +- .../components/filterFields/TagsFilter.jsx | 182 +- .../components/filterFields/buildOptions.js | 22 - .../mapUtils/PointDistanceMap.jsx | 117 -- .../header/AvatarAndUserProfile.jsx | 83 +- frontend/src/components/header/Menu.jsx | 175 +- frontend/src/components/home/LandingImage.jsx | 12 +- .../components/home/LatestActivityItem.jsx | 43 +- frontend/src/components/home/LatestData.jsx | 1 + frontend/src/components/home/Progress.jsx | 5 +- frontend/src/components/home/Projects.jsx | 166 +- frontend/src/components/inputs/AreaInput.jsx | 76 - .../navBar/CollaborationMessages.jsx | 3 + .../src/components/navBar/MergeMessages.jsx | 318 +-- .../components/navBar/NotificationButton.jsx | 2 +- frontend/src/components/svg/DownIcon.jsx | 19 +- frontend/src/components/svg/RightIcon.jsx | 22 +- frontend/src/components/svg/Svg_400.jsx | 8 +- frontend/src/components/svg/Svg_401.jsx | 8 +- frontend/src/components/svg/Svg_403.jsx | 8 +- frontend/src/components/svg/Svg_404.jsx | 8 +- frontend/src/components/svg/Svg_500.jsx | 8 +- frontend/src/components/svg/Tail.jsx | 16 - frontend/src/eslint.config.mjs | 11 + frontend/src/hooks/useDocumentTitle.js | 19 +- frontend/src/hooks/useFetch.js | 26 +- frontend/src/models/auth/users/useGetMe.js | 7 +- .../models/encounters/useFilterEncounters.js | 54 +- .../notifications/getMergeNotifications.js | 34 +- .../models/sightings/useGetLatestSightings.js | 27 +- frontend/src/pages/Home.jsx | 2 +- frontend/src/pages/Login.jsx | 5 +- frontend/src/pages/Profile.jsx | 35 +- frontend/src/pages/errorPages/ErrorPage.jsx | 14 +- frontend/src/service-worker.js | 170 +- frontend/src/serviceWorkerRegistration.js | 2 + frontend/src/utils/formatters.js | 26 +- 79 files changed, 4503 insertions(+), 4390 deletions(-) delete mode 100644 frontend/src/components/filterFields/OptionTermFilter.jsx delete mode 100644 frontend/src/components/filterFields/PointDistanceFilter.jsx delete mode 100644 frontend/src/components/filterFields/buildOptions.js delete mode 100644 frontend/src/components/filterFields/mapUtils/PointDistanceMap.jsx delete mode 100644 frontend/src/components/inputs/AreaInput.jsx delete mode 100644 frontend/src/components/svg/Tail.jsx create mode 100644 frontend/src/eslint.config.mjs diff --git a/frontend/config-overrides.js b/frontend/config-overrides.js index 3ce1986cad..98dddc1d9e 100644 --- a/frontend/config-overrides.js +++ b/frontend/config-overrides.js @@ -1,14 +1,15 @@ // config-overrides.js -const webpack = require('webpack'); -module.exports = function override(config, env) { - if(env === 'production'){ - config.devtool = 'source-map'; +/* eslint-disable no-undef */ +const webpack = require("webpack"); +module.exports = function override(config, env) { + if (env === "production") { + config.devtool = "source-map"; // config.devtool = 'cheap-module-source-map'; } - config.plugins.push( - new webpack.DefinePlugin({ - 'process.env.SITE_NAME': JSON.stringify(process.env.SITE_NAME), - }) - ); - return config; - }; + config.plugins.push( + new webpack.DefinePlugin({ + "process.env.SITE_NAME": JSON.stringify(process.env.SITE_NAME), + }), + ); + return config; +}; diff --git a/frontend/config/webpack/webpack.dev.js b/frontend/config/webpack/webpack.dev.js index a696932425..edf48f4ab9 100644 --- a/frontend/config/webpack/webpack.dev.js +++ b/frontend/config/webpack/webpack.dev.js @@ -1,14 +1,16 @@ -const path = require('path'); -const webpack = require('webpack'); -const UnusedWebpackPlugin = require('unused-webpack-plugin'); +/* eslint-disable no-undef */ + +const path = require("path"); +const webpack = require("webpack"); +const UnusedWebpackPlugin = require("unused-webpack-plugin"); module.exports = { - mode: 'development', - devtool: 'source-map', + mode: "development", + devtool: "source-map", devServer: { disableHostCheck: true, headers: { - 'Access-Control-Allow-Origin': '*', + "Access-Control-Allow-Origin": "*", }, historyApiFallback: true, hot: true, @@ -18,7 +20,7 @@ module.exports = { plugins: [ new webpack.HotModuleReplacementPlugin(), new UnusedWebpackPlugin({ - directories: [path.join(__dirname, '../../src')], + directories: [path.join(__dirname, "../../src")], }), ], }; diff --git a/frontend/config/webpack/webpack.prod.js b/frontend/config/webpack/webpack.prod.js index 311030feb9..febd85c698 100644 --- a/frontend/config/webpack/webpack.prod.js +++ b/frontend/config/webpack/webpack.prod.js @@ -1,24 +1,26 @@ +/* eslint-disable no-undef */ + // const webpack = require("webpack"); -const { resolve } = require('path'); -const path = require('path'); -const TerserPlugin = require('terser-webpack-plugin'); +const { resolve } = require("path"); +const path = require("path"); +const TerserPlugin = require("terser-webpack-plugin"); -const rootDir = resolve(__dirname, '../../'); -const dist = path.resolve(rootDir, 'dist'); +const rootDir = resolve(__dirname, "../../"); +const dist = path.resolve(rootDir, "dist"); module.exports = { - mode: 'production', - devtool: 'source-map', + mode: "production", + devtool: "source-map", entry: { - main: path.resolve(rootDir, 'src/index.jsx'), + main: path.resolve(rootDir, "src/index.jsx"), }, output: { path: dist, - filename: '[name].js', - chunkFilename: '[name].chunk.js', - publicPath: '/', + filename: "[name].js", + chunkFilename: "[name].chunk.js", + publicPath: "/", }, optimization: { - minimizer: [new TerserPlugin()], + minimizer: [new TerserPlugin()], }, }; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4a7c83c8dc..6b3b879d73 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -51,9 +51,13 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@eslint/js": "^9.9.1", "bootstrap-icons": "^1.11.3", "css-loader": "^6.10.0", "date-fns": "^3.6.0", + "eslint": "^8.57.0", + "eslint-plugin-react": "^7.35.0", + "globals": "^15.9.0", "html-webpack-plugin": "^5.6.0", "husky": "^9.0.11", "react-app-rewired": "^2.2.1", @@ -163,9 +167,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.23.10", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz", - "integrity": "sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.1.tgz", + "integrity": "sha512-Y956ghgTT4j7rKesabkh5WeqgSFZVFwaPR0IWFm7KFHFmmJ4afbG49SmfW4S+GyRPx0Dy5jxEWA5t0rpxfElWg==", "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -176,7 +180,7 @@ }, "peerDependencies": { "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0" + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { @@ -1124,6 +1128,14 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", @@ -2066,6 +2078,14 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.23.9", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", @@ -2528,9 +2548,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -2599,11 +2619,12 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", + "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", + "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@floating-ui/core": { @@ -2726,6 +2747,7 @@ "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", "debug": "^4.3.1", @@ -2748,9 +2770,10 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -3854,9 +3877,9 @@ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" }, "node_modules/@rushstack/eslint-patch": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz", - "integrity": "sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==" + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==" }, "node_modules/@sinclair/typebox": { "version": "0.24.51", @@ -4953,9 +4976,9 @@ "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "node_modules/@types/semver": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==" + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "node_modules/@types/send": { "version": "0.17.4", @@ -5468,9 +5491,9 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { "acorn": "bin/acorn" }, @@ -5724,14 +5747,15 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -5749,16 +5773,17 @@ "node": ">=8" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5768,14 +5793,15 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" }, "engines": { @@ -5838,15 +5864,18 @@ } }, "node_modules/array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/arraybuffer.prototype.slice": { @@ -5963,14 +5992,6 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dependencies": { - "has-symbols": "^1.0.3" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -6021,9 +6042,12 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", - "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -6032,9 +6056,9 @@ } }, "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", "engines": { "node": ">=4" } @@ -6063,11 +6087,11 @@ } }, "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", "dependencies": { - "dequal": "^2.0.3" + "deep-equal": "^2.0.5" } }, "node_modules/babel-jest": { @@ -6636,14 +6660,15 @@ } }, "node_modules/call-bind": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", - "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "set-function-length": "^1.2.0" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -7682,6 +7707,54 @@ "node": ">=10" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/date-fns": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", @@ -7789,14 +7862,13 @@ } }, "node_modules/define-data-property": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.3.tgz", - "integrity": "sha512-h3GBouC+RPtNX2N0hHVLo2ZwPYurq8mLmXpOLTsw71gr7lHt5VaI4vVkDUNOfiWmm48JEXe3VM7PmLX45AMmmg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -7967,14 +8039,14 @@ } }, "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dependencies": { "esutils": "^2.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, "node_modules/dom-accessibility-api": { @@ -8207,49 +8279,56 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -8263,6 +8342,17 @@ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", @@ -8291,25 +8381,24 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.16.tgz", - "integrity": "sha512-CREG2A9Vq7bpDRnldhFcMKuKArvkZtsH6Y0DHOHVg49qhf+LD8uEdUM3OkOAICv0EziGtDEnQtqY2/mfBILpFw==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", "dependencies": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.1", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" + "safe-array-concat": "^1.1.2" }, "engines": { "node": ">= 0.4" @@ -8320,14 +8409,25 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -8408,15 +8508,15 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -8507,9 +8607,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", + "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", "dependencies": { "debug": "^3.2.7" }, @@ -8585,17 +8685,6 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -8628,26 +8717,26 @@ } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" }, "engines": { "node": ">=4.0" @@ -8656,39 +8745,49 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, "node_modules/eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", + "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", + "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", "engines": { "node": ">=10" }, @@ -8696,17 +8795,6 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -8796,14 +8884,14 @@ } }, "node_modules/eslint-webpack-plugin/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -8879,6 +8967,14 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -8929,6 +9025,17 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/eslint/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -9231,6 +9338,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -9431,9 +9543,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/follow-redirects": { "version": "1.15.6", @@ -9910,11 +10022,15 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { @@ -10030,20 +10146,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -10077,9 +10193,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -10661,6 +10777,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -10750,9 +10880,12 @@ } }, "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10763,9 +10896,9 @@ "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "engines": { "node": ">= 0.4" }, @@ -10870,19 +11003,25 @@ } }, "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10947,9 +11086,12 @@ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10966,12 +11108,15 @@ } }, "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13322,9 +13467,9 @@ } }, "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==" }, "node_modules/language-tags": { "version": "1.0.9", @@ -13993,26 +14138,27 @@ } }, "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -14040,37 +14186,26 @@ } }, "node_modules/object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dependencies": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" - } - }, - "node_modules/object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "dependencies": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "es-abstract": "^1.23.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -14521,6 +14656,14 @@ "node": ">=4" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", @@ -16789,15 +16932,15 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", - "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0", - "get-intrinsic": "^1.2.3", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" }, @@ -17168,12 +17311,12 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -17520,13 +17663,14 @@ } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -17581,11 +17725,11 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -17959,33 +18103,58 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -17995,26 +18164,29 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -18804,11 +18976,11 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz", - "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-typed-array": "^1.1.13" }, @@ -18817,14 +18989,15 @@ } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -18834,15 +19007,16 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -18852,13 +19026,19 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -19773,12 +19953,12 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -19787,8 +19967,8 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -19798,29 +19978,32 @@ } }, "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -20459,9 +20642,9 @@ } }, "@babel/eslint-parser": { - "version": "7.23.10", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz", - "integrity": "sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.1.tgz", + "integrity": "sha512-Y956ghgTT4j7rKesabkh5WeqgSFZVFwaPR0IWFm7KFHFmmJ4afbG49SmfW4S+GyRPx0Dy5jxEWA5t0rpxfElWg==", "requires": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -21092,6 +21275,13 @@ "@babel/helper-replace-supers": "^7.22.20", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + } } }, "@babel/plugin-transform-computed-properties": { @@ -21709,6 +21899,13 @@ "@babel/types": "^7.23.9", "debug": "^4.3.1", "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + } } }, "@babel/types": { @@ -22004,9 +22201,9 @@ } }, "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==" + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==" }, "@eslint/eslintrc": { "version": "2.1.4", @@ -22053,9 +22250,10 @@ } }, "@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==" + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", + "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", + "dev": true }, "@floating-ui/core": { "version": "1.6.4", @@ -22181,9 +22379,9 @@ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" }, "@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==" }, "@isaacs/cliui": { "version": "8.0.2", @@ -22972,9 +23170,9 @@ } }, "@rushstack/eslint-patch": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz", - "integrity": "sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==" + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==" }, "@sinclair/typebox": { "version": "0.24.51", @@ -23829,9 +24027,9 @@ "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "@types/semver": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==" + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "@types/send": { "version": "0.17.4", @@ -24214,9 +24412,9 @@ } }, "acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==" + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==" }, "acorn-globals": { "version": "6.0.0", @@ -24398,14 +24596,15 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, @@ -24414,27 +24613,29 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, - "array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", + "array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" } }, "array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "requires": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, @@ -24473,14 +24674,14 @@ } }, "array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "requires": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, @@ -24566,14 +24767,6 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, - "asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "requires": { - "has-symbols": "^1.0.3" - } - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -24598,14 +24791,17 @@ } }, "available-typed-arrays": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", - "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "requires": { + "possible-typed-array-names": "^1.0.0" + } }, "axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==" + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==" }, "axios": { "version": "1.6.7", @@ -24630,11 +24826,11 @@ } }, "axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", "requires": { - "dequal": "^2.0.3" + "deep-equal": "^2.0.5" } }, "babel-jest": { @@ -25063,14 +25259,15 @@ "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" }, "call-bind": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", - "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "requires": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "set-function-length": "^1.2.0" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" } }, "callsites": { @@ -25789,6 +25986,36 @@ "whatwg-url": "^8.0.0" } }, + "data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, "date-fns": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", @@ -25869,14 +26096,13 @@ } }, "define-data-property": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.3.tgz", - "integrity": "sha512-h3GBouC+RPtNX2N0hHVLo2ZwPYurq8mLmXpOLTsw71gr7lHt5VaI4vVkDUNOfiWmm48JEXe3VM7PmLX45AMmmg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "requires": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "gopd": "^1.0.1" } }, "define-lazy-prop": { @@ -25999,9 +26225,9 @@ } }, "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "requires": { "esutils": "^2.0.2" } @@ -26180,49 +26406,56 @@ } }, "es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "requires": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.15" } }, "es-array-method-boxes-properly": { @@ -26230,6 +26463,14 @@ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "requires": { + "get-intrinsic": "^1.2.4" + } + }, "es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", @@ -26252,25 +26493,24 @@ } }, "es-iterator-helpers": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.16.tgz", - "integrity": "sha512-CREG2A9Vq7bpDRnldhFcMKuKArvkZtsH6Y0DHOHVg49qhf+LD8uEdUM3OkOAICv0EziGtDEnQtqY2/mfBILpFw==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", "requires": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.1", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" + "safe-array-concat": "^1.1.2" } }, "es-module-lexer": { @@ -26278,14 +26518,22 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, + "es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "requires": { + "es-errors": "^1.3.0" + } + }, "es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "requires": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" } }, "es-shim-unscopables": { @@ -26341,15 +26589,15 @@ } }, "eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -26385,6 +26633,11 @@ "text-table": "^0.2.0" }, "dependencies": { + "@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==" + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -26420,6 +26673,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "requires": { + "esutils": "^2.0.2" + } + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -26503,9 +26764,9 @@ } }, "eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", + "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", "requires": { "debug": "^3.2.7" }, @@ -26561,14 +26822,6 @@ "ms": "^2.1.1" } }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "requires": { - "esutils": "^2.0.2" - } - }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -26585,59 +26838,63 @@ } }, "eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", "requires": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "dependencies": { + "aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "requires": { + "deep-equal": "^2.0.5" + } + } } }, "eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", "requires": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", + "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", + "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "requires": { - "esutils": "^2.0.2" - } - }, "resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -26656,9 +26913,9 @@ } }, "eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", "requires": {} }, "eslint-plugin-testing-library": { @@ -26696,14 +26953,14 @@ }, "dependencies": { "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" } }, "ajv-keywords": { @@ -26943,6 +27200,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" + }, "fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -27098,9 +27360,9 @@ } }, "flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "follow-redirects": { "version": "1.15.6", @@ -27413,9 +27675,10 @@ } }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "dev": true }, "globalthis": { "version": "1.0.3", @@ -27496,17 +27759,17 @@ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "requires": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" } }, "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" }, "has-symbols": { "version": "1.0.3", @@ -27522,9 +27785,9 @@ } }, "hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "requires": { "function-bind": "^1.1.2" } @@ -27933,6 +28196,14 @@ "hasown": "^2.0.0" } }, + "is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "requires": { + "is-typed-array": "^1.1.13" + } + }, "is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -27986,9 +28257,9 @@ } }, "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" }, "is-module": { "version": "1.0.0", @@ -27996,9 +28267,9 @@ "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" }, "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==" }, "is-number": { "version": "7.0.0", @@ -28061,16 +28332,16 @@ "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" }, "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" }, "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "requires": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" } }, "is-stream": { @@ -28108,9 +28379,9 @@ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" }, "is-weakref": { "version": "1.0.2", @@ -28121,12 +28392,12 @@ } }, "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" } }, "is-wsl": { @@ -29848,9 +30119,9 @@ "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==" }, "language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==" }, "language-tags": { "version": "1.0.9", @@ -30349,23 +30620,24 @@ } }, "object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" } }, "object.getownpropertydescriptors": { @@ -30381,34 +30653,23 @@ } }, "object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "requires": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" - } - }, - "object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "requires": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "es-abstract": "^1.23.2" } }, "object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "oblivious-set": { @@ -30730,6 +30991,11 @@ } } }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==" + }, "postcss": { "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", @@ -32140,15 +32406,15 @@ } }, "reflect.getprototypeof": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", - "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "requires": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0", - "get-intrinsic": "^1.2.3", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" } @@ -32406,12 +32672,12 @@ } }, "safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "requires": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" } @@ -32663,13 +32929,14 @@ } }, "set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "requires": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" } }, "setprototypeof": { @@ -32709,11 +32976,11 @@ "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" }, "side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "requires": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -33009,50 +33276,72 @@ } } }, + "string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + } + }, + "string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" } }, "string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "stringify-object": { @@ -33620,46 +33909,51 @@ } }, "typed-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz", - "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "requires": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-typed-array": "^1.1.13" } }, "typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" } }, "typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" } }, "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" } }, "typedarray-to-buffer": { @@ -34310,12 +34604,12 @@ } }, "which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "requires": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -34324,31 +34618,31 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" } }, "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" } }, "which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "requires": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" } }, "wildcard": { diff --git a/frontend/package.json b/frontend/package.json index 9cb7030120..15c32b95b9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -70,9 +70,13 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@eslint/js": "^9.9.1", "bootstrap-icons": "^1.11.3", "css-loader": "^6.10.0", "date-fns": "^3.6.0", + "eslint": "^8.57.0", + "eslint-plugin-react": "^7.35.0", + "globals": "^15.9.0", "html-webpack-plugin": "^5.6.0", "husky": "^9.0.11", "react-app-rewired": "^2.2.1", diff --git a/frontend/src/About.jsx b/frontend/src/About.jsx index 510eebdf79..5acf2b4b41 100644 --- a/frontend/src/About.jsx +++ b/frontend/src/About.jsx @@ -1,16 +1,13 @@ -import React, { useEffect, useState } from "react"; +import React from "react"; import { Alert } from "react-bootstrap"; import FilterPanel from "./components/FilterPanel"; export default function About() { - - return (

About

This is a simple page about wildbook. -
); } diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index c1abbac6b2..264f19c665 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,4 +1,4 @@ -import React, { useState, createContext } from "react"; +import React, { useState } from "react"; import { IntlProvider } from "react-intl"; import messagesEn from "./locale/en.json"; import messagesEs from "./locale/es.json"; @@ -9,7 +9,7 @@ import "bootstrap/dist/css/bootstrap.min.css"; import "bootstrap-icons/font/bootstrap-icons.css"; import { QueryClient, QueryClientProvider } from "react-query"; import FrontDesk from "./FrontDesk"; -import { BrowserRouter, useLocation, useRoutes } from "react-router-dom"; +import { BrowserRouter } from "react-router-dom"; import LocaleContext from "./IntlProvider"; import FooterVisibilityContext from "./FooterVisibilityContext"; import Cookies from "js-cookie"; @@ -30,7 +30,7 @@ function App() { // maxWidth: "1440px", display: "flex", flexDirection: "column", - minHeight: "100vh", + minHeight: "100vh", }; const queryClient = new QueryClient(); @@ -46,11 +46,10 @@ function App() { ...prevFilters, [filterName]: value, })); - - } + }; const resetFilters = () => { - setFilters({}); + setFilters({}); }; return ( @@ -69,9 +68,14 @@ function App() { messages={messageMap[locale]} > - - - + + + diff --git a/frontend/src/App.test.js b/frontend/src/App.test.js index 2a68616d98..7b8f80f3af 100644 --- a/frontend/src/App.test.js +++ b/frontend/src/App.test.js @@ -1,8 +1,10 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; +/* eslint-disable no-undef */ -test('renders learn react link', () => { +import React from "react"; +import { render, screen } from "@testing-library/react"; +import App from "./App"; + +test("renders learn react link", () => { render(); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); diff --git a/frontend/src/AuthenticatedSwitch.jsx b/frontend/src/AuthenticatedSwitch.jsx index a0f97ec0d7..34d28bbf32 100644 --- a/frontend/src/AuthenticatedSwitch.jsx +++ b/frontend/src/AuthenticatedSwitch.jsx @@ -6,13 +6,12 @@ import Profile from "./pages/Profile"; import Home from "./pages/Home"; import Footer from "./components/Footer"; import AuthenticatedAppHeader from "./components/AuthenticatedAppHeader"; -import UnAuthenticatedAppHeader from "./components/UnAuthenticatedAppHeader"; import useGetMe from "./models/auth/users/useGetMe"; import AlertBanner from "./components/AlertBanner"; import EncounterSearch from "./pages/EncounterSearch"; export default function AuthenticatedSwitch({ showAlert, setShowAlert }) { - const { isFetched, data, error } = useGetMe(); + const { data } = useGetMe(); const username = data?.username; const avatar = data?.imageURL || "/react/images/Avatar.png"; const [header, setHeader] = React.useState(true); @@ -44,7 +43,7 @@ export default function AuthenticatedSwitch({ showAlert, setShowAlert }) { boxSizing: "border-box", // maxWidth: "1440px", overflow: "hidden", - paddingTop: header? "48px" : "0", + paddingTop: header ? "48px" : "0", }} > @@ -53,7 +52,7 @@ export default function AuthenticatedSwitch({ showAlert, setShowAlert }) { } /> } /> } /> - } /> + } /> diff --git a/frontend/src/FrontDesk.jsx b/frontend/src/FrontDesk.jsx index a4128e9586..627c01ccfa 100644 --- a/frontend/src/FrontDesk.jsx +++ b/frontend/src/FrontDesk.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useContext } from "react"; +import React, { useEffect, useState } from "react"; import UnauthenticatedSwitch from "./UnAuthenticatedSwitch"; import AuthenticatedSwitch from "./AuthenticatedSwitch"; import axios from "axios"; @@ -12,12 +12,14 @@ import "./css/scrollBar.css"; export default function FrontDesk() { const [isLoggedIn, setIsLoggedIn] = useState(false); - const [error, setError] = useState(); + const [setError] = useState(); const [collaborationTitle, setCollaborationTitle] = useState(); const [collaborationData, setCollaborationData] = useState([]); const [mergeData, setMergeData] = useState([]); const [count, setCount] = useState(0); - const [showAlert, setShowAlert] = useState(() => Cookies.get("showAlert") === "false" ? false : true); + const [showAlert, setShowAlert] = useState(() => + Cookies.get("showAlert") === "false" ? false : true, + ); const [loading, setLoading] = useState(true); const checkLoginStatus = () => { diff --git a/frontend/src/GoogleTagManager.jsx b/frontend/src/GoogleTagManager.jsx index 1151b2a97c..443a18b5b9 100644 --- a/frontend/src/GoogleTagManager.jsx +++ b/frontend/src/GoogleTagManager.jsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import { useEffect } from "react"; const loadScript = (src, id) => { return new Promise((resolve, reject) => { diff --git a/frontend/src/ThemeColorProvider.jsx b/frontend/src/ThemeColorProvider.jsx index 82d165c0ec..dd2537d3e1 100644 --- a/frontend/src/ThemeColorProvider.jsx +++ b/frontend/src/ThemeColorProvider.jsx @@ -1,155 +1,115 @@ -import React from 'react'; +import React from "react"; const ThemeColorContext = React.createContext({ - primaryColors: { - primary50: '#E5F6FF', - primary100: '#CCF0FF', - primary400: '#33D6FF', - primary500: '#00ACCE', - primary600: '#00A5CE', - primary700: '#007599', - primary800: '#004B66', - }, - secondaryColors: { - secondary50: '#E5FFF5', - secondary100: '#CCFFEB', - secondary400: '#33FFAD', - secondary500: '#00CC79', - secondary700: '#00995C', - secondary800: '#00663D', - }, - defaultColors: { - white: '#FFFFFF', - black: '#000000', - }, - grayColors: { - gray50: '#F2F2F3', - gray100: '#E5E6E7', - gray600: '#616668', - gray700: '#494D50', - gray800: '#303336', - gray900: '#181A1B', - }, - statusColors: { - green50: '#E9FBF3', - green100: '#D4F7E7', - green400: '#52E0A0', - green500: '#26D988', - green600: '#1FAD6D', - green800: '#057536', - red50: '#FBE9EB', - red100: '#F8D7DA', - red400: '#E0525D', - red500: '#D92635', - red600: '#A32933', - red800: '#570F15', - yellow50: '#FFF9E6', - yellow100: '#FFF3CD', - yellow400: '#FFCC33', - yellow500: '#FFB800', - yellow600: '#CC9900', - yellow800: '#664D00', - indigo50: '#F0E7FD', - indigo100: '#E0CFFC', - indigo400: '#8440F2', - indigo500: '#6511EE', - indigo600: '#510DBF', - indigo800: '#290760', - blue50: '#E6F0FF', - blue100: '#CDE0FE', - blue400: '#3586FD', - blue500: '#0267FD', - blue600: '#0253CA', - blue800: '#012A65', - }, - wildMeColors: { - cyan: '#00ACCE', - teal: '#00CC79', - cyan50: '#E5F6FF', - cyan100: '#CCF0FF', - cyan200: '#99E4FF', - cyan300: '#66DBFF', - cyan400: '#33D6FF', - cyan500: '#00ACCE', - cyan600: '#00A5CE', - cyan700: '#007599', - cyan800: '#004B66', - cyan900: '#002433', - teal50: '#E5FFF5', - teal100: '#CCFFEB', - teal200: '#99FFD6', - teal300: '#66FFC2', - teal400: '#33FFAD', - teal500: '#00CC79', - teal600: '#00CC7A', - teal700: '#00995C', - teal800: '#00663D', - teal900: '#00331F', - }, - grayColors: { - gray50: '#F2F2F3', - gray100: '#E5E6E7', - gray200: '#C9CCCF', - gray300: '#AFB3B7', - gray400: '#94999E', - gray500: '#798086', - gray600: '#616668', - gray700: '#494D50', - gray800: '#303336', - gray900: '#181A1B', - }, - statusColors: { - green50: '#E9FBF3', - green100: '#D4F7E7', - green200: '#A8F0CF', - green300: '#7DE8B8', - green400: '#52E0A0', - green500: '#26D988', - green600: '#1FAD6D', - green700: '#178252', - green800: '#057536', - green900: '#082B1B', - red50: '#FBE9EB', - red100: '#F8D7DA', - red200: '#F0A8AE', - red300: '#E87D86', - red400: '#E0525D', - red500: '#D92635', - red600: '#A32933', - red700: '#821721', - red800: '#570F15', - red900: '#2B080B', - yellow50: '#FFF9E6', - yellow100: '#FFF2CD', - yellow200: '#FFE599', - yellow300: '#FFD966', - yellow400: '#FFCC33', - yellow500: '#FFB800', - yellow600: '#E5AC00', - yellow700: '#997300', - yellow800: '#664C00', - yellow900: '#342700', - indigo50: '#F0E7FD', - indigo100: '#E0CFFC', - indigo200: '#C2A1F8', - indigo300: '#A372F5', - indigo400: '#8440F2', - indigo500: '#6511EE', - indigo600: '#510DBF', - indigo700: '#3D0A91', - indigo800: '#290760', - indigo900: '#140330', - blue50: '#E6F0FF', - blue100: '#CDE0FE', - blue200: '#9AC3FE', - blue300: '#68A4FD', - blue400: '#3586FD', - blue500: '#0267FD', - blue600: '#0253CA', - blue700: '#023E97', - blue800: '#012A65', - blue900: '#011432', - } - }); + primaryColors: { + primary50: "#E5F6FF", + primary100: "#CCF0FF", + primary400: "#33D6FF", + primary500: "#00ACCE", + primary600: "#00A5CE", + primary700: "#007599", + primary800: "#004B66", + }, + secondaryColors: { + secondary50: "#E5FFF5", + secondary100: "#CCFFEB", + secondary400: "#33FFAD", + secondary500: "#00CC79", + secondary700: "#00995C", + secondary800: "#00663D", + }, + defaultColors: { + white: "#FFFFFF", + black: "#000000", + }, + wildMeColors: { + cyan: "#00ACCE", + teal: "#00CC79", + cyan50: "#E5F6FF", + cyan100: "#CCF0FF", + cyan200: "#99E4FF", + cyan300: "#66DBFF", + cyan400: "#33D6FF", + cyan500: "#00ACCE", + cyan600: "#00A5CE", + cyan700: "#007599", + cyan800: "#004B66", + cyan900: "#002433", + teal50: "#E5FFF5", + teal100: "#CCFFEB", + teal200: "#99FFD6", + teal300: "#66FFC2", + teal400: "#33FFAD", + teal500: "#00CC79", + teal600: "#00CC7A", + teal700: "#00995C", + teal800: "#00663D", + teal900: "#00331F", + }, + grayColors: { + gray50: "#F2F2F3", + gray100: "#E5E6E7", + gray200: "#C9CCCF", + gray300: "#AFB3B7", + gray400: "#94999E", + gray500: "#798086", + gray600: "#616668", + gray700: "#494D50", + gray800: "#303336", + gray900: "#181A1B", + }, + statusColors: { + green50: "#E9FBF3", + green100: "#D4F7E7", + green200: "#A8F0CF", + green300: "#7DE8B8", + green400: "#52E0A0", + green500: "#26D988", + green600: "#1FAD6D", + green700: "#178252", + green800: "#057536", + green900: "#082B1B", + red50: "#FBE9EB", + red100: "#F8D7DA", + red200: "#F0A8AE", + red300: "#E87D86", + red400: "#E0525D", + red500: "#D92635", + red600: "#A32933", + red700: "#821721", + red800: "#570F15", + red900: "#2B080B", + yellow50: "#FFF9E6", + yellow100: "#FFF2CD", + yellow200: "#FFE599", + yellow300: "#FFD966", + yellow400: "#FFCC33", + yellow500: "#FFB800", + yellow600: "#E5AC00", + yellow700: "#997300", + yellow800: "#664C00", + yellow900: "#342700", + indigo50: "#F0E7FD", + indigo100: "#E0CFFC", + indigo200: "#C2A1F8", + indigo300: "#A372F5", + indigo400: "#8440F2", + indigo500: "#6511EE", + indigo600: "#510DBF", + indigo700: "#3D0A91", + indigo800: "#290760", + indigo900: "#140330", + blue50: "#E6F0FF", + blue100: "#CDE0FE", + blue200: "#9AC3FE", + blue300: "#68A4FD", + blue400: "#3586FD", + blue500: "#0267FD", + blue600: "#0253CA", + blue700: "#023E97", + blue800: "#012A65", + blue900: "#011432", + }, +}); -export default ThemeColorContext; \ No newline at end of file +export default ThemeColorContext; diff --git a/frontend/src/UnAuthenticatedSwitch.jsx b/frontend/src/UnAuthenticatedSwitch.jsx index ccab409b5a..809320868b 100644 --- a/frontend/src/UnAuthenticatedSwitch.jsx +++ b/frontend/src/UnAuthenticatedSwitch.jsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React from "react"; import { Routes, Route } from "react-router-dom"; import Login from "./pages/Login"; import Footer from "./components/Footer"; @@ -6,14 +6,11 @@ import AlertBanner from "./components/AlertBanner"; import UnAuthenticatedAppHeader from "./components/UnAuthenticatedAppHeader"; import NotFound from "./pages/errorPages/NotFound"; import Unauthorized from "./pages/errorPages/Unauthorized"; -import About from "./About"; -import EncounterSearch from "./pages/EncounterSearch"; -import Home from "./pages/Home"; export default function UnAuthenticatedSwitch({ showAlert, setShowAlert }) { const [header, setHeader] = React.useState(true); - const [headerTop, setHeaderTop] = React.useState("60px"); - const alertBannerRef = React.useRef(null); + // const [headerTop, setHeaderTop] = React.useState("60px"); + // const alertBannerRef = React.useRef(null); return (
@@ -25,11 +22,9 @@ export default function UnAuthenticatedSwitch({ showAlert, setShowAlert }) { height: "50px", backgroundColor: "#303336", }} - > - {showAlert && } - + {showAlert && } +
{/* } /> */} - } /> + } + /> {/* } /> */} } /> } /> @@ -52,6 +50,6 @@ export default function UnAuthenticatedSwitch({ showAlert, setShowAlert }) {