From b583f0b3161b7ac163993b559a86515a308f50fc Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 1 Jul 2021 14:03:20 +0200 Subject: [PATCH 001/275] add auto build actions --- .github/workflows/dev.yaml | 23 +++++++++++++++++++++++ .github/workflows/master.yaml | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 .github/workflows/dev.yaml create mode 100644 .github/workflows/master.yaml diff --git a/.github/workflows/dev.yaml b/.github/workflows/dev.yaml new file mode 100644 index 000000000..7a581c836 --- /dev/null +++ b/.github/workflows/dev.yaml @@ -0,0 +1,23 @@ +name: Build and Deploy Dev +on: + push: + branches: + - dev +jobs: + build-and-deploy-dev: + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2.3.1 + + - name: Build 🔧 + run: | + npm install + npx gulp build-dev + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@4.1.1 + with: + branch: dist # The branch the action should deploy to. + folder: releases # The folder the action should deploy. + clean: false # build is already clean (keep prod/dev) diff --git a/.github/workflows/master.yaml b/.github/workflows/master.yaml new file mode 100644 index 000000000..1bfc20a6d --- /dev/null +++ b/.github/workflows/master.yaml @@ -0,0 +1,23 @@ +name: Build and Deploy Prod +on: + push: + branches: + - master +jobs: + build-and-deploy-prod: + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2.3.1 + + - name: Build 🔧 + run: | + npm install + npx gulp build-prod + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@4.1.1 + with: + branch: dist # The branch the action should deploy to. + folder: releases # The folder the action should deploy. + clean: false # build is already clean (keep prod/dev) From 9f86514984f085d7d1f1b677f77d50c075f647e4 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 13:43:01 +0200 Subject: [PATCH 002/275] move data -> ./model --- src/code/buttons/quickdrawButton.js | 2 +- src/code/buttons/syncButton.js | 2 +- src/code/buttons/uploadButton.js | 2 +- src/code/buttons/wasabeeButton.js | 2 +- src/code/crosslinks.js | 4 ++-- src/code/dialogs/agentDialog.js | 2 +- src/code/dialogs/assignDialog.js | 10 +++++----- src/code/dialogs/authDialog.js | 2 +- src/code/dialogs/checklist.js | 6 +++--- src/code/dialogs/defensiveKeysDialog.js | 4 ++-- src/code/dialogs/fanfield.js | 4 ++-- src/code/dialogs/homogeneous.js | 4 ++-- src/code/dialogs/importDialog.js | 4 ++-- src/code/dialogs/keyListPortal.js | 2 +- src/code/dialogs/keysList.js | 2 +- src/code/dialogs/linkDialog.js | 2 +- src/code/dialogs/madrid.js | 2 +- src/code/dialogs/manageTeamDialog.js | 4 ++-- src/code/dialogs/markerAddDialog.js | 6 +++--- src/code/dialogs/mergeDialog.js | 4 ++-- src/code/dialogs/multimaxDialog.js | 2 +- src/code/dialogs/newopDialog.js | 2 +- src/code/dialogs/onionfield.js | 4 ++-- src/code/dialogs/onlineAgentList.js | 2 +- src/code/dialogs/opPerms.js | 4 ++-- src/code/dialogs/opSettings.js | 2 +- src/code/dialogs/opsDialog.js | 6 +++--- src/code/dialogs/saveLinks.js | 2 +- src/code/dialogs/sendTargetDialog.js | 8 ++++---- src/code/dialogs/setCommentDialog.js | 6 +++--- src/code/dialogs/settingsDialog.js | 2 +- src/code/dialogs/starburst.js | 2 +- src/code/dialogs/stateDialog.js | 4 ++-- src/code/dialogs/teamListDialog.js | 2 +- src/code/dialogs/teamMembershipList.js | 2 +- src/code/dialogs/wasabeeDlist.js | 4 ++-- src/code/firebaseSupport.js | 4 ++-- src/code/init.js | 4 ++-- src/code/mapDrawing.js | 10 +++++----- src/code/{ => model}/agent.js | 10 +++++----- src/code/{ => model}/anchor.js | 14 +++++++------- src/code/{ => model}/link.js | 10 +++++----- src/code/{ => model}/marker.js | 18 +++++++++--------- src/code/{ => model}/me.js | 2 +- src/code/{ => model}/operation.js | 8 ++++---- src/code/{ => model}/portal.js | 4 ++-- src/code/{ => model}/team.js | 2 +- src/code/{ => model}/zone.js | 0 src/code/selectedOp.js | 2 +- src/code/server.js | 6 +++--- src/code/uiCommands.js | 6 +++--- src/code/wd.js | 4 ++-- 52 files changed, 114 insertions(+), 114 deletions(-) rename src/code/{ => model}/agent.js (98%) rename src/code/{ => model}/anchor.js (93%) rename src/code/{ => model}/link.js (96%) rename src/code/{ => model}/marker.js (94%) rename src/code/{ => model}/me.js (98%) rename src/code/{ => model}/operation.js (99%) rename src/code/{ => model}/portal.js (98%) rename src/code/{ => model}/team.js (97%) rename src/code/{ => model}/zone.js (100%) diff --git a/src/code/buttons/quickdrawButton.js b/src/code/buttons/quickdrawButton.js index e9b93187b..32acb6917 100644 --- a/src/code/buttons/quickdrawButton.js +++ b/src/code/buttons/quickdrawButton.js @@ -1,6 +1,6 @@ import { WTooltip, WButton } from "../leafletClasses"; import wX from "../wX"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import { postToFirebase } from "../firebaseSupport"; diff --git a/src/code/buttons/syncButton.js b/src/code/buttons/syncButton.js index edd85f1da..ce173247c 100644 --- a/src/code/buttons/syncButton.js +++ b/src/code/buttons/syncButton.js @@ -1,5 +1,5 @@ import { WButton } from "../leafletClasses"; -import WasabeeMe from "../me"; +import WasabeeMe from "../model/me"; import { fullSync } from "../uiCommands"; import wX from "../wX"; diff --git a/src/code/buttons/uploadButton.js b/src/code/buttons/uploadButton.js index de72c86a1..ec8f0f067 100644 --- a/src/code/buttons/uploadButton.js +++ b/src/code/buttons/uploadButton.js @@ -5,7 +5,7 @@ import { GetWasabeeServer, opPromise, } from "../server"; -import WasabeeMe from "../me"; +import WasabeeMe from "../model/me"; import { getSelectedOperation, makeSelectedOperation } from "../selectedOp"; import ConfirmDialog from "../dialogs/confirmDialog"; import MergeDialog from "../dialogs/mergeDialog"; diff --git a/src/code/buttons/wasabeeButton.js b/src/code/buttons/wasabeeButton.js index 79f9855cd..1178a8620 100644 --- a/src/code/buttons/wasabeeButton.js +++ b/src/code/buttons/wasabeeButton.js @@ -1,5 +1,5 @@ import { WButton } from "../leafletClasses"; -import WasabeeMe from "../me"; +import WasabeeMe from "../model/me"; import TeamListDialog from "../dialogs/teamListDialog"; import OpsDialog from "../dialogs/opsDialog"; import AuthDialog from "../dialogs/authDialog"; diff --git a/src/code/crosslinks.js b/src/code/crosslinks.js index 3ae8b62ae..710520398 100644 --- a/src/code/crosslinks.js +++ b/src/code/crosslinks.js @@ -1,5 +1,5 @@ -import WasabeePortal from "./portal"; -import WasabeeLink from "./link"; +import WasabeePortal from "./model/portal"; +import WasabeeLink from "./model/link"; import { getSelectedOperation } from "./selectedOp"; const Wasabee = window.plugin.wasabee; diff --git a/src/code/dialogs/agentDialog.js b/src/code/dialogs/agentDialog.js index 1e8434814..7f646b1d3 100644 --- a/src/code/dialogs/agentDialog.js +++ b/src/code/dialogs/agentDialog.js @@ -1,6 +1,6 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; -import WasabeeAgent from "../agent"; +import WasabeeAgent from "../model/agent"; const AgentDialog = WDialog.extend({ statics: { diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index cd949330d..89d10ddad 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -1,9 +1,9 @@ import { WDialog } from "../leafletClasses"; -import WasabeeLink from "../link"; -import WasabeeMarker from "../marker"; -import WasabeeAnchor from "../anchor"; -import WasabeeMe from "../me"; -import WasabeeTeam from "../team"; +import WasabeeLink from "../model/link"; +import WasabeeMarker from "../model/marker"; +import WasabeeAnchor from "../model/anchor"; +import WasabeeMe from "../model/me"; +import WasabeeTeam from "../model/team"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index bb8e9f141..9759ecf6b 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -10,7 +10,7 @@ import PromptDialog from "./promptDialog"; import { sendLocation, fullSync } from "../uiCommands"; import { wX } from "../wX"; import { postToFirebase } from "../firebaseSupport"; -import WasabeeMe from "../me"; +import WasabeeMe from "../model/me"; const AuthDialog = WDialog.extend({ statics: { diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index cc8280427..0cc20890d 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -1,7 +1,7 @@ import { WDialog } from "../leafletClasses"; -import WasabeeAgent from "../agent"; -import WasabeeLink from "../link"; -import WasabeeMarker from "../marker"; +import WasabeeAgent from "../model/agent"; +import WasabeeLink from "../model/link"; +import WasabeeMarker from "../model/marker"; import Sortable from "../sortable"; import AssignDialog from "./assignDialog"; import StateDialog from "./stateDialog"; diff --git a/src/code/dialogs/defensiveKeysDialog.js b/src/code/dialogs/defensiveKeysDialog.js index c71925665..8c1563013 100644 --- a/src/code/dialogs/defensiveKeysDialog.js +++ b/src/code/dialogs/defensiveKeysDialog.js @@ -1,6 +1,6 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; -import WasabeeMe from "../me"; +import WasabeePortal from "../model/portal"; +import WasabeeMe from "../model/me"; import { dKeyPromise } from "../server"; import wX from "../wX"; import WasabeeDList from "./wasabeeDlist"; diff --git a/src/code/dialogs/fanfield.js b/src/code/dialogs/fanfield.js index 8195d8850..36b8d72ed 100644 --- a/src/code/dialogs/fanfield.js +++ b/src/code/dialogs/fanfield.js @@ -1,8 +1,8 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import { greatCircleArcIntersect, GeodesicLine } from "../crosslinks"; -import WasabeeLink from "../link"; +import WasabeeLink from "../model/link"; import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; import wX from "../wX"; diff --git a/src/code/dialogs/homogeneous.js b/src/code/dialogs/homogeneous.js index e3eb19064..3f9359f7b 100644 --- a/src/code/dialogs/homogeneous.js +++ b/src/code/dialogs/homogeneous.js @@ -1,8 +1,8 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import { greatCircleArcIntersectByLatLngs } from "../crosslinks"; -// import WasabeeLink from "../link"; +// import WasabeeLink from "../model/link"; import { clearAllLinks, getAllPortalsOnScreen, diff --git a/src/code/dialogs/importDialog.js b/src/code/dialogs/importDialog.js index ff32232e4..84f40ca5f 100644 --- a/src/code/dialogs/importDialog.js +++ b/src/code/dialogs/importDialog.js @@ -1,5 +1,5 @@ -import WasabeeOp from "../operation"; -import WasabeePortal from "../portal"; +import WasabeeOp from "../model/operation"; +import WasabeePortal from "../model/portal"; import { WDialog } from "../leafletClasses"; import OperationChecklistDialog from "./checklist"; import wX from "../wX"; diff --git a/src/code/dialogs/keyListPortal.js b/src/code/dialogs/keyListPortal.js index 2a4d8e3dc..b54c258d8 100644 --- a/src/code/dialogs/keyListPortal.js +++ b/src/code/dialogs/keyListPortal.js @@ -1,6 +1,6 @@ import { WDialog } from "../leafletClasses"; import Sortable from "../sortable"; -import WasabeeAgent from "../agent"; +import WasabeeAgent from "../model/agent"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; diff --git a/src/code/dialogs/keysList.js b/src/code/dialogs/keysList.js index b602257f1..9c35e259a 100644 --- a/src/code/dialogs/keysList.js +++ b/src/code/dialogs/keysList.js @@ -1,7 +1,7 @@ import { WDialog } from "../leafletClasses"; import Sortable from "../sortable"; import { opKeyPromise } from "../server"; -import WasabeeMe from "../me"; +import WasabeeMe from "../model/me"; import KeyListPortal from "./keyListPortal"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; diff --git a/src/code/dialogs/linkDialog.js b/src/code/dialogs/linkDialog.js index aab280908..4b05f3523 100644 --- a/src/code/dialogs/linkDialog.js +++ b/src/code/dialogs/linkDialog.js @@ -1,5 +1,5 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; diff --git a/src/code/dialogs/madrid.js b/src/code/dialogs/madrid.js index c90885b1a..721380f87 100644 --- a/src/code/dialogs/madrid.js +++ b/src/code/dialogs/madrid.js @@ -1,5 +1,5 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import { getAllPortalsOnScreen, diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 3b0e53e3b..09175f1fd 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -10,8 +10,8 @@ import { deleteJoinLinkPromise, createJoinLinkPromise, } from "../server"; -import WasabeeMe from "../me"; -import WasabeeTeam from "../team"; +import WasabeeMe from "../model/me"; +import WasabeeTeam from "../model/team"; import Sortable from "../sortable"; import PromptDialog from "./promptDialog"; import wX from "../wX"; diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index f1ef46571..22c9746d2 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -1,7 +1,7 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; -import WasabeeMe from "../me"; -import WasabeeTeam from "../team"; +import WasabeePortal from "../model/portal"; +import WasabeeMe from "../model/me"; +import WasabeeTeam from "../model/team"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index d14a7d202..e2cc1d61e 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -1,7 +1,7 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; -import WasabeeAgent from "../agent"; -import WasabeeOp from "../operation"; +import WasabeeAgent from "../model/agent"; +import WasabeeOp from "../model/operation"; import Sortable from "../sortable"; import { getSelectedOperation, makeSelectedOperation } from "../selectedOp"; import { drawBackgroundOp } from "../mapDrawing"; diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/multimaxDialog.js index abeee322e..fcc952aac 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/multimaxDialog.js @@ -1,5 +1,5 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; import { diff --git a/src/code/dialogs/newopDialog.js b/src/code/dialogs/newopDialog.js index 906ed4536..ea63c77aa 100644 --- a/src/code/dialogs/newopDialog.js +++ b/src/code/dialogs/newopDialog.js @@ -1,5 +1,5 @@ import { WDialog } from "../leafletClasses"; -import WasabeeOp from "../operation"; +import WasabeeOp from "../model/operation"; import ImportDialog from "./importDialog"; import PromptDialog from "./promptDialog"; import { makeSelectedOperation } from "../selectedOp"; diff --git a/src/code/dialogs/onionfield.js b/src/code/dialogs/onionfield.js index d089c1a3e..26d3b4c0f 100644 --- a/src/code/dialogs/onionfield.js +++ b/src/code/dialogs/onionfield.js @@ -1,8 +1,8 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import { greatCircleArcIntersect } from "../crosslinks"; -import WasabeeLink from "../link"; +import WasabeeLink from "../model/link"; import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; import wX from "../wX"; diff --git a/src/code/dialogs/onlineAgentList.js b/src/code/dialogs/onlineAgentList.js index 164ee0562..47166d1ed 100644 --- a/src/code/dialogs/onlineAgentList.js +++ b/src/code/dialogs/onlineAgentList.js @@ -1,6 +1,6 @@ import { WDialog } from "../leafletClasses"; import Sortable from "../sortable"; -import WasabeeAgent from "../agent"; +import WasabeeAgent from "../model/agent"; import wX from "../wX"; const OnlineAgentList = WDialog.extend({ diff --git a/src/code/dialogs/opPerms.js b/src/code/dialogs/opPerms.js index 2d07067a1..83e5bb4e5 100644 --- a/src/code/dialogs/opPerms.js +++ b/src/code/dialogs/opPerms.js @@ -1,8 +1,8 @@ import { WDialog } from "../leafletClasses"; import Sortable from "../sortable"; import { getSelectedOperation } from "../selectedOp"; -import WasabeeTeam from "../team"; -import WasabeeMe from "../me"; +import WasabeeTeam from "../model/team"; +import WasabeeMe from "../model/me"; import { addPermPromise, delPermPromise } from "../server"; import wX from "../wX"; diff --git a/src/code/dialogs/opSettings.js b/src/code/dialogs/opSettings.js index 65db6421c..7b3e2fe11 100644 --- a/src/code/dialogs/opSettings.js +++ b/src/code/dialogs/opSettings.js @@ -13,7 +13,7 @@ import { import OpPermList from "./opPerms"; import wX from "../wX"; import { addToColorList } from "../skin"; -import WasabeeMe from "../me"; +import WasabeeMe from "../model/me"; import { convertColorToHex } from "../auxiliar"; diff --git a/src/code/dialogs/opsDialog.js b/src/code/dialogs/opsDialog.js index b1a2807ef..d00c4f53c 100644 --- a/src/code/dialogs/opsDialog.js +++ b/src/code/dialogs/opsDialog.js @@ -1,4 +1,4 @@ -import WasabeeOp from "../operation"; +import WasabeeOp from "../model/operation"; import { WDialog } from "../leafletClasses"; import { getSelectedOperation, @@ -12,8 +12,8 @@ import { } from "../selectedOp"; import OpPermList from "./opPerms"; import wX from "../wX"; -import WasabeeMe from "../me"; -import WasabeeAgent from "../agent"; +import WasabeeMe from "../model/me"; +import WasabeeAgent from "../model/agent"; import { syncOp, deleteLocalOp, zoomToOperation } from "../uiCommands"; import Sortable from "../sortable"; diff --git a/src/code/dialogs/saveLinks.js b/src/code/dialogs/saveLinks.js index 26af69fb1..97439f4b5 100644 --- a/src/code/dialogs/saveLinks.js +++ b/src/code/dialogs/saveLinks.js @@ -1,5 +1,5 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import { clearAllLinks, getAllPortalsLinked } from "../uiCommands"; import wX from "../wX"; diff --git a/src/code/dialogs/sendTargetDialog.js b/src/code/dialogs/sendTargetDialog.js index 2664c8de6..d735212c5 100644 --- a/src/code/dialogs/sendTargetDialog.js +++ b/src/code/dialogs/sendTargetDialog.js @@ -1,8 +1,8 @@ import { WDialog } from "../leafletClasses"; -import WasabeeMarker from "../marker"; -import WasabeeAnchor from "../anchor"; -import WasabeeMe from "../me"; -import WasabeeTeam from "../team"; +import WasabeeMarker from "../model/marker"; +import WasabeeAnchor from "../model/anchor"; +import WasabeeMe from "../model/me"; +import WasabeeTeam from "../model/team"; import { targetPromise } from "../server"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; diff --git a/src/code/dialogs/setCommentDialog.js b/src/code/dialogs/setCommentDialog.js index 7fe0e2690..68821f0e7 100644 --- a/src/code/dialogs/setCommentDialog.js +++ b/src/code/dialogs/setCommentDialog.js @@ -1,7 +1,7 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; -import WasabeeLink from "../link"; -import WasabeeMarker from "../marker"; +import WasabeePortal from "../model/portal"; +import WasabeeLink from "../model/link"; +import WasabeeMarker from "../model/marker"; import wX from "../wX"; export const SetCommentDialog = WDialog.extend({ diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index c20244945..0f69b4330 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -1,6 +1,6 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; -import WasabeeMe from "../me"; +import WasabeeMe from "../model/me"; import { GetWasabeeServer, SetWasabeeServer } from "../server"; import PromptDialog from "./promptDialog"; import SkinDialog from "./skinDialog"; diff --git a/src/code/dialogs/starburst.js b/src/code/dialogs/starburst.js index bd6e148de..8eb6d69d1 100644 --- a/src/code/dialogs/starburst.js +++ b/src/code/dialogs/starburst.js @@ -1,5 +1,5 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../portal"; +import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; import wX from "../wX"; diff --git a/src/code/dialogs/stateDialog.js b/src/code/dialogs/stateDialog.js index 2f0f7d4e1..7bca225c0 100644 --- a/src/code/dialogs/stateDialog.js +++ b/src/code/dialogs/stateDialog.js @@ -1,6 +1,6 @@ import { WDialog } from "../leafletClasses"; -import WasabeeLink from "../link"; -import WasabeeMarker from "../marker"; +import WasabeeLink from "../model/link"; +import WasabeeMarker from "../model/marker"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; diff --git a/src/code/dialogs/teamListDialog.js b/src/code/dialogs/teamListDialog.js index a3f3f8720..15aadd2a9 100644 --- a/src/code/dialogs/teamListDialog.js +++ b/src/code/dialogs/teamListDialog.js @@ -1,5 +1,5 @@ import { WDialog } from "../leafletClasses"; -import WasabeeMe from "../me"; +import WasabeeMe from "../model/me"; import Sortable from "../sortable"; import { SetTeamState, diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index 7a47146ce..e6723e0e3 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -1,6 +1,6 @@ import { WDialog } from "../leafletClasses"; import Sortable from "../sortable"; -import WasabeeTeam from "../team"; +import WasabeeTeam from "../model/team"; import wX from "../wX"; const TeamMembershipList = WDialog.extend({ diff --git a/src/code/dialogs/wasabeeDlist.js b/src/code/dialogs/wasabeeDlist.js index 9e99bcea9..9887d98be 100644 --- a/src/code/dialogs/wasabeeDlist.js +++ b/src/code/dialogs/wasabeeDlist.js @@ -1,8 +1,8 @@ import { WDialog } from "../leafletClasses"; import Sortable from "../sortable"; import wX from "../wX"; -import WasabeeMe from "../me"; -import WasabeePortal from "../portal"; +import WasabeeMe from "../model/me"; +import WasabeePortal from "../model/portal"; import { getAgentWasabeeDkeys } from "../wd"; const WasabeeDList = WDialog.extend({ diff --git a/src/code/firebaseSupport.js b/src/code/firebaseSupport.js index d9f7fcf5a..d908e4b1a 100644 --- a/src/code/firebaseSupport.js +++ b/src/code/firebaseSupport.js @@ -13,8 +13,8 @@ import { loadNewDefaultOp, } from "./selectedOp"; import { updateLocalOp } from "./uiCommands"; -import WasabeeOp from "./operation"; -import WasabeePortal from "./portal"; +import WasabeeOp from "./model/operation"; +import WasabeePortal from "./model/portal"; // TODO: use a dedicated message channel: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging diff --git a/src/code/init.js b/src/code/init.js index 62f39e9e7..3ead3d7e6 100644 --- a/src/code/init.js +++ b/src/code/init.js @@ -15,8 +15,8 @@ import { listenForPortalDetails, sendLocation } from "./uiCommands"; import { initSkin, changeSkin } from "./skin"; import { WPane } from "./leafletClasses"; import OperationChecklist from "./dialogs/checklist"; -import WasabeeMe from "./me"; -import WasabeeOp from "./operation"; +import WasabeeMe from "./model/me"; +import WasabeeOp from "./model/operation"; import { openDB } from "idb"; import polyfill from "./polyfill"; diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index 970edd4f4..5966ca0f3 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -1,8 +1,8 @@ -import WasabeeMe from "./me"; -import WasabeeAnchor from "./anchor"; -import WasabeeTeam from "./team"; -import WasabeeAgent from "./agent"; -import WasabeeOp from "./operation"; +import WasabeeMe from "./model/me"; +import WasabeeAnchor from "./model/anchor"; +import WasabeeTeam from "./model/team"; +import WasabeeAgent from "./model/agent"; +import WasabeeOp from "./model/operation"; import { newColors } from "./auxiliar"; import { getSelectedOperation, opsList } from "./selectedOp"; diff --git a/src/code/agent.js b/src/code/model/agent.js similarity index 98% rename from src/code/agent.js rename to src/code/model/agent.js index cc70f3a8b..37f6e2bc2 100644 --- a/src/code/agent.js +++ b/src/code/model/agent.js @@ -1,9 +1,9 @@ import WasabeePortal from "./portal"; -import ConfirmDialog from "./dialogs/confirmDialog"; -import AgentDialog from "./dialogs/agentDialog"; -import { agentPromise, targetPromise, routePromise } from "./server"; -import { getSelectedOperation } from "./selectedOp"; -import wX from "./wX"; +import ConfirmDialog from "../dialogs/confirmDialog"; +import AgentDialog from "../dialogs/agentDialog"; +import { agentPromise, targetPromise, routePromise } from "../server"; +import { getSelectedOperation } from "../selectedOp"; +import wX from "../wX"; import WasabeeMe from "./me"; import WasabeeTeam from "./team"; diff --git a/src/code/anchor.js b/src/code/model/anchor.js similarity index 93% rename from src/code/anchor.js rename to src/code/model/anchor.js index f20261b7b..7dc3ad4b3 100644 --- a/src/code/anchor.js +++ b/src/code/model/anchor.js @@ -1,10 +1,10 @@ -import { swapPortal, deletePortal } from "./uiCommands"; -import { getSelectedOperation } from "./selectedOp"; -import AssignDialog from "./dialogs/assignDialog"; -import SendTargetDialog from "./dialogs/sendTargetDialog"; -import SetCommentDialog from "./dialogs/setCommentDialog"; -import LinkListDialog from "./dialogs/linkListDialog"; -import wX from "./wX"; +import { swapPortal, deletePortal } from "../uiCommands"; +import { getSelectedOperation } from "../selectedOp"; +import AssignDialog from "../dialogs/assignDialog"; +import SendTargetDialog from "../dialogs/sendTargetDialog"; +import SetCommentDialog from "../dialogs/setCommentDialog"; +import LinkListDialog from "../dialogs/linkListDialog"; +import wX from "../wX"; // this class is for the popups, and for assign menu export default class WasabeeAnchor { diff --git a/src/code/link.js b/src/code/model/link.js similarity index 96% rename from src/code/link.js rename to src/code/model/link.js index d51fe30cd..396c86cc8 100644 --- a/src/code/link.js +++ b/src/code/model/link.js @@ -1,8 +1,8 @@ -import { generateId, convertColorToHex, newColors } from "./auxiliar"; -import { getSelectedOperation } from "./selectedOp"; -import wX from "./wX"; -import AssignDialog from "./dialogs/assignDialog"; -import { addToColorList } from "./skin"; +import { generateId, convertColorToHex, newColors } from "../auxiliar"; +import { getSelectedOperation } from "../selectedOp"; +import wX from "../wX"; +import AssignDialog from "../dialogs/assignDialog"; +import { addToColorList } from "../skin"; export default class WasabeeLink { constructor(obj) { diff --git a/src/code/marker.js b/src/code/model/marker.js similarity index 94% rename from src/code/marker.js rename to src/code/model/marker.js index e30aa768e..ddc88ae49 100644 --- a/src/code/marker.js +++ b/src/code/model/marker.js @@ -1,13 +1,13 @@ -import { generateId } from "./auxiliar"; -import { deleteMarker } from "./uiCommands"; +import { generateId } from "../auxiliar"; +import { deleteMarker } from "../uiCommands"; import WasabeeAgent from "./agent"; -import AssignDialog from "./dialogs/assignDialog"; -import SendTargetDialog from "./dialogs/sendTargetDialog"; -import wX from "./wX"; -import SetCommentDialog from "./dialogs/setCommentDialog"; -import MarkerChangeDialog from "./dialogs/markerChangeDialog"; -import StateDialog from "./dialogs/stateDialog"; -import { getSelectedOperation } from "./selectedOp"; +import AssignDialog from "../dialogs/assignDialog"; +import SendTargetDialog from "../dialogs/sendTargetDialog"; +import wX from "../wX"; +import SetCommentDialog from "../dialogs/setCommentDialog"; +import MarkerChangeDialog from "../dialogs/markerChangeDialog"; +import StateDialog from "../dialogs/stateDialog"; +import { getSelectedOperation } from "../selectedOp"; const STATE_UNASSIGNED = "pending"; const STATE_ASSIGNED = "assigned"; diff --git a/src/code/me.js b/src/code/model/me.js similarity index 98% rename from src/code/me.js rename to src/code/model/me.js index 5a6bcda4d..af2c9455a 100644 --- a/src/code/me.js +++ b/src/code/model/me.js @@ -1,4 +1,4 @@ -import { mePromise } from "./server"; +import { mePromise } from "../server"; const Wasabee = window.plugin.wasabee; diff --git a/src/code/operation.js b/src/code/model/operation.js similarity index 99% rename from src/code/operation.js rename to src/code/model/operation.js index 44c3a5160..dd8c19842 100644 --- a/src/code/operation.js +++ b/src/code/model/operation.js @@ -3,11 +3,11 @@ import WasabeePortal from "./portal"; import WasabeeMarker from "./marker"; import WasabeeMe from "./me"; import WasabeeZone from "./zone"; -import { generateId, newColors } from "./auxiliar"; -import { GetWasabeeServer } from "./server"; -import { getSelectedOperation } from "./selectedOp"; +import { generateId, newColors } from "../auxiliar"; +import { GetWasabeeServer } from "../server"; +import { getSelectedOperation } from "../selectedOp"; -import wX from "./wX"; +import wX from "../wX"; const Wasabee = window.plugin.wasabee; diff --git a/src/code/portal.js b/src/code/model/portal.js similarity index 98% rename from src/code/portal.js rename to src/code/model/portal.js index 63db0e0d8..3323fb10f 100644 --- a/src/code/portal.js +++ b/src/code/model/portal.js @@ -1,5 +1,5 @@ -import { generateId } from "./auxiliar"; -import wX from "./wX"; +import { generateId } from "../auxiliar"; +import wX from "../wX"; export default class WasabeePortal { constructor(obj) { diff --git a/src/code/team.js b/src/code/model/team.js similarity index 97% rename from src/code/team.js rename to src/code/model/team.js index a7f3b5e30..980d276f9 100644 --- a/src/code/team.js +++ b/src/code/model/team.js @@ -1,6 +1,6 @@ import WasabeeAgent from "./agent"; import WasabeeMe from "./me"; -import { teamPromise } from "./server"; +import { teamPromise } from "../server"; export default class WasabeeTeam { constructor(data) { diff --git a/src/code/zone.js b/src/code/model/zone.js similarity index 100% rename from src/code/zone.js rename to src/code/model/zone.js diff --git a/src/code/selectedOp.js b/src/code/selectedOp.js index b482d258f..0910c1ba7 100644 --- a/src/code/selectedOp.js +++ b/src/code/selectedOp.js @@ -1,4 +1,4 @@ -import WasabeeOp from "./operation"; +import WasabeeOp from "./model/operation"; import wX from "./wX"; import { generateId } from "./auxiliar"; diff --git a/src/code/server.js b/src/code/server.js index ca4da1d3a..f4b01b3f4 100644 --- a/src/code/server.js +++ b/src/code/server.js @@ -1,8 +1,8 @@ -import WasabeeMe from "./me"; -import WasabeeOp from "./operation"; +import WasabeeMe from "./model/me"; +import WasabeeOp from "./model/operation"; import { getSelectedOperation, removeOperation } from "./selectedOp"; import wX from "./wX"; -import WasabeeMarker from "./marker"; +import WasabeeMarker from "./model/marker"; export default function () { return GetWasabeeServer(); diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index 2b0bfcf8f..83f09781e 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -1,8 +1,8 @@ -import WasabeeOp from "./operation"; -import WasabeePortal from "./portal"; +import WasabeeOp from "./model/operation"; +import WasabeePortal from "./model/portal"; import ConfirmDialog from "./dialogs/confirmDialog"; import MergeDialog from "./dialogs/mergeDialog"; -import WasabeeMe from "./me"; +import WasabeeMe from "./model/me"; import wX from "./wX"; import { opPromise, GetWasabeeServer, locationPromise } from "./server"; import AuthDialog from "./dialogs/authDialog"; diff --git a/src/code/wd.js b/src/code/wd.js index ab2cc4eed..35f9ba25c 100644 --- a/src/code/wd.js +++ b/src/code/wd.js @@ -1,6 +1,6 @@ -import WasabeeMe from "./me"; +import WasabeeMe from "./model/me"; import { dKeylistPromise } from "./server"; -import WasabeeAgent from "./agent"; +import WasabeeAgent from "./model/agent"; import wX from "./wX"; // import { getPortalDetails } from "./uiCommands"; From 02e181264371f39bcfabddbe9855a61e1abaa8cb Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 14:07:53 +0200 Subject: [PATCH 003/275] add portalUI --- src/code/buttons/quickdrawButton.js | 5 +- src/code/crosslinks.js | 6 +- src/code/dialogs/assignDialog.js | 14 ++-- src/code/dialogs/blockersList.js | 6 +- src/code/dialogs/checklist.js | 4 +- src/code/dialogs/defensiveKeysDialog.js | 7 +- src/code/dialogs/fanfield.js | 22 +++--- src/code/dialogs/homogeneous.js | 22 +++--- src/code/dialogs/keyListPortal.js | 10 ++- src/code/dialogs/keysList.js | 4 +- src/code/dialogs/linkDialog.js | 20 ++--- src/code/dialogs/linkListDialog.js | 6 +- src/code/dialogs/madrid.js | 14 ++-- src/code/dialogs/markerAddDialog.js | 9 ++- src/code/dialogs/markerChangeDialog.js | 6 +- src/code/dialogs/mergeDialog.js | 6 +- src/code/dialogs/multimaxDialog.js | 14 ++-- src/code/dialogs/onionfield.js | 8 +- src/code/dialogs/saveLinks.js | 8 +- src/code/dialogs/sendTargetDialog.js | 6 +- src/code/dialogs/setCommentDialog.js | 10 ++- src/code/dialogs/starburst.js | 8 +- src/code/dialogs/stateDialog.js | 4 +- src/code/dialogs/wasabeeDlist.js | 4 +- src/code/firebaseSupport.js | 4 +- src/code/model/agent.js | 11 +-- src/code/model/anchor.js | 6 +- src/code/model/link.js | 9 ++- src/code/model/marker.js | 4 +- src/code/model/portal.js | 93 ----------------------- src/code/ui/portal.js | 99 +++++++++++++++++++++++++ src/code/uiCommands.js | 18 +++-- 32 files changed, 271 insertions(+), 196 deletions(-) create mode 100644 src/code/ui/portal.js diff --git a/src/code/buttons/quickdrawButton.js b/src/code/buttons/quickdrawButton.js index 32acb6917..311b0d8e6 100644 --- a/src/code/buttons/quickdrawButton.js +++ b/src/code/buttons/quickdrawButton.js @@ -1,9 +1,10 @@ import { WTooltip, WButton } from "../leafletClasses"; import wX from "../wX"; -import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import { postToFirebase } from "../firebaseSupport"; +import PortalUI from "../ui/portal"; + const QuickdrawButton = WButton.extend({ statics: { TYPE: "QuickdrawButton", @@ -253,7 +254,7 @@ const QuickDrawControl = L.Handler.extend({ }, _portalClicked: function (portal) { - const selectedPortal = WasabeePortal.fromIITC(portal); + const selectedPortal = PortalUI.fromIITC(portal); if (!selectedPortal) { // XXX wX this this._tooltip.updateContent({ diff --git a/src/code/crosslinks.js b/src/code/crosslinks.js index 710520398..e84ecf5b4 100644 --- a/src/code/crosslinks.js +++ b/src/code/crosslinks.js @@ -2,6 +2,8 @@ import WasabeePortal from "./model/portal"; import WasabeeLink from "./model/link"; import { getSelectedOperation } from "./selectedOp"; +import PortalUI from "./ui/portal"; + const Wasabee = window.plugin.wasabee; // from iitc rework : https://github.com/IITC-CE/ingress-intel-total-conversion/pull/333 @@ -180,7 +182,7 @@ function testLink(link, operation) { for (const drawnLink of operation.links) { if (testPolyLine(drawnLink, link, operation)) { showCrossLink(link, operation); - let fromPortal = WasabeePortal.get(link.options.data.oGuid); + let fromPortal = PortalUI.get(link.options.data.oGuid); if (!fromPortal) fromPortal = WasabeePortal.fake( (link.options.data.oLatE6 / 1e6).toFixed(6), @@ -188,7 +190,7 @@ function testLink(link, operation) { link.options.data.oGuid ); operation._addPortal(fromPortal); - let toPortal = WasabeePortal.get(link.options.data.dGuid); + let toPortal = PortalUI.get(link.options.data.dGuid); if (!toPortal) toPortal = WasabeePortal.fake( (link.options.data.dLatE6 / 1e6).toFixed(6), diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index 89d10ddad..d14bddefb 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -7,6 +7,8 @@ import WasabeeTeam from "../model/team"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; +import PortalUI from "../ui/portal"; + const AssignDialog = WDialog.extend({ statics: { TYPE: "assignDialog", @@ -53,7 +55,9 @@ const AssignDialog = WDialog.extend({ if (target instanceof WasabeeLink) { const portal = operation.getPortal(target.fromPortalId); this._type = "Link"; - this._name = wX("ASSIGN LINK PROMPT", { portalName: portal.displayName }); + this._name = wX("ASSIGN LINK PROMPT", { + portalName: PortalUI.displayName(portal), + }); divtitle.appendChild(target.displayFormat(operation, this._smallScreen)); const t = L.DomUtil.create("label", null); t.textContent = wX("LINK ASSIGNMENT"); @@ -64,9 +68,9 @@ const AssignDialog = WDialog.extend({ const portal = operation.getPortal(target.portalId); this._type = "Marker"; this._name = wX("ASSIGN MARKER PROMPT", { - portalName: portal.displayName, + portalName: PortalUI.displayName(portal), }); - divtitle.appendChild(portal.displayFormat(this._smallScreen)); + divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); const t = L.DomUtil.create("label", null); t.textContent = wX("MARKER ASSIGNMENT"); menu.prepend(t); @@ -76,9 +80,9 @@ const AssignDialog = WDialog.extend({ const portal = operation.getPortal(target.portalId); this._type = "Anchor"; this._name = wX("ASSIGN OUTBOUND PROMPT", { - portalName: portal.displayName, + portalName: PortalUI.displayName(portal), }); - divtitle.appendChild(portal.displayFormat(this._smallScreen)); + divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); const t = L.DomUtil.create("label", null); t.textContent = wX("ANCHOR ASSIGNMENT"); menu.prepend(t); diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index 2bc5e841b..9816be0ab 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -10,6 +10,8 @@ import { import wX from "../wX"; import TrawlDialog from "./trawl"; +import PortalUI from "../ui/portal"; + const BlockerList = WDialog.extend({ statics: { TYPE: "blockerList", @@ -107,7 +109,7 @@ const BlockerList = WDialog.extend({ sort: (a, b) => a.localeCompare(b), format: (row, value, blocker) => { const p = operation.getPortal(blocker.fromPortalId); - row.appendChild(p.displayFormat()); + row.appendChild(PortalUI.displayFormat(p)); }, }, { @@ -130,7 +132,7 @@ const BlockerList = WDialog.extend({ sort: (a, b) => a.localeCompare(b), format: (row, value, blocker) => { const p = operation.getPortal(blocker.toPortalId); - row.appendChild(p.displayFormat()); + row.appendChild(PortalUI.displayFormat(p)); }, }, { diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 0cc20890d..6d4403a3f 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -17,6 +17,8 @@ import { import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const OperationChecklistDialog = WDialog.extend({ statics: { TYPE: "operationChecklist", @@ -131,7 +133,7 @@ const OperationChecklistDialog = WDialog.extend({ if (this._smallScreen) cell.colSpan = 2; } else { cell.appendChild( - operation.getPortal(thing.portalId).displayFormat() + PortalUI.displayFormat(operation.getPortal(thing.portalId)) ); } }, diff --git a/src/code/dialogs/defensiveKeysDialog.js b/src/code/dialogs/defensiveKeysDialog.js index 8c1563013..246fcd0f1 100644 --- a/src/code/dialogs/defensiveKeysDialog.js +++ b/src/code/dialogs/defensiveKeysDialog.js @@ -1,11 +1,12 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; import WasabeeMe from "../model/me"; import { dKeyPromise } from "../server"; import wX from "../wX"; import WasabeeDList from "./wasabeeDlist"; import { getAgentPortalWasabeeDkeys } from "../wd"; +import PortalUI from "../ui/portal"; + const DefensiveKeysDialog = WDialog.extend({ statics: { TYPE: "defensiveKeysDialog", @@ -28,11 +29,11 @@ const DefensiveKeysDialog = WDialog.extend({ }, _portalClickedHook: async function () { - this._selectedPortal = WasabeePortal.getSelected(); + this._selectedPortal = PortalUI.getSelected(); if (this._selectedPortal) { this._portal.textContent = ""; this._portal.appendChild( - this._selectedPortal.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._selectedPortal, this._smallScreen) ); const mine = await getAgentPortalWasabeeDkeys( this._me.GoogleID, diff --git a/src/code/dialogs/fanfield.js b/src/code/dialogs/fanfield.js index 36b8d72ed..7dc8b4d44 100644 --- a/src/code/dialogs/fanfield.js +++ b/src/code/dialogs/fanfield.js @@ -6,6 +6,8 @@ import WasabeeLink from "../model/link"; import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const FanfieldDialog = WDialog.extend({ statics: { TYPE: "FanfieldDialog", @@ -28,19 +30,19 @@ const FanfieldDialog = WDialog.extend({ this._anchorDisplay = L.DomUtil.create("span", null, container); if (this._anchor) { this._anchorDisplay.appendChild( - this._anchor.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor, this._smallScreen) ); } else { this._anchorDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorButton, "click", (ev) => { L.DomEvent.stop(ev); - this._anchor = WasabeePortal.getSelected(); + this._anchor = PortalUI.getSelected(); if (this._anchor) { localStorage["wasabee-anchor-1"] = JSON.stringify(this._anchor); this._anchorDisplay.textContent = ""; this._anchorDisplay.appendChild( - this._anchor.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -54,19 +56,19 @@ const FanfieldDialog = WDialog.extend({ this._startDisplay = L.DomUtil.create("span", null, container); if (this._start) { this._startDisplay.appendChild( - this._start.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._start, this._smallScreen) ); } else { this._startDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(startButton, "click", (ev) => { L.DomEvent.stop(ev); - this._start = WasabeePortal.getSelected(); + this._start = PortalUI.getSelected(); if (this._start) { localStorage["wasabee-fanfield-start"] = JSON.stringify(this._start); this._startDisplay.textContent = ""; this._startDisplay.appendChild( - this._start.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._start, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -79,18 +81,20 @@ const FanfieldDialog = WDialog.extend({ endButton.textContent = wX("SET"); this._endDisplay = L.DomUtil.create("span", null, container); if (this._end) { - this._endDisplay.appendChild(this._end.displayFormat(this._smallScreen)); + this._endDisplay.appendChild( + PortalUI.displayFormat(this._end, this._smallScreen) + ); } else { this._endDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(endButton, "click", (ev) => { L.DomEvent.stop(ev); - this._end = WasabeePortal.getSelected(); + this._end = PortalUI.getSelected(); if (this._end) { localStorage["wasabee-fanfield-end"] = JSON.stringify(this._end); this._endDisplay.textContent = ""; this._endDisplay.appendChild( - this._end.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._end, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); diff --git a/src/code/dialogs/homogeneous.js b/src/code/dialogs/homogeneous.js index 3f9359f7b..6910ee5b6 100644 --- a/src/code/dialogs/homogeneous.js +++ b/src/code/dialogs/homogeneous.js @@ -10,6 +10,8 @@ import { } from "../uiCommands"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const HomogeneousDialog = WDialog.extend({ statics: { TYPE: "HomogeneousDialog", @@ -40,20 +42,20 @@ const HomogeneousDialog = WDialog.extend({ this._anchorDisplayOne = L.DomUtil.create("span", "portal", container); if (this._anchorOne) { this._anchorDisplayOne.appendChild( - this._anchorOne.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorOne, this._smallScreen) ); } else { this._anchorDisplayOne.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorButtonOne, "click", (ev) => { L.DomEvent.stop(ev); - this._anchorOne = WasabeePortal.getSelected(); + this._anchorOne = PortalUI.getSelected(); if (this._anchorOne) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = JSON.stringify(this._anchorOne); this._anchorDisplayOne.textContent = ""; this._anchorDisplayOne.appendChild( - this._anchorOne.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorOne, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -67,20 +69,20 @@ const HomogeneousDialog = WDialog.extend({ this._anchorDisplayTwo = L.DomUtil.create("span", "portal", container); if (this._anchorTwo) { this._anchorDisplayTwo.appendChild( - this._anchorTwo.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorTwo, this._smallScreen) ); } else { this._anchorDisplayTwo.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorButtonTwo, "click", (ev) => { L.DomEvent.stop(ev); - this._anchorTwo = WasabeePortal.getSelected(); + this._anchorTwo = PortalUI.getSelected(); if (this._anchorTwo) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY] = JSON.stringify(this._anchorTwo); this._anchorDisplayTwo.textContent = ""; this._anchorDisplayTwo.appendChild( - this._anchorTwo.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorTwo, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -94,20 +96,20 @@ const HomogeneousDialog = WDialog.extend({ this._anchorDisplayThree = L.DomUtil.create("span", "portal", container); if (this._anchorThree) { this._anchorDisplayThree.appendChild( - this._anchorThree.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorThree, this._smallScreen) ); } else { this._anchorDisplayThree.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorButtonThree, "click", (ev) => { L.DomEvent.stop(ev); - this._anchorThree = WasabeePortal.getSelected(); + this._anchorThree = PortalUI.getSelected(); if (this._anchorThree) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_THREE_KEY] = JSON.stringify(this._anchorThree); this._anchorDisplayThree.textContent = ""; this._anchorDisplayThree.appendChild( - this._anchorThree.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorThree, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -486,7 +488,7 @@ const HomogeneousDialog = WDialog.extend({ children: null, }; for (const k of sorted.keys()) { - const wp = WasabeePortal.get(k); + const wp = PortalUI.get(k); const subregions = this._getSubregions( wp, new Array(...portalsCovered), diff --git a/src/code/dialogs/keyListPortal.js b/src/code/dialogs/keyListPortal.js index b54c258d8..c6f095d20 100644 --- a/src/code/dialogs/keyListPortal.js +++ b/src/code/dialogs/keyListPortal.js @@ -4,6 +4,8 @@ import WasabeeAgent from "../model/agent"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const KeyListPortal = WDialog.extend({ statics: { TYPE: "keyListPortal", @@ -41,7 +43,9 @@ const KeyListPortal = WDialog.extend({ const portal = op.getPortal(this.options.portalID); this.createDialog({ - title: wX("PORTAL KEY LIST", { portalName: portal.displayName }), + title: wX("PORTAL KEY LIST", { + portalName: PortalUI.displayName(portal), + }), html: this.getListDialogContent(this.options.portalID), width: "auto", dialogClass: "keylistportal", @@ -63,7 +67,9 @@ const KeyListPortal = WDialog.extend({ const table = this.getListDialogContent(this.options.portalID); this.setContent(table); - this.setTitle(wX("PORTAL KEY LIST", { portalName: portal.displayName })); + this.setTitle( + wX("PORTAL KEY LIST", { portalName: PortalUI.displayName(portal) }) + ); }, getSortable: function () { diff --git a/src/code/dialogs/keysList.js b/src/code/dialogs/keysList.js index 9c35e259a..cff6729a1 100644 --- a/src/code/dialogs/keysList.js +++ b/src/code/dialogs/keysList.js @@ -6,6 +6,8 @@ import KeyListPortal from "./keyListPortal"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const KeysList = WDialog.extend({ statics: { TYPE: "keysList", @@ -75,7 +77,7 @@ const KeysList = WDialog.extend({ value: (key) => operation.getPortal(key.id).name, sort: (a, b) => a.localeCompare(b), format: (cell, value, key) => { - cell.appendChild(operation.getPortal(key.id).displayFormat()); + cell.appendChild(PortalUI.displayFormat(operation.getPortal(key.id))); }, }, { diff --git a/src/code/dialogs/linkDialog.js b/src/code/dialogs/linkDialog.js index 4b05f3523..076d5113d 100644 --- a/src/code/dialogs/linkDialog.js +++ b/src/code/dialogs/linkDialog.js @@ -3,6 +3,8 @@ import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const LinkDialog = WDialog.extend({ statics: { TYPE: "linkDialog", @@ -38,20 +40,20 @@ const LinkDialog = WDialog.extend({ this._sourceDisplay = L.DomUtil.create("span", "portal", container); if (this._source) { this._sourceDisplay.appendChild( - this._source.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._source, this._smallScreen) ); } else { this._sourceDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(sourceButton, "click", (ev) => { L.DomEvent.stop(ev); - this._source = WasabeePortal.getSelected(); + this._source = PortalUI.getSelected(); if (this._source) { localStorage[window.plugin.wasabee.static.constants.LINK_SOURCE_KEY] = JSON.stringify(this._source); this._sourceDisplay.textContent = ""; this._sourceDisplay.appendChild( - this._source.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._source, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -65,20 +67,20 @@ const LinkDialog = WDialog.extend({ this._anchor1Display = L.DomUtil.create("span", "portal", container); if (this._anchor1) { this._anchor1Display.appendChild( - this._anchor1.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor1, this._smallScreen) ); } else { this._anchor1Display.textContent = wX("NOT_SET"); } L.DomEvent.on(anchor1Button, "click", (ev) => { L.DomEvent.stop(ev); - this._anchor1 = WasabeePortal.getSelected(); + this._anchor1 = PortalUI.getSelected(); if (this._anchor1) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = JSON.stringify(this._anchor1); this._anchor1Display.textContent = ""; this._anchor1Display.appendChild( - this._anchor1.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor1, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -106,20 +108,20 @@ const LinkDialog = WDialog.extend({ this._anchor2Display = L.DomUtil.create("span", "portal", container); if (this._anchor2) { this._anchor2Display.appendChild( - this._anchor2.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor2, this._smallScreen) ); } else { this._anchor2Display.textContent = wX("NOT_SET"); } L.DomEvent.on(anchor2Button, "click", (ev) => { L.DomEvent.stop(ev); - this._anchor2 = WasabeePortal.getSelected(); + this._anchor2 = PortalUI.getSelected(); if (this._anchor2) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY] = JSON.stringify(this._anchor2); this._anchor2Display.textContent = ""; this._anchor2Display.appendChild( - this._anchor2.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor2, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); diff --git a/src/code/dialogs/linkListDialog.js b/src/code/dialogs/linkListDialog.js index 85364e2c5..9563836e7 100644 --- a/src/code/dialogs/linkListDialog.js +++ b/src/code/dialogs/linkListDialog.js @@ -3,6 +3,8 @@ import wX from "../wX"; import { loadFaked } from "../uiCommands"; import { getSelectedOperation } from "../selectedOp"; +import PortalUI from "../ui/portal"; + const LinkListDialog = OperationChecklistDialog.extend({ statics: { TYPE: "linkListDialog", @@ -60,7 +62,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ this.createDialog({ title: wX("LINKS2", { - portalName: this.options.portal.displayName, + portalName: PortalUI.displayName(this.options.portal), outgoing: fromCount, incoming: toCount, }), @@ -89,7 +91,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ this.setContent(this.sortable.table); this.setTitle( wX("LINKS2", { - portalName: this.options.portal.displayName, + portalName: PortalUI.displayName(this.options.portal), outgoing: fromCount, incoming: toCount, }) diff --git a/src/code/dialogs/madrid.js b/src/code/dialogs/madrid.js index 721380f87..b7f286366 100644 --- a/src/code/dialogs/madrid.js +++ b/src/code/dialogs/madrid.js @@ -9,6 +9,8 @@ import { import wX from "../wX"; import MultimaxDialog from "./multimaxDialog"; +import PortalUI from "../ui/portal"; + // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX const MadridDialog = MultimaxDialog.extend({ @@ -31,19 +33,19 @@ const MadridDialog = MultimaxDialog.extend({ this._anchorOneDisplay = L.DomUtil.create("span", null, container); if (this._anchorOne) { this._anchorOneDisplay.appendChild( - this._anchorOne.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorOne, this._smallScreen) ); } else { this._anchorOneDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorOneButton, "click", () => { - this._anchorOne = WasabeePortal.getSelected(); + this._anchorOne = PortalUI.getSelected(); if (this._anchorOne) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = JSON.stringify(this._anchorOne); this._anchorOneDisplay.textContent = ""; this._anchorOneDisplay.appendChild( - this._anchorOne.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorOne, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -77,19 +79,19 @@ const MadridDialog = MultimaxDialog.extend({ this._anchorTwoDisplay = L.DomUtil.create("span", null, container); if (this._anchorTwo) { this._anchorTwoDisplay.appendChild( - this._anchorTwo.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorTwo, this._smallScreen) ); } else { this._anchorTwoDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorTwoButton, "click", () => { - this._anchorTwo = WasabeePortal.getSelected(); + this._anchorTwo = PortalUI.getSelected(); if (this._anchorTwo) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY] = JSON.stringify(this._anchorTwo); this._anchorTwoDisplay.textContent = ""; this._anchorTwoDisplay.appendChild( - this._anchorTwo.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorTwo, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index 22c9746d2..e76e2efce 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -1,10 +1,11 @@ import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; import WasabeeMe from "../model/me"; import WasabeeTeam from "../model/team"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const MarkerAddDialog = WDialog.extend({ statics: { TYPE: "markerButton", @@ -46,12 +47,12 @@ const MarkerAddDialog = WDialog.extend({ this._assign.innerHTML = ""; await this._getAgentMenu(this._assign); - this._selectedPortal = WasabeePortal.getSelected(); + this._selectedPortal = PortalUI.getSelected(); if (this._selectedPortal) { this._portal.textContent = ""; this._portal.textContent = ""; this._portal.appendChild( - this._selectedPortal.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._selectedPortal, this._smallScreen) ); this._zones.value = getSelectedOperation().determineZone( @@ -147,7 +148,7 @@ const MarkerAddDialog = WDialog.extend({ }; // XXX remove comment from args in 0.20 - operation.addMarker(selectedType, WasabeePortal.getSelected(), options); + operation.addMarker(selectedType, PortalUI.getSelected(), options); await this.update(); localStorage[window.plugin.wasabee.static.constants.LAST_MARKER_KEY] = selectedType; diff --git a/src/code/dialogs/markerChangeDialog.js b/src/code/dialogs/markerChangeDialog.js index aa2788ec1..c5257aacc 100644 --- a/src/code/dialogs/markerChangeDialog.js +++ b/src/code/dialogs/markerChangeDialog.js @@ -2,6 +2,8 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; +import PortalUI from "../ui/portal"; + const MarkerChangeDialog = WDialog.extend({ statics: { TYPE: "markerButton", @@ -25,7 +27,9 @@ const MarkerChangeDialog = WDialog.extend({ const portal = operation.getPortal(this.options.marker.portalId); const portalDisplay = L.DomUtil.create("div", "portal", content); - portalDisplay.appendChild(portal.displayFormat(this._smallScreen)); + portalDisplay.appendChild( + PortalUI.displayFormat(portal, this._smallScreen) + ); this._type = L.DomUtil.create("select", null, content); diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index e2cc1d61e..1e4dfbaa5 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -6,6 +6,8 @@ import Sortable from "../sortable"; import { getSelectedOperation, makeSelectedOperation } from "../selectedOp"; import { drawBackgroundOp } from "../mapDrawing"; +import PortalUI from "../ui/portal"; + const MergeDialog = WDialog.extend({ statics: { TYPE: "mergeDialog", @@ -231,10 +233,10 @@ const MergeDialog = WDialog.extend({ if (e.data.type === "link") { cell.appendChild(e.data.link.displayFormat(op)); } else if (e.data.type === "portal") { - cell.appendChild(e.data.portal.displayFormat()); + cell.appendChild(PortalUI.displayFormat(e.data.portal)); } else if (e.data.type === "marker") { const portal = op.getPortal(e.data.marker.portalId); - cell.appendChild(portal.displayFormat()); + cell.appendChild(PortalUI.displayFormat(portal)); } else { cell.textContent = value; } diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/multimaxDialog.js index fcc952aac..483e2367e 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/multimaxDialog.js @@ -9,6 +9,8 @@ import { } from "../uiCommands"; import { greatCircleArcIntersectByLatLngs } from "../crosslinks"; +import PortalUI from "../ui/portal"; + // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX const MultimaxDialog = WDialog.extend({ @@ -38,19 +40,19 @@ const MultimaxDialog = WDialog.extend({ this._anchorOneDisplay = L.DomUtil.create("span", null, container); if (this._anchorOne) { this._anchorOneDisplay.appendChild( - this._anchorOne.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorOne, this._smallScreen) ); } else { this._anchorOneDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorOneButton, "click", () => { - this._anchorOne = WasabeePortal.getSelected(); + this._anchorOne = PortalUI.getSelected(); if (this._anchorOne) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = JSON.stringify(this._anchorOne); this._anchorOneDisplay.textContent = ""; this._anchorOneDisplay.appendChild( - this._anchorOne.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorOne, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); @@ -64,19 +66,19 @@ const MultimaxDialog = WDialog.extend({ this._anchorTwoDisplay = L.DomUtil.create("span", null, container); if (this._anchorTwo) { this._anchorTwoDisplay.appendChild( - this._anchorTwo.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorTwo, this._smallScreen) ); } else { this._anchorTwoDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorTwoButton, "click", () => { - this._anchorTwo = WasabeePortal.getSelected(); + this._anchorTwo = PortalUI.getSelected(); if (this._anchorTwo) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY] = JSON.stringify(this._anchorTwo); this._anchorTwoDisplay.textContent = ""; this._anchorTwoDisplay.appendChild( - this._anchorTwo.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchorTwo, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); diff --git a/src/code/dialogs/onionfield.js b/src/code/dialogs/onionfield.js index 26d3b4c0f..e53514680 100644 --- a/src/code/dialogs/onionfield.js +++ b/src/code/dialogs/onionfield.js @@ -6,6 +6,8 @@ import WasabeeLink from "../model/link"; import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const OnionfieldDialog = WDialog.extend({ statics: { TYPE: "OnionDialog", @@ -35,20 +37,20 @@ const OnionfieldDialog = WDialog.extend({ this._anchorDisplay = L.DomUtil.create("span", null, container); if (this._anchor) { this._anchorDisplay.appendChild( - this._anchor.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor, this._smallScreen) ); } else { this._anchorDisplay.textContent = wX("NOT_SET"); } L.DomEvent.on(anchorButton, "click", (ev) => { L.DomEvent.stop(ev); - this._anchor = WasabeePortal.getSelected(); + this._anchor = PortalUI.getSelected(); if (this._anchor) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = JSON.stringify(this._anchor); this._anchorDisplay.textContent = ""; this._anchorDisplay.appendChild( - this._anchor.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); diff --git a/src/code/dialogs/saveLinks.js b/src/code/dialogs/saveLinks.js index 97439f4b5..efe8fe4f7 100644 --- a/src/code/dialogs/saveLinks.js +++ b/src/code/dialogs/saveLinks.js @@ -4,6 +4,8 @@ import { getSelectedOperation } from "../selectedOp"; import { clearAllLinks, getAllPortalsLinked } from "../uiCommands"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const SaveLinksDialog = WDialog.extend({ statics: { TYPE: "SaveLinksDialog", @@ -34,7 +36,7 @@ const SaveLinksDialog = WDialog.extend({ //do magic if (this._anchor) { this._anchorDisplay.appendChild( - this._anchor.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor, this._smallScreen) ); } else { this._anchorDisplay.textContent = wX("NOT_SET"); @@ -42,13 +44,13 @@ const SaveLinksDialog = WDialog.extend({ L.DomEvent.on(anchorButton, "click", (ev) => { L.DomEvent.stop(ev); - this._anchor = WasabeePortal.getSelected(); + this._anchor = PortalUI.getSelected(); if (this._anchor) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = JSON.stringify(this._anchor); this._anchorDisplay.textContent = ""; this._anchorDisplay.appendChild( - this._anchor.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); diff --git a/src/code/dialogs/sendTargetDialog.js b/src/code/dialogs/sendTargetDialog.js index d735212c5..ca2aa30a9 100644 --- a/src/code/dialogs/sendTargetDialog.js +++ b/src/code/dialogs/sendTargetDialog.js @@ -7,6 +7,8 @@ import { targetPromise } from "../server"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; +import PortalUI from "../ui/portal"; + const SendTargetDialog = WDialog.extend({ statics: { TYPE: "sendTargetDialog", @@ -50,7 +52,7 @@ const SendTargetDialog = WDialog.extend({ if (this.options.target instanceof WasabeeMarker) { const portal = operation.getPortal(this.options.target.portalId); this._targettype = this.options.target.type; - divtitle.appendChild(portal.displayFormat(this._smallScreen)); + divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); const t = L.DomUtil.create("label", null); t.textContent = wX("SEND TARGET AGENT"); menu.prepend(t); @@ -59,7 +61,7 @@ const SendTargetDialog = WDialog.extend({ if (this.options.target instanceof WasabeeAnchor) { const portal = operation.getPortal(this.options.target.portalId); this._targettype = "anchor"; - divtitle.appendChild(portal.displayFormat(this._smallScreen)); + divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); const t = L.DomUtil.create("label", null); t.textContent = wX("SEND TARGET AGENT"); menu.prepend(t); diff --git a/src/code/dialogs/setCommentDialog.js b/src/code/dialogs/setCommentDialog.js index 68821f0e7..af138ddee 100644 --- a/src/code/dialogs/setCommentDialog.js +++ b/src/code/dialogs/setCommentDialog.js @@ -4,6 +4,8 @@ import WasabeeLink from "../model/link"; import WasabeeMarker from "../model/marker"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + export const SetCommentDialog = WDialog.extend({ statics: { TYPE: "setCommentDialog", @@ -33,14 +35,14 @@ export const SetCommentDialog = WDialog.extend({ this.options.target.portalId ); this.dialogTitle = wX("SET_MCOMMENT", { - portalName: this.portal.displayName, + portalName: PortalUI.displayName(this.portal), }); } if (this.options.target instanceof WasabeePortal) { this.commentType = "portal"; this.dialogTitle = wX("SET_PCOMMENT", { - portalName: this.options.target.displayName, + portalName: PortalUI.displayName(this.options.target), }); this.portal = this.options.target; } @@ -102,7 +104,7 @@ export const SetCommentDialog = WDialog.extend({ if (this.commentType == "marker") { desc.textContent = wX("SET_MARKER_COMMENT"); - desc.appendChild(this.portal.displayFormat(this.options.operation)); + desc.appendChild(PortalUI.displayFormat(this.portal)); if (this.options.target.comment) input.value = this.options.target.comment; @@ -120,7 +122,7 @@ export const SetCommentDialog = WDialog.extend({ if (this.commentType == "portal") { desc.textContent = wX("SET_PORT_COMMENT"); - desc.appendChild(this.portal.displayFormat(this._smallScreen)); + desc.appendChild(PortalUI.displayFormat(this.portal)); if (this.portal.comment) input.value = this.portal.comment; input.addEventListener( diff --git a/src/code/dialogs/starburst.js b/src/code/dialogs/starburst.js index 8eb6d69d1..3eb9fb109 100644 --- a/src/code/dialogs/starburst.js +++ b/src/code/dialogs/starburst.js @@ -4,6 +4,8 @@ import { getSelectedOperation } from "../selectedOp"; import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + const StarburstDialog = WDialog.extend({ statics: { TYPE: "StarburstDialog", @@ -34,7 +36,7 @@ const StarburstDialog = WDialog.extend({ //do magic if (this._anchor) { this._anchorDisplay.appendChild( - this._anchor.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor, this._smallScreen) ); } else { this._anchorDisplay.textContent = wX("NOT_SET"); @@ -42,13 +44,13 @@ const StarburstDialog = WDialog.extend({ L.DomEvent.on(anchorButton, "click", (ev) => { L.DomEvent.stop(ev); - this._anchor = WasabeePortal.getSelected(); + this._anchor = PortalUI.getSelected(); if (this._anchor) { localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = JSON.stringify(this._anchor); this._anchorDisplay.textContent = ""; this._anchorDisplay.appendChild( - this._anchor.displayFormat(this._smallScreen) + PortalUI.displayFormat(this._anchor, this._smallScreen) ); } else { alert(wX("PLEASE_SELECT_PORTAL")); diff --git a/src/code/dialogs/stateDialog.js b/src/code/dialogs/stateDialog.js index 7bca225c0..07f50be74 100644 --- a/src/code/dialogs/stateDialog.js +++ b/src/code/dialogs/stateDialog.js @@ -4,6 +4,8 @@ import WasabeeMarker from "../model/marker"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; +import PortalUI from "../ui/portal"; + const StateDialog = WDialog.extend({ statics: { TYPE: "stateDialog", @@ -68,7 +70,7 @@ const StateDialog = WDialog.extend({ const portal = operation.getPortal(this.options.target.portalId); this._type = "Marker"; this._name = wX("MARKER STATE PROMPT", portal.name); - divtitle.appendChild(portal.displayFormat(this._smallScreen)); + divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); const t = L.DomUtil.create("label", null); t.textContent = wX("MARKER STATE"); menu.prepend(t); diff --git a/src/code/dialogs/wasabeeDlist.js b/src/code/dialogs/wasabeeDlist.js index 9887d98be..8f90ccc63 100644 --- a/src/code/dialogs/wasabeeDlist.js +++ b/src/code/dialogs/wasabeeDlist.js @@ -5,6 +5,8 @@ import WasabeeMe from "../model/me"; import WasabeePortal from "../model/portal"; import { getAgentWasabeeDkeys } from "../wd"; +import PortalUI from "../ui/portal"; + const WasabeeDList = WDialog.extend({ statics: { TYPE: "wasabeeDList", @@ -66,7 +68,7 @@ const WasabeeDList = WDialog.extend({ lat: n.Lat, lng: n.Lng, }); - cell.appendChild(p.displayFormat(this._smallScreen)); + cell.appendChild(PortalUI.displayFormat(p, this._smallScreen)); }, }, { diff --git a/src/code/firebaseSupport.js b/src/code/firebaseSupport.js index d908e4b1a..0f683235e 100644 --- a/src/code/firebaseSupport.js +++ b/src/code/firebaseSupport.js @@ -16,6 +16,8 @@ import { updateLocalOp } from "./uiCommands"; import WasabeeOp from "./model/operation"; import WasabeePortal from "./model/portal"; +import PortalUI from "./ui/portal"; + // TODO: use a dedicated message channel: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging const frameID = "wasabeeFirebaseFrame"; @@ -107,7 +109,7 @@ export function initFirebase() { lng: target.Lon, }; const portal = new WasabeePortal(raw); - const f = portal.displayFormat(); + const f = PortalUI.displayFormat(portal); alert(f.outerHTML + "
Sent by: " + target.Sender, true); } catch (e) { console.error(e); diff --git a/src/code/model/agent.js b/src/code/model/agent.js index 37f6e2bc2..245c52dbe 100644 --- a/src/code/model/agent.js +++ b/src/code/model/agent.js @@ -1,4 +1,3 @@ -import WasabeePortal from "./portal"; import ConfirmDialog from "../dialogs/confirmDialog"; import AgentDialog from "../dialogs/agentDialog"; import { agentPromise, targetPromise, routePromise } from "../server"; @@ -7,6 +6,8 @@ import wX from "../wX"; import WasabeeMe from "./me"; import WasabeeTeam from "./team"; +import PortalUI from "../ui/portal"; + export default class WasabeeAgent { constructor(obj) { if (typeof obj == "string") { @@ -184,7 +185,7 @@ export default class WasabeeAgent { sendTarget.textContent = wX("SEND TARGET"); L.DomEvent.on(sendTarget, "click", (ev) => { L.DomEvent.stop(ev); - const selectedPortal = WasabeePortal.getSelected(); + const selectedPortal = PortalUI.getSelected(); if (!selectedPortal) { alert(wX("SELECT PORTAL")); return; @@ -193,7 +194,7 @@ export default class WasabeeAgent { const d = new ConfirmDialog({ title: wX("SEND TARGET"), label: wX("SEND TARGET CONFIRM", { - portalName: selectedPortal.displayName, + portalName: PortalUI.displayName(selectedPortal), agent: this.name, }), type: "agent", @@ -215,7 +216,7 @@ export default class WasabeeAgent { requestRoute.style.display = "none"; // hide this until the server-side is ready L.DomEvent.on(requestRoute, "click", (ev) => { L.DomEvent.stop(ev); - const selectedPortal = WasabeePortal.getSelected(); + const selectedPortal = PortalUI.getSelected(); if (!selectedPortal) { alert(wX("SELECT PORTAL")); return; @@ -244,7 +245,7 @@ export default class WasabeeAgent { const a = L.DomUtil.create("li", "assignment", assignments); const portal = op.getPortal(m.portalId); a.textContent = `${m.order}: ${wX(m.type)} `; - a.appendChild(portal.displayFormat()); + a.appendChild(PortalUI.displayFormat(portal)); } return content; diff --git a/src/code/model/anchor.js b/src/code/model/anchor.js index 7dc3ad4b3..b63740d00 100644 --- a/src/code/model/anchor.js +++ b/src/code/model/anchor.js @@ -6,6 +6,8 @@ import SetCommentDialog from "../dialogs/setCommentDialog"; import LinkListDialog from "../dialogs/linkListDialog"; import wX from "../wX"; +import PortalUI from "../ui/portal"; + // this class is for the popups, and for assign menu export default class WasabeeAnchor { constructor(portalId) { @@ -51,7 +53,7 @@ export default class WasabeeAnchor { } displayFormat(smallScreen = false) { - return this._portal.displayFormat(smallScreen); + return PortalUI.displayFormat(this._portal, smallScreen); } get latLng() { @@ -72,7 +74,7 @@ export default class WasabeeAnchor { marker.className = "wasabee-anchor-popup"; const content = L.DomUtil.create("div", null); const title = L.DomUtil.create("div", "desc", content); - title.appendChild(this._portal.displayFormat()); + title.appendChild(PortalUI.displayFormat(this._portal)); const portalComment = L.DomUtil.create( "div", "wasabee-portal-comment", diff --git a/src/code/model/link.js b/src/code/model/link.js index 396c86cc8..09858983e 100644 --- a/src/code/model/link.js +++ b/src/code/model/link.js @@ -4,6 +4,8 @@ import wX from "../wX"; import AssignDialog from "../dialogs/assignDialog"; import { addToColorList } from "../skin"; +import PortalUI from "../ui/portal"; + export default class WasabeeLink { constructor(obj) { this.ID = obj.ID ? obj.ID : generateId(); @@ -104,7 +106,10 @@ export default class WasabeeLink { displayFormat(operation, smallScreen = false) { const d = L.DomUtil.create("div", null); d.appendChild( - operation.getPortal(this.fromPortalId).displayFormat(smallScreen) + PortalUI.displayFormat( + operation.getPortal(this.fromPortalId), + smallScreen + ) ); const arrow = L.DomUtil.create("span", "wasabee-link-seperator", d); arrow.style.color = this.getColor(operation); @@ -123,7 +128,7 @@ export default class WasabeeLink { }); d.appendChild( - operation.getPortal(this.toPortalId).displayFormat(smallScreen) + PortalUI.displayFormat(operation.getPortal(this.toPortalId), smallScreen) ); return d; } diff --git a/src/code/model/marker.js b/src/code/model/marker.js index ddc88ae49..dad1c67da 100644 --- a/src/code/model/marker.js +++ b/src/code/model/marker.js @@ -9,6 +9,8 @@ import MarkerChangeDialog from "../dialogs/markerChangeDialog"; import StateDialog from "../dialogs/stateDialog"; import { getSelectedOperation } from "../selectedOp"; +import PortalUI from "../ui/portal"; + const STATE_UNASSIGNED = "pending"; const STATE_ASSIGNED = "assigned"; const STATE_ACKNOWLEDGED = "acknowledged"; @@ -217,7 +219,7 @@ export default class WasabeeMarker { const kind = L.DomUtil.create("span", "wasabee-marker-popup-kind", title); L.DomUtil.addClass(kind, this.type); kind.textContent = wX(this.type); - title.appendChild(portal.displayFormat()); + title.appendChild(PortalUI.displayFormat(portal)); kind.href = "#"; L.DomEvent.on(kind, "click", (ev) => { diff --git a/src/code/model/portal.js b/src/code/model/portal.js index 3323fb10f..9b90c712a 100644 --- a/src/code/model/portal.js +++ b/src/code/model/portal.js @@ -1,5 +1,4 @@ import { generateId } from "../auxiliar"; -import wX from "../wX"; export default class WasabeePortal { constructor(obj) { @@ -41,96 +40,10 @@ export default class WasabeePortal { }; } - // create a wasabee portal from a IITC portal (leaflet marker) - static fromIITC(p) { - // we have all the details - if (p && p.options && p.options.data && p.options.guid) { - const data = p.options.data; - const id = p.options.guid; - if (data.title) { - return new WasabeePortal({ - id: id, - name: data.title, - lat: (data.latE6 / 1e6).toFixed(6), - lng: (data.lngE6 / 1e6).toFixed(6), - }); - } - // do we have enough to fake it? - if (data.latE6) { - return WasabeePortal.fake( - (data.latE6 / 1e6).toFixed(6), - (data.lngE6 / 1e6).toFixed(6), - id - ); - } - } - // nothing to get - return null; - } - get latLng() { return this._latLng; } - get team() { - if (window.portals[this.id] && window.portals[this.id].options.data) - return window.portals[this.id].options.data.team; - return ""; - } - - get displayName() { - if (this.pureFaked) return wX("FAKED", { portalId: this.id }); - if (this.loading) return wX("LOADING1", { portalGuid: this.id }); - return this.name; - } - - displayFormat(shortName = false) { - const pt = this.latLng; - const v = `${this.lat},${this.lng}`; - const name = this.displayName; - const e = L.DomUtil.create("a", "wasabee-portal"); - if (shortName === true && this.name.length > 12) { - e.textContent = name.slice(0, 8) + "..."; - } else { - e.textContent = name; - } - - const team = this.team; - if (team == "E") { - e.classList.add("enl"); - } - if (team == "R") { - e.classList.add("res"); - } - if (team == "N") { - e.classList.add("unclaimed"); - } - - // e.title = this.name; - e.href = `/intel?ll=${v}&pll=${v}`; - - L.DomEvent.on(e, "click", (event) => { - if (window.selectedPortal != this.id && this.id.length == 35) - window.renderPortalDetails(this.id); - else window.map.panTo(pt); - event.preventDefault(); - return false; - }).on(e, "dblclick", (event) => { - if (window.selectedPortal != this.id && this.id.length == 35) - window.renderPortalDetails(this.id); - if (window.map.getBounds().contains(pt)) - window.zoomToAndShowPortal(this.id, pt); - else window.map.panTo(pt); - event.preventDefault(); - return false; - }); - return e; - } - - static get(id) { - return WasabeePortal.fromIITC(window.portals[id]); - } - static fake(lat, lng, id, name) { console.assert(lat && lng, "WasabeePortal.fake called w/o lat/lng"); @@ -151,10 +64,4 @@ export default class WasabeePortal { get pureFaked() { return this.id.length != 35; } - - static getSelected() { - return window.selectedPortal - ? WasabeePortal.get(window.selectedPortal) - : null; - } } diff --git a/src/code/ui/portal.js b/src/code/ui/portal.js new file mode 100644 index 000000000..cff24df2d --- /dev/null +++ b/src/code/ui/portal.js @@ -0,0 +1,99 @@ +import WasabeePortal from "../model/portal"; +import wX from "../wX"; + +export default { + fromIITC, + displayName, + displayFormat, + get, + getSelected, +}; + +function fromIITC(p) { + // we have all the details + if (p && p.options && p.options.data && p.options.guid) { + const data = p.options.data; + const id = p.options.guid; + if (data.title) { + return new WasabeePortal({ + id: id, + name: data.title, + lat: (data.latE6 / 1e6).toFixed(6), + lng: (data.lngE6 / 1e6).toFixed(6), + }); + } + // do we have enough to fake it? + if (data.latE6) { + return WasabeePortal.fake( + (data.latE6 / 1e6).toFixed(6), + (data.lngE6 / 1e6).toFixed(6), + id + ); + } + } + // nothing to get + return null; +} + +function team(portal) { + if (window.portals[portal.id] && window.portals[portal.id].options.data) + return window.portals[portal.id].options.data.team; + return ""; +} + +function displayName(portal) { + if (portal.pureFaked) return wX("FAKED", { portalId: portal.id }); + if (portal.loading) return wX("LOADING1", { portalGuid: portal.id }); + return portal.name; +} + +function displayFormat(portal, shortName = false) { + const pt = portal.latLng; + const v = `${portal.lat},${portal.lng}`; + const name = displayName(portal); + const e = L.DomUtil.create("a", "wasabee-portal"); + if (shortName === true && portal.name.length > 12) { + e.textContent = name.slice(0, 8) + "..."; + } else { + e.textContent = name; + } + + const t = team(portal); + if (t == "E") { + e.classList.add("enl"); + } + if (t == "R") { + e.classList.add("res"); + } + if (t == "N") { + e.classList.add("unclaimed"); + } + + // e.title = this.name; + e.href = `/intel?ll=${v}&pll=${v}`; + + L.DomEvent.on(e, "click", (event) => { + if (window.selectedPortal != portal.id && portal.id.length == 35) + window.renderPortalDetails(portal.id); + else window.map.panTo(pt); + event.preventDefault(); + return false; + }).on(e, "dblclick", (event) => { + if (window.selectedPortal != portal.id && portal.id.length == 35) + window.renderPortalDetails(portal.id); + if (window.map.getBounds().contains(pt)) + window.zoomToAndShowPortal(portal.id, pt); + else window.map.panTo(pt); + event.preventDefault(); + return false; + }); + return e; +} + +function get(id) { + return fromIITC(window.portals[id]); +} + +function getSelected() { + return window.selectedPortal ? get(window.selectedPortal) : null; +} diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index 83f09781e..4cc081ce9 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -15,6 +15,8 @@ import { duplicateOperation, } from "./selectedOp"; +import PortalUI from "./ui/portal"; + export function addPortal(operation, portal) { if (!portal) { alert(wX("SELECT PORTAL")); @@ -24,7 +26,7 @@ export function addPortal(operation, portal) { } export function swapPortal(operation, portal) { - const selectedPortal = WasabeePortal.getSelected(); + const selectedPortal = PortalUI.getSelected(); if (!selectedPortal) { alert(wX("SELECT PORTAL")); return; @@ -36,9 +38,9 @@ export function swapPortal(operation, portal) { const pr = L.DomUtil.create("div", null); pr.textContent = wX("SWAP PROMPT"); - pr.appendChild(portal.displayFormat()); + pr.appendChild(PortalUI.displayFormat(portal)); L.DomUtil.create("span", null, pr).textContent = wX("SWAP WITH"); - pr.appendChild(selectedPortal.displayFormat()); + pr.appendChild(PortalUI.displayFormat(selectedPortal)); L.DomUtil.create("span", null, pr).textContent = "?"; const con = new ConfirmDialog({ title: wX("SWAP TITLE"), @@ -54,7 +56,7 @@ export function swapPortal(operation, portal) { export function deletePortal(operation, portal) { const pr = L.DomUtil.create("div", null); pr.textContent = wX("DELETE ANCHOR PROMPT"); - pr.appendChild(portal.displayFormat()); + pr.appendChild(PortalUI.displayFormat(portal)); const con = new ConfirmDialog({ title: wX("DELETE ANCHOR TITLE"), label: pr, @@ -70,7 +72,7 @@ export function deletePortal(operation, portal) { export function deleteMarker(operation, marker, portal) { const pr = L.DomUtil.create("div", null); pr.textContent = wX("DELETE MARKER PROMPT"); - pr.appendChild(portal.displayFormat()); + pr.appendChild(PortalUI.displayFormat(portal)); const con = new ConfirmDialog({ title: wX("DELETE MARKER TITLE"), label: pr, @@ -126,7 +128,7 @@ export function listenForAddedPortals(newPortal) { if (!newPortal.portal.options.data.title) return; const op = getSelectedOperation(); - op.updatePortal(WasabeePortal.fromIITC(newPortal.portal)); + op.updatePortal(PortalUI.fromIITC(newPortal.portal)); } export function listenForPortalDetails(e) { @@ -240,7 +242,7 @@ export function getAllPortalsOnScreen(operation) { ) ) continue; - const wp = WasabeePortal.fromIITC(window.portals[portal]); + const wp = PortalUI.fromIITC(window.portals[portal]); if (wp) x.push(wp); } } @@ -354,7 +356,7 @@ export function blockerAutomark(operation, first = true) { // get WasabeePortal for portalId let wportal = operation.getPortal(portalId); - if (!wportal) wportal = WasabeePortal.get(portalId); + if (!wportal) wportal = PortalUI.get(portalId); if (!wportal) { alert(wX("AUTOMARK STOP")); return; From 565ea571ca22adb31088844cfd256f0346535ddf Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 14:15:07 +0200 Subject: [PATCH 004/275] add LinkUI --- src/code/dialogs/assignDialog.js | 5 +- src/code/dialogs/checklist.js | 5 +- src/code/dialogs/linkListDialog.js | 3 +- src/code/dialogs/mergeDialog.js | 3 +- src/code/dialogs/setCommentDialog.js | 4 +- src/code/dialogs/stateDialog.js | 3 +- src/code/mapDrawing.js | 4 +- src/code/model/link.js | 119 +-------------------------- src/code/ui/link.js | 117 ++++++++++++++++++++++++++ 9 files changed, 137 insertions(+), 126 deletions(-) create mode 100644 src/code/ui/link.js diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index d14bddefb..6fd8bc2d8 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -8,6 +8,7 @@ import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; import PortalUI from "../ui/portal"; +import LinkUI from "../ui/link"; const AssignDialog = WDialog.extend({ statics: { @@ -58,7 +59,9 @@ const AssignDialog = WDialog.extend({ this._name = wX("ASSIGN LINK PROMPT", { portalName: PortalUI.displayName(portal), }); - divtitle.appendChild(target.displayFormat(operation, this._smallScreen)); + divtitle.appendChild( + LinkUI.displayFormat(target, operation, this._smallScreen) + ); const t = L.DomUtil.create("label", null); t.textContent = wX("LINK ASSIGNMENT"); menu.prepend(t); diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 6d4403a3f..abb5dde1d 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -18,6 +18,7 @@ import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; import PortalUI from "../ui/portal"; +import LinkUI from "../ui/link"; const OperationChecklistDialog = WDialog.extend({ statics: { @@ -129,7 +130,7 @@ const OperationChecklistDialog = WDialog.extend({ sort: (a, b) => a.localeCompare(b), format: (cell, value, thing) => { if (thing instanceof WasabeeLink) { - cell.appendChild(thing.displayFormat(operation)); + cell.appendChild(LinkUI.displayFormat(thing, operation)); if (this._smallScreen) cell.colSpan = 2; } else { cell.appendChild( @@ -362,7 +363,7 @@ const OperationChecklistDialog = WDialog.extend({ for (const [link, c] of emptyFieldLinks) { const li = L.DomUtil.create("li", "empty-field-link", content); li.textContent = c; - li.appendChild(link.displayFormat(operation)); + li.appendChild(LinkUI.displayFormat(link, operation)); } alert(container, true); } else { diff --git a/src/code/dialogs/linkListDialog.js b/src/code/dialogs/linkListDialog.js index 9563836e7..8d384d2de 100644 --- a/src/code/dialogs/linkListDialog.js +++ b/src/code/dialogs/linkListDialog.js @@ -4,6 +4,7 @@ import { loadFaked } from "../uiCommands"; import { getSelectedOperation } from "../selectedOp"; import PortalUI from "../ui/portal"; +import LinkUI from "../ui/link"; const LinkListDialog = OperationChecklistDialog.extend({ statics: { @@ -36,7 +37,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ title: wX("MIN_SRC_PORT_LVL"), value: (link) => link.length(operation), format: (cell, data, link) => { - cell.appendChild(link.minLevel(operation)); + cell.appendChild(LinkUI.minLevel(link, operation)); }, smallScreenHide: true, }, diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index 1e4dfbaa5..fe619e7a9 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -7,6 +7,7 @@ import { getSelectedOperation, makeSelectedOperation } from "../selectedOp"; import { drawBackgroundOp } from "../mapDrawing"; import PortalUI from "../ui/portal"; +import LinkUI from "../ui/link"; const MergeDialog = WDialog.extend({ statics: { @@ -231,7 +232,7 @@ const MergeDialog = WDialog.extend({ format: async (cell, value, e) => { const op = e.type === "-" ? origin : operation; if (e.data.type === "link") { - cell.appendChild(e.data.link.displayFormat(op)); + cell.appendChild(LinkUI.displayFormat(e.data.link, op)); } else if (e.data.type === "portal") { cell.appendChild(PortalUI.displayFormat(e.data.portal)); } else if (e.data.type === "marker") { diff --git a/src/code/dialogs/setCommentDialog.js b/src/code/dialogs/setCommentDialog.js index af138ddee..35e892b79 100644 --- a/src/code/dialogs/setCommentDialog.js +++ b/src/code/dialogs/setCommentDialog.js @@ -5,6 +5,7 @@ import WasabeeMarker from "../model/marker"; import wX from "../wX"; import PortalUI from "../ui/portal"; +import LinkUI from "../ui/link"; export const SetCommentDialog = WDialog.extend({ statics: { @@ -83,7 +84,8 @@ export const SetCommentDialog = WDialog.extend({ if (this.commentType == "link") { desc.textContent = wX("SET_LINK_COMMENT"); desc.appendChild( - this.options.target.displayFormat( + LinkUI.displayFormat( + this.options.target, this.options.operation, this._smallScreen ) diff --git a/src/code/dialogs/stateDialog.js b/src/code/dialogs/stateDialog.js index 07f50be74..767cbf59f 100644 --- a/src/code/dialogs/stateDialog.js +++ b/src/code/dialogs/stateDialog.js @@ -5,6 +5,7 @@ import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; import PortalUI from "../ui/portal"; +import LinkUI from "../ui/link"; const StateDialog = WDialog.extend({ statics: { @@ -59,7 +60,7 @@ const StateDialog = WDialog.extend({ this._type = "Link"; this._name = wX("LINK STATE PROMPT", portal.name); divtitle.appendChild( - this.options.target.displayFormat(operation, this._smallScreen) + LinkUI.displayFormat(this.options.target, operation, this._smallScreen) ); const t = L.DomUtil.create("label", null); t.textContent = wX("LINK STATE"); diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index 5966ca0f3..c24e294d7 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -6,6 +6,8 @@ import WasabeeOp from "./model/operation"; import { newColors } from "./auxiliar"; import { getSelectedOperation, opsList } from "./selectedOp"; +import LinkUI from "./ui/link"; + const Wasabee = window.plugin.wasabee; // draws all anchors, markers, and links @@ -201,7 +203,7 @@ function addLink(wlink, operation) { L.DomEvent.stop(ev); if (ev.target._popup._wrapper) ev.target._popup._wrapper.classList.add("wasabee-popup"); - const div = wlink.getPopup(operation); + const div = LinkUI.getPopup(wlink, operation); ev.target.setPopupContent(div); ev.target.openPopup(ev.latlng); return true; diff --git a/src/code/model/link.js b/src/code/model/link.js index 09858983e..3d2e86e7b 100644 --- a/src/code/model/link.js +++ b/src/code/model/link.js @@ -1,10 +1,5 @@ -import { generateId, convertColorToHex, newColors } from "../auxiliar"; +import { generateId, newColors } from "../auxiliar"; import { getSelectedOperation } from "../selectedOp"; -import wX from "../wX"; -import AssignDialog from "../dialogs/assignDialog"; -import { addToColorList } from "../skin"; - -import PortalUI from "../ui/portal"; export default class WasabeeLink { constructor(obj) { @@ -101,52 +96,16 @@ export default class WasabeeLink { return this.getLatLngs(getSelectedOperation()); } - // returns a DOM object appropriate for display - // do we still need the operation here? - displayFormat(operation, smallScreen = false) { - const d = L.DomUtil.create("div", null); - d.appendChild( - PortalUI.displayFormat( - operation.getPortal(this.fromPortalId), - smallScreen - ) - ); - const arrow = L.DomUtil.create("span", "wasabee-link-seperator", d); - arrow.style.color = this.getColor(operation); - const picker = L.DomUtil.create("input", "hidden-color-picker", arrow); - picker.type = "color"; - picker.value = convertColorToHex(this.getColor(operation)); - picker.setAttribute("list", "wasabee-colors-datalist"); - picker.disabled = !operation.canWrite(); - - L.DomEvent.on(arrow, "click", () => { - picker.click(); - }); - - L.DomEvent.on(picker, "change", (ev) => { - this.setColor(ev.target.value, operation); - }); - - d.appendChild( - PortalUI.displayFormat(operation.getPortal(this.toPortalId), smallScreen) - ); - return d; - } - setColor(color, operation) { this.color = color; if (this.color == operation.color) this.color = "main"; operation.update(); - addToColorList(color); } getColor(operation) { - // 0.17 -- use the old names internally no matter what we are sent let color = this.color; if (color == "main") color = operation.color; color = newColors(color); - if (window.plugin.wasabee.skin.layerTypes.has(color)) - color = window.plugin.wasabee.skin.layerTypes.get(color).color; return color; } @@ -154,80 +113,4 @@ export default class WasabeeLink { const latlngs = this.getLatLngs(operation); return L.latLng(latlngs[0]).distanceTo(latlngs[1]); } - - minLevel(operation) { - const b = this.length(operation); - let s = wX("UNKNOWN"); - const a = L.DomUtil.create("span", null); - - if (b > 6881280) { - s = wX("IMPOSSIBLE"); - } else { - if (b > 1966080) { - s = wX("VRLA"); - a.title = wX("VRLA DESC"); - a.classList.add("help"); - } else { - if (b > 655360) { - s = wX("LA"); - a.title = wX("LA DESC"); - a.classList.add("help"); - } else { - const d = Math.max(1, Math.ceil(8 * Math.pow(b / 160, 0.25)) / 8); - const msd = 8 * (d - Math.floor(d)); - s = "L" + d; - if (0 != msd) { - if (!(1 & msd)) { - s = s + "\u2007"; - } - if (!(1 & msd || 2 & msd)) { - s = s + "\u2007"; - } - s = - s + - (" = L" + - Math.floor(d) + - "0\u215b\u00bc\u215c\u00bd\u215d\u00be\u215e".charAt(msd)); - } - } - } - } - a.textContent = s; - return a; - } - - getPopup(operation) { - const div = L.DomUtil.create("div", null); - L.DomUtil.create("div", null, div).appendChild( - this.displayFormat(operation, true) - ); - if (this.description) - L.DomUtil.create("div", "enl", div).textContent = this.description; - L.DomUtil.create("div", "enl", div).textContent = "# " + this.throwOrderPos; - if (operation.canWrite()) { - const del = L.DomUtil.create("button", null, div); - del.textContent = wX("DELETE_LINK"); - L.DomEvent.on(del, "click", (ev) => { - L.DomEvent.stop(ev); - operation.removeLink(this.fromPortalId, this.toPortalId); - }); - const rev = L.DomUtil.create("button", null, div); - rev.textContent = wX("REVERSE"); - L.DomEvent.on(rev, "click", (ev) => { - L.DomEvent.stop(ev); - operation.reverseLink(this.fromPortalId, this.toPortalId); - }); - } - - if (operation.canWriteServer()) { - const assignButton = L.DomUtil.create("button", null, div); - assignButton.textContent = wX("ASSIGN"); - L.DomEvent.on(assignButton, "click", (ev) => { - L.DomEvent.stop(ev); - const ad = new AssignDialog({ target: this }); - ad.enable(); - }); - } - return div; - } } diff --git a/src/code/ui/link.js b/src/code/ui/link.js new file mode 100644 index 000000000..ba88b566f --- /dev/null +++ b/src/code/ui/link.js @@ -0,0 +1,117 @@ +import AssignDialog from "../dialogs/assignDialog"; +import { convertColorToHex } from "../auxiliar"; +import { addToColorList } from "../skin"; +import wX from "../wX"; + +import PortalUI from "./portal"; + +export default { + displayFormat, + minLevel, + getPopup, +}; + +// returns a DOM object appropriate for display +// do we still need the operation here? +function displayFormat(link, operation, smallScreen = false) { + const d = L.DomUtil.create("div", null); + d.appendChild( + PortalUI.displayFormat(operation.getPortal(link.fromPortalId), smallScreen) + ); + const arrow = L.DomUtil.create("span", "wasabee-link-seperator", d); + arrow.style.color = link.getColor(operation); + const picker = L.DomUtil.create("input", "hidden-color-picker", arrow); + picker.type = "color"; + picker.value = convertColorToHex(link.getColor(operation)); + picker.setAttribute("list", "wasabee-colors-datalist"); + picker.disabled = !operation.canWrite(); + + L.DomEvent.on(arrow, "click", () => { + picker.click(); + }); + + L.DomEvent.on(picker, "change", (ev) => { + link.setColor(ev.target.value, operation); + addToColorList(ev.target.value); + }); + + d.appendChild( + PortalUI.displayFormat(operation.getPortal(link.toPortalId), smallScreen) + ); + return d; +} + +function minLevel(link, operation) { + const b = link.length(operation); + let s = wX("UNKNOWN"); + const a = L.DomUtil.create("span", null); + + if (b > 6881280) { + s = wX("IMPOSSIBLE"); + } else { + if (b > 1966080) { + s = wX("VRLA"); + a.title = wX("VRLA DESC"); + a.classList.add("help"); + } else { + if (b > 655360) { + s = wX("LA"); + a.title = wX("LA DESC"); + a.classList.add("help"); + } else { + const d = Math.max(1, Math.ceil(8 * Math.pow(b / 160, 0.25)) / 8); + const msd = 8 * (d - Math.floor(d)); + s = "L" + d; + if (0 != msd) { + if (!(1 & msd)) { + s = s + "\u2007"; + } + if (!(1 & msd || 2 & msd)) { + s = s + "\u2007"; + } + s = + s + + (" = L" + + Math.floor(d) + + "0\u215b\u00bc\u215c\u00bd\u215d\u00be\u215e".charAt(msd)); + } + } + } + } + a.textContent = s; + return a; +} + +function getPopup(link, operation) { + const div = L.DomUtil.create("div", null); + L.DomUtil.create("div", null, div).appendChild( + displayFormat(link, operation, true) + ); + if (link.description) + L.DomUtil.create("div", "enl", div).textContent = link.description; + L.DomUtil.create("div", "enl", div).textContent = "# " + link.throwOrderPos; + const del = L.DomUtil.create("button", null, div); + if (operation.canWrite()) { + del.textContent = wX("DELETE_LINK"); + L.DomEvent.on(del, "click", (ev) => { + L.DomEvent.stop(ev); + operation.removeLink(link.fromPortalId, link.toPortalId); + }); + const rev = L.DomUtil.create("button", null, div); + rev.textContent = wX("REVERSE"); + L.DomEvent.on(rev, "click", (ev) => { + L.DomEvent.stop(ev); + operation.reverseLink(link.fromPortalId, link.toPortalId); + }); + } + if (operation.canWriteServer()) { + const assignButton = L.DomUtil.create("button", null, div); + assignButton.textContent = wX("ASSIGN"); + L.DomEvent.on(assignButton, "click", (ev) => { + L.DomEvent.stop(ev); + const ad = new AssignDialog({ target: link }); + ad.enable(); + }); + } + return div; +} From af34297c94f4d16be11f95f74ad060af1776d877 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 14:19:15 +0200 Subject: [PATCH 005/275] add anchor ui --- src/code/mapDrawing.js | 3 +- src/code/model/anchor.js | 156 --------------------------------------- src/code/ui/anchor.js | 150 +++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 157 deletions(-) create mode 100644 src/code/ui/anchor.js diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index c24e294d7..45968bd27 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -7,6 +7,7 @@ import { newColors } from "./auxiliar"; import { getSelectedOperation, opsList } from "./selectedOp"; import LinkUI from "./ui/link"; +import AnchorUI from "./ui/anchor"; const Wasabee = window.plugin.wasabee; @@ -440,7 +441,7 @@ function addAnchorToMap(portalId, operation) { (ev) => { L.DomEvent.stop(ev); if (marker.isPopupOpen && marker.isPopupOpen()) return; - const content = anchor.popupContent(marker); + const content = AnchorUI.popupContent(anchor, marker); marker.setPopupContent(content); if (marker._popup._wrapper) marker._popup._wrapper.classList.add("wasabee-popup"); diff --git a/src/code/model/anchor.js b/src/code/model/anchor.js index b63740d00..732ba0e74 100644 --- a/src/code/model/anchor.js +++ b/src/code/model/anchor.js @@ -1,12 +1,4 @@ -import { swapPortal, deletePortal } from "../uiCommands"; import { getSelectedOperation } from "../selectedOp"; -import AssignDialog from "../dialogs/assignDialog"; -import SendTargetDialog from "../dialogs/sendTargetDialog"; -import SetCommentDialog from "../dialogs/setCommentDialog"; -import LinkListDialog from "../dialogs/linkListDialog"; -import wX from "../wX"; - -import PortalUI from "../ui/portal"; // this class is for the popups, and for assign menu export default class WasabeeAnchor { @@ -52,155 +44,7 @@ export default class WasabeeAnchor { return this._portal.name; } - displayFormat(smallScreen = false) { - return PortalUI.displayFormat(this._portal, smallScreen); - } - get latLng() { return this._portal.latLng; } - - popupContent(marker) { - // just log for now, if we see it, then we can figure out what is really going on - const operation = getSelectedOperation(); - const canWrite = operation.canWrite(); - if (operation == null) { - console.log("null op for anchor?"); - } - if (this._opID != operation.ID) { - console.log("anchor opID != selected opID"); - } - - marker.className = "wasabee-anchor-popup"; - const content = L.DomUtil.create("div", null); - const title = L.DomUtil.create("div", "desc", content); - title.appendChild(PortalUI.displayFormat(this._portal)); - const portalComment = L.DomUtil.create( - "div", - "wasabee-portal-comment", - content - ); - const pcLink = L.DomUtil.create("a", null, portalComment); - pcLink.textContent = this._portal.comment || wX("SET_PORTAL_COMMENT"); - if (canWrite) { - pcLink.href = "#"; - L.DomEvent.on(pcLink, "click", (ev) => { - L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: this._portal, - operation: operation, - }); - scd.enable(); - marker.closePopup(); - }); - } - if (this._portal.hardness) { - const portalHardness = L.DomUtil.create( - "div", - "wasabee-portal-hardness", - content - ); - const phLink = L.DomUtil.create("a", null, portalHardness); - phLink.textContent = this._portal.hardness; - if (canWrite) { - phLink.href = "#"; - L.DomEvent.on(phLink, "click", (ev) => { - L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: this._portal, - operation: operation, - }); - scd.enable(); - marker.closePopup(); - }); - } - } - - const requiredKeys = L.DomUtil.create("div", "desc", content); - const onHand = operation.KeysOnHandForPortal(this._portal.id); - const required = operation.KeysRequiredForPortal(this._portal.id); - requiredKeys.textContent = "Keys: " + onHand + " / " + required; - - const buttonSet = L.DomUtil.create( - "div", - "wasabee-marker-buttonset", - content - ); - const linksButton = L.DomUtil.create("button", null, buttonSet); - linksButton.textContent = wX("LINKS"); - L.DomEvent.on(linksButton, "click", (ev) => { - L.DomEvent.stop(ev); - const lld = new LinkListDialog({ portal: this._portal }); - lld.enable(); - marker.closePopup(); - }); - if (canWrite) { - const swapButton = L.DomUtil.create("button", null, buttonSet); - swapButton.textContent = wX("SWAP"); - L.DomEvent.on(swapButton, "click", (ev) => { - L.DomEvent.stop(ev); - swapPortal(operation, this._portal); - marker.closePopup(); - }); - const deleteButton = L.DomUtil.create("button", null, buttonSet); - deleteButton.textContent = wX("DELETE_ANCHOR"); - L.DomEvent.on(deleteButton, "click", (ev) => { - L.DomEvent.stop(ev); - deletePortal(operation, this._portal); - marker.closePopup(); - }); - } - - const gmapButton = L.DomUtil.create("button", null, buttonSet); - gmapButton.textContent = wX("ANCHOR_GMAP"); - L.DomEvent.on(gmapButton, "click", (ev) => { - L.DomEvent.stop(ev); - marker.closePopup(); - // use intent on android - if ( - typeof window.android !== "undefined" && - window.android && - window.android.intentPosLink - ) { - window.android.intentPosLink( - +this._portal.lat, - +this._portal.lng, - window.map.getZoom(), - this.name, - true - ); - } else { - window.open( - "https://www.google.com/maps/search/?api=1&query=" + - this._portal.lat + - "," + - this._portal.lng - ); - } - }); - - if (operation.canWriteServer()) { - const assignButton = L.DomUtil.create("button", null, buttonSet); - assignButton.textContent = wX("ASSIGN OUTBOUND"); - L.DomEvent.on(assignButton, "click", (ev) => { - L.DomEvent.stop(ev); - const ad = new AssignDialog({ target: this }); - ad.enable(); - marker.closePopup(); - }); - } - - if (operation.isOnCurrentServer()) { - const sendButton = L.DomUtil.create("button", null, buttonSet); - sendButton.textContent = wX("SEND TARGET"); - L.DomEvent.on(sendButton, "click", (ev) => { - L.DomEvent.stop(ev); - const std = new SendTargetDialog({ target: this }); - std.enable(); - marker.closePopup(); - }); - } - - return content; - } } diff --git a/src/code/ui/anchor.js b/src/code/ui/anchor.js new file mode 100644 index 000000000..52273f146 --- /dev/null +++ b/src/code/ui/anchor.js @@ -0,0 +1,150 @@ +import AssignDialog from "../dialogs/assignDialog"; +import SendTargetDialog from "../dialogs/sendTargetDialog"; +import SetCommentDialog from "../dialogs/setCommentDialog"; +import LinkListDialog from "../dialogs/linkListDialog"; +import { getSelectedOperation } from "../selectedOp"; +import { swapPortal, deletePortal } from "../uiCommands"; +import wX from "../wX"; + +import PortalUI from "./portal"; + +export default { + popupContent, +}; + +function popupContent(anchor, leafletMarker) { + const operation = getSelectedOperation(); + const canWrite = operation.canWrite(); + const portal = operation.getPortal(anchor.ID); + + leafletMarker.className = "wasabee-anchor-popup"; + const content = L.DomUtil.create("div", null); + const title = L.DomUtil.create("div", "desc", content); + title.appendChild(PortalUI.displayFormat(portal)); + const portalComment = L.DomUtil.create( + "div", + "wasabee-portal-comment", + content + ); + const pcLink = L.DomUtil.create("a", null, portalComment); + pcLink.textContent = portal.comment || wX("SET_PORTAL_COMMENT"); + if (canWrite) { + pcLink.href = "#"; + L.DomEvent.on(pcLink, "click", (ev) => { + L.DomEvent.stop(ev); + const scd = new SetCommentDialog({ + target: portal, + operation: operation, + }); + scd.enable(); + leafletMarker.closePopup(); + }); + } + if (portal.hardness) { + const portalHardness = L.DomUtil.create( + "div", + "wasabee-portal-hardness", + content + ); + const phLink = L.DomUtil.create("a", null, portalHardness); + phLink.textContent = portal.hardness; + if (canWrite) { + phLink.href = "#"; + L.DomEvent.on(phLink, "click", (ev) => { + L.DomEvent.stop(ev); + const scd = new SetCommentDialog({ + target: portal, + operation: operation, + }); + scd.enable(); + leafletMarker.closePopup(); + }); + } + } + + const requiredKeys = L.DomUtil.create("div", "desc", content); + const onHand = operation.KeysOnHandForPortal(portal.id); + const required = operation.KeysRequiredForPortal(portal.id); + requiredKeys.textContent = "Keys: " + onHand + " / " + required; + + const buttonSet = L.DomUtil.create( + "div", + "wasabee-marker-buttonset", + content + ); + const linksButton = L.DomUtil.create("button", null, buttonSet); + linksButton.textContent = wX("LINKS"); + L.DomEvent.on(linksButton, "click", (ev) => { + L.DomEvent.stop(ev); + const lld = new LinkListDialog({ portal: portal }); + lld.enable(); + leafletMarker.closePopup(); + }); + if (canWrite) { + const swapButton = L.DomUtil.create("button", null, buttonSet); + swapButton.textContent = wX("SWAP"); + L.DomEvent.on(swapButton, "click", (ev) => { + L.DomEvent.stop(ev); + swapPortal(operation, portal); + leafletMarker.closePopup(); + }); + const deleteButton = L.DomUtil.create("button", null, buttonSet); + deleteButton.textContent = wX("DELETE_ANCHOR"); + L.DomEvent.on(deleteButton, "click", (ev) => { + L.DomEvent.stop(ev); + deletePortal(operation, portal); + leafletMarker.closePopup(); + }); + } + const gmapButton = L.DomUtil.create("button", null, buttonSet); + gmapButton.textContent = wX("ANCHOR_GMAP"); + L.DomEvent.on(gmapButton, "click", (ev) => { + L.DomEvent.stop(ev); + leafletMarker.closePopup(); + // use intent on android + if ( + typeof window.android !== "undefined" && + window.android && + window.android.intentPosLink + ) { + window.android.intentPosLink( + +portal.lat, + +portal.lng, + window.map.getZoom(), + portal.name, + true + ); + } else { + window.open( + "https://www.google.com/maps/search/?api=1&query=" + + portal.lat + + "," + + portal.lng + ); + } + }); + + if (operation.canWriteServer()) { + const assignButton = L.DomUtil.create("button", null, buttonSet); + assignButton.textContent = wX("ASSIGN OUTBOUND"); + L.DomEvent.on(assignButton, "click", (ev) => { + L.DomEvent.stop(ev); + const ad = new AssignDialog({ target: portal }); + ad.enable(); + leafletMarker.closePopup(); + }); + } + + if (operation.isOnCurrentServer()) { + const sendButton = L.DomUtil.create("button", null, buttonSet); + sendButton.textContent = wX("SEND TARGET"); + L.DomEvent.on(sendButton, "click", (ev) => { + L.DomEvent.stop(ev); + const std = new SendTargetDialog({ target: portal }); + std.enable(); + leafletMarker.closePopup(); + }); + } + + return content; +} From 558e9cf776c3917cd1c1768108342261c44195c6 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 14:27:49 +0200 Subject: [PATCH 006/275] add agent UI --- src/code/dialogs/manageTeamDialog.js | 6 +- src/code/dialogs/onlineAgentList.js | 4 +- src/code/dialogs/opsDialog.js | 4 +- src/code/dialogs/teamMembershipList.js | 6 +- src/code/mapDrawing.js | 15 +- src/code/model/agent.js | 195 +----------------------- src/code/model/marker.js | 3 +- src/code/ui/agent.js | 199 +++++++++++++++++++++++++ src/code/wd.js | 4 +- 9 files changed, 230 insertions(+), 206 deletions(-) create mode 100644 src/code/ui/agent.js diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 09175f1fd..23fa464a8 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -17,6 +17,8 @@ import PromptDialog from "./promptDialog"; import wX from "../wX"; import ConfirmDialog from "./confirmDialog"; +import AgentUI from "../ui/agent"; + // The update method here is the best so far, bring all the others up to this one const ManageTeamDialog = WDialog.extend({ statics: { @@ -48,7 +50,9 @@ const ManageTeamDialog = WDialog.extend({ value: (agent) => agent.name, sort: (a, b) => a.localeCompare(b), format: async (cell, value, agent) => - cell.appendChild(await agent.formatDisplay(this.options.team.id)), + cell.appendChild( + await AgentUI.formatDisplay(agent, this.options.team.id) + ), }, { name: wX("TEAM STATE"), diff --git a/src/code/dialogs/onlineAgentList.js b/src/code/dialogs/onlineAgentList.js index 47166d1ed..a13469387 100644 --- a/src/code/dialogs/onlineAgentList.js +++ b/src/code/dialogs/onlineAgentList.js @@ -3,6 +3,8 @@ import Sortable from "../sortable"; import WasabeeAgent from "../model/agent"; import wX from "../wX"; +import AgentUI from "../ui/agent"; + const OnlineAgentList = WDialog.extend({ statics: { TYPE: "OnlineAgentList", @@ -46,7 +48,7 @@ const OnlineAgentList = WDialog.extend({ value: (agent) => agent.name, sort: (a, b) => a.localeCompare(b), format: async (cell, value, agent) => - cell.appendChild(await agent.formatDisplay(0)), + cell.appendChild(await AgentUI.formatDisplay(agent)), }, { name: "Last Seen", diff --git a/src/code/dialogs/opsDialog.js b/src/code/dialogs/opsDialog.js index d00c4f53c..93136e810 100644 --- a/src/code/dialogs/opsDialog.js +++ b/src/code/dialogs/opsDialog.js @@ -17,6 +17,8 @@ import WasabeeAgent from "../model/agent"; import { syncOp, deleteLocalOp, zoomToOperation } from "../uiCommands"; import Sortable from "../sortable"; +import AgentUI from "../ui/agent"; + const OpsDialog = WDialog.extend({ statics: { TYPE: "opsDialog", @@ -280,7 +282,7 @@ const OpsDialog = WDialog.extend({ if (sum.currentserver) { const agent = await WasabeeAgent.get(tmpOp.creator); sum.owner = agent.name; - sum.ownerDisplay = await agent.formatDisplay(); + sum.ownerDisplay = await AgentUI.formatDisplay(agent); } else { sum.owner = window.PLAYER.nickname; } diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index e6723e0e3..a6df0068b 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -3,6 +3,8 @@ import Sortable from "../sortable"; import WasabeeTeam from "../model/team"; import wX from "../wX"; +import AgentUI from "../ui/agent"; + const TeamMembershipList = WDialog.extend({ statics: { TYPE: "teamMembershipList", @@ -54,7 +56,9 @@ const TeamMembershipList = WDialog.extend({ value: (agent) => agent.name, sort: (a, b) => a.localeCompare(b), format: async (cell, value, agent) => - cell.appendChild(await agent.formatDisplay(this.options.teamID)), + cell.appendChild( + await AgentUI.formatDisplay(agent, this.options.teamID) + ), }, { name: wX("SQUAD"), diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index 45968bd27..08b5ff30b 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -8,6 +8,7 @@ import { getSelectedOperation, opsList } from "./selectedOp"; import LinkUI from "./ui/link"; import AnchorUI from "./ui/anchor"; +import AgentUI from "./ui/agent"; const Wasabee = window.plugin.wasabee; @@ -296,10 +297,10 @@ function _drawAgent(agent, layerMap = agentLayerMap()) { title: agent.name, icon: L.divIcon({ className: "wasabee-agent-icon", - iconSize: agent.iconSize(zoom), - iconAnchor: agent.iconAnchor(zoom), + iconSize: AgentUI.iconSize(zoom), + iconAnchor: AgentUI.iconAnchor(zoom), popupAnchor: L.point(0, -70), - html: agent.icon(zoom), + html: AgentUI.icon(agent, zoom), }), id: agent.id, zoom: zoom, @@ -317,7 +318,7 @@ function _drawAgent(agent, layerMap = agentLayerMap()) { L.DomEvent.stop(ev); if (marker.isPopupOpen && marker.isPopupOpen()) return; const a = await WasabeeAgent.get(agent.id); - marker.setPopupContent(await a.getPopup()); + marker.setPopupContent(await AgentUI.getPopup(a)); if (marker._popup._wrapper) marker._popup._wrapper.classList.add("wasabee-popup"); marker.update(); @@ -344,10 +345,10 @@ function _drawAgent(agent, layerMap = agentLayerMap()) { al.setIcon( L.divIcon({ className: "wasabee-agent-icon", - iconSize: agent.iconSize(zoom), - iconAnchor: agent.iconAnchor(zoom), + iconSize: AgentUI.iconSize(zoom), + iconAnchor: AgentUI.iconAnchor(zoom), popupAnchor: L.point(0, -70), - html: agent.icon(zoom), + html: AgentUI.icon(agent, zoom), }) ); al.options.zoom = zoom; diff --git a/src/code/model/agent.js b/src/code/model/agent.js index 245c52dbe..b85b24986 100644 --- a/src/code/model/agent.js +++ b/src/code/model/agent.js @@ -1,13 +1,7 @@ -import ConfirmDialog from "../dialogs/confirmDialog"; -import AgentDialog from "../dialogs/agentDialog"; -import { agentPromise, targetPromise, routePromise } from "../server"; -import { getSelectedOperation } from "../selectedOp"; -import wX from "../wX"; +import { agentPromise } from "../server"; import WasabeeMe from "./me"; import WasabeeTeam from "./team"; -import PortalUI from "../ui/portal"; - export default class WasabeeAgent { constructor(obj) { if (typeof obj == "string") { @@ -58,7 +52,7 @@ export default class WasabeeAgent { this._updateCache(); } - async _getDisplayName(teamID = 0) { + async getTeamName(teamID = 0) { if (teamID == 0) return this.name; const team = await WasabeeTeam.get(teamID); @@ -156,189 +150,4 @@ export default class WasabeeAgent { // console.debug("giving up"); return null; } - - async formatDisplay(teamID = 0) { - const display = L.DomUtil.create("a", "wasabee-agent-label"); - if (this.Vverified || this.rocks) { - L.DomUtil.addClass(display, "enl"); - } - if (this.blacklisted) { - L.DomUtil.addClass(display, "res"); - } - L.DomEvent.on(display, "click", (ev) => { - L.DomEvent.stop(ev); - const ad = new AgentDialog({ gid: this.id }); - ad.enable(); - }); - display.textContent = await this._getDisplayName(teamID); - return display; - } - - async getPopup() { - const content = L.DomUtil.create("div", "wasabee-agent-popup"); - const title = L.DomUtil.create("div", "desc", content); - title.id = this.id; - const fd = await this.formatDisplay(0); - title.innerHTML = fd.outerHTML + this.timeSinceformat(); - - const sendTarget = L.DomUtil.create("button", null, content); - sendTarget.textContent = wX("SEND TARGET"); - L.DomEvent.on(sendTarget, "click", (ev) => { - L.DomEvent.stop(ev); - const selectedPortal = PortalUI.getSelected(); - if (!selectedPortal) { - alert(wX("SELECT PORTAL")); - return; - } - - const d = new ConfirmDialog({ - title: wX("SEND TARGET"), - label: wX("SEND TARGET CONFIRM", { - portalName: PortalUI.displayName(selectedPortal), - agent: this.name, - }), - type: "agent", - callback: async () => { - try { - await targetPromise(this.id, selectedPortal); - alert(wX("TARGET SENT")); - } catch (e) { - console.error(e); - } - }, - }); - d.enable(); - }); - - // this needs wX - const requestRoute = L.DomUtil.create("button", null, content); - requestRoute.textContent = "Send Route to Target"; - requestRoute.style.display = "none"; // hide this until the server-side is ready - L.DomEvent.on(requestRoute, "click", (ev) => { - L.DomEvent.stop(ev); - const selectedPortal = PortalUI.getSelected(); - if (!selectedPortal) { - alert(wX("SELECT PORTAL")); - return; - } - - const d = new ConfirmDialog({ - title: "Send Route to Target", - label: "Do you really want to request the route to be sent?", - type: "agent", - callback: async () => { - try { - await routePromise(this.id, selectedPortal); - alert("Route Sent"); - } catch (e) { - console.error(e); - } - }, - }); - d.enable(); - }); - - const op = getSelectedOperation(); - const assignments = L.DomUtil.create("ul", "assignments", content); - for (const m of op.markers) { - if (m.assignedTo != this.id) continue; - const a = L.DomUtil.create("li", "assignment", assignments); - const portal = op.getPortal(m.portalId); - a.textContent = `${m.order}: ${wX(m.type)} `; - a.appendChild(PortalUI.displayFormat(portal)); - } - - return content; - } - - timeSinceformat() { - if (!this.date) return ""; - const date = Date.parse(this.date + " UTC"); - if (Number.isNaN(date)) return `(${this.date} UTC)`; // FireFox Date.parse no good - if (date == 0) return ""; - - const seconds = Math.floor((new Date() - date) / 1000); - if (seconds < 0) return ""; - let interval = Math.floor(seconds / 31536000 / 2592000 / 86400); - - if (interval > 1) return wX("AGES"); - interval = Math.floor(seconds / 3600); - if (interval > 1) return wX("HOURS", { hours: interval }); - interval = Math.floor(seconds / 60); - if (interval > 1) return wX("MINUTES", { minutes: interval }); - interval = Math.floor(seconds); - return wX("SECONDS", { seconds: interval }); - } - - // change this to return an L.Marker() to make the logic in mapDrawing simpler - icon(z = 7) { - if (z < 6) return this.globalIcon(); - if (z >= 6 && z < 9) return this.smallIcon(); - if (z >= 9 && z < 15) return this.mediumIcon(); - return this.bigIcon(); - } - - iconSize(z = 7) { - if (z < 6) return [30, 30]; - if (z >= 6 && z < 9) return [36, 47]; - if (z >= 9 && z < 15) return [40, 52]; - return [46, 60]; - } - - iconAnchor(z = 7) { - if (z < 6) return [15, 30]; - if (z >= 6 && z < 9) return [18, 47]; - if (z >= 9 && z < 15) return [20, 52]; - return [23, 60]; - } - - // XXX there has to be a way to apply the viewBox onto the paths, to get rid of that extra nonsense - globalIcon() { - const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - icon.setAttribute("xmlns", "http://www.w3.org/2000/svg"); - icon.setAttribute("viewBox", "200 70 630 520"); - icon.setAttribute("height", "30"); - icon.setAttribute("width", "30"); - icon.setAttribute( - "style", - "fill-rule: evenodd; clip-rule: evenodd; stroke-miterlimit: 10;" - ); - icon.innerHTML = ``; - return icon; - } - - // XXX resize this properly - smallIcon() { - const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - icon.setAttribute("xmlns", "http://www.w3.org/2000/svg"); - icon.setAttribute("viewBox", "0 0 52 68"); - icon.innerHTML = ` - - - `; - return icon; - } - - // XXX resize this properly - mediumIcon() { - const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - icon.setAttribute("xmlns", "http://www.w3.org/2000/svg"); - icon.setAttribute("viewBox", "0 0 52 68"); - icon.innerHTML = ` - - - `; - return icon; - } - - bigIcon() { - const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - icon.setAttribute("xmlns", "http://www.w3.org/2000/svg"); - icon.setAttribute("viewBox", "0 0 52 68"); - icon.innerHTML = ` - - - `; - return icon; - } } diff --git a/src/code/model/marker.js b/src/code/model/marker.js index dad1c67da..5f5a5e993 100644 --- a/src/code/model/marker.js +++ b/src/code/model/marker.js @@ -10,6 +10,7 @@ import StateDialog from "../dialogs/stateDialog"; import { getSelectedOperation } from "../selectedOp"; import PortalUI from "../ui/portal"; +import AgentUI from "../ui/agent"; const STATE_UNASSIGNED = "pending"; const STATE_ASSIGNED = "assigned"; @@ -118,7 +119,7 @@ export default class WasabeeMarker { try { const a = await WasabeeAgent.get(this.assignedTo); assignment.textContent = wX("ASS_TO"); // FIXME convert formatDisplay to html and add as value to wX - if (a) assignment.appendChild(await a.formatDisplay()); + if (a) assignment.appendChild(await AgentUI.formatDisplay(a)); else assignment.textContent += " " + this.assignedTo; } catch (err) { console.error(err); diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js new file mode 100644 index 000000000..6d107c31d --- /dev/null +++ b/src/code/ui/agent.js @@ -0,0 +1,199 @@ +import PortalUI from "./portal"; +import ConfirmDialog from "../dialogs/confirmDialog"; +import AgentDialog from "../dialogs/agentDialog"; +import { targetPromise, routePromise } from "../server"; +import { getSelectedOperation } from "../selectedOp"; +import wX from "../wX"; + +export default { + formatDisplay, + getPopup, + icon, + iconSize, + iconAnchor, +}; + +async function formatDisplay(agent, teamID = 0) { + const display = L.DomUtil.create("a", "wasabee-agent-label"); + if (agent.Vverified || agent.rocks) { + L.DomUtil.addClass(display, "enl"); + } + if (agent.blacklisted) { + L.DomUtil.addClass(display, "res"); + } + L.DomEvent.on(display, "click", (ev) => { + L.DomEvent.stop(ev); + const ad = new AgentDialog({ gid: agent.id }); + ad.enable(); + }); + display.textContent = await agent.getTeamName(teamID); + return display; +} + +async function getPopup(agent) { + const content = L.DomUtil.create("div", "wasabee-agent-popup"); + const title = L.DomUtil.create("div", "desc", content); + title.id = agent.id; + const fd = await formatDisplay(agent, 0); + title.innerHTML = fd.outerHTML + timeSinceformat(agent); + + const sendTarget = L.DomUtil.create("button", null, content); + sendTarget.textContent = wX("SEND TARGET"); + L.DomEvent.on(sendTarget, "click", (ev) => { + L.DomEvent.stop(ev); + const selectedPortal = PortalUI.getSelected(); + if (!selectedPortal) { + alert(wX("SELECT PORTAL")); + return; + } + + const d = new ConfirmDialog({ + title: wX("SEND TARGET"), + label: wX("SEND TARGET CONFIRM", { + portalName: PortalUI.displayName(selectedPortal), + agent: agent.name, + }), + type: "agent", + callback: async () => { + try { + await targetPromise(agent.id, selectedPortal); + alert(wX("TARGET SENT")); + } catch (e) { + console.error(e); + } + }, + }); + d.enable(); + }); + + // this needs wX + const requestRoute = L.DomUtil.create("button", null, content); + requestRoute.textContent = "Send Route to Target"; + requestRoute.style.display = "none"; // hide this until the server-side is ready + L.DomEvent.on(requestRoute, "click", (ev) => { + L.DomEvent.stop(ev); + const selectedPortal = PortalUI.getSelected(); + if (!selectedPortal) { + alert(wX("SELECT PORTAL")); + return; + } + + const d = new ConfirmDialog({ + title: "Send Route to Target", + label: "Do you really want to request the route to be sent?", + type: "agent", + callback: async () => { + try { + await routePromise(agent.id, selectedPortal); + alert("Route Sent"); + } catch (e) { + console.error(e); + } + }, + }); + d.enable(); + }); + + const op = getSelectedOperation(); + const assignments = L.DomUtil.create("ul", "assignments", content); + for (const m of op.markers) { + if (m.assignedTo != agent.id) continue; + const a = L.DomUtil.create("li", "assignment", assignments); + const portal = op.getPortal(m.portalId); + a.textContent = `${m.order}: ${wX(m.type)} `; + a.appendChild(PortalUI.displayFormat(portal)); + } + + return content; +} + +function timeSinceformat(agent) { + if (!agent.date) return ""; + const date = Date.parse(agent.date + " UTC"); + if (Number.isNaN(date)) return `(${agent.date} UTC)`; // FireFox Date.parse no good + if (date == 0) return ""; + + const seconds = Math.floor((new Date() - date) / 1000); + if (seconds < 0) return ""; + let interval = Math.floor(seconds / 31536000 / 2592000 / 86400); + + if (interval > 1) return wX("AGES"); + interval = Math.floor(seconds / 3600); + if (interval > 1) return wX("HOURS", { hours: interval }); + interval = Math.floor(seconds / 60); + if (interval > 1) return wX("MINUTES", { minutes: interval }); + interval = Math.floor(seconds); + return wX("SECONDS", { seconds: interval }); +} + +// change this to return an L.Marker() to make the logic in mapDrawing simpler +function icon(agent, z = 7) { + if (z < 6) return globalIcon(); + if (z >= 6 && z < 9) return smallIcon(agent); + if (z >= 9 && z < 15) return mediumIcon(agent); + return bigIcon(agent); +} + +function iconSize(z = 7) { + if (z < 6) return [30, 30]; + if (z >= 6 && z < 9) return [36, 47]; + if (z >= 9 && z < 15) return [40, 52]; + return [46, 60]; +} + +function iconAnchor(z = 7) { + if (z < 6) return [15, 30]; + if (z >= 6 && z < 9) return [18, 47]; + if (z >= 9 && z < 15) return [20, 52]; + return [23, 60]; +} + +// XXX there has to be a way to apply the viewBox onto the paths, to get rid of that extra nonsense +function globalIcon() { + const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + icon.setAttribute("xmlns", "http://www.w3.org/2000/svg"); + icon.setAttribute("viewBox", "200 70 630 520"); + icon.setAttribute("height", "30"); + icon.setAttribute("width", "30"); + icon.setAttribute( + "style", + "fill-rule: evenodd; clip-rule: evenodd; stroke-miterlimit: 10;" + ); + icon.innerHTML = ``; + return icon; +} + +// XXX resize this properly +function smallIcon(agent) { + const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + icon.setAttribute("xmlns", "http://www.w3.org/2000/svg"); + icon.setAttribute("viewBox", "0 0 52 68"); + icon.innerHTML = ` + + + `; + return icon; +} + +// XXX resize this properly +function mediumIcon(agent) { + const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + icon.setAttribute("xmlns", "http://www.w3.org/2000/svg"); + icon.setAttribute("viewBox", "0 0 52 68"); + icon.innerHTML = ` + + + `; + return icon; +} + +function bigIcon(agent) { + const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + icon.setAttribute("xmlns", "http://www.w3.org/2000/svg"); + icon.setAttribute("viewBox", "0 0 52 68"); + icon.innerHTML = ` + + + `; + return icon; +} diff --git a/src/code/wd.js b/src/code/wd.js index 35f9ba25c..902e9cf99 100644 --- a/src/code/wd.js +++ b/src/code/wd.js @@ -4,6 +4,8 @@ import WasabeeAgent from "./model/agent"; import wX from "./wX"; // import { getPortalDetails } from "./uiCommands"; +import AgentUI from "./ui/agent"; + // setup function export function initWasabeeD() { window.plugin.wasabee.defensiveLayers = new L.LayerGroup(); @@ -153,7 +155,7 @@ async function getMarkerPopup(PortalID) { const a = await WasabeeAgent.get(dk.GID); const li = L.DomUtil.create("li", null, ul); if (a) { - li.appendChild(await a.formatDisplay()); + li.appendChild(await AgentUI.formatDisplay(a)); } else { const fake = L.DomUtil.create("span", null, li); fake.textContent = wX("LOADING"); From b0ab7057ea4a85aea846ade3fb220241293a5b73 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 14:31:02 +0200 Subject: [PATCH 007/275] add markerUI --- src/code/mapDrawing.js | 3 +- src/code/model/marker.js | 198 -------------------------------------- src/code/ui/marker.js | 201 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 199 deletions(-) create mode 100644 src/code/ui/marker.js diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index 08b5ff30b..a47fa49f5 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -9,6 +9,7 @@ import { getSelectedOperation, opsList } from "./selectedOp"; import LinkUI from "./ui/link"; import AnchorUI from "./ui/anchor"; import AgentUI from "./ui/agent"; +import MarkerUI from "./ui/marker"; const Wasabee = window.plugin.wasabee; @@ -89,7 +90,7 @@ function addMarker(target, operation) { if (this.isPopupOpen()) return; const sop = getSelectedOperation(); const target = sop.getMarker(this.options.id); - const c = await target.popupContent(this); + const c = await MarkerUI.popupContent(target, this); this.setPopupContent(c); this._popup._wrapper.classList.add("wasabee-popup"); this.update(); diff --git a/src/code/model/marker.js b/src/code/model/marker.js index 5f5a5e993..258e62183 100644 --- a/src/code/model/marker.js +++ b/src/code/model/marker.js @@ -1,16 +1,4 @@ import { generateId } from "../auxiliar"; -import { deleteMarker } from "../uiCommands"; -import WasabeeAgent from "./agent"; -import AssignDialog from "../dialogs/assignDialog"; -import SendTargetDialog from "../dialogs/sendTargetDialog"; -import wX from "../wX"; -import SetCommentDialog from "../dialogs/setCommentDialog"; -import MarkerChangeDialog from "../dialogs/markerChangeDialog"; -import StateDialog from "../dialogs/stateDialog"; -import { getSelectedOperation } from "../selectedOp"; - -import PortalUI from "../ui/portal"; -import AgentUI from "../ui/agent"; const STATE_UNASSIGNED = "pending"; const STATE_ASSIGNED = "assigned"; @@ -95,190 +83,4 @@ export default class WasabeeMarker { get state() { return this._state; } - - async popupContent(marker, operation) { - if (!operation) operation = getSelectedOperation(); - const canWrite = operation.canWrite(); - - const portal = operation.getPortal(this.portalId); - if (portal == null) { - console.log("null portal getting marker popup"); - return (L.DomUtil.create("div", "wasabee-marker-popup").textContent = - "invalid portal"); - } - - const content = L.DomUtil.create("div", "wasabee-marker-popup"); - content.appendChild(this._getPopupBodyWithType(portal, operation, marker)); - - const assignment = L.DomUtil.create( - "div", - "wasabee-popup-assignment", - content - ); - if (this.state != "completed" && this.assignedTo) { - try { - const a = await WasabeeAgent.get(this.assignedTo); - assignment.textContent = wX("ASS_TO"); // FIXME convert formatDisplay to html and add as value to wX - if (a) assignment.appendChild(await AgentUI.formatDisplay(a)); - else assignment.textContent += " " + this.assignedTo; - } catch (err) { - console.error(err); - } - } - if (this.state == "completed" && this.completedID) { - try { - const a = await WasabeeAgent.get(this.completedID); - assignment.innerHTML = wX("COMPLETED BY", { - agentName: a ? a.name : this.completedID, - }); - } catch (e) { - console.error(e); - } - } - - const buttonSet = L.DomUtil.create( - "div", - "wasabee-marker-buttonset", - content - ); - if (canWrite) { - const deleteButton = L.DomUtil.create("button", null, buttonSet); - deleteButton.textContent = wX("DELETE_ANCHOR"); - L.DomEvent.on(deleteButton, "click", (ev) => { - L.DomEvent.stop(ev); - deleteMarker(operation, this, portal); - marker.closePopup(); - }); - } - - if (operation.canWriteServer()) { - const assignButton = L.DomUtil.create("button", null, buttonSet); - assignButton.textContent = wX("ASSIGN"); - L.DomEvent.on(assignButton, "click", (ev) => { - L.DomEvent.stop(ev); - const ad = new AssignDialog({ target: this }); - ad.enable(); - marker.closePopup(); - }); - } - - if (canWrite) { - const stateButton = L.DomUtil.create("button", null, buttonSet); - stateButton.textContent = wX("MARKER STATE"); - L.DomEvent.on(stateButton, "click", (ev) => { - L.DomEvent.stop(ev); - const sd = new StateDialog({ target: this, opID: operation.ID }); - sd.enable(); - marker.closePopup(); - }); - } - - if (operation.isOnCurrentServer()) { - const sendTargetButton = L.DomUtil.create("button", null, buttonSet); - sendTargetButton.textContent = wX("SEND TARGET"); - L.DomEvent.on(sendTargetButton, "click", (ev) => { - L.DomEvent.stop(ev); - const std = new SendTargetDialog({ target: this }); - std.enable(); - marker.closePopup(); - }); - } - - const gmapButton = L.DomUtil.create("button", null, buttonSet); - gmapButton.textContent = wX("ANCHOR_GMAP"); - L.DomEvent.on(gmapButton, "click", (ev) => { - L.DomEvent.stop(ev); - marker.closePopup(); - // use intent on android - if ( - typeof window.android !== "undefined" && - window.android && - window.android.intentPosLink - ) { - window.android.intentPosLink( - +portal.lat, - +portal.lng, - window.map.getZoom(), - portal.name, - true - ); - } else { - window.open( - "https://www.google.com/maps/search/?api=1&query=" + - portal.lat + - "," + - portal.lng - ); - } - }); - - return content; - } - - _getPopupBodyWithType(portal, operation, marker) { - const title = L.DomUtil.create("div", "desc"); - const kind = L.DomUtil.create("span", "wasabee-marker-popup-kind", title); - L.DomUtil.addClass(kind, this.type); - kind.textContent = wX(this.type); - title.appendChild(PortalUI.displayFormat(portal)); - - kind.href = "#"; - L.DomEvent.on(kind, "click", (ev) => { - L.DomEvent.stop(ev); - const ch = new MarkerChangeDialog({ marker: this }); - ch.enable(); - marker.closePopup(); - }); - - if (this.comment) { - const comment = L.DomUtil.create( - "div", - "wasabee-marker-popup-comment", - title - ); - comment.textContent = this.comment; - L.DomEvent.on(comment, "click", (ev) => { - L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: this, - operation: operation, - }); - scd.enable(); - marker.closePopup(); - }); - } - const comment = L.DomUtil.create("div", "wasabee-portal-comment", title); - const cl = L.DomUtil.create("a", null, comment); - cl.textContent = portal.comment || wX("SET_PORTAL_COMMENT"); - cl.href = "#"; - L.DomEvent.on(cl, "click", (ev) => { - L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: portal, - operation: operation, - }); - scd.enable(); - marker.closePopup(); - }); - if (portal.hardness) { - const hardness = L.DomUtil.create( - "div", - "wasabee-portal-hardness", - title - ); - const hl = L.DomUtil.create("a", null, hardness); - hl.textContent = portal.hardness; - hl.href = "#"; - L.DomEvent.on(hl, "click", (ev) => { - L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: portal, - operation: operation, - }); - scd.enable(); - marker.closePopup(); - }); - } - return title; - } } diff --git a/src/code/ui/marker.js b/src/code/ui/marker.js new file mode 100644 index 000000000..0eabf58da --- /dev/null +++ b/src/code/ui/marker.js @@ -0,0 +1,201 @@ +import WasabeeAgent from "../model/agent"; + +import AssignDialog from "../dialogs/assignDialog"; +import SendTargetDialog from "../dialogs/sendTargetDialog"; +import SetCommentDialog from "../dialogs/setCommentDialog"; +import MarkerChangeDialog from "../dialogs/markerChangeDialog"; +import StateDialog from "../dialogs/stateDialog"; +import { getSelectedOperation } from "../selectedOp"; +import { deleteMarker } from "../uiCommands"; + +import AgentUI from "./agent"; +import PortalUI from "./portal"; + +import wX from "../wX"; + +export default { + popupContent, +}; + +async function popupContent(marker, leafletMarker, operation) { + if (!operation) operation = getSelectedOperation(); + const canWrite = operation.canWrite(); + + const portal = operation.getPortal(marker.portalId); + if (portal == null) { + console.log("null portal getting marker popup"); + return (L.DomUtil.create("div", "wasabee-marker-popup").textContent = + "invalid portal"); + } + + const content = L.DomUtil.create("div", "wasabee-marker-popup"); + content.appendChild( + getPopupBodyWithType(marker, portal, operation, leafletMarker) + ); + + const assignment = L.DomUtil.create( + "div", + "wasabee-popup-assignment", + content + ); + if (marker.state != "completed" && marker.assignedTo) { + try { + const a = await WasabeeAgent.get(marker.assignedTo); + assignment.textContent = wX("ASS_TO"); // FIXME convert formatDisplay to html and add as value to wX + if (a) assignment.appendChild(await AgentUI.formatDisplay(a)); + else assignment.textContent += " " + marker.assignedTo; + } catch (err) { + console.error(err); + } + } + if (marker.state == "completed" && marker.completedID) { + try { + const a = await WasabeeAgent.get(marker.completedID); + assignment.innerHTML = wX("COMPLETED BY", { + agentName: a ? a.name : marker.completedID, + }); + } catch (e) { + console.error(e); + } + } + + const buttonSet = L.DomUtil.create( + "div", + "wasabee-marker-buttonset", + content + ); + if (canWrite) { + const deleteButton = L.DomUtil.create("button", null, buttonSet); + deleteButton.textContent = wX("DELETE_ANCHOR"); + L.DomEvent.on(deleteButton, "click", (ev) => { + L.DomEvent.stop(ev); + deleteMarker(operation, marker, portal); + leafletMarker.closePopup(); + }); + } + if (operation.canWriteServer()) { + const assignButton = L.DomUtil.create("button", null, buttonSet); + assignButton.textContent = wX("ASSIGN"); + L.DomEvent.on(assignButton, "click", (ev) => { + L.DomEvent.stop(ev); + const ad = new AssignDialog({ target: marker }); + ad.enable(); + leafletMarker.closePopup(); + }); + } + + if (canWrite) { + const stateButton = L.DomUtil.create("button", null, buttonSet); + stateButton.textContent = wX("MARKER STATE"); + L.DomEvent.on(stateButton, "click", (ev) => { + L.DomEvent.stop(ev); + const sd = new StateDialog({ target: marker, opID: operation.ID }); + sd.enable(); + leafletMarker.closePopup(); + }); + } + + if (operation.isOnCurrentServer()) { + const sendTargetButton = L.DomUtil.create("button", null, buttonSet); + sendTargetButton.textContent = wX("SEND TARGET"); + L.DomEvent.on(sendTargetButton, "click", (ev) => { + L.DomEvent.stop(ev); + const std = new SendTargetDialog({ target: marker }); + std.enable(); + leafletMarker.closePopup(); + }); + } + + const gmapButton = L.DomUtil.create("button", null, buttonSet); + gmapButton.textContent = wX("ANCHOR_GMAP"); + L.DomEvent.on(gmapButton, "click", (ev) => { + L.DomEvent.stop(ev); + leafletMarker.closePopup(); + // use intent on android + if ( + typeof window.android !== "undefined" && + window.android && + window.android.intentPosLink + ) { + window.android.intentPosLink( + +portal.lat, + +portal.lng, + window.map.getZoom(), + portal.name, + true + ); + } else { + window.open( + "https://www.google.com/maps/search/?api=1&query=" + + portal.lat + + "," + + portal.lng + ); + } + }); + + return content; +} + +function getPopupBodyWithType(marker, portal, operation, leafletMarker) { + const title = L.DomUtil.create("div", "desc"); + const kind = L.DomUtil.create("span", "wasabee-marker-popup-kind", title); + L.DomUtil.addClass(kind, marker.type); + kind.textContent = wX(marker.type); + title.appendChild(PortalUI.displayFormat(portal)); + + kind.href = "#"; + L.DomEvent.on(kind, "click", (ev) => { + L.DomEvent.stop(ev); + const ch = new MarkerChangeDialog({ marker: marker }); + ch.enable(); + leafletMarker.closePopup(); + }); + + if (marker.comment) { + const comment = L.DomUtil.create( + "div", + "wasabee-marker-popup-comment", + title + ); + comment.textContent = marker.comment; + L.DomEvent.on(comment, "click", (ev) => { + L.DomEvent.stop(ev); + const scd = new SetCommentDialog({ + target: marker, + operation: operation, + }); + scd.enable(); + leafletMarker.closePopup(); + }); + } + const comment = L.DomUtil.create("div", "wasabee-portal-comment", title); + const cl = L.DomUtil.create("a", null, comment); + cl.textContent = portal.comment || wX("SET_PORTAL_COMMENT"); + cl.href = "#"; + L.DomEvent.on(cl, "click", (ev) => { + L.DomEvent.stop(ev); + const scd = new SetCommentDialog({ + target: portal, + operation: operation, + }); + scd.enable(); + leafletMarker.closePopup(); + }); + if (portal.hardness) { + const hardness = L.DomUtil.create("div", "wasabee-portal-hardness", title); + const hl = L.DomUtil.create("a", null, hardness); + hl.textContent = portal.hardness; + hl.href = "#"; + L.DomEvent.on(hl, "click", (ev) => { + L.DomEvent.stop(ev); + const scd = new SetCommentDialog({ + target: portal, + operation: operation, + }); + scd.enable(); + leafletMarker.closePopup(); + }); + } + return title; +} From 754e1a32af32d8cc1caccf6894548abfa8a5ec7a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 14:43:52 +0200 Subject: [PATCH 008/275] add db.js --- src/code/db.js | 38 ++++++++++++++++++++++++++++++++++ src/code/init.js | 41 ++----------------------------------- src/code/model/agent.js | 9 ++++---- src/code/model/me.js | 3 ++- src/code/model/operation.js | 9 ++++---- src/code/model/team.js | 5 +++-- 6 files changed, 55 insertions(+), 50 deletions(-) create mode 100644 src/code/db.js diff --git a/src/code/db.js b/src/code/db.js new file mode 100644 index 000000000..ede9a7200 --- /dev/null +++ b/src/code/db.js @@ -0,0 +1,38 @@ +import { openDB } from "idb"; + +const version = 2; + +// XXX audit these to make sure all the various indexes are used +const db = openDB("wasabee", version, { + upgrade(db, oldVersion, newVersion, tx) { + if (oldVersion < 1) { + const agents = db.createObjectStore("agents", { keyPath: "id" }); + agents.createIndex("date", "date"); // last location change + agents.createIndex("fetched", "fetched"); // last pull from server + const teams = db.createObjectStore("teams", { keyPath: "id" }); + teams.createIndex("fetched", "fetched"); // last pull from server + + // do not set an implied key, explicitly set GID/PortalID on insert + // XXX we can do this with a keyPath https://stackoverflow.com/questions/33852508/how-to-create-an-indexeddb-composite-key + // const defensivekeys = db.createObjectStore("defensivekeys"); + const defensivekeys = db.createObjectStore("defensivekeys", { + keyPath: ["GID", "PortalID"], + }); + defensivekeys.createIndex("PortalID", "PortalID"); + defensivekeys.createIndex("Count", "Count"); // To be used to remove 0-count entries + // defensivekeys.createIndex("pk", ["GID", "PortalID"], { unique: true }); + } + if (oldVersion < 2) { + const ops = db.createObjectStore("operations", { keyPath: "ID" }); + ops.createIndex("fetched", "fetched"); + ops.createIndex("server", "server"); + } + /* if (oldVersion < 3) { + const teams = tx.objectStore("teams"); + teams.createIndex("_agents", "_agents[].id"); + } */ + console.debug(newVersion, tx); + }, +}); + +export default db; diff --git a/src/code/init.js b/src/code/init.js index 3ead3d7e6..d3203d900 100644 --- a/src/code/init.js +++ b/src/code/init.js @@ -17,7 +17,7 @@ import { WPane } from "./leafletClasses"; import OperationChecklist from "./dialogs/checklist"; import WasabeeMe from "./model/me"; import WasabeeOp from "./model/operation"; -import { openDB } from "idb"; +import db from "./db"; import polyfill from "./polyfill"; const Wasabee = window.plugin.wasabee; @@ -40,7 +40,7 @@ window.plugin.wasabee.init = async () => { return; } - await initIdb(); + Wasabee.idb = await db; Wasabee._selectedOp = null; // the in-memory working op; Wasabee._updateList = new Map(); Wasabee.portalDetailQueue = new Array(); @@ -241,40 +241,3 @@ function initGoogleAPI() { script ); } - -async function initIdb() { - const version = 2; - - // XXX audit these to make sure all the various indexes are used - Wasabee.idb = await openDB("wasabee", version, { - upgrade(db, oldVersion, newVersion, tx) { - if (oldVersion < 1) { - const agents = db.createObjectStore("agents", { keyPath: "id" }); - agents.createIndex("date", "date"); // last location change - agents.createIndex("fetched", "fetched"); // last pull from server - const teams = db.createObjectStore("teams", { keyPath: "id" }); - teams.createIndex("fetched", "fetched"); // last pull from server - - // do not set an implied key, explicitly set GID/PortalID on insert - // XXX we can do this with a keyPath https://stackoverflow.com/questions/33852508/how-to-create-an-indexeddb-composite-key - // const defensivekeys = db.createObjectStore("defensivekeys"); - const defensivekeys = db.createObjectStore("defensivekeys", { - keyPath: ["GID", "PortalID"], - }); - defensivekeys.createIndex("PortalID", "PortalID"); - defensivekeys.createIndex("Count", "Count"); // To be used to remove 0-count entries - // defensivekeys.createIndex("pk", ["GID", "PortalID"], { unique: true }); - } - if (oldVersion < 2) { - const ops = db.createObjectStore("operations", { keyPath: "ID" }); - ops.createIndex("fetched", "fetched"); - ops.createIndex("server", "server"); - } - /* if (oldVersion < 3) { - const teams = tx.objectStore("teams"); - teams.createIndex("_agents", "_agents[].id"); - } */ - console.debug(newVersion, tx); - }, - }); -} diff --git a/src/code/model/agent.js b/src/code/model/agent.js index b85b24986..3d13ab083 100644 --- a/src/code/model/agent.js +++ b/src/code/model/agent.js @@ -1,6 +1,7 @@ import { agentPromise } from "../server"; import WasabeeMe from "./me"; import WasabeeTeam from "./team"; +import db from "../db"; export default class WasabeeAgent { constructor(obj) { @@ -67,14 +68,14 @@ export default class WasabeeAgent { async _updateCache() { // load anything currently cached - const cached = await window.plugin.wasabee.idb.get("agents", this.id); + const cached = await (await db).get("agents", this.id); // nothing already in the cache, just dump this in and call it good // will contain the extras, but that's fine for now if (cached == null) { // console.debug("not cached, adding"); try { - await window.plugin.wasabee.idb.put("agents", this); + await (await db).put("agents", this); } catch (e) { console.error(e); } @@ -114,7 +115,7 @@ export default class WasabeeAgent { delete cached.state; try { - await window.plugin.wasabee.idb.put("agents", cached); + await (await db).put("agents", cached); } catch (e) { console.error(e); } @@ -127,7 +128,7 @@ export default class WasabeeAgent { // hold agent data up to 24 hours by default -- don't bother the server if all we need to do is resolve GID -> name static async get(gid, maxAgeSeconds = 86400) { - const cached = await window.plugin.wasabee.idb.get("agents", gid); + const cached = await (await db).get("agents", gid); if (cached && cached.fetched > Date.now() - 1000 * maxAgeSeconds) { const a = new WasabeeAgent(cached); a.cached = true; diff --git a/src/code/model/me.js b/src/code/model/me.js index af2c9455a..b40862c9b 100644 --- a/src/code/model/me.js +++ b/src/code/model/me.js @@ -1,4 +1,5 @@ import { mePromise } from "../server"; +import db from "../db"; const Wasabee = window.plugin.wasabee; @@ -128,7 +129,7 @@ export default class WasabeeMe { delete localStorage[Wasabee.static.constants.AGENT_INFO_KEY]; delete localStorage["sentToServer"]; // resend firebase token on login - const tr = window.plugin.wasabee.idb.transaction( + const tr = (await db).transaction( ["agents", "teams", "defensivekeys"], "readwrite" ); diff --git a/src/code/model/operation.js b/src/code/model/operation.js index dd8c19842..5ce4f0d8a 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -6,6 +6,7 @@ import WasabeeZone from "./zone"; import { generateId, newColors } from "../auxiliar"; import { GetWasabeeServer } from "../server"; import { getSelectedOperation } from "../selectedOp"; +import db from "../db"; import wX from "../wX"; @@ -66,7 +67,7 @@ export default class WasabeeOp { static async load(opID) { try { - const raw = await window.plugin.wasabee.idb.get("operations", opID); + const raw = await (await db).get("operations", opID); if (raw == null) //throw new Error("invalid operation ID"); return null; @@ -81,12 +82,12 @@ export default class WasabeeOp { static async delete(opID) { delete localStorage[opID]; // leave for now - await window.plugin.wasabee.idb.delete("operations", opID); + await (await db).delete("operations", opID); } static async migrate(opID) { // skip ones already completed - const have = await window.plugin.wasabee.idb.get("operations", opID); + const have = await (await db).get("operations", opID); if (have != null) { delete localStorage[opID]; // active now return; @@ -128,7 +129,7 @@ export default class WasabeeOp { // store to idb try { - await window.plugin.wasabee.idb.put("operations", json); + await (await db).put("operations", json); } catch (e) { console.error(e); } diff --git a/src/code/model/team.js b/src/code/model/team.js index 980d276f9..b8c1b4e2b 100644 --- a/src/code/model/team.js +++ b/src/code/model/team.js @@ -1,6 +1,7 @@ import WasabeeAgent from "./agent"; import WasabeeMe from "./me"; import { teamPromise } from "../server"; +import db from "../db"; export default class WasabeeTeam { constructor(data) { @@ -41,7 +42,7 @@ export default class WasabeeTeam { async _updateCache() { try { - await window.plugin.wasabee.idb.put("teams", this); + await (await db).put("teams", this); } catch (e) { console.error(e); } @@ -49,7 +50,7 @@ export default class WasabeeTeam { // 60 seconds seems too short for the default here... static async get(teamID, maxAgeSeconds = 60) { - const cached = await window.plugin.wasabee.idb.get("teams", teamID); + const cached = await (await db).get("teams", teamID); if (cached) { const t = new WasabeeTeam(cached); if (t.fetched > Date.now() - 1000 * maxAgeSeconds) { From 0a404741f59106dea268a5751c93db4e105c1d40 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 14:48:00 +0200 Subject: [PATCH 009/275] remove plugin reference from model --- src/code/model/me.js | 11 +++++------ src/code/model/operation.js | 14 +++++++------- src/code/static.js | 2 ++ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/code/model/me.js b/src/code/model/me.js index b40862c9b..15d028bd8 100644 --- a/src/code/model/me.js +++ b/src/code/model/me.js @@ -1,7 +1,7 @@ import { mePromise } from "../server"; import db from "../db"; -const Wasabee = window.plugin.wasabee; +import { constants } from "../static"; export default class WasabeeMe { constructor(data) { @@ -54,16 +54,15 @@ export default class WasabeeMe { } store() { - localStorage[Wasabee.static.constants.AGENT_INFO_KEY] = - JSON.stringify(this); + localStorage[constants.AGENT_INFO_KEY] = JSON.stringify(this); } remove() { - delete localStorage[Wasabee.static.constants.AGENT_INFO_KEY]; + delete localStorage[constants.AGENT_INFO_KEY]; } static localGet() { - const lsme = localStorage[Wasabee.static.constants.AGENT_INFO_KEY]; + const lsme = localStorage[constants.AGENT_INFO_KEY]; if (typeof lsme == "string") { return new WasabeeMe(lsme); // do not store } @@ -126,7 +125,7 @@ export default class WasabeeMe { } static async purge() { - delete localStorage[Wasabee.static.constants.AGENT_INFO_KEY]; + delete localStorage[constants.AGENT_INFO_KEY]; delete localStorage["sentToServer"]; // resend firebase token on login const tr = (await db).transaction( diff --git a/src/code/model/operation.js b/src/code/model/operation.js index 5ce4f0d8a..a2fff26c3 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -8,9 +8,9 @@ import { GetWasabeeServer } from "../server"; import { getSelectedOperation } from "../selectedOp"; import db from "../db"; -import wX from "../wX"; +import { constants } from "../static"; -const Wasabee = window.plugin.wasabee; +import wX from "../wX"; export default class WasabeeOp { constructor(obj) { @@ -29,7 +29,7 @@ export default class WasabeeOp { this.anchors = obj.anchors ? obj.anchors : Array(); this.links = this.convertLinksToObjs(obj.links); this.markers = this.convertMarkersToObjs(obj.markers); - this.color = obj.color ? obj.color : Wasabee.skin.defaultOperationColor; + this.color = obj.color ? obj.color : "main"; this.color = newColors(this.color); this.comment = obj.comment ? obj.comment : null; this.teamlist = obj.teamlist ? obj.teamlist : Array(); @@ -237,7 +237,7 @@ export default class WasabeeOp { getColor() { if (this.color == null) { - return Wasabee.skin.defaultOperationColor; + return "main"; } else { return this.color; } @@ -810,9 +810,9 @@ export default class WasabeeOp { // only need this for virus/destroy/decay -- this should be in the marker class const destructMarkerTypes = [ - window.plugin.wasabee.static.constants.MARKER_TYPE_DECAY, - window.plugin.wasabee.static.constants.MARKER_TYPE_DESTROY, - window.plugin.wasabee.static.constants.MARKER_TYPE_VIRUS, + constants.MARKER_TYPE_DECAY, + constants.MARKER_TYPE_DESTROY, + constants.MARKER_TYPE_VIRUS, ]; if (destructMarkerTypes.includes(markerType)) { // remove related blockers diff --git a/src/code/static.js b/src/code/static.js index f279431a6..729b77c66 100644 --- a/src/code/static.js +++ b/src/code/static.js @@ -206,3 +206,5 @@ W.static.layerTypes = new Map([ }, ], ]); + +export const constants = W.static.constants; From 46c684d8d5d4880723a3f197a6e5dbc06d8bd84c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 14:54:30 +0200 Subject: [PATCH 010/275] remove wX from model --- src/code/dialogs/markerAddDialog.js | 5 ++- src/code/model/operation.js | 66 ++++++++++++++--------------- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index e76e2efce..c775b3aff 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -148,8 +148,9 @@ const MarkerAddDialog = WDialog.extend({ }; // XXX remove comment from args in 0.20 - operation.addMarker(selectedType, PortalUI.getSelected(), options); - await this.update(); + if (operation.addMarker(selectedType, PortalUI.getSelected(), options)) + await this.update(); + else alert(wX("ALREADY_HAS_MARKER")); localStorage[window.plugin.wasabee.static.constants.LAST_MARKER_KEY] = selectedType; }, diff --git a/src/code/model/operation.js b/src/code/model/operation.js index a2fff26c3..937839a38 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -10,8 +10,6 @@ import db from "../db"; import { constants } from "../static"; -import wX from "../wX"; - export default class WasabeeOp { constructor(obj) { if (typeof obj == "string") { @@ -792,40 +790,38 @@ export default class WasabeeOp { } addMarker(markerType, portal, options) { - if (!portal) return; - if (this.containsMarker(portal, markerType)) { - alert(wX("ALREADY_HAS_MARKER")); - } else { - // save a trip to update() - this._addPortal(portal); - const marker = new WasabeeMarker({ - type: markerType, - portalId: portal.id, - }); - if (options && options.comment) marker.comment = options.comment; - if (options && options.zone) marker.zone = options.zone; - if (options && options.assign && options.assign != 0) - marker.assign(options.assign); - this.markers.push(marker); - - // only need this for virus/destroy/decay -- this should be in the marker class - const destructMarkerTypes = [ - constants.MARKER_TYPE_DECAY, - constants.MARKER_TYPE_DESTROY, - constants.MARKER_TYPE_VIRUS, - ]; - if (destructMarkerTypes.includes(markerType)) { - // remove related blockers - this.blockers = this.blockers.filter( - (b) => b.fromPortalId !== portal.id && b.toPortalId !== portal.id - ); - } - - this.update(true); - // run crosslink to update the layer - // XXX: we don't need to check, only redraw, so we need something clever, probably in mapDraw or crosslink.js - if (destructMarkerTypes.includes(markerType)) this.runCrosslinks(); + if (!portal) return false; + if (this.containsMarker(portal, markerType)) return false; + // save a trip to update() + this._addPortal(portal); + const marker = new WasabeeMarker({ + type: markerType, + portalId: portal.id, + }); + if (options && options.comment) marker.comment = options.comment; + if (options && options.zone) marker.zone = options.zone; + if (options && options.assign && options.assign != 0) + marker.assign(options.assign); + this.markers.push(marker); + + // only need this for virus/destroy/decay -- this should be in the marker class + const destructMarkerTypes = [ + constants.MARKER_TYPE_DECAY, + constants.MARKER_TYPE_DESTROY, + constants.MARKER_TYPE_VIRUS, + ]; + if (destructMarkerTypes.includes(markerType)) { + // remove related blockers + this.blockers = this.blockers.filter( + (b) => b.fromPortalId !== portal.id && b.toPortalId !== portal.id + ); } + + this.update(true); + // run crosslink to update the layer + // XXX: we don't need to check, only redraw, so we need something clever, probably in mapDraw or crosslink.js + if (destructMarkerTypes.includes(markerType)) this.runCrosslinks(); + return true; } assignMarker(id, gid) { From 842c3b826ae78a54ae1c14180b3fa2dc2c813169 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 15:48:54 +0200 Subject: [PATCH 011/275] add Evented and remove window.map from model --- src/code/model/evented.js | 51 +++++++++++++++++++++++++++++++++++++ src/code/model/operation.js | 26 ++++++++++--------- src/code/selectedOp.js | 6 +++++ 3 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 src/code/model/evented.js diff --git a/src/code/model/evented.js b/src/code/model/evented.js new file mode 100644 index 000000000..aac98c209 --- /dev/null +++ b/src/code/model/evented.js @@ -0,0 +1,51 @@ +/* + light es6 version of L.Evented + current design to fail safe is: + - events array is increaing only, removed listeners are replaced by a null function + - loop are prevented by removing listeners during its call + - try/catch +*/ + +function doNothing() {} + +export default class Evented { + constructor() { + this._events = {}; + } + + on(event, func, context) { + if (!(event in this._events)) this._events[event] = []; + this._events[event].push({ fct: func, context: context }); + return this; + } + + off(event, func, context) { + const listeners = this._events[event].slice(); + if (listeners) { + for (const listener of listeners) { + if (listener.fct === func && listener.context === context) { + listener.fct = doNothing; + delete listener.context; + } + } + } + return this; + } + + fire(event, data) { + const listeners = this._events[event].slice(); + if (listeners) { + for (const listener of listeners) { + const fct = listener.fct; + listener.fct = doNothing; + try { + fct.call(listener.context, data); + } catch (e) { + console.error(e); + } + listener.fct = fct; + } + } + return this; + } +} diff --git a/src/code/model/operation.js b/src/code/model/operation.js index 937839a38..fa3a428d8 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -3,6 +3,7 @@ import WasabeePortal from "./portal"; import WasabeeMarker from "./marker"; import WasabeeMe from "./me"; import WasabeeZone from "./zone"; +import Evented from "./evented"; import { generateId, newColors } from "../auxiliar"; import { GetWasabeeServer } from "../server"; import { getSelectedOperation } from "../selectedOp"; @@ -10,8 +11,9 @@ import db from "../db"; import { constants } from "../static"; -export default class WasabeeOp { +export default class WasabeeOp extends Evented { constructor(obj) { + super(); if (typeof obj == "string") { try { obj = JSON.parse(obj); @@ -347,7 +349,7 @@ export default class WasabeeOp { this.cleanAnchorList(); this.cleanPortalList(); this.update(true); - this.runCrosslinks(); + this.updateBlockers(); } removeMarker(marker) { @@ -356,7 +358,7 @@ export default class WasabeeOp { }); this.cleanPortalList(); this.update(true); - this.runCrosslinks(); + this.updateBlockers(); } setMarkerComment(marker, comment) { @@ -451,7 +453,7 @@ export default class WasabeeOp { this.cleanAnchorList(); this.cleanPortalList(); this.update(true); - this.runCrosslinks(); + this.updateBlockers(); } reverseLink(startPortalID, endPortalID) { @@ -673,10 +675,10 @@ export default class WasabeeOp { if (!existingLink) { this.links.push(link); this.update(true); - this.runCrosslinks(); + this.updateBlockers(); } else if (options.replace) { this.update(true); - this.runCrosslinks(); + this.updateBlockers(); } else { console.debug( "Link Already Exists In Operation -> " + JSON.stringify(link) @@ -786,7 +788,7 @@ export default class WasabeeOp { this._addPortal(newPortal); this._swapPortal(originalPortal, newPortal); this.update(true); - this.runCrosslinks(); + this.updateBlockers(); } addMarker(markerType, portal, options) { @@ -820,7 +822,7 @@ export default class WasabeeOp { this.update(true); // run crosslink to update the layer // XXX: we don't need to check, only redraw, so we need something clever, probably in mapDraw or crosslink.js - if (destructMarkerTypes.includes(markerType)) this.runCrosslinks(); + if (destructMarkerTypes.includes(markerType)) this.updateBlockers(); return true; } @@ -877,12 +879,12 @@ export default class WasabeeOp { } this.store(); // no await, let it happen in the background unless we see races - window.map.fire("wasabee:op:change"); + this.fire("update"); } - runCrosslinks() { + updateBlockers() { if (this._batchmode === true) return; - window.map.fire("wasabee:crosslinks"); + this.fire("blockers"); } startBatchMode() { @@ -892,7 +894,7 @@ export default class WasabeeOp { endBatchMode() { this._batchmode = false; this.update(true); - this.runCrosslinks(); + this.updateBlockers(); } convertLinksToObjs(links) { diff --git a/src/code/selectedOp.js b/src/code/selectedOp.js index 0910c1ba7..ba891b706 100644 --- a/src/code/selectedOp.js +++ b/src/code/selectedOp.js @@ -80,7 +80,13 @@ export async function makeSelectedOperation(opID) { if (op == null) { console.log("makeSelectedOperation called on invalid opID"); alert("attempted to load invalid opID"); + return; } + + // remove old listeners ? old object should never .store + op.on("update", () => window.map.fire("wasabee:op:change")); + op.on("blockers", () => window.map.fire("wasabee:crosslinks")); + // the only place we should change the selected op. delete window.plugin.wasabee._selectedOp; window.plugin.wasabee._selectedOp = op; From 7a91c18eb249b82560b419875d32f0aeb2a6173f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 16:12:13 +0200 Subject: [PATCH 012/275] move marker types to marker model --- src/code/crosslinks.js | 9 ++++---- src/code/dialogs/keysList.js | 5 ++--- src/code/dialogs/markerAddDialog.js | 5 +++-- src/code/dialogs/markerChangeDialog.js | 5 +++-- src/code/dialogs/trawl.js | 5 +++-- src/code/model/marker.js | 27 ++++++++++++++++++++++++ src/code/model/operation.js | 8 +++---- src/code/static.js | 29 -------------------------- src/code/uiCommands.js | 11 +++++----- 9 files changed, 51 insertions(+), 53 deletions(-) diff --git a/src/code/crosslinks.js b/src/code/crosslinks.js index e84ecf5b4..c7818825f 100644 --- a/src/code/crosslinks.js +++ b/src/code/crosslinks.js @@ -1,11 +1,10 @@ import WasabeePortal from "./model/portal"; import WasabeeLink from "./model/link"; +import WasabeeMarker from "./model/marker"; import { getSelectedOperation } from "./selectedOp"; import PortalUI from "./ui/portal"; -const Wasabee = window.plugin.wasabee; - // from iitc rework : https://github.com/IITC-CE/ingress-intel-total-conversion/pull/333 const d2r = Math.PI / 180; @@ -141,9 +140,9 @@ function testPolyLine(wasabeeLink, realLink, operation) { for (const marker of operation.markers) { if ( - marker.type == Wasabee.static.constants.MARKER_TYPE_DESTROY || - marker.type == Wasabee.static.constants.MARKER_TYPE_VIRUS || - marker.type == Wasabee.static.constants.MARKER_TYPE_DECAY + marker.type == WasabeeMarker.constants.MARKER_TYPE_DESTROY || + marker.type == WasabeeMarker.constants.MARKER_TYPE_VIRUS || + marker.type == WasabeeMarker.constants.MARKER_TYPE_DECAY ) { if ( marker.portalId == realLink.options.data.dGuid || diff --git a/src/code/dialogs/keysList.js b/src/code/dialogs/keysList.js index cff6729a1..1445192e2 100644 --- a/src/code/dialogs/keysList.js +++ b/src/code/dialogs/keysList.js @@ -2,6 +2,7 @@ import { WDialog } from "../leafletClasses"; import Sortable from "../sortable"; import { opKeyPromise } from "../server"; import WasabeeMe from "../model/me"; +import WasabeeMarker from "../model/marker"; import KeyListPortal from "./keyListPortal"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; @@ -186,9 +187,7 @@ const KeysList = WDialog.extend({ } for (const p of operation.markers.filter(function (marker) { - return ( - marker.type == window.plugin.wasabee.static.constants.MARKER_TYPE_KEY - ); + return marker.type == WasabeeMarker.constants.MARKER_TYPE_KEY; })) { const k = {}; k.id = p.portalId; diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index c775b3aff..7c3841e57 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -1,6 +1,7 @@ import { WDialog } from "../leafletClasses"; import WasabeeMe from "../model/me"; import WasabeeTeam from "../model/team"; +import WasabeeMarker from "../model/marker"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; @@ -74,7 +75,7 @@ const MarkerAddDialog = WDialog.extend({ } defaultType = markers.has(defaultType) ? null : defaultType; - for (const k of window.plugin.wasabee.static.markerTypes) { + for (const k of WasabeeMarker.markerTypes) { const o = L.DomUtil.create("option", null, this._type); o.value = k; o.textContent = wX(k); @@ -114,7 +115,7 @@ const MarkerAddDialog = WDialog.extend({ L.DomEvent.on(addMarkerButton, "click", (ev) => { L.DomEvent.stop(ev); - if (window.plugin.wasabee.static.markerTypes.has(this._type.value)) + if (WasabeeMarker.markerTypes.has(this._type.value)) this._addMarker( this._type.value, this._comment.value, diff --git a/src/code/dialogs/markerChangeDialog.js b/src/code/dialogs/markerChangeDialog.js index c5257aacc..4f24c7062 100644 --- a/src/code/dialogs/markerChangeDialog.js +++ b/src/code/dialogs/markerChangeDialog.js @@ -1,6 +1,7 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; +import WasabeeMarker from "../model/marker"; import PortalUI from "../ui/portal"; @@ -34,7 +35,7 @@ const MarkerChangeDialog = WDialog.extend({ this._type = L.DomUtil.create("select", null, content); const markers = operation.getPortalMarkers(portal); - for (const k of window.plugin.wasabee.static.markerTypes) { + for (const k of WasabeeMarker.markerTypes) { const o = L.DomUtil.create("option", null, this._type); o.value = k; o.textContent = wX(k); @@ -45,7 +46,7 @@ const MarkerChangeDialog = WDialog.extend({ const buttons = {}; buttons[wX("OK")] = () => { if ( - window.plugin.wasabee.static.markerTypes.has(this._type.value) && + WasabeeMarker.markerTypes.has(this._type.value) && !markers.has(this._type.value) ) { operation.removeMarker(this.options.marker); diff --git a/src/code/dialogs/trawl.js b/src/code/dialogs/trawl.js index 569ca5939..35a83ac32 100644 --- a/src/code/dialogs/trawl.js +++ b/src/code/dialogs/trawl.js @@ -3,6 +3,7 @@ import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; import { blockerAutomark } from "../uiCommands"; import VLatLon from "geodesy/latlon-ellipsoidal-vincenty"; +import WasabeeMarker from "../model/marker"; const TrawlerDialog = WDialog.extend({ statics: { @@ -315,8 +316,8 @@ const TrawlDialog = WDialog.extend({ operation.startBatchMode(); for (const m of operation.markers) { if ( - m.type == window.plugin.wasabee.static.constants.MARKER_TYPE_DESTROY || - m.type == window.plugin.wasabee.static.constants.MARKER_TYPE_VIRUS + m.type == WasabeeMarker.constants.MARKER_TYPE_DESTROY || + m.type == WasabeeMarker.constants.MARKER_TYPE_VIRUS ) operation.removeMarker(m); } diff --git a/src/code/model/marker.js b/src/code/model/marker.js index 258e62183..0618026f3 100644 --- a/src/code/model/marker.js +++ b/src/code/model/marker.js @@ -1,11 +1,38 @@ import { generateId } from "../auxiliar"; +const markers = { + MARKER_TYPE_CAPTURE: "CapturePortalMarker", + MARKER_TYPE_DECAY: "LetDecayPortalAlert", + MARKER_TYPE_EXCLUDE: "ExcludeMarker", + MARKER_TYPE_DESTROY: "DestroyPortalAlert", + MARKER_TYPE_FARM: "FarmPortalMarker", + MARKER_TYPE_GOTO: "GotoPortalMarker", + MARKER_TYPE_KEY: "GetKeyPortalMarker", + MARKER_TYPE_LINK: "CreateLinkAlert", + MARKER_TYPE_MEETAGENT: "MeetAgentPortalMarker", + MARKER_TYPE_OTHER: "OtherPortalAlert", + MARKER_TYPE_RECHARGE: "RechargePortalAlert", + MARKER_TYPE_UPGRADE: "UpgradePortalAlert", + MARKER_TYPE_VIRUS: "UseVirusPortalAlert", +}; + +const markerTypes = new Set(Object.values(markers)); + const STATE_UNASSIGNED = "pending"; const STATE_ASSIGNED = "assigned"; const STATE_ACKNOWLEDGED = "acknowledged"; const STATE_COMPLETED = "completed"; export default class WasabeeMarker { + // static properties is not supported by eslint yet + static get markerTypes() { + return markerTypes; + } + + static get constants() { + return markers; + } + constructor(obj) { this.ID = obj.ID ? obj.ID : generateId(); this.portalId = obj.portalId; diff --git a/src/code/model/operation.js b/src/code/model/operation.js index fa3a428d8..23bfe507b 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -9,8 +9,6 @@ import { GetWasabeeServer } from "../server"; import { getSelectedOperation } from "../selectedOp"; import db from "../db"; -import { constants } from "../static"; - export default class WasabeeOp extends Evented { constructor(obj) { super(); @@ -808,9 +806,9 @@ export default class WasabeeOp extends Evented { // only need this for virus/destroy/decay -- this should be in the marker class const destructMarkerTypes = [ - constants.MARKER_TYPE_DECAY, - constants.MARKER_TYPE_DESTROY, - constants.MARKER_TYPE_VIRUS, + WasabeeMarker.constants.MARKER_TYPE_DECAY, + WasabeeMarker.constants.MARKER_TYPE_DESTROY, + WasabeeMarker.constants.MARKER_TYPE_VIRUS, ]; if (destructMarkerTypes.includes(markerType)) { // remove related blockers diff --git a/src/code/static.js b/src/code/static.js index 729b77c66..db3405d73 100644 --- a/src/code/static.js +++ b/src/code/static.js @@ -67,19 +67,6 @@ W.static = { SERVER_BASE_KEY: "wasabee-server", SERVER_BASE_DEFAULT: "https://am.wasabee.rocks", REBASE_UPDATE_KEY: "wasabee-rebase-on-update", - MARKER_TYPE_CAPTURE: "CapturePortalMarker", - MARKER_TYPE_DECAY: "LetDecayPortalAlert", - MARKER_TYPE_EXCLUDE: "ExcludeMarker", - MARKER_TYPE_DESTROY: "DestroyPortalAlert", - MARKER_TYPE_FARM: "FarmPortalMarker", - MARKER_TYPE_GOTO: "GotoPortalMarker", - MARKER_TYPE_KEY: "GetKeyPortalMarker", - MARKER_TYPE_LINK: "CreateLinkAlert", - MARKER_TYPE_MEETAGENT: "MeetAgentPortalMarker", - MARKER_TYPE_OTHER: "OtherPortalAlert", - MARKER_TYPE_RECHARGE: "RechargePortalAlert", - MARKER_TYPE_UPGRADE: "UpgradePortalAlert", - MARKER_TYPE_VIRUS: "UseVirusPortalAlert", DEFAULT_MARKER_TYPE: "DestroyPortalAlert", QUICKDRAW_GUIDE_STYLE: { color: "#0f0", @@ -105,22 +92,6 @@ W.static.strings.Italiano = require("./translations/italian.json"); W.static.strings.Tagalog = require("./translations/filipino.json"); W.static.strings.French = require("./translations/french.json"); -W.static.markerTypes = new Set([ - W.static.constants.MARKER_TYPE_CAPTURE, - W.static.constants.MARKER_TYPE_DECAY, - W.static.constants.MARKER_TYPE_DESTROY, - W.static.constants.MARKER_TYPE_FARM, - W.static.constants.MARKER_TYPE_GOTO, - W.static.constants.MARKER_TYPE_KEY, - W.static.constants.MARKER_TYPE_LINK, - W.static.constants.MARKER_TYPE_MEETAGENT, - W.static.constants.MARKER_TYPE_OTHER, - W.static.constants.MARKER_TYPE_RECHARGE, - W.static.constants.MARKER_TYPE_UPGRADE, - W.static.constants.MARKER_TYPE_VIRUS, - W.static.constants.MARKER_TYPE_EXCLUDE, -]); - W.static.defaultOperationColor = "orange"; W.static.linkStyle = { diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index 4cc081ce9..6cd4c0cc8 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -1,5 +1,6 @@ import WasabeeOp from "./model/operation"; import WasabeePortal from "./model/portal"; +import WasabeeMarker from "./model/marker"; import ConfirmDialog from "./dialogs/confirmDialog"; import MergeDialog from "./dialogs/mergeDialog"; import WasabeeMe from "./model/me"; @@ -238,7 +239,7 @@ export function getAllPortalsOnScreen(operation) { if ( operation.containsMarkerByID( window.portals[portal].options.guid, - window.plugin.wasabee.static.constants.MARKER_TYPE_EXCLUDE + WasabeeMarker.constants.MARKER_TYPE_EXCLUDE ) ) continue; @@ -324,14 +325,14 @@ export function blockerAutomark(operation, first = true) { if ( !operation.containsMarkerByID( b.fromPortalId, - window.plugin.wasabee.static.constants.MARKER_TYPE_EXCLUDE + WasabeeMarker.constants.MARKER_TYPE_EXCLUDE ) ) portals.push(b.fromPortalId); if ( !operation.containsMarkerByID( b.toPortalId, - window.plugin.wasabee.static.constants.MARKER_TYPE_EXCLUDE + WasabeeMarker.constants.MARKER_TYPE_EXCLUDE ) ) portals.push(b.toPortalId); @@ -364,9 +365,9 @@ export function blockerAutomark(operation, first = true) { // console.log(wportal); // add marker - let type = window.plugin.wasabee.static.constants.MARKER_TYPE_DESTROY; + let type = WasabeeMarker.constants.MARKER_TYPE_DESTROY; if (wportal.team == "E") { - type = window.plugin.wasabee.static.constants.MARKER_TYPE_VIRUS; + type = WasabeeMarker.constants.MARKER_TYPE_VIRUS; } const zone = operation.determineZone(wportal.latLng); operation.addMarker(type, wportal, { comment: "auto-marked", zone: zone }); From 0fa813b91cdacce3d00f59acb1b2d4ce1d2ceb4f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 26 Jun 2021 23:56:41 +0200 Subject: [PATCH 013/275] move map object to ui class --- src/code/mapDrawing.js | 174 +---------------------- src/code/ui/agent.js | 223 +++++++++++++++++++----------- src/code/ui/anchor.js | 214 ++++++++++++---------------- src/code/ui/marker.js | 306 ++++++++++++++++++----------------------- src/code/ui/portal.js | 163 ++++++++++++++++++++-- 5 files changed, 524 insertions(+), 556 deletions(-) diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index a47fa49f5..b6694beed 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -1,9 +1,7 @@ import WasabeeMe from "./model/me"; -import WasabeeAnchor from "./model/anchor"; import WasabeeTeam from "./model/team"; import WasabeeAgent from "./model/agent"; import WasabeeOp from "./model/operation"; -import { newColors } from "./auxiliar"; import { getSelectedOperation, opsList } from "./selectedOp"; import LinkUI from "./ui/link"; @@ -41,14 +39,11 @@ function updateMarkers(op) { for (const m of op.markers) { if (layerMap.has(m.ID)) { const ll = Wasabee.markerLayerGroup.getLayer(layerMap.get(m.ID)); - if (m.state != ll.options.state) { - L.DomUtil.removeClass(ll._icon, `wasabee-status-${ll.options.state}`); - L.DomUtil.addClass(ll._icon, `wasabee-status-${m.state}`); - ll.options.state = m.state; - } + ll.setState(m.state); layerMap.delete(m.ID); } else { - addMarker(m, op); + const lMarker = new MarkerUI.WLMarker(m, op); + lMarker.addTo(Wasabee.markerLayerGroup); } } @@ -59,49 +54,6 @@ function updateMarkers(op) { } } -// adds a new marker -function addMarker(target, operation) { - const targetPortal = operation.getPortal(target.portalId); - const marker = L.marker(targetPortal.latLng, { - title: targetPortal.name, - id: target.ID, - state: target.state, - icon: L.divIcon({ - className: `wasabee-marker-icon ${target.type} wasabee-status-${target.state}`, - shadowUrl: null, - iconSize: L.point(24, 40), - iconAnchor: L.point(12, 40), - popupAnchor: L.point(-1, -48), - }), - }); - - // register the marker for spiderfied click - window.registerMarkerForOMS(marker); - marker.bindPopup("loading...", { - className: "wasabee-popup", - closeButton: false, - }); - // marker.off("click", marker.openPopup, marker); - marker.on( - "click spiderfiedclick", - async function (ev) { - /* eslint-disable no-invalid-this */ - L.DomEvent.stop(ev); - if (this.isPopupOpen()) return; - const sop = getSelectedOperation(); - const target = sop.getMarker(this.options.id); - const c = await MarkerUI.popupContent(target, this); - this.setPopupContent(c); - this._popup._wrapper.classList.add("wasabee-popup"); - this.update(); - this.openPopup(); - /* eslint-enable no-invalid-this */ - }, - marker - ); - marker.addTo(Wasabee.markerLayerGroup); -} - // resetting is consistently 1ms faster than trying to update function resetLinks(operation) { if (window.isLayerGroupDisplayed("Wasabee Draw Links") === false) return; // yes, === false, undefined == true @@ -291,42 +243,9 @@ function _drawAgent(agent, layerMap = agentLayerMap()) { return false; } - const zoom = window.map.getZoom(); if (!layerMap.has(agent.id)) { // new, add to map - const marker = L.marker(agent.latLng, { - title: agent.name, - icon: L.divIcon({ - className: "wasabee-agent-icon", - iconSize: AgentUI.iconSize(zoom), - iconAnchor: AgentUI.iconAnchor(zoom), - popupAnchor: L.point(0, -70), - html: AgentUI.icon(agent, zoom), - }), - id: agent.id, - zoom: zoom, - }); - - window.registerMarkerForOMS(marker); - marker.bindPopup("Loading...", { - className: "wasabee-popup", - closeButton: false, - }); - // marker.off("click", agent.openPopup, agent); - marker.on( - "click spiderfiedclick", - async (ev) => { - L.DomEvent.stop(ev); - if (marker.isPopupOpen && marker.isPopupOpen()) return; - const a = await WasabeeAgent.get(agent.id); - marker.setPopupContent(await AgentUI.getPopup(a)); - if (marker._popup._wrapper) - marker._popup._wrapper.classList.add("wasabee-popup"); - marker.update(); - marker.openPopup(); - }, - marker - ); + const marker = new AgentUI.WLAgent(agent); marker.addTo(Wasabee.agentLayerGroup); } else { // move existing icons, if they actually moved @@ -337,23 +256,6 @@ function _drawAgent(agent, layerMap = agentLayerMap()) { if (agent.lat != ll.lat || agent.lng != ll.lng) { // console.debug("moving ", agent.name, agent.latLng, al.getLatLng()); al.setLatLng(agent.latLng); - al.update(); - } - - // if the zoom factor changed, refresh the icon - if (zoom != al.options.zoom) { - // console.debug("changing icon zoom: ", zoom, al.options.zoom); - al.setIcon( - L.divIcon({ - className: "wasabee-agent-icon", - iconSize: AgentUI.iconSize(zoom), - iconAnchor: AgentUI.iconAnchor(zoom), - popupAnchor: L.point(0, -70), - html: AgentUI.icon(agent, zoom), - }) - ); - al.options.zoom = zoom; - al.update(); } } return true; @@ -381,7 +283,8 @@ function updateAnchors(op) { if (layerMap.has(a)) { layerMap.delete(a); } else { - addAnchorToMap(a, op); + const lAnchor = new AnchorUI.WLAnchor(a, op); + lAnchor.addTo(Wasabee.portalLayerGroup); } } @@ -389,68 +292,3 @@ function updateAnchors(op) { Wasabee.portalLayerGroup.removeLayer(v); } } - -// adds a single anchor to the map -function addAnchorToMap(portalId, operation) { - const anchor = new WasabeeAnchor(portalId, operation); - // use newColors(anchor.color) for 0.19 - let layer = anchor.color; - if (newColors(layer) == layer) layer = "custom"; - let marker; - if (layer != "custom") { - marker = L.marker(anchor.latLng, { - title: anchor.name, - alt: anchor.name, - id: portalId, - color: anchor.color, - icon: L.divIcon({ - className: `wasabee-anchor-icon wasabee-layer-${layer}`, - shadowUrl: null, - iconAnchor: [12, 41], - iconSize: [25, 41], - popupAnchor: [0, -35], - }), - }); - } else { - const svg = L.Util.template( - '', - { color: anchor.color } - ); - marker = L.marker(anchor.latLng, { - title: anchor.name, - alt: anchor.name, - id: portalId, - color: anchor.color, - icon: L.divIcon({ - className: "wasabee-anchor-icon", - shadowUrl: null, - iconAnchor: [12, 41], - iconSize: [25, 41], - popupAnchor: [0, -35], - html: svg, - }), - }); - } - - window.registerMarkerForOMS(marker); - marker.bindPopup("loading...", { - className: "wasabee-popup", - closeButton: false, - }); - // marker.off("click", marker.openPopup, marker); - marker.on( - "click spiderfiedclick", - (ev) => { - L.DomEvent.stop(ev); - if (marker.isPopupOpen && marker.isPopupOpen()) return; - const content = AnchorUI.popupContent(anchor, marker); - marker.setPopupContent(content); - if (marker._popup._wrapper) - marker._popup._wrapper.classList.add("wasabee-popup"); - marker.update(); - marker.openPopup(); - }, - marker - ); - marker.addTo(Wasabee.portalLayerGroup); -} diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index 6d107c31d..8269bdd9d 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -5,13 +5,7 @@ import { targetPromise, routePromise } from "../server"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; -export default { - formatDisplay, - getPopup, - icon, - iconSize, - iconAnchor, -}; +import WasabeeAgent from "../model/agent"; async function formatDisplay(agent, teamID = 0) { const display = L.DomUtil.create("a", "wasabee-agent-label"); @@ -30,83 +24,6 @@ async function formatDisplay(agent, teamID = 0) { return display; } -async function getPopup(agent) { - const content = L.DomUtil.create("div", "wasabee-agent-popup"); - const title = L.DomUtil.create("div", "desc", content); - title.id = agent.id; - const fd = await formatDisplay(agent, 0); - title.innerHTML = fd.outerHTML + timeSinceformat(agent); - - const sendTarget = L.DomUtil.create("button", null, content); - sendTarget.textContent = wX("SEND TARGET"); - L.DomEvent.on(sendTarget, "click", (ev) => { - L.DomEvent.stop(ev); - const selectedPortal = PortalUI.getSelected(); - if (!selectedPortal) { - alert(wX("SELECT PORTAL")); - return; - } - - const d = new ConfirmDialog({ - title: wX("SEND TARGET"), - label: wX("SEND TARGET CONFIRM", { - portalName: PortalUI.displayName(selectedPortal), - agent: agent.name, - }), - type: "agent", - callback: async () => { - try { - await targetPromise(agent.id, selectedPortal); - alert(wX("TARGET SENT")); - } catch (e) { - console.error(e); - } - }, - }); - d.enable(); - }); - - // this needs wX - const requestRoute = L.DomUtil.create("button", null, content); - requestRoute.textContent = "Send Route to Target"; - requestRoute.style.display = "none"; // hide this until the server-side is ready - L.DomEvent.on(requestRoute, "click", (ev) => { - L.DomEvent.stop(ev); - const selectedPortal = PortalUI.getSelected(); - if (!selectedPortal) { - alert(wX("SELECT PORTAL")); - return; - } - - const d = new ConfirmDialog({ - title: "Send Route to Target", - label: "Do you really want to request the route to be sent?", - type: "agent", - callback: async () => { - try { - await routePromise(agent.id, selectedPortal); - alert("Route Sent"); - } catch (e) { - console.error(e); - } - }, - }); - d.enable(); - }); - - const op = getSelectedOperation(); - const assignments = L.DomUtil.create("ul", "assignments", content); - for (const m of op.markers) { - if (m.assignedTo != agent.id) continue; - const a = L.DomUtil.create("li", "assignment", assignments); - const portal = op.getPortal(m.portalId); - a.textContent = `${m.order}: ${wX(m.type)} `; - a.appendChild(PortalUI.displayFormat(portal)); - } - - return content; -} - function timeSinceformat(agent) { if (!agent.date) return ""; const date = Date.parse(agent.date + " UTC"); @@ -197,3 +114,141 @@ function bigIcon(agent) { `; return icon; } + +const WLAgent = L.Marker.extend({ + initialize: function (agent) { + const zoom = window.map.getZoom(); + L.Marker.prototype.initialize.call(this, agent.latLng, { + title: agent.name, + icon: L.divIcon({ + className: "wasabee-agent-icon", + iconSize: iconSize(zoom), + iconAnchor: iconAnchor(zoom), + popupAnchor: L.point(0, -70), + html: icon(agent, zoom), + }), + id: agent.id, + agent: agent, + zoom: zoom, + }); + + window.registerMarkerForOMS(this); + this.bindPopup("Loading...", { + className: "wasabee-popup", + closeButton: false, + }); + // marker.off("click", agent.openPopup, agent); + this.on("click spiderfiedclick", this._onClick, this); + }, + + _onClick: async function (ev) { + L.DomEvent.stop(ev); + if (this.isPopupOpen && this.isPopupOpen()) return; + const a = await WasabeeAgent.get(this.options.id); + this.options.agent = a; + this.setPopupContent(await this._getPopup(a)); + if (this._popup._wrapper) + this._popup._wrapper.classList.add("wasabee-popup"); + this.update(); + this.openPopup(); + }, + + update: function () { + const zoom = window.map.getZoom(); + if (this.options.zoom != zoom) { + this.options.zoom = zoom; + this.setIcon( + L.divIcon({ + className: "wasabee-agent-icon", + iconSize: iconSize(zoom), + iconAnchor: iconAnchor(zoom), + popupAnchor: L.point(0, -70), + html: icon(this.options.agent, zoom), + }) + ); + } else L.Marker.prototype.update.call(this); + }, + + _getPopup: async function () { + const agent = this.options.agent; + const content = L.DomUtil.create("div", "wasabee-agent-popup"); + const title = L.DomUtil.create("div", "desc", content); + title.id = agent.id; + const fd = await formatDisplay(agent, 0); + title.innerHTML = fd.outerHTML + timeSinceformat(agent); + + const sendTarget = L.DomUtil.create("button", null, content); + sendTarget.textContent = wX("SEND TARGET"); + L.DomEvent.on(sendTarget, "click", (ev) => { + L.DomEvent.stop(ev); + const selectedPortal = PortalUI.getSelected(); + if (!selectedPortal) { + alert(wX("SELECT PORTAL")); + return; + } + + const d = new ConfirmDialog({ + title: wX("SEND TARGET"), + label: wX("SEND TARGET CONFIRM", { + portalName: PortalUI.displayName(selectedPortal), + agent: agent.name, + }), + type: "agent", + callback: async () => { + try { + await targetPromise(agent.id, selectedPortal); + alert(wX("TARGET SENT")); + } catch (e) { + console.error(e); + } + }, + }); + d.enable(); + }); + + // this needs wX + const requestRoute = L.DomUtil.create("button", null, content); + requestRoute.textContent = "Send Route to Target"; + requestRoute.style.display = "none"; // hide this until the server-side is ready + L.DomEvent.on(requestRoute, "click", (ev) => { + L.DomEvent.stop(ev); + const selectedPortal = PortalUI.getSelected(); + if (!selectedPortal) { + alert(wX("SELECT PORTAL")); + return; + } + + const d = new ConfirmDialog({ + title: "Send Route to Target", + label: "Do you really want to request the route to be sent?", + type: "agent", + callback: async () => { + try { + await routePromise(agent.id, selectedPortal); + alert("Route Sent"); + } catch (e) { + console.error(e); + } + }, + }); + d.enable(); + }); + + const op = getSelectedOperation(); + const assignments = L.DomUtil.create("ul", "assignments", content); + for (const m of op.markers) { + if (m.assignedTo != agent.id) continue; + const a = L.DomUtil.create("li", "assignment", assignments); + const portal = op.getPortal(m.portalId); + a.textContent = `${m.order}: ${wX(m.type)} `; + a.appendChild(PortalUI.displayFormat(portal)); + } + + return content; + }, +}); + +export default { + formatDisplay, + WLAgent, +}; diff --git a/src/code/ui/anchor.js b/src/code/ui/anchor.js index 52273f146..98b4ac41d 100644 --- a/src/code/ui/anchor.js +++ b/src/code/ui/anchor.js @@ -1,150 +1,110 @@ -import AssignDialog from "../dialogs/assignDialog"; -import SendTargetDialog from "../dialogs/sendTargetDialog"; -import SetCommentDialog from "../dialogs/setCommentDialog"; import LinkListDialog from "../dialogs/linkListDialog"; import { getSelectedOperation } from "../selectedOp"; import { swapPortal, deletePortal } from "../uiCommands"; +import { newColors } from "../auxiliar"; import wX from "../wX"; +import WasabeeAnchor from "../model/anchor"; + import PortalUI from "./portal"; -export default { - popupContent, -}; +const WLAnchor = PortalUI.WLPortal.extend({ + initialize: function (portalId, operation) { + const anchor = new WasabeeAnchor(portalId, operation); + // use newColors(anchor.color) for 0.19 + let layer = anchor.color; + if (newColors(layer) == layer) layer = "custom"; + const icon = L.divIcon({ + className: + layer != "custom" + ? `wasabee-anchor-icon wasabee-layer-${layer}` + : "wasabee-anchor-icon", + shadowUrl: null, + iconAnchor: [12, 41], + iconSize: [25, 41], + popupAnchor: [0, -35], + html: + layer != "custom" + ? null + : L.Util.template( + '', + { color: anchor.color } + ), + }); + PortalUI.WLPortal.prototype.initialize.call(this, { + portalId: portalId, + id: portalId, + color: anchor.color, + icon: icon, + }); + }, -function popupContent(anchor, leafletMarker) { - const operation = getSelectedOperation(); - const canWrite = operation.canWrite(); - const portal = operation.getPortal(anchor.ID); + _popupContent: function () { + const operation = getSelectedOperation(); + const canWrite = operation.canWrite(); + const portal = operation.getPortal(this.options.portalId); - leafletMarker.className = "wasabee-anchor-popup"; - const content = L.DomUtil.create("div", null); - const title = L.DomUtil.create("div", "desc", content); - title.appendChild(PortalUI.displayFormat(portal)); - const portalComment = L.DomUtil.create( - "div", - "wasabee-portal-comment", - content - ); - const pcLink = L.DomUtil.create("a", null, portalComment); - pcLink.textContent = portal.comment || wX("SET_PORTAL_COMMENT"); - if (canWrite) { - pcLink.href = "#"; - L.DomEvent.on(pcLink, "click", (ev) => { - L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: portal, - operation: operation, - }); - scd.enable(); - leafletMarker.closePopup(); - }); - } - if (portal.hardness) { - const portalHardness = L.DomUtil.create( + const content = PortalUI.WLPortal.prototype._popupContent.call(this); + const desc = L.DomUtil.create("div", "desc", content); + desc.appendChild(PortalUI.displayFormat(portal)); + this._popupPortalComments(desc, portal, canWrite); + + const requiredKeys = L.DomUtil.create("div", "desc", content); + const onHand = operation.KeysOnHandForPortal(portal.id); + const required = operation.KeysRequiredForPortal(portal.id); + requiredKeys.textContent = "Keys: " + onHand + " / " + required; + + const buttonSet = L.DomUtil.create( "div", - "wasabee-portal-hardness", + "wasabee-marker-buttonset", content ); - const phLink = L.DomUtil.create("a", null, portalHardness); - phLink.textContent = portal.hardness; + this._linksButton(buttonSet); if (canWrite) { - phLink.href = "#"; - L.DomEvent.on(phLink, "click", (ev) => { - L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: portal, - operation: operation, - }); - scd.enable(); - leafletMarker.closePopup(); - }); + this._swapButton(buttonSet); + this._deleteButton(buttonSet, wX("DELETE_ANCHOR")); } - } + this._mapButton(buttonSet, wX("ANCHOR_GMAP")); + if (operation.canWriteServer()) + this._assignButton(buttonSet, wX("ASSIGN OUTBOUND"), portal); + if (operation.isOnCurrentServer()) + this._sendTargetButton(buttonSet, wX("SEND TARGET"), portal); - const requiredKeys = L.DomUtil.create("div", "desc", content); - const onHand = operation.KeysOnHandForPortal(portal.id); - const required = operation.KeysRequiredForPortal(portal.id); - requiredKeys.textContent = "Keys: " + onHand + " / " + required; + return content; + }, - const buttonSet = L.DomUtil.create( - "div", - "wasabee-marker-buttonset", - content - ); - const linksButton = L.DomUtil.create("button", null, buttonSet); - linksButton.textContent = wX("LINKS"); - L.DomEvent.on(linksButton, "click", (ev) => { - L.DomEvent.stop(ev); - const lld = new LinkListDialog({ portal: portal }); - lld.enable(); - leafletMarker.closePopup(); - }); - if (canWrite) { - const swapButton = L.DomUtil.create("button", null, buttonSet); - swapButton.textContent = wX("SWAP"); - L.DomEvent.on(swapButton, "click", (ev) => { + _linksButton: function (container) { + const operation = getSelectedOperation(); + const portal = operation.getPortal(this.options.portalId); + const linksButton = L.DomUtil.create("button", null, container); + linksButton.textContent = wX("LINKS"); + L.DomEvent.on(linksButton, "click", (ev) => { L.DomEvent.stop(ev); - swapPortal(operation, portal); - leafletMarker.closePopup(); - }); - const deleteButton = L.DomUtil.create("button", null, buttonSet); - deleteButton.textContent = wX("DELETE_ANCHOR"); - L.DomEvent.on(deleteButton, "click", (ev) => { - L.DomEvent.stop(ev); - deletePortal(operation, portal); - leafletMarker.closePopup(); + const lld = new LinkListDialog({ portal: portal }); + lld.enable(); + this.closePopup(); }); - } - const gmapButton = L.DomUtil.create("button", null, buttonSet); - gmapButton.textContent = wX("ANCHOR_GMAP"); - L.DomEvent.on(gmapButton, "click", (ev) => { - L.DomEvent.stop(ev); - leafletMarker.closePopup(); - // use intent on android - if ( - typeof window.android !== "undefined" && - window.android && - window.android.intentPosLink - ) { - window.android.intentPosLink( - +portal.lat, - +portal.lng, - window.map.getZoom(), - portal.name, - true - ); - } else { - window.open( - "https://www.google.com/maps/search/?api=1&query=" + - portal.lat + - "," + - portal.lng - ); - } - }); + }, - if (operation.canWriteServer()) { - const assignButton = L.DomUtil.create("button", null, buttonSet); - assignButton.textContent = wX("ASSIGN OUTBOUND"); - L.DomEvent.on(assignButton, "click", (ev) => { + _swapButton: function (container) { + const operation = getSelectedOperation(); + const portal = operation.getPortal(this.options.portalId); + const swapButton = L.DomUtil.create("button", null, container); + swapButton.textContent = wX("SWAP"); + L.DomEvent.on(swapButton, "click", (ev) => { L.DomEvent.stop(ev); - const ad = new AssignDialog({ target: portal }); - ad.enable(); - leafletMarker.closePopup(); + swapPortal(operation, portal); + this.closePopup(); }); - } + }, - if (operation.isOnCurrentServer()) { - const sendButton = L.DomUtil.create("button", null, buttonSet); - sendButton.textContent = wX("SEND TARGET"); - L.DomEvent.on(sendButton, "click", (ev) => { - L.DomEvent.stop(ev); - const std = new SendTargetDialog({ target: portal }); - std.enable(); - leafletMarker.closePopup(); - }); - } + _deleteAction: function () { + const operation = getSelectedOperation(); + const portal = operation.getPortal(this.options.portalId); + deletePortal(operation, portal); + }, +}); - return content; -} +export default { + WLAnchor, +}; diff --git a/src/code/ui/marker.js b/src/code/ui/marker.js index 0eabf58da..ea41a8e95 100644 --- a/src/code/ui/marker.js +++ b/src/code/ui/marker.js @@ -1,7 +1,5 @@ import WasabeeAgent from "../model/agent"; -import AssignDialog from "../dialogs/assignDialog"; -import SendTargetDialog from "../dialogs/sendTargetDialog"; import SetCommentDialog from "../dialogs/setCommentDialog"; import MarkerChangeDialog from "../dialogs/markerChangeDialog"; import StateDialog from "../dialogs/stateDialog"; @@ -13,189 +11,159 @@ import PortalUI from "./portal"; import wX from "../wX"; -export default { - popupContent, -}; +const WLMarker = PortalUI.WLPortal.extend({ + initialize: function (marker) { + PortalUI.WLPortal.prototype.initialize.call(this, { + portalId: marker.portalId, + id: marker.ID, + state: marker.state, + icon: L.divIcon({ + className: `wasabee-marker-icon ${marker.type} wasabee-status-${marker.state}`, + shadowUrl: null, + iconSize: L.point(24, 40), + iconAnchor: L.point(12, 40), + popupAnchor: L.point(-1, -48), + }), + }); + }, -async function popupContent(marker, leafletMarker, operation) { - if (!operation) operation = getSelectedOperation(); - const canWrite = operation.canWrite(); - - const portal = operation.getPortal(marker.portalId); - if (portal == null) { - console.log("null portal getting marker popup"); - return (L.DomUtil.create("div", "wasabee-marker-popup").textContent = - "invalid portal"); - } - - const content = L.DomUtil.create("div", "wasabee-marker-popup"); - content.appendChild( - getPopupBodyWithType(marker, portal, operation, leafletMarker) - ); - - const assignment = L.DomUtil.create( - "div", - "wasabee-popup-assignment", - content - ); - if (marker.state != "completed" && marker.assignedTo) { - try { - const a = await WasabeeAgent.get(marker.assignedTo); - assignment.textContent = wX("ASS_TO"); // FIXME convert formatDisplay to html and add as value to wX - if (a) assignment.appendChild(await AgentUI.formatDisplay(a)); - else assignment.textContent += " " + marker.assignedTo; - } catch (err) { - console.error(err); + setState: function (state) { + if (state != this.options.state) { + L.DomUtil.removeClass(this._icon, `wasabee-status-${this.options.state}`); + L.DomUtil.addClass(this._icon, `wasabee-status-${state}`); + this.options.state = state; } - } - if (marker.state == "completed" && marker.completedID) { - try { - const a = await WasabeeAgent.get(marker.completedID); - assignment.innerHTML = wX("COMPLETED BY", { - agentName: a ? a.name : marker.completedID, - }); - } catch (e) { - console.error(e); + }, + + _popupContent: function () { + const operation = getSelectedOperation(); + const marker = operation.getMarker(this.options.id); + const portal = operation.getPortal(marker.portalId); + + if (portal == null) { + console.log("null portal getting marker popup"); + return (L.DomUtil.create("div", "wasabee-marker-popup").textContent = + "invalid portal"); } - } - - const buttonSet = L.DomUtil.create( - "div", - "wasabee-marker-buttonset", - content - ); - if (canWrite) { - const deleteButton = L.DomUtil.create("button", null, buttonSet); - deleteButton.textContent = wX("DELETE_ANCHOR"); - L.DomEvent.on(deleteButton, "click", (ev) => { - L.DomEvent.stop(ev); - deleteMarker(operation, marker, portal); - leafletMarker.closePopup(); - }); - } - if (operation.canWriteServer()) { - const assignButton = L.DomUtil.create("button", null, buttonSet); - assignButton.textContent = wX("ASSIGN"); - L.DomEvent.on(assignButton, "click", (ev) => { - L.DomEvent.stop(ev); - const ad = new AssignDialog({ target: marker }); - ad.enable(); - leafletMarker.closePopup(); - }); - } - if (canWrite) { - const stateButton = L.DomUtil.create("button", null, buttonSet); - stateButton.textContent = wX("MARKER STATE"); - L.DomEvent.on(stateButton, "click", (ev) => { - L.DomEvent.stop(ev); - const sd = new StateDialog({ target: marker, opID: operation.ID }); - sd.enable(); - leafletMarker.closePopup(); - }); - } + const canWrite = operation.canWrite(); - if (operation.isOnCurrentServer()) { - const sendTargetButton = L.DomUtil.create("button", null, buttonSet); - sendTargetButton.textContent = wX("SEND TARGET"); - L.DomEvent.on(sendTargetButton, "click", (ev) => { - L.DomEvent.stop(ev); - const std = new SendTargetDialog({ target: marker }); - std.enable(); - leafletMarker.closePopup(); - }); - } + const content = PortalUI.WLPortal.prototype._popupContent.call(this); - const gmapButton = L.DomUtil.create("button", null, buttonSet); - gmapButton.textContent = wX("ANCHOR_GMAP"); - L.DomEvent.on(gmapButton, "click", (ev) => { - L.DomEvent.stop(ev); - leafletMarker.closePopup(); - // use intent on android - if ( - typeof window.android !== "undefined" && - window.android && - window.android.intentPosLink - ) { - window.android.intentPosLink( - +portal.lat, - +portal.lng, - window.map.getZoom(), - portal.name, - true - ); - } else { - window.open( - "https://www.google.com/maps/search/?api=1&query=" + - portal.lat + - "," + - portal.lng - ); + const desc = L.DomUtil.create("div", "desc", content); + const kind = L.DomUtil.create( + "span", + `wasabee-marker-popup-kind ${marker.type}`, + desc + ); + kind.textContent = wX(marker.type); + desc.appendChild(PortalUI.displayFormat(portal)); + if (canWrite) { + kind.href = "#"; + L.DomEvent.on(kind, "click", this._setMarkerType, this); } - }); + this._popupMarkerComment(desc, marker, canWrite); + this._popupPortalComments(desc, portal, canWrite); - return content; -} + this._popupAssignState(content, marker); -function getPopupBodyWithType(marker, portal, operation, leafletMarker) { - const title = L.DomUtil.create("div", "desc"); - const kind = L.DomUtil.create("span", "wasabee-marker-popup-kind", title); - L.DomUtil.addClass(kind, marker.type); - kind.textContent = wX(marker.type); - title.appendChild(PortalUI.displayFormat(portal)); - - kind.href = "#"; - L.DomEvent.on(kind, "click", (ev) => { - L.DomEvent.stop(ev); - const ch = new MarkerChangeDialog({ marker: marker }); - ch.enable(); - leafletMarker.closePopup(); - }); + const buttonSet = L.DomUtil.create( + "div", + "wasabee-marker-buttonset", + content + ); + if (canWrite) this._deleteButton(buttonSet, wX("DELETE_ANCHOR")); + if (operation.canWriteServer()) + this._assignButton(buttonSet, wX("ASSIGN"), marker); + if (canWrite) this._stateButton(buttonSet, marker); + if (operation.isOnCurrentServer()) + this._sendTargetButton(buttonSet, wX("SEND TARGET"), marker); + this._mapButton(buttonSet, wX("ANCHOR_GMAP")); + + return content; + }, + + _popupMarkerComment: function (container, marker, canWrite) { + if (marker.comment) { + const comment = L.DomUtil.create( + "div", + "wasabee-marker-popup-comment", + container + ); + comment.textContent = marker.comment; + if (canWrite) L.DomEvent.on(comment, "click", this._setComment, this); + } + }, - if (marker.comment) { - const comment = L.DomUtil.create( + _popupAssignState: async function (container, marker) { + const assignment = L.DomUtil.create( "div", - "wasabee-marker-popup-comment", - title + "wasabee-popup-assignment", + container ); - comment.textContent = marker.comment; - L.DomEvent.on(comment, "click", (ev) => { + if (marker.state != "completed" && marker.assignedTo) { + try { + const a = await WasabeeAgent.get(marker.assignedTo); + assignment.textContent = wX("ASS_TO"); // FIXME convert formatDisplay to html and add as value to wX + if (a) assignment.appendChild(await AgentUI.formatDisplay(a)); + else assignment.textContent += " " + marker.assignedTo; + } catch (err) { + console.error(err); + } + } + if (marker.state == "completed" && marker.completedID) { + try { + const a = await WasabeeAgent.get(marker.completedID); + assignment.innerHTML = wX("COMPLETED BY", { + agentName: a ? a.name : marker.completedID, + }); + } catch (e) { + console.error(e); + } + } + }, + + _stateButton: function (container, marker) { + const operation = getSelectedOperation(); + const stateButton = L.DomUtil.create("button", null, container); + stateButton.textContent = wX("MARKER STATE"); + L.DomEvent.on(stateButton, "click", (ev) => { L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: marker, - operation: operation, - }); - scd.enable(); - leafletMarker.closePopup(); + const sd = new StateDialog({ target: marker, opID: operation.ID }); + sd.enable(); + this.closePopup(); }); - } - const comment = L.DomUtil.create("div", "wasabee-portal-comment", title); - const cl = L.DomUtil.create("a", null, comment); - cl.textContent = portal.comment || wX("SET_PORTAL_COMMENT"); - cl.href = "#"; - L.DomEvent.on(cl, "click", (ev) => { + }, + + _deleteAction: function () { + const operation = getSelectedOperation(); + const portal = operation.getPortal(this.options.portalId); + const marker = operation.getMarker(this.options.id); + deleteMarker(operation, marker, portal); + }, + + _setComment: function (ev) { L.DomEvent.stop(ev); + const operation = getSelectedOperation(); + const marker = operation.getMarker(this.options.id); const scd = new SetCommentDialog({ - target: portal, + target: marker, operation: operation, }); scd.enable(); - leafletMarker.closePopup(); - }); - if (portal.hardness) { - const hardness = L.DomUtil.create("div", "wasabee-portal-hardness", title); - const hl = L.DomUtil.create("a", null, hardness); - hl.textContent = portal.hardness; - hl.href = "#"; - L.DomEvent.on(hl, "click", (ev) => { - L.DomEvent.stop(ev); - const scd = new SetCommentDialog({ - target: portal, - operation: operation, - }); - scd.enable(); - leafletMarker.closePopup(); - }); - } - return title; -} + this.closePopup(); + }, + + _setMarkerType: function (ev) { + L.DomEvent.stop(ev); + const operation = getSelectedOperation(); + const marker = operation.getMarker(this.options.id); + const ch = new MarkerChangeDialog({ marker: marker }); + ch.enable(); + this.closePopup(); + }, +}); + +export default { + WLMarker, +}; diff --git a/src/code/ui/portal.js b/src/code/ui/portal.js index cff24df2d..d36fe7e93 100644 --- a/src/code/ui/portal.js +++ b/src/code/ui/portal.js @@ -1,13 +1,10 @@ import WasabeePortal from "../model/portal"; -import wX from "../wX"; -export default { - fromIITC, - displayName, - displayFormat, - get, - getSelected, -}; +import { getSelectedOperation } from "../selectedOp"; +import AssignDialog from "../dialogs/assignDialog"; +import SendTargetDialog from "../dialogs/sendTargetDialog"; +import SetCommentDialog from "../dialogs/setCommentDialog"; +import wX from "../wX"; function fromIITC(p) { // we have all the details @@ -97,3 +94,153 @@ function get(id) { function getSelected() { return window.selectedPortal ? get(window.selectedPortal) : null; } + +// common part for marker and anchors +const WLPortal = L.Marker.extend({ + initialize: function (options) { + const operation = getSelectedOperation(); + const portal = operation.getPortal(options.portalId); + options.title = portal.name; + L.Marker.prototype.initialize.call(this, portal.latLng, options); + window.registerMarkerForOMS(this); + }, + + onAdd: function (map) { + L.Marker.prototype.onAdd.call(this, map); + this.bindPopup("loading...", { + className: "wasabee-popup", + closeButton: false, + }); + // marker.off("click", marker.openPopup, marker); + this.on("click spiderfiedclick", this._onClick, this); + }, + + _onClick: function (ev) { + L.DomEvent.stop(ev); + if (this.isPopupOpen && this.isPopupOpen()) return; + const content = this._popupContent(); + this.setPopupContent(content); + if (this._popup._wrapper) + this._popup._wrapper.classList.add("wasabee-popup"); + this.update(); + this.openPopup(); + }, + + _popupContent: function () { + const div = L.DomUtil.create("div", "wasabee-marker-popup"); + return div; + }, + + _popupPortalComments: function (container, portal, canWrite) { + const portalComment = L.DomUtil.create( + "div", + "wasabee-portal-comment", + container + ); + const pcLink = L.DomUtil.create("a", null, portalComment); + pcLink.textContent = portal.comment || wX("SET_PORTAL_COMMENT"); + if (canWrite) { + pcLink.href = "#"; + L.DomEvent.on(pcLink, "click", this._setPortalComment, this); + } + if (portal.hardness) { + const portalHardness = L.DomUtil.create( + "div", + "wasabee-portal-hardness", + container + ); + const phLink = L.DomUtil.create("a", null, portalHardness); + phLink.textContent = portal.hardness; + if (canWrite) { + phLink.href = "#"; + L.DomEvent.on(phLink, "click", this._setPortalComment, this); + } + } + }, + + _setPortalComment: function (ev) { + L.DomEvent.stop(ev); + const operation = getSelectedOperation(); + const portal = operation.getPortal(this.options.portalId); + const scd = new SetCommentDialog({ + target: portal, + operation: operation, + }); + scd.enable(); + this.closePopup(); + }, + + _assignButton: function (container, text, target) { + const assignButton = L.DomUtil.create("button", null, container); + assignButton.textContent = text; + L.DomEvent.on(assignButton, "click", (ev) => { + L.DomEvent.stop(ev); + const ad = new AssignDialog({ target: target }); + ad.enable(); + this.closePopup(); + }); + return assignButton; + }, + + _deleteButton: function (container, text) { + const deleteButton = L.DomUtil.create("button", null, container); + deleteButton.textContent = text; + L.DomEvent.on(deleteButton, "click", (ev) => { + L.DomEvent.stop(ev); + if (this._deleteAction) this._deleteAction(); + this.closePopup(); + }); + }, + + _sendTargetButton: function (container, text, target) { + const sendButton = L.DomUtil.create("button", null, container); + sendButton.textContent = text; + L.DomEvent.on(sendButton, "click", (ev) => { + L.DomEvent.stop(ev); + const std = new SendTargetDialog({ target: target }); + std.enable(); + this.closePopup(); + }); + return sendButton; + }, + + _mapButton: function (container, text) { + const gmapButton = L.DomUtil.create("button", null, container); + gmapButton.textContent = text; + L.DomEvent.on(gmapButton, "click", (ev) => { + L.DomEvent.stop(ev); + this.closePopup(); + const latLng = this.getLatLng(); + // use intent on android + if ( + typeof window.android !== "undefined" && + window.android && + window.android.intentPosLink + ) { + window.android.intentPosLink( + +latLng.lat, + +latLng.lng, + window.map.getZoom(), + this.options.title, + true + ); + } else { + window.open( + "https://www.google.com/maps/search/?api=1&query=" + + latLng.lat + + "," + + latLng.lng + ); + } + }); + }, +}); + +export default { + fromIITC, + displayName, + displayFormat, + get, + getSelected, + WLPortal, +}; From 73200b78cca6b0b239026862172dc1a2a6560274 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 27 Jun 2021 16:35:19 +0200 Subject: [PATCH 014/275] factor + move link map code node: background ops are still treated differently --- src/code/css/map.css | 359 +++++++++++++++++++++++++++++++++++++++ src/code/css/wasabee.css | 355 -------------------------------------- src/code/mapDrawing.js | 49 +----- src/code/static.js | 1 + src/code/ui/agent.js | 27 +-- src/code/ui/anchor.js | 2 + src/code/ui/link.js | 104 +++++++----- src/code/ui/marker.js | 2 + src/code/ui/portal.js | 26 +-- 9 files changed, 448 insertions(+), 477 deletions(-) create mode 100644 src/code/css/map.css diff --git a/src/code/css/map.css b/src/code/css/map.css new file mode 100644 index 000000000..5a5bdee59 --- /dev/null +++ b/src/code/css/map.css @@ -0,0 +1,359 @@ +/* wasabee-tooltip is used for the quickdraw mouse follower */ +.wasabee-tooltip { + background: rgba(30, 130, 76, 0.66); + border: 1px solid transparent; + -webkit-border-radius: 4px; + border-radius: 4px; + color: #fff; + /* font: 12px/18px "Helvetica Neue",Arial,Helvetica,sans-serif; */ + margin-left: 20px; + margin-top: -21px; + padding: 2px 4px; + position: absolute; + white-space: nowrap; + z-index: 6; +} +.wasabee-tooltip:before { + border-right: 6px solid #000; + border-right-color: rgba(99, 99, 88, 0.66); + border-top: 6px solid transparent; + border-bottom: 6px solid transparent; + content: ""; + position: absolute; + top: 7px; + left: -7px; +} +.wasabee-tooltip-single { + margin-top: -12px; +} +.wasabee-error-tooltip { + background-color: #f2dede; + border: 1px solid #e6b6bd; + color: #b94a48; +} +.wasabee-error-tooltip:before { + border-right-color: #e6b6bd; +} + +/* this class is appended to leaflet-popup so we can adjust without stepping on other plugins */ +.leaflet-popup.wasabee-popup .leaflet-popup-content-wrapper { + background: rgba(235, 235, 235, 0.75) !important; + -webkit-border-radius: 6px !important; + font-weight: bolder; +} + +#map .wasabee-popup .leaflet-popup-content { + color: black; +} + +.wasabee-popup a.enl { + color: rgb(56, 142, 60) !important; +} +.wasabee-popup a.res { + color: rgb(0, 135, 255) !important; +} + +.wasabee-link-popup .buttonset { + display: grid; +} + +.wasabee-marker-popup { +} +.wasabee-marker-popup div.desc { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + color: #000; + padding: 4px 4px; +} + +.wasabee-popup-assignment { + padding: 0px 4px 0px 4px; + text-overflow: ellipsis; + white-space: nowrap; + color: #000; +} + +.wasabee-popup-assignment a.wasabee-agent-label { + margin-left: 4px; +} + +.wasabee-marker-popup-kind { + margin-right: 4px; + text-overflow: ellipsis; + white-space: nowrap; + color: #000; +} + +.wasabee-marker-popup-comment { + font-weight: initial; +} + +.wasabee-marker-popup-kind { + cursor: pointer; +} + +.wasabee-marker-popup-kind:hover { + text-decoration: underline; +} + +.wasabee-marker-buttonset { +} +.wasabee-marker-buttonset button { + display: block; + width: 100%; +} + +.wasabee-agent-popup { +} +.wasabee-agent-popup div.desc { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + color: #000; + padding: 0px 4px; +} + +.wasabee-agent-popup button { + display: block; + width: 100%; +} + +.wasabee-agent-popup ul.assignments { + color: rgb(56, 142, 60); +} + +.wasabee-agent-popup li.assignment { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.wasabee-anchor-popup { +} +.wasabee-anchor-popup div.desc { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + color: #000; + padding: 0px 4px; +} + +.wasabee-anchor-buttonset { +} +.wasabee-anchor-buttonset button { + display: block; + width: 100%; +} + +.wasabee-wd-popup ul { + padding-left: 1em; +} + +.wasabee-marker-icon { + background-size: cover; +} + +.wasabee-marker-icon.CapturePortalMarker { + background-image: url(../images/wasabee_markers_capture_pending.svg) +} +.wasabee-marker-icon.CapturePortalMarker.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_capture_assigned.svg) +} +.wasabee-marker-icon.CapturePortalMarker.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_capture_acknowledge.svg) +} +.wasabee-marker-icon.CapturePortalMarker.wasabee-status-completed { + background-image: url(../images/wasabee_markers_capture_done.svg) +} +.wasabee-marker-icon.LetDecayPortalAlert { + background-image: url(../images/wasabee_markers_decay_pending.svg) +} +.wasabee-marker-icon.LetDecayPortalAlert.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_decay_assigned.svg) +} +.wasabee-marker-icon.LetDecayPortalAlert.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_decay_acknowledge.svg) +} +.wasabee-marker-icon.LetDecayPortalAlert.wasabee-status-completed { + background-image: url(../images/wasabee_markers_decay_done.svg) +} +.wasabee-marker-icon.DestroyPortalAlert { + background-image: url(../images/wasabee_markers_destroy_pending.svg) +} +.wasabee-marker-icon.DestroyPortalAlert.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_destroy_assigned.svg) +} +.wasabee-marker-icon.DestroyPortalAlert.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_destroy_acknowledge.svg) +} +.wasabee-marker-icon.DestroyPortalAlert.wasabee-status-completed { + background-image: url(../images/wasabee_markers_destroy_done.svg) +} +.wasabee-marker-icon.FarmPortalMarker { + background-image: url(../images/wasabee_markers_farm_pending.svg) +} +.wasabee-marker-icon.FarmPortalMarker.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_farm_assigned.svg) +} +.wasabee-marker-icon.FarmPortalMarker.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_farm_acknowledge.svg) +} +.wasabee-marker-icon.FarmPortalMarker.wasabee-status-completed { + background-image: url(../images/wasabee_markers_farm_done.svg) +} +.wasabee-marker-icon.GotoPortalMarker { + background-image: url(../images/wasabee_markers_goto_pending.svg) +} +.wasabee-marker-icon.GotoPortalMarker.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_goto_assigned.svg) +} +.wasabee-marker-icon.GotoPortalMarker.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_goto_acknowledged.svg) +} +.wasabee-marker-icon.GotoPortalMarker.wasabee-status-completed { + background-image: url(../images/wasabee_markers_goto_done.svg) +} +.wasabee-marker-icon.GetKeyPortalMarker { + background-image: url(../images/wasabee_markers_key_pending.svg) +} +.wasabee-marker-icon.GetKeyPortalMarker.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_key_assigned.svg) +} +.wasabee-marker-icon.GetKeyPortalMarker.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_key_acknowledged.svg) +} +.wasabee-marker-icon.GetKeyPortalMarker.wasabee-status-completed { + background-image: url(../images/wasabee_markers_key_done.svg) +} +.wasabee-marker-icon.CreateLinkAlert { + background-image: url(../images/wasabee_markers_link_pending.svg) +} +.wasabee-marker-icon.CreateLinkAlert.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_link_assigned.svg) +} +.wasabee-marker-icon.CreateLinkAlert.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_link_acknowledged.svg) +} +.wasabee-marker-icon.CreateLinkAlert.wasabee-status-completed { + background-image: url(../images/wasabee_markers_link_done.svg) +} +.wasabee-marker-icon.MeetAgentPortalMarker { + background-image: url(../images/wasabee_markers_meetagent_pending.svg) +} +.wasabee-marker-icon.MeetAgentPortalMarker.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_meetagent_assigned.svg) +} +.wasabee-marker-icon.MeetAgentPortalMarker.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_meetagent_acknowledge.svg) +} +.wasabee-marker-icon.MeetAgentPortalMarker.wasabee-status-completed { + background-image: url(../images/wasabee_markers_meetagent_done.svg) +} +.wasabee-marker-icon.OtherPortalAlert { + background-image: url(../images/wasabee_markers_other_pending.svg) +} +.wasabee-marker-icon.OtherPortalAlert.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_other_assigned.svg) +} +.wasabee-marker-icon.OtherPortalAlert.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_other_acknowledge.svg) +} +.wasabee-marker-icon.OtherPortalAlert.wasabee-status-completed { + background-image: url(../images/wasabee_markers_other_done.svg) +} +.wasabee-marker-icon.RechargePortalAlert { + background-image: url(../images/wasabee_markers_recharge_pending.svg) +} +.wasabee-marker-icon.RechargePortalAlert.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_recharge_assigned.svg) +} +.wasabee-marker-icon.RechargePortalAlert.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_recharge_acknowledge.svg) +} +.wasabee-marker-icon.RechargePortalAlert.wasabee-status-completed { + background-image: url(../images/wasabee_markers_recharge_done.svg) +} +.wasabee-marker-icon.UpgradePortalAlert { + background-image: url(../images/wasabee_markers_upgrade_pending.svg) +} +.wasabee-marker-icon.UpgradePortalAlert.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_upgrade_assigned.svg) +} +.wasabee-marker-icon.UpgradePortalAlert.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_upgrade_acknowledge.svg) +} +.wasabee-marker-icon.UpgradePortalAlert.wasabee-status-completed { + background-image: url(../images/wasabee_markers_upgrade_done.svg) +} +.wasabee-marker-icon.UseVirusPortalAlert { + background-image: url(../images/wasabee_markers_virus_pending.svg) +} +.wasabee-marker-icon.UseVirusPortalAlert.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_virus_assigned.svg) +} +.wasabee-marker-icon.UseVirusPortalAlert.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_virus_acknowledge.svg) +} +.wasabee-marker-icon.UseVirusPortalAlert.wasabee-status-completed { + background-image: url(../images/wasabee_markers_virus_done.svg) +} +.wasabee-marker-icon.ExcludeMarker { + background-image: url(../images/wasabee_markers_exclude_pending.svg) +} +.wasabee-marker-icon.ExcludeMarker.wasabee-status-assigned { + background-image: url(../images/wasabee_markers_exclude_assigned.svg) +} +.wasabee-marker-icon.ExcludeMarker.wasabee-status-acknowledged { + background-image: url(../images/wasabee_markers_exclude_assigned.svg) +} +.wasabee-marker-icon.ExcludeMarker.wasabee-status-completed { + background-image: url(../images/wasabee_markers_exclude_done.svg) +} + +.wasabee-defense-icon { + background-size: cover; + background-image: url(../images/wasabee_markers_key_done.svg) +} + +.wasabee-anchor-icon { + background-size: 25px 41px; +} +.wasabee-anchor-icon.wasabee-layer-main { + background-image: url(../images/pin_red.svg) +} +.wasabee-anchor-icon.wasabee-layer-groupa { + background-image: url(../images/pin_orange.svg) +} +.wasabee-anchor-icon.wasabee-layer-groupb { + background-image: url(../images/pin_yellow.svg) +} +.wasabee-anchor-icon.wasabee-layer-groupc { + background-image: url(../images/pin_tan.svg) +} +.wasabee-anchor-icon.wasabee-layer-groupd { + background-image: url(../images/pin_purple.svg) +} +.wasabee-anchor-icon.wasabee-layer-groupe { + background-image: url(../images/pin_teal.svg) +} +.wasabee-anchor-icon.wasabee-layer-groupf { + background-image: url(../images/pin_magenta.svg) +} + +.wasabee-portal-comment { + font-size: smaller; + font-weight: lighter; + margin-left: 12px; +} + +.wasabee-portal-hardness { + font-size: smaller; + font-weight: lighter; + margin-left: 12px; +} + +.wasabee-portal-hardness a { + color: #f00 !important; +} + diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index 65347432a..f2629261c 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -1,40 +1,3 @@ -/* wasabee-tooltip is used for the quickdraw mouse follower */ -.wasabee-tooltip { - background: rgba(30, 130, 76, 0.66); - border: 1px solid transparent; - -webkit-border-radius: 4px; - border-radius: 4px; - color: #fff; - /* font: 12px/18px "Helvetica Neue",Arial,Helvetica,sans-serif; */ - margin-left: 20px; - margin-top: -21px; - padding: 2px 4px; - position: absolute; - white-space: nowrap; - z-index: 6; -} -.wasabee-tooltip:before { - border-right: 6px solid #000; - border-right-color: rgba(99, 99, 88, 0.66); - border-top: 6px solid transparent; - border-bottom: 6px solid transparent; - content: ""; - position: absolute; - top: 7px; - left: -7px; -} -.wasabee-tooltip-single { - margin-top: -12px; -} -.wasabee-error-tooltip { - background-color: #f2dede; - border: 1px solid #e6b6bd; - color: #b94a48; -} -.wasabee-error-tooltip:before { - border-right-color: #e6b6bd; -} - /* used in anything that is a sortable table */ /* .wasabee-table tbody tr:nth-child(2n + 1) td { border-color: rgba(50, 0, 125, 1); } */ .wasabee-table tr { @@ -104,308 +67,6 @@ pointer-events: none; } -/* this class is appended to leaflet-popup so we can adjust without stepping on other plugins */ -.wasabee-popup { - background: rgba(235, 235, 235, 0.75) !important; - -webkit-border-radius: 6px !important; - font-weight: bolder; -} - -#map .wasabee-popup .leaflet-popup-content { - color: black; -} - -.wasabee-popup a.enl { - color: rgb(56, 142, 60) !important; -} -.wasabee-popup a.res { - color: rgb(0, 135, 255) !important; -} - -.wasabee-marker-popup { -} -.wasabee-marker-popup div.desc { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - color: #000; - padding: 4px 4px; -} - -.wasabee-popup-assignment { - padding: 0px 4px 0px 4px; - text-overflow: ellipsis; - white-space: nowrap; - color: #000; -} - -.wasabee-popup-assignment a.wasabee-agent-label { - margin-left: 4px; -} - -.wasabee-marker-popup-kind { - margin-right: 4px; - text-overflow: ellipsis; - white-space: nowrap; - color: #000; -} - -.wasabee-marker-popup-comment { - font-weight: initial; -} - -.wasabee-marker-popup-kind { - cursor: pointer; -} - -.wasabee-marker-popup-kind:hover { - text-decoration: underline; -} - -.wasabee-marker-buttonset { -} -.wasabee-marker-buttonset button { - display: block; - width: 100%; -} - -.wasabee-agent-popup { -} -.wasabee-agent-popup div.desc { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - color: #000; - padding: 0px 4px; -} - -.wasabee-agent-popup button { - display: block; - width: 100%; -} - -.wasabee-agent-popup ul.assignments { - color: rgb(56, 142, 60); -} - -.wasabee-agent-popup li.assignment { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -.wasabee-anchor-popup { -} -.wasabee-anchor-popup div.desc { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - color: #000; - padding: 0px 4px; -} - -.wasabee-anchor-buttonset { -} -.wasabee-anchor-buttonset button { - display: block; - width: 100%; -} - -.wasabee-wd-popup ul { - padding-left: 1em; -} - -.wasabee-marker-icon { - background-size: cover; -} - -.wasabee-marker-icon.CapturePortalMarker { - background-image: url(../images/wasabee_markers_capture_pending.svg) -} -.wasabee-marker-icon.CapturePortalMarker.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_capture_assigned.svg) -} -.wasabee-marker-icon.CapturePortalMarker.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_capture_acknowledge.svg) -} -.wasabee-marker-icon.CapturePortalMarker.wasabee-status-completed { - background-image: url(../images/wasabee_markers_capture_done.svg) -} -.wasabee-marker-icon.LetDecayPortalAlert { - background-image: url(../images/wasabee_markers_decay_pending.svg) -} -.wasabee-marker-icon.LetDecayPortalAlert.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_decay_assigned.svg) -} -.wasabee-marker-icon.LetDecayPortalAlert.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_decay_acknowledge.svg) -} -.wasabee-marker-icon.LetDecayPortalAlert.wasabee-status-completed { - background-image: url(../images/wasabee_markers_decay_done.svg) -} -.wasabee-marker-icon.DestroyPortalAlert { - background-image: url(../images/wasabee_markers_destroy_pending.svg) -} -.wasabee-marker-icon.DestroyPortalAlert.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_destroy_assigned.svg) -} -.wasabee-marker-icon.DestroyPortalAlert.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_destroy_acknowledge.svg) -} -.wasabee-marker-icon.DestroyPortalAlert.wasabee-status-completed { - background-image: url(../images/wasabee_markers_destroy_done.svg) -} -.wasabee-marker-icon.FarmPortalMarker { - background-image: url(../images/wasabee_markers_farm_pending.svg) -} -.wasabee-marker-icon.FarmPortalMarker.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_farm_assigned.svg) -} -.wasabee-marker-icon.FarmPortalMarker.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_farm_acknowledge.svg) -} -.wasabee-marker-icon.FarmPortalMarker.wasabee-status-completed { - background-image: url(../images/wasabee_markers_farm_done.svg) -} -.wasabee-marker-icon.GotoPortalMarker { - background-image: url(../images/wasabee_markers_goto_pending.svg) -} -.wasabee-marker-icon.GotoPortalMarker.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_goto_assigned.svg) -} -.wasabee-marker-icon.GotoPortalMarker.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_goto_acknowledged.svg) -} -.wasabee-marker-icon.GotoPortalMarker.wasabee-status-completed { - background-image: url(../images/wasabee_markers_goto_done.svg) -} -.wasabee-marker-icon.GetKeyPortalMarker { - background-image: url(../images/wasabee_markers_key_pending.svg) -} -.wasabee-marker-icon.GetKeyPortalMarker.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_key_assigned.svg) -} -.wasabee-marker-icon.GetKeyPortalMarker.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_key_acknowledged.svg) -} -.wasabee-marker-icon.GetKeyPortalMarker.wasabee-status-completed { - background-image: url(../images/wasabee_markers_key_done.svg) -} -.wasabee-marker-icon.CreateLinkAlert { - background-image: url(../images/wasabee_markers_link_pending.svg) -} -.wasabee-marker-icon.CreateLinkAlert.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_link_assigned.svg) -} -.wasabee-marker-icon.CreateLinkAlert.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_link_acknowledged.svg) -} -.wasabee-marker-icon.CreateLinkAlert.wasabee-status-completed { - background-image: url(../images/wasabee_markers_link_done.svg) -} -.wasabee-marker-icon.MeetAgentPortalMarker { - background-image: url(../images/wasabee_markers_meetagent_pending.svg) -} -.wasabee-marker-icon.MeetAgentPortalMarker.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_meetagent_assigned.svg) -} -.wasabee-marker-icon.MeetAgentPortalMarker.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_meetagent_acknowledge.svg) -} -.wasabee-marker-icon.MeetAgentPortalMarker.wasabee-status-completed { - background-image: url(../images/wasabee_markers_meetagent_done.svg) -} -.wasabee-marker-icon.OtherPortalAlert { - background-image: url(../images/wasabee_markers_other_pending.svg) -} -.wasabee-marker-icon.OtherPortalAlert.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_other_assigned.svg) -} -.wasabee-marker-icon.OtherPortalAlert.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_other_acknowledge.svg) -} -.wasabee-marker-icon.OtherPortalAlert.wasabee-status-completed { - background-image: url(../images/wasabee_markers_other_done.svg) -} -.wasabee-marker-icon.RechargePortalAlert { - background-image: url(../images/wasabee_markers_recharge_pending.svg) -} -.wasabee-marker-icon.RechargePortalAlert.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_recharge_assigned.svg) -} -.wasabee-marker-icon.RechargePortalAlert.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_recharge_acknowledge.svg) -} -.wasabee-marker-icon.RechargePortalAlert.wasabee-status-completed { - background-image: url(../images/wasabee_markers_recharge_done.svg) -} -.wasabee-marker-icon.UpgradePortalAlert { - background-image: url(../images/wasabee_markers_upgrade_pending.svg) -} -.wasabee-marker-icon.UpgradePortalAlert.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_upgrade_assigned.svg) -} -.wasabee-marker-icon.UpgradePortalAlert.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_upgrade_acknowledge.svg) -} -.wasabee-marker-icon.UpgradePortalAlert.wasabee-status-completed { - background-image: url(../images/wasabee_markers_upgrade_done.svg) -} -.wasabee-marker-icon.UseVirusPortalAlert { - background-image: url(../images/wasabee_markers_virus_pending.svg) -} -.wasabee-marker-icon.UseVirusPortalAlert.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_virus_assigned.svg) -} -.wasabee-marker-icon.UseVirusPortalAlert.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_virus_acknowledge.svg) -} -.wasabee-marker-icon.UseVirusPortalAlert.wasabee-status-completed { - background-image: url(../images/wasabee_markers_virus_done.svg) -} -.wasabee-marker-icon.ExcludeMarker { - background-image: url(../images/wasabee_markers_exclude_pending.svg) -} -.wasabee-marker-icon.ExcludeMarker.wasabee-status-assigned { - background-image: url(../images/wasabee_markers_exclude_assigned.svg) -} -.wasabee-marker-icon.ExcludeMarker.wasabee-status-acknowledged { - background-image: url(../images/wasabee_markers_exclude_assigned.svg) -} -.wasabee-marker-icon.ExcludeMarker.wasabee-status-completed { - background-image: url(../images/wasabee_markers_exclude_done.svg) -} - -.wasabee-defense-icon { - background-size: cover; - background-image: url(../images/wasabee_markers_key_done.svg) -} - -.wasabee-anchor-icon { - background-size: 25px 41px; -} -.wasabee-anchor-icon.wasabee-layer-main { - background-image: url(../images/pin_red.svg) -} -.wasabee-anchor-icon.wasabee-layer-groupa { - background-image: url(../images/pin_orange.svg) -} -.wasabee-anchor-icon.wasabee-layer-groupb { - background-image: url(../images/pin_yellow.svg) -} -.wasabee-anchor-icon.wasabee-layer-groupc { - background-image: url(../images/pin_tan.svg) -} -.wasabee-anchor-icon.wasabee-layer-groupd { - background-image: url(../images/pin_purple.svg) -} -.wasabee-anchor-icon.wasabee-layer-groupe { - background-image: url(../images/pin_teal.svg) -} -.wasabee-anchor-icon.wasabee-layer-groupf { - background-image: url(../images/pin_magenta.svg) -} - /* all dialogs get this class -- do global stuff with it */ /* .wasabee-dialog { background-color: rgba(250, 250, 250, 0.9); @@ -784,22 +445,6 @@ content: " ➾ "; } -.wasabee-portal-comment { - font-size: smaller; - font-weight: lighter; - margin-left: 12px; -} - -.wasabee-portal-hardness { - font-size: smaller; - font-weight: lighter; - margin-left: 12px; -} - -.wasabee-portal-hardness a { - color: #f00 !important; -} - /* in our dialogs and popups, use a darker green for ENL for better contrast */ /* .wasabee-dialog a.wasabee-portal { color: #ff6600; diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index b6694beed..946800b3e 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -62,7 +62,8 @@ function resetLinks(operation) { if (!operation.links || operation.links.length == 0) return; for (const l of operation.links) { - addLink(l, operation); + const link = new LinkUI.WLLink(l, operation); + link.addTo(Wasabee.linkLayerGroup); } } @@ -126,52 +127,6 @@ function resetZones(operation) { Wasabee.zoneLayerGroup.bringToBack(); } -// draw a single link -function addLink(wlink, operation) { - const latLngs = wlink.getLatLngs(operation); - if (!latLngs) { - console.log("LatLngs was null: op missing portal data?"); - return; - } - - const color = wlink.getColor(operation); - - const style = L.extend( - { - color: color, - }, - Wasabee.skin.linkStyle - ); - - if (wlink.assignedTo) style.dashArray = style.assignedDashArray; - - const newlink = new L.GeodesicPolyline(latLngs, style); - - newlink.bindPopup("loading...", { - className: "wasabee-popup", - closeButton: false, - }); - - newlink.on( - "click", - (ev) => { - L.DomEvent.stop(ev); - if (ev.target._popup._wrapper) - ev.target._popup._wrapper.classList.add("wasabee-popup"); - const div = LinkUI.getPopup(wlink, operation); - ev.target.setPopupContent(div); - ev.target.openPopup(ev.latlng); - return true; - }, - newlink - ); - newlink.addTo(Wasabee.linkLayerGroup); - - // setText only works on polylines, not geodesic ones. - // newlink.on("mouseover", () => { console.log(newlink); // newlink.setText(" ► ", { repeat: true, attributes: { fill: "red" } }); }); - // newlink.on("mouseout", () => { newlink.setText(null); }); -} - // fetch and draw agent locations export async function drawAgents() { if (window.isLayerGroupDisplayed("Wasabee Agents") === false) return; // yes, === false, undefined == true diff --git a/src/code/static.js b/src/code/static.js index db3405d73..67b1db74c 100644 --- a/src/code/static.js +++ b/src/code/static.js @@ -6,6 +6,7 @@ W.static = { main: require("./css/wasabee.css"), autodraws: require("./css/autodraws.css"), toolbar: require("./css/toolbar.css"), + map: require("./css/map.css"), panes: require("./css/panes.css"), smallScreen: require("./css/smallscreen.css"), // fix for dialogs on mobile from iitc dev version diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index 8269bdd9d..ab00db528 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -133,24 +133,10 @@ const WLAgent = L.Marker.extend({ }); window.registerMarkerForOMS(this); - this.bindPopup("Loading...", { + this.bindPopup((layer) => layer._getPopup(), { className: "wasabee-popup", closeButton: false, }); - // marker.off("click", agent.openPopup, agent); - this.on("click spiderfiedclick", this._onClick, this); - }, - - _onClick: async function (ev) { - L.DomEvent.stop(ev); - if (this.isPopupOpen && this.isPopupOpen()) return; - const a = await WasabeeAgent.get(this.options.id); - this.options.agent = a; - this.setPopupContent(await this._getPopup(a)); - if (this._popup._wrapper) - this._popup._wrapper.classList.add("wasabee-popup"); - this.update(); - this.openPopup(); }, update: function () { @@ -169,13 +155,18 @@ const WLAgent = L.Marker.extend({ } else L.Marker.prototype.update.call(this); }, - _getPopup: async function () { + _getPopup: function () { const agent = this.options.agent; const content = L.DomUtil.create("div", "wasabee-agent-popup"); const title = L.DomUtil.create("div", "desc", content); title.id = agent.id; - const fd = await formatDisplay(agent, 0); - title.innerHTML = fd.outerHTML + timeSinceformat(agent); + title.textContent = agent.name; + + WasabeeAgent.get(this.options.id) + .then(formatDisplay) + .then((fd) => { + title.innerHTML = fd.outerHTML + timeSinceformat(agent); + }); const sendTarget = L.DomUtil.create("button", null, content); sendTarget.textContent = wX("SEND TARGET"); diff --git a/src/code/ui/anchor.js b/src/code/ui/anchor.js index 98b4ac41d..b7aad09ff 100644 --- a/src/code/ui/anchor.js +++ b/src/code/ui/anchor.js @@ -9,6 +9,8 @@ import WasabeeAnchor from "../model/anchor"; import PortalUI from "./portal"; const WLAnchor = PortalUI.WLPortal.extend({ + type: "anchor", + initialize: function (portalId, operation) { const anchor = new WasabeeAnchor(portalId, operation); // use newColors(anchor.color) for 0.19 diff --git a/src/code/ui/link.js b/src/code/ui/link.js index ba88b566f..af07ce27e 100644 --- a/src/code/ui/link.js +++ b/src/code/ui/link.js @@ -1,16 +1,11 @@ import AssignDialog from "../dialogs/assignDialog"; +import { getSelectedOperation } from "../selectedOp"; import { convertColorToHex } from "../auxiliar"; import { addToColorList } from "../skin"; import wX from "../wX"; import PortalUI from "./portal"; -export default { - displayFormat, - minLevel, - getPopup, -}; - // returns a DOM object appropriate for display // do we still need the operation here? function displayFormat(link, operation, smallScreen = false) { @@ -82,36 +77,69 @@ function minLevel(link, operation) { return a; } -function getPopup(link, operation) { - const div = L.DomUtil.create("div", null); - L.DomUtil.create("div", null, div).appendChild( - displayFormat(link, operation, true) - ); - if (link.description) - L.DomUtil.create("div", "enl", div).textContent = link.description; - L.DomUtil.create("div", "enl", div).textContent = "# " + link.throwOrderPos; - const del = L.DomUtil.create("button", null, div); - if (operation.canWrite()) { - del.textContent = wX("DELETE_LINK"); - L.DomEvent.on(del, "click", (ev) => { - L.DomEvent.stop(ev); - operation.removeLink(link.fromPortalId, link.toPortalId); - }); - const rev = L.DomUtil.create("button", null, div); - rev.textContent = wX("REVERSE"); - L.DomEvent.on(rev, "click", (ev) => { - L.DomEvent.stop(ev); - operation.reverseLink(link.fromPortalId, link.toPortalId); - }); - } - if (operation.canWriteServer()) { - const assignButton = L.DomUtil.create("button", null, div); - assignButton.textContent = wX("ASSIGN"); - L.DomEvent.on(assignButton, "click", (ev) => { - L.DomEvent.stop(ev); - const ad = new AssignDialog({ target: link }); - ad.enable(); +const WLLink = L.GeodesicPolyline.extend({ + initialize: function (link, operation) { + const latLngs = link.getLatLngs(operation); + const options = L.extend( + { + color: link.getColor(operation), + opID: operation.ID, + linkID: link.ID, + }, + window.plugin.wasabee.skin.linkStyle + ); + if (link.assignedTo) options.dashArray = options.assignedDashArray; + + L.GeodesicPolyline.prototype.initialize.call(this, latLngs, options); + + this._wlink = link; + + this.bindPopup((layer) => layer._getPopup(), { + className: "wasabee-popup", + closeButton: false, }); - } - return div; -} + }, + + _getPopup: function () { + const operation = getSelectedOperation(); + const link = this._wlink; + const div = L.DomUtil.create("div", "wasabee-link-popup"); + L.DomUtil.create("div", null, div).appendChild( + displayFormat(link, operation) + ); + if (link.description) + L.DomUtil.create("div", "enl", div).textContent = link.description; + L.DomUtil.create("div", "enl", div).textContent = "# " + link.throwOrderPos; + const buttonset = L.DomUtil.create("div", "buttonset", div); + const del = L.DomUtil.create("button", null, buttonset); + if (operation.canWrite()) { + del.textContent = wX("DELETE_LINK"); + L.DomEvent.on(del, "click", (ev) => { + L.DomEvent.stop(ev); + operation.removeLink(link.fromPortalId, link.toPortalId); + }); + const rev = L.DomUtil.create("button", null, buttonset); + rev.textContent = wX("REVERSE"); + L.DomEvent.on(rev, "click", (ev) => { + L.DomEvent.stop(ev); + operation.reverseLink(link.fromPortalId, link.toPortalId); + }); + } + if (operation.canWriteServer()) { + const assignButton = L.DomUtil.create("button", null, buttonset); + assignButton.textContent = wX("ASSIGN"); + L.DomEvent.on(assignButton, "click", (ev) => { + L.DomEvent.stop(ev); + const ad = new AssignDialog({ target: link }); + ad.enable(); + }); + } + return div; + }, +}); + +export default { + displayFormat, + minLevel, + WLLink, +}; diff --git a/src/code/ui/marker.js b/src/code/ui/marker.js index ea41a8e95..c7dd426a7 100644 --- a/src/code/ui/marker.js +++ b/src/code/ui/marker.js @@ -12,6 +12,8 @@ import PortalUI from "./portal"; import wX from "../wX"; const WLMarker = PortalUI.WLPortal.extend({ + type: "marker", + initialize: function (marker) { PortalUI.WLPortal.prototype.initialize.call(this, { portalId: marker.portalId, diff --git a/src/code/ui/portal.js b/src/code/ui/portal.js index d36fe7e93..0d6a227ae 100644 --- a/src/code/ui/portal.js +++ b/src/code/ui/portal.js @@ -97,37 +97,25 @@ function getSelected() { // common part for marker and anchors const WLPortal = L.Marker.extend({ + type: "portal", + initialize: function (options) { const operation = getSelectedOperation(); const portal = operation.getPortal(options.portalId); options.title = portal.name; L.Marker.prototype.initialize.call(this, portal.latLng, options); - window.registerMarkerForOMS(this); - }, - - onAdd: function (map) { - L.Marker.prototype.onAdd.call(this, map); - this.bindPopup("loading...", { + this.bindPopup((layer) => layer._popupContent(), { className: "wasabee-popup", closeButton: false, }); - // marker.off("click", marker.openPopup, marker); - this.on("click spiderfiedclick", this._onClick, this); - }, - _onClick: function (ev) { - L.DomEvent.stop(ev); - if (this.isPopupOpen && this.isPopupOpen()) return; - const content = this._popupContent(); - this.setPopupContent(content); - if (this._popup._wrapper) - this._popup._wrapper.classList.add("wasabee-popup"); - this.update(); - this.openPopup(); + this.off("click", this._openPopup); + window.registerMarkerForOMS(this); + this.on("spiderfiedclick", this._openPopup); }, _popupContent: function () { - const div = L.DomUtil.create("div", "wasabee-marker-popup"); + const div = L.DomUtil.create("div", `wasabee-${this.type}-popup`); return div; }, From 89b53d09e9cea5089e24da8aebfdcb80168fddd8 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 27 Jun 2021 17:13:26 +0200 Subject: [PATCH 015/275] assume new colors and move logic to ui --- src/code/auxiliar.js | 2 +- src/code/dialogs/exportDialog.js | 3 ++- src/code/model/link.js | 3 +-- src/code/model/operation.js | 3 +-- src/code/ui/anchor.js | 27 ++++++++------------------- src/code/ui/link.js | 7 +++++-- 6 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/code/auxiliar.js b/src/code/auxiliar.js index c8a53fea2..4ced73101 100644 --- a/src/code/auxiliar.js +++ b/src/code/auxiliar.js @@ -24,7 +24,7 @@ export function newColors(incoming) { case "groupf": return "fuchsia"; case "main": - return "red"; + return window.plugin.wasabee.skin.defaultOperationColor; default: return incoming; } diff --git a/src/code/dialogs/exportDialog.js b/src/code/dialogs/exportDialog.js index a818ab23d..f1f383ec6 100644 --- a/src/code/dialogs/exportDialog.js +++ b/src/code/dialogs/exportDialog.js @@ -1,5 +1,6 @@ import { WDialog } from "../leafletClasses"; import { getSelectedOperation } from "../selectedOp"; +import { convertColorToHex } from "../auxiliar"; import wX from "../wX"; // export screen @@ -51,7 +52,7 @@ const ExportDialog = WDialog.extend({ for (const link of operation.links) { const l = {}; l.type = "polyline"; - l.color = link.getColor(operation); + l.color = convertColorToHex(link.getColor(operation)); l.latLngs = link.getLatLngs(operation); output.push(l); } diff --git a/src/code/model/link.js b/src/code/model/link.js index 3d2e86e7b..e70da8ea3 100644 --- a/src/code/model/link.js +++ b/src/code/model/link.js @@ -1,4 +1,4 @@ -import { generateId, newColors } from "../auxiliar"; +import { generateId } from "../auxiliar"; import { getSelectedOperation } from "../selectedOp"; export default class WasabeeLink { @@ -105,7 +105,6 @@ export default class WasabeeLink { getColor(operation) { let color = this.color; if (color == "main") color = operation.color; - color = newColors(color); return color; } diff --git a/src/code/model/operation.js b/src/code/model/operation.js index 23bfe507b..69709fd17 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -4,7 +4,7 @@ import WasabeeMarker from "./marker"; import WasabeeMe from "./me"; import WasabeeZone from "./zone"; import Evented from "./evented"; -import { generateId, newColors } from "../auxiliar"; +import { generateId } from "../auxiliar"; import { GetWasabeeServer } from "../server"; import { getSelectedOperation } from "../selectedOp"; import db from "../db"; @@ -28,7 +28,6 @@ export default class WasabeeOp extends Evented { this.links = this.convertLinksToObjs(obj.links); this.markers = this.convertMarkersToObjs(obj.markers); this.color = obj.color ? obj.color : "main"; - this.color = newColors(this.color); this.comment = obj.comment ? obj.comment : null; this.teamlist = obj.teamlist ? obj.teamlist : Array(); this.fetched = obj.fetched ? obj.fetched : null; diff --git a/src/code/ui/anchor.js b/src/code/ui/anchor.js index b7aad09ff..8e1ca3e99 100644 --- a/src/code/ui/anchor.js +++ b/src/code/ui/anchor.js @@ -1,42 +1,31 @@ import LinkListDialog from "../dialogs/linkListDialog"; import { getSelectedOperation } from "../selectedOp"; import { swapPortal, deletePortal } from "../uiCommands"; -import { newColors } from "../auxiliar"; import wX from "../wX"; -import WasabeeAnchor from "../model/anchor"; - import PortalUI from "./portal"; const WLAnchor = PortalUI.WLPortal.extend({ type: "anchor", initialize: function (portalId, operation) { - const anchor = new WasabeeAnchor(portalId, operation); - // use newColors(anchor.color) for 0.19 - let layer = anchor.color; - if (newColors(layer) == layer) layer = "custom"; + let color = operation.color; + if (color == "main") + color = window.plugin.wasabee.skin.defaultOperationColor; const icon = L.divIcon({ - className: - layer != "custom" - ? `wasabee-anchor-icon wasabee-layer-${layer}` - : "wasabee-anchor-icon", + className: "wasabee-anchor-icon", shadowUrl: null, iconAnchor: [12, 41], iconSize: [25, 41], popupAnchor: [0, -35], - html: - layer != "custom" - ? null - : L.Util.template( - '', - { color: anchor.color } - ), + html: L.Util.template( + '', + { color: color } + ), }); PortalUI.WLPortal.prototype.initialize.call(this, { portalId: portalId, id: portalId, - color: anchor.color, icon: icon, }); }, diff --git a/src/code/ui/link.js b/src/code/ui/link.js index af07ce27e..5587d42dc 100644 --- a/src/code/ui/link.js +++ b/src/code/ui/link.js @@ -14,7 +14,7 @@ function displayFormat(link, operation, smallScreen = false) { PortalUI.displayFormat(operation.getPortal(link.fromPortalId), smallScreen) ); const arrow = L.DomUtil.create("span", "wasabee-link-seperator", d); - arrow.style.color = link.getColor(operation); + arrow.style.color = convertColorToHex(link.getColor(operation)); const picker = L.DomUtil.create("input", "hidden-color-picker", arrow); picker.type = "color"; picker.value = convertColorToHex(link.getColor(operation)); @@ -80,9 +80,12 @@ function minLevel(link, operation) { const WLLink = L.GeodesicPolyline.extend({ initialize: function (link, operation) { const latLngs = link.getLatLngs(operation); + let color = link.getColor(operation); + if (color == "main") + color = window.plugin.wasabee.skin.defaultOperationColor; const options = L.extend( { - color: link.getColor(operation), + color: color, opID: operation.ID, linkID: link.ID, }, From be4c1c61790d4f08a55f73b07ed075ab04a96665 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 1 Jul 2021 23:00:31 +0200 Subject: [PATCH 016/275] move zone drawing to ./ui --- src/code/mapDrawing.js | 23 +++-------------------- src/code/ui/zone.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 src/code/ui/zone.js diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index 946800b3e..f307a93d9 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -8,6 +8,7 @@ import LinkUI from "./ui/link"; import AnchorUI from "./ui/anchor"; import AgentUI from "./ui/agent"; import MarkerUI from "./ui/marker"; +import ZoneUI from "./ui/zone"; const Wasabee = window.plugin.wasabee; @@ -103,26 +104,8 @@ function resetZones(operation) { if (!operation.zones || operation.zones.length == 0) return; for (const z of operation.zones) { - if (z.points.length == 1) { - L.marker(z.points[0], { color: z.color }).addTo(Wasabee.zoneLayerGroup); - continue; - } - if (z.points.length == 2) { - L.polyline(z.points, { color: z.color }).addTo(Wasabee.zoneLayerGroup); - continue; - } - z.points.sort((a, b) => { - return a.position - b.position; - }); - L.polygon(z.points, { - color: z.color, - shapeOptions: { - stroke: false, - opacity: 0.7, - fill: true, - interactive: false, - }, - }).addTo(Wasabee.zoneLayerGroup); + const l = new ZoneUI.WLZone(z); + l.addTo(Wasabee.zoneLayerGroup); } Wasabee.zoneLayerGroup.bringToBack(); } diff --git a/src/code/ui/zone.js b/src/code/ui/zone.js new file mode 100644 index 000000000..72f204506 --- /dev/null +++ b/src/code/ui/zone.js @@ -0,0 +1,31 @@ +const zoneShape = { + stroke: false, + opacity: 0.7, + fill: true, + interactive: false, +}; + +const WLZone = L.LayerGroup.extend({ + initialize: function (zone) { + zone.points.sort((a, b) => { + return a.position - b.position; + }); + let layer; + if (zone.points.length == 1) + layer = L.marker(zone.points[0], { + icon: L.divIcon.coloredSvg(zone.color), + }); + else if (zone.points.length == 2) + layer = L.polyline(zone.points, { color: zone.color }); + else + layer = L.polygon(zone.points, { + color: zone.color, + shapeOptions: zoneShape, + }); + L.LayerGroup.prototype.initialize.call(this, [layer]); + }, +}); + +export default { + WLZone, +}; From 2027f3790efd36703fc0e5d771eed6fa72a9d9ce Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 2 Jul 2021 11:13:36 +0200 Subject: [PATCH 017/275] remove anchor model --- src/code/dialogs/assignDialog.js | 6 ++-- src/code/dialogs/sendTargetDialog.js | 6 ++-- src/code/model/anchor.js | 50 ---------------------------- 3 files changed, 6 insertions(+), 56 deletions(-) delete mode 100644 src/code/model/anchor.js diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index 6fd8bc2d8..7c3bd7e15 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -1,7 +1,7 @@ import { WDialog } from "../leafletClasses"; import WasabeeLink from "../model/link"; import WasabeeMarker from "../model/marker"; -import WasabeeAnchor from "../model/anchor"; +import WasabeePortal from "../model/portal"; import WasabeeMe from "../model/me"; import WasabeeTeam from "../model/team"; import wX from "../wX"; @@ -79,8 +79,8 @@ const AssignDialog = WDialog.extend({ menu.prepend(t); } - if (target instanceof WasabeeAnchor) { - const portal = operation.getPortal(target.portalId); + if (target instanceof WasabeePortal) { + const portal = target; this._type = "Anchor"; this._name = wX("ASSIGN OUTBOUND PROMPT", { portalName: PortalUI.displayName(portal), diff --git a/src/code/dialogs/sendTargetDialog.js b/src/code/dialogs/sendTargetDialog.js index ca2aa30a9..518a7e7cc 100644 --- a/src/code/dialogs/sendTargetDialog.js +++ b/src/code/dialogs/sendTargetDialog.js @@ -1,6 +1,6 @@ import { WDialog } from "../leafletClasses"; import WasabeeMarker from "../model/marker"; -import WasabeeAnchor from "../model/anchor"; +import WasabeePortal from "../model/portal"; import WasabeeMe from "../model/me"; import WasabeeTeam from "../model/team"; import { targetPromise } from "../server"; @@ -58,8 +58,8 @@ const SendTargetDialog = WDialog.extend({ menu.prepend(t); } - if (this.options.target instanceof WasabeeAnchor) { - const portal = operation.getPortal(this.options.target.portalId); + if (this.options.target instanceof WasabeePortal) { + const portal = this.options.target; this._targettype = "anchor"; divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); const t = L.DomUtil.create("label", null); diff --git a/src/code/model/anchor.js b/src/code/model/anchor.js deleted file mode 100644 index 732ba0e74..000000000 --- a/src/code/model/anchor.js +++ /dev/null @@ -1,50 +0,0 @@ -import { getSelectedOperation } from "../selectedOp"; - -// this class is for the popups, and for assign menu -export default class WasabeeAnchor { - constructor(portalId) { - const op = getSelectedOperation(); - this.ID = portalId; - this.portalId = portalId; - this.type = "anchor"; - this.comment = null; - this.state = null; - this.assignedTo = null; - this.order = 0; - - this._portal = op.getPortal(this.ID); - this.color = op.color; - this._opID = op.ID; - } - - // currently unused - toJSON() { - return { - ID: this.ID, - portalId: this.portalId, - type: this.type, - comment: this.coment, - state: this.state, - assignedTo: this.assignedTo, - order: this.order, - color: this.color, - }; - } - - // pointless, since these are never pushed to the server - set opOrder(o) { - this.order = Number.parseInt(o, 10); - } - - get opOrder() { - return this.order; - } - - get name() { - return this._portal.name; - } - - get latLng() { - return this._portal.latLng; - } -} From a491972995b8b71078d62d10a77c865eeb11bfa5 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 2 Jul 2021 11:14:47 +0200 Subject: [PATCH 018/275] remove unused return --- src/code/ui/portal.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/code/ui/portal.js b/src/code/ui/portal.js index 0d6a227ae..2a057e21c 100644 --- a/src/code/ui/portal.js +++ b/src/code/ui/portal.js @@ -167,7 +167,6 @@ const WLPortal = L.Marker.extend({ ad.enable(); this.closePopup(); }); - return assignButton; }, _deleteButton: function (container, text) { @@ -189,7 +188,6 @@ const WLPortal = L.Marker.extend({ std.enable(); this.closePopup(); }); - return sendButton; }, _mapButton: function (container, text) { From a63828dd6c2f6f43a88b7e21cc4bb8cfb5d5424f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 2 Jul 2021 12:48:18 +0200 Subject: [PATCH 019/275] model default values --- src/code/model/agent.js | 8 ++++---- src/code/model/link.js | 8 ++++++-- src/code/model/marker.js | 8 ++++---- src/code/model/operation.js | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/code/model/agent.js b/src/code/model/agent.js index 3d13ab083..bf2332b21 100644 --- a/src/code/model/agent.js +++ b/src/code/model/agent.js @@ -23,11 +23,11 @@ export default class WasabeeAgent { this.intelname = obj.intelname; this.intelfaction = obj.intelfaction; this.level = obj.level ? Number(obj.level) : 0; - this.enlid = obj.enlid ? obj.enlid : 0; + this.enlid = obj.enlid ? obj.enlid : null; this.pic = obj.pic ? obj.pic : null; - this.Vverified = obj.Vverified ? obj.Vverified : false; - this.blacklisted = obj.blacklisted ? obj.blacklisted : false; - this.rocks = obj.rocks ? obj.rocks : false; + this.Vverified = !!obj.Vverified; + this.blacklisted = !!obj.blacklisted; + this.rocks = !!obj.rocks; this.lat = obj.lat ? obj.lat : 0; this.lng = obj.lng ? obj.lng : 0; this.date = obj.date ? obj.date : null; // last location sub, not fetched diff --git a/src/code/model/link.js b/src/code/model/link.js index e70da8ea3..aa2011988 100644 --- a/src/code/model/link.js +++ b/src/code/model/link.js @@ -6,14 +6,18 @@ export default class WasabeeLink { this.ID = obj.ID ? obj.ID : generateId(); this.fromPortalId = obj.fromPortalId; this.toPortalId = obj.toPortalId; - this.description = obj.description ? obj.description : null; - this.assignedTo = obj.assignedTo ? obj.assignedTo : ""; + this.description = obj.description; + this.assignedTo = obj.assignedTo ? obj.assignedTo : null; this.throwOrderPos = obj.throwOrderPos ? Number(obj.throwOrderPos) : 0; this.color = obj.color ? obj.color : "main"; this.completed = obj.completed ? !!obj.completed : false; this.zone = obj.zone ? Number(obj.zone) : 1; } + assign(gid) { + this.assignedTo = gid ? gid : null; + } + // build object to serialize toJSON() { return { diff --git a/src/code/model/marker.js b/src/code/model/marker.js index 0618026f3..94c181ae7 100644 --- a/src/code/model/marker.js +++ b/src/code/model/marker.js @@ -37,12 +37,12 @@ export default class WasabeeMarker { this.ID = obj.ID ? obj.ID : generateId(); this.portalId = obj.portalId; this.type = obj.type; - this.comment = obj.comment ? obj.comment : ""; // why "" and not null? This isn't go - this.completedID = obj.completedID ? obj.completedID : ""; + this.comment = obj.comment; + this.completedID = obj.completedID ? obj.completedID : null; this.order = obj.order ? Number(obj.order) : 0; this.zone = obj.zone ? Number(obj.zone) : 1; - this.assign(obj.assignedTo); // WAS this.assignedTo = obj.assignedTo ? obj.assignedTo : ""; + this.assign(obj.assignedTo); // WAS this.assignedTo = obj.assignedTo ? obj.assignedTo : null; // if ._state then it came from indexeddb, otherwise from server/localStorage if (obj._state) { this.state = obj._state; @@ -75,7 +75,7 @@ export default class WasabeeMarker { assign(gid) { if (!gid || gid == "") { this._state = STATE_UNASSIGNED; - this.assignedTo = ""; + this.assignedTo = null; return; } diff --git a/src/code/model/operation.js b/src/code/model/operation.js index 69709fd17..c200b385b 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -835,7 +835,7 @@ export default class WasabeeOp extends Evented { assignLink(id, gid) { for (const v of this.links) { if (v.ID == id) { - v.assignedTo = gid; + v.assign(gid); this.update(true); } } From 6117d0e59117d3eb42faabda48e363a364a7ef02 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 10 Jul 2021 10:31:03 +0200 Subject: [PATCH 020/275] fix: portal team is part of UI --- src/code/ui/portal.js | 1 + src/code/uiCommands.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/code/ui/portal.js b/src/code/ui/portal.js index 2a057e21c..95bbff0dd 100644 --- a/src/code/ui/portal.js +++ b/src/code/ui/portal.js @@ -228,5 +228,6 @@ export default { displayFormat, get, getSelected, + team, WLPortal, }; diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index 6cd4c0cc8..64947dbbd 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -366,7 +366,7 @@ export function blockerAutomark(operation, first = true) { // add marker let type = WasabeeMarker.constants.MARKER_TYPE_DESTROY; - if (wportal.team == "E") { + if (PortalUI.team(wportal) == "E") { type = WasabeeMarker.constants.MARKER_TYPE_VIRUS; } const zone = operation.determineZone(wportal.latLng); From 19e9b548c29ab3f625f8a40b513ac52b07ed7c8c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 19 Jul 2021 10:28:42 +0200 Subject: [PATCH 021/275] add blockers(_portals) to db --- src/code/db.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/code/db.js b/src/code/db.js index ede9a7200..2b2f7feff 100644 --- a/src/code/db.js +++ b/src/code/db.js @@ -1,6 +1,6 @@ import { openDB } from "idb"; -const version = 2; +const version = 3; // XXX audit these to make sure all the various indexes are used const db = openDB("wasabee", version, { @@ -27,6 +27,22 @@ const db = openDB("wasabee", version, { ops.createIndex("fetched", "fetched"); ops.createIndex("server", "server"); } + if (oldVersion < 3) { + // { opID, from, to } + const blockers = db.createObjectStore("blockers", { + keyPath: ["opID", "from", "to"], + }); + blockers.createIndex("opID", "opID", { unique: false }); + blockers.createIndex("from", ["opID", "from"], { unique: false }); + blockers.createIndex("to", ["opID", "to"], { unique: false }); + + // portals for blockers + // { id, lat, lng, name } + const portals = db.createObjectStore("blockers_portals", { + keyPath: ["opID", "id"], + }); + portals.createIndex("opID", "opID", { unique: false }); + } /* if (oldVersion < 3) { const teams = tx.objectStore("teams"); teams.createIndex("_agents", "_agents[].id"); From 657052f49874f4e41cc9b53a8cd8120a1dd80e15 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 10 Jul 2021 10:09:23 +0200 Subject: [PATCH 022/275] move blockers away from op object --- src/code/dialogs/blockersList.js | 44 +++++----- src/code/dialogs/markerChangeDialog.js | 2 + src/code/dialogs/mergeDialog.js | 2 - src/code/dialogs/trawl.js | 9 +- src/code/model/blocker.js | 109 +++++++++++++++++++++++++ src/code/model/operation.js | 72 +++------------- src/code/server.js | 2 - src/code/uiCommands.js | 65 +++++++++------ 8 files changed, 192 insertions(+), 113 deletions(-) create mode 100644 src/code/model/blocker.js diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index 9816be0ab..e4fe4478a 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -9,6 +9,7 @@ import { } from "../uiCommands"; import wX from "../wX"; import TrawlDialog from "./trawl"; +import WasabeeBlocker from "../model/blocker"; import PortalUI from "../ui/portal"; @@ -40,9 +41,9 @@ const BlockerList = WDialog.extend({ window.removeHook("portalDetailLoaded", listenForPortalDetails); }, - _displayDialog: function () { + _displayDialog: async function () { const operation = getSelectedOperation(); - this.sortable = this._getListDialogContent(0, false); // defaults to sorting by op order + this.sortable = await this._getListDialogContent(0, false); // defaults to sorting by op order loadFaked(operation); const buttons = {}; buttons[wX("OK")] = () => { @@ -52,9 +53,9 @@ const BlockerList = WDialog.extend({ const operation = getSelectedOperation(); blockerAutomark(operation); }; - buttons[wX("RESET")] = () => { + buttons[wX("RESET")] = async () => { const operation = getSelectedOperation(); - operation.blockers = new Array(); + await WasabeeBlocker.removeBlockers(operation); this.update(); operation.update(false); // blockers do not need to be sent to server window.map.fire("wasabee:crosslinks"); @@ -69,9 +70,11 @@ const BlockerList = WDialog.extend({ }; buttons["Clear Automark"] = () => { const operation = getSelectedOperation(); + operation.startBatchMode(); for (const m of operation.markers) { if (m.comment == "auto-marked") operation.removeMarker(m); } + operation.endBatchMode(); }; this.createDialog({ @@ -85,10 +88,10 @@ const BlockerList = WDialog.extend({ }, // when op changed or crosslink ended - update: function () { + update: async function () { const operation = getSelectedOperation(); if (!this._enabled) return; - this.sortable = this._getListDialogContent( + this.sortable = await this._getListDialogContent( this.sortable.sortBy, this.sortable.sortAsc ); @@ -97,28 +100,28 @@ const BlockerList = WDialog.extend({ }, // because the sortable values depend on the operation, we can't have it created at addHooks unless we want a lot of getSelectedOperations embedded here - _getListDialogContent(sortBy, sortAsc) { + async _getListDialogContent(sortBy, sortAsc) { const operation = getSelectedOperation(); const content = new Sortable(); + + const blockers = await WasabeeBlocker.getAll(operation); + content.fields = [ { name: wX("FROM_PORT"), value: (blocker) => { - return operation.getPortal(blocker.fromPortalId).name; + return blocker.fromPortal.name; }, sort: (a, b) => a.localeCompare(b), format: (row, value, blocker) => { - const p = operation.getPortal(blocker.fromPortalId); - row.appendChild(PortalUI.displayFormat(p)); + row.appendChild(PortalUI.displayFormat(blocker.fromPortal)); }, }, { name: this._smallScreen ? "#" : wX("COUNT"), value: (blocker) => { - const c = operation.blockers.filter( - (b) => - b.fromPortalId == blocker.fromPortalId || - b.toPortalID == blocker.fromPortalId + const c = blockers.filter( + (b) => b.from == blocker.from || b.to == blocker.from ); return c.length; }, @@ -127,21 +130,18 @@ const BlockerList = WDialog.extend({ { name: wX("TO_PORT"), value: (blocker) => { - return operation.getPortal(blocker.toPortalId).name; + return blocker.toPortal.name; }, sort: (a, b) => a.localeCompare(b), format: (row, value, blocker) => { - const p = operation.getPortal(blocker.toPortalId); - row.appendChild(PortalUI.displayFormat(p)); + row.appendChild(PortalUI.displayFormat(blocker.toPortal)); }, }, { name: this._smallScreen ? "#" : wX("COUNT"), value: (blocker) => { - const c = operation.blockers.filter( - (b) => - b.fromPortalId == blocker.toPortalId || - b.toPortalId == blocker.toPortalId + const c = blockers.filter( + (b) => b.from == blocker.to || b.to == blocker.to ); return c.length; }, @@ -150,7 +150,7 @@ const BlockerList = WDialog.extend({ ]; content.sortBy = sortBy; content.sortAsc = sortAsc; - content.items = operation.blockers; + content.items = blockers; return content; }, }); diff --git a/src/code/dialogs/markerChangeDialog.js b/src/code/dialogs/markerChangeDialog.js index 4f24c7062..308de782a 100644 --- a/src/code/dialogs/markerChangeDialog.js +++ b/src/code/dialogs/markerChangeDialog.js @@ -49,12 +49,14 @@ const MarkerChangeDialog = WDialog.extend({ WasabeeMarker.markerTypes.has(this._type.value) && !markers.has(this._type.value) ) { + operation.startBatchMode(); operation.removeMarker(this.options.marker); operation.addMarker(this._type.value, portal, { zone: this.options.marker.zone, comment: this.options.marker.comment, assign: this.options.marker.assignedTo, }); + operation.endBatchMode(); } this.closeDialog(); }; diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index fe619e7a9..3f76757a5 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -43,8 +43,6 @@ const MergeDialog = WDialog.extend({ }, useServer: async function () { - // merge blockers and related portals - this.options.opRemote.mergeBlockers(this.options.opOwn); await this.options.opRemote.store(); if (getSelectedOperation().ID == this.options.opRemote.ID) await makeSelectedOperation(this.options.opRemote.ID); diff --git a/src/code/dialogs/trawl.js b/src/code/dialogs/trawl.js index 35a83ac32..75a611b67 100644 --- a/src/code/dialogs/trawl.js +++ b/src/code/dialogs/trawl.js @@ -4,6 +4,7 @@ import { getSelectedOperation } from "../selectedOp"; import { blockerAutomark } from "../uiCommands"; import VLatLon from "geodesy/latlon-ellipsoidal-vincenty"; import WasabeeMarker from "../model/marker"; +import WasabeeBlocker from "../model/blocker"; const TrawlerDialog = WDialog.extend({ statics: { @@ -227,10 +228,10 @@ const TrawlDialog = WDialog.extend({ const button = L.DomUtil.create("button", null, container); button.textContent = wX("TRAWL"); - L.DomEvent.on(button, "click", () => { + L.DomEvent.on(button, "click", async () => { const op = getSelectedOperation(); if (clearMarkers.checked == true) this._clearMarkers(); - op.blockers = Array(); + await WasabeeBlocker.removeBlockers(op); const points = this._getTrawlPoints(); const td = new TrawlerDialog({ points: points, @@ -245,9 +246,9 @@ const TrawlDialog = WDialog.extend({ crazyWarning.textContent = wX("TRAWL_BULK_LOAD_WARNING"); const crazyButton = L.DomUtil.create("button", null, container); crazyButton.textContent = wX("TRAWL_BULK_LOAD"); - L.DomEvent.on(crazyButton, "click", () => { + L.DomEvent.on(crazyButton, "click", async () => { const op = getSelectedOperation(); - op.blockers = Array(); + await WasabeeBlocker.removeBlockers(op); if (clearMarkers.checked == true) this._clearMarkers(); const points = this._getTrawlPoints(); this._bulkLoad(points, 14); diff --git a/src/code/model/blocker.js b/src/code/model/blocker.js new file mode 100644 index 000000000..dabef533c --- /dev/null +++ b/src/code/model/blocker.js @@ -0,0 +1,109 @@ +import db from "../db"; + +export default class WasabeeBlocker { + constructor(obj) { + this.opID = obj.opID; + this.from = obj.fromPortal.id; + this.to = obj.toPortal.id; + } + + static async addPortal(op, portal) { + const store = await (await db).transaction("blockers_portals", "readwrite") + .store; + const ent = { + opID: op.ID, + id: portal.id, + name: portal.name, + lat: portal.lat, + lng: portal.lng, + }; + if (ent.id === ent.name) { + const p = await store.get([op.ID, ent.id]); + if (p && p.name !== p.id) ent.name = p.name; + } + await store.put(ent); + } + + static async updatePortal(op, portal) { + const store = (await db).transaction("blockers_portals", "readwrite").store; + if (portal.name === portal.id) return; + const p = await store.get([op.ID, portal.id]); + if (!p) return; + await store.put({ + opID: op.ID, + id: portal.id, + name: portal.name, + lat: portal.lat, + lng: portal.lng, + }); + return true; + } + + static async removeBlocker(op, portalId) { + const store = (await db).transaction("blockers", "readwrite").store; + let cursor = await store + .index("from") + .openKeyCursor(IDBKeyRange.only([op.ID, portalId])); + while (cursor) { + store.delete(cursor.primaryKey); + cursor = await cursor.continue(); + } + cursor = await store + .index("to") + .openKeyCursor(IDBKeyRange.only([op.ID, portalId])); + while (cursor) { + store.delete(cursor.primaryKey); + cursor = await cursor.continue(); + } + await (await db).delete("blockers_portals", [op.ID, portalId]); + } + + static async removeBlockers(op) { + let store = (await db).transaction("blockers", "readwrite").store; + let cursor = await store + .index("opID") + .openKeyCursor(IDBKeyRange.only(op.ID)); + while (cursor) { + store.delete(cursor.primaryKey); + cursor = await cursor.continue(); + } + store = (await db).transaction("blockers_portals", "readwrite").store; + cursor = await store.index("opID").openKeyCursor(IDBKeyRange.only(op.ID)); + while (cursor) { + store.delete(cursor.primaryKey); + cursor = await cursor.continue(); + } + } + + static async addBlocker(op, wlink) { + const fromPortal = op.getPortal(wlink.fromPortalId); + const toPortal = op.getPortal(wlink.toPortalId); + const blocker = new WasabeeBlocker({ + opID: op.ID, + fromPortal: fromPortal, + toPortal: toPortal, + }); + await (await db).put("blockers", blocker); + // to store portals + await WasabeeBlocker.addPortal(op, fromPortal); + await WasabeeBlocker.addPortal(op, toPortal); + } + + static async getAll(op) { + const blockers = await ( + await db + ).getAllFromIndex("blockers", "opID", op.ID); + const portals = await ( + await db + ).getAllFromIndex("blockers_portals", "opID", op.ID); + const portalsMap = new Map(); + for (const p of portals) { + portalsMap.set(p.id, p); + } + for (const b of blockers) { + b.fromPortal = portalsMap.get(b.from); + b.toPortal = portalsMap.get(b.to); + } + return blockers.filter((b) => b.fromPortal && b.toPortal); + } +} diff --git a/src/code/model/operation.js b/src/code/model/operation.js index c200b385b..3eb4e75c4 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -1,4 +1,5 @@ import WasabeeLink from "./link"; +import WasabeeBlocker from "./blocker"; import WasabeePortal from "./portal"; import WasabeeMarker from "./marker"; import WasabeeMe from "./me"; @@ -33,7 +34,6 @@ export default class WasabeeOp extends Evented { this.fetched = obj.fetched ? obj.fetched : null; this.stored = obj.stored ? obj.stored : null; this.localchanged = obj.localchanged === false ? obj.localchanged : true; - this.blockers = this.convertBlockersToObjs(obj.blockers); this.keysonhand = obj.keysonhand ? obj.keysonhand : Array(); this.zones = this.convertZonesToObjs(obj.zones); // this.modified = obj.modified ? obj.modified : null; @@ -50,7 +50,6 @@ export default class WasabeeOp extends Evented { if (!this.links) this.links = new Array(); if (!this.markers) this.markers = new Array(); - if (!this.blockers) this.blockers = new Array(); const opportals = this.convertPortalsToObjs(obj.opportals); this._idToOpportals = new Map(); @@ -116,7 +115,6 @@ export default class WasabeeOp extends Evented { json.fetched = this.fetched; json.stored = this.stored; json.localchanged = this.localchanged; - json.blockers = this.blockers; json.keysonhand = this.keysonhand; json.teamlist = this.teamlist; json.background = this.background; @@ -221,10 +219,6 @@ export default class WasabeeOp extends Evented { m.portalId = rename.get(m.portalId); } this.anchors = this.anchors.map((a) => rename.get(a)); - for (const b of this.blockers) { - b.fromPortalId = rename.get(b.fromPortalId); - b.toPortalId = rename.get(b.toPortalId); - } for (const id of toRemove) this._idToOpportals.delete(id); } @@ -502,33 +496,25 @@ export default class WasabeeOp extends Evented { for (const a of this.anchors) { newPortals.set(a, this._idToOpportals.get(a)); } - for (const b of this.blockers) { - newPortals.set(b.fromPortalId, this._idToOpportals.get(b.fromPortalId)); - newPortals.set(b.toPortalId, this._idToOpportals.get(b.toPortalId)); - } // sanitize OP if it get corrupt by my code elsewhere... const missingPortal = new Set(); - let corrupt = - this.links.length + this.markers.length + this.blockers.length; + let corrupt = this.links.length + this.markers.length; for (const [id, v] of newPortals) { if (v === undefined) { this.links = this.links.filter( (l) => l.fromPortalId != id && l.toPortalId != id ); this.markers = this.markers.filter((m) => m.portalId != id); - this.blockers = this.blockers.filter( - (b) => b.fromPortalId != id && b.toPortalId != id - ); missingPortal.add(id); } } - corrupt -= this.links.length + this.markers.length + this.blockers.length; + corrupt -= this.links.length + this.markers.length; if (missingPortal.size > 0) { // leave some trace console.trace("op corruption: missing portals"); alert( - `Oops, something went wrong and OP ${this.name} got corrupted. Fix by removing ${missingPortal.size} missing portals and ${corrupt} links/markers/blockers. Please check your OP and report to the devs.` + `Oops, something went wrong and OP ${this.name} got corrupted. Fix by removing ${missingPortal.size} missing portals and ${corrupt} links/markers. Please check your OP and report to the devs.` ); this.cleanAnchorList(); for (const id of missingPortal) newPortals.delete(id); @@ -596,9 +582,8 @@ export default class WasabeeOp extends Evented { if (m.portalId == old.id) m.portalId = fake.id; } // remove blockers on the old portal - this.blockers = this.blockers.filter( - (b) => b.fromPortalId != old.id && b.toPortalId != old.id - ); + WasabeeBlocker.removeBlocker(this, old.id); + this._idToOpportals.delete(old.id); // add the new portal so any data related to the real portal (keys) still works this._addPortal(portal); @@ -625,10 +610,7 @@ export default class WasabeeOp extends Evented { for (const m of this.markers) { if (m.portalId == old.id) m.portalId = portal.id; } - for (const b of this.blockers) { - if (b.fromPortalId == old.id) b.fromPortalId = portal.id; - if (b.toPortalId == old.id) b.toPortalId = portal.id; - } + this._idToOpportals.delete(old.id); //this.opportals = Array.from(this._idToOpportals.values()); @@ -703,27 +685,9 @@ export default class WasabeeOp extends Evented { } } - containsBlocker(link) { - if (!this.blockers || this.blockers.length == 0) return false; - - for (const l of this.blockers) { - if ( - l.fromPortalId == link.fromPortalId && - l.toPortalId == link.toPortalId - ) { - return true; - } - } - return false; - } - addBlocker(link) { if (!link.fromPortalId || !link.toPortalId) return; - if (!this.containsBlocker(link)) { - this.blockers.push(link); - // this.update(false); // can trigger a redraw-storm, just skip - // this.store(); // do not await, let it happen in the background -- ideally now blockers should not be part of the op json, but stored independently in indexeddb - } + WasabeeBlocker.addBlocker(this, link); } get fakedPortals() { @@ -811,9 +775,7 @@ export default class WasabeeOp extends Evented { ]; if (destructMarkerTypes.includes(markerType)) { // remove related blockers - this.blockers = this.blockers.filter( - (b) => b.fromPortalId !== portal.id && b.toPortalId !== portal.id - ); + WasabeeBlocker.removeBlocker(this, portal.id); } this.update(true); @@ -845,7 +807,6 @@ export default class WasabeeOp extends Evented { this.anchors = Array(); this.links = Array(); this.markers = Array(); - this.blockers = Array(); this._idToOpportals.clear(); this._coordsToOpportals.clear(); @@ -854,7 +815,6 @@ export default class WasabeeOp extends Evented { clearAllLinks() { this.links = Array(); - this.blockers = Array(); this.cleanAnchorList(); this.cleanPortalList(); this.update(true); @@ -1293,14 +1253,6 @@ export default class WasabeeOp extends Evented { return this.localchanged; } - mergeBlockers(op) { - // merge portals - for (const p of op.opportals) { - this._addPortal(p); - } - for (const b of op.blockers) this.blockers.push(b); // do not use addBlocker - } - mergeZones(op) { const ids = new Set(); let count = 0; @@ -1347,8 +1299,10 @@ export default class WasabeeOp extends Evented { }, }; - // merge *portals* and blockers - this.mergeBlockers(op); + // merge *portals* + for (const p of op.opportals) { + this._addPortal(p); + } // add missing zones summary.addition.zone = this.mergeZones(op); diff --git a/src/code/server.js b/src/code/server.js index f4b01b3f4..0a7d32e9b 100644 --- a/src/code/server.js +++ b/src/code/server.js @@ -22,8 +22,6 @@ export async function uploadOpPromise() { const newme = new WasabeeMe(response); newme.store(); const newop = await opPromise(operation.ID); - // merge blockers and related portals - newop.mergeBlockers(operation); newop.localchanged = false; await newop.store(); return newop; diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index 64947dbbd..63de31018 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -1,5 +1,6 @@ import WasabeeOp from "./model/operation"; import WasabeePortal from "./model/portal"; +import WasabeeBlocker from "./model/blocker"; import WasabeeMarker from "./model/marker"; import ConfirmDialog from "./dialogs/confirmDialog"; import MergeDialog from "./dialogs/mergeDialog"; @@ -134,15 +135,15 @@ export function listenForAddedPortals(newPortal) { export function listenForPortalDetails(e) { if (!e.success) return; + const portal = new WasabeePortal({ + id: e.guid, + name: e.details.title, + lat: (e.details.latE6 / 1e6).toFixed(6), + lng: (e.details.lngE6 / 1e6).toFixed(6), + }); const op = getSelectedOperation(); - op.updatePortal( - new WasabeePortal({ - id: e.guid, - name: e.details.title, - lat: (e.details.latE6 / 1e6).toFixed(6), - lng: (e.details.lngE6 / 1e6).toFixed(6), - }) - ); + op.updatePortal(portal); + WasabeeBlocker.updatePortal(op, portal); } // This is what should be called to add to the queue @@ -317,25 +318,47 @@ export function testPortal(recursed = false) { } // recursive function to auto-mark blockers -export function blockerAutomark(operation, first = true) { - if (first) operation.startBatchMode(); +export async function blockerAutomark(operation, first = true) { + const blockers = await WasabeeBlocker.getAll(operation); + if (first) { + operation.startBatchMode(); + // add blocker portals + for (const b of blockers) { + operation._addPortal( + new WasabeePortal({ + id: b.from, + name: b.fromPortal.name, + lat: b.fromPortal.lat, + lng: b.fromPortal.lng, + }) + ); + operation._addPortal( + new WasabeePortal({ + id: b.to, + name: b.toPortal.name, + lat: b.toPortal.lat, + lng: b.toPortal.lng, + }) + ); + } + } // build count list const portals = new Array(); - for (const b of operation.blockers) { + for (const b of blockers) { if ( !operation.containsMarkerByID( - b.fromPortalId, + b.from, WasabeeMarker.constants.MARKER_TYPE_EXCLUDE ) ) - portals.push(b.fromPortalId); + portals.push(b.from); if ( !operation.containsMarkerByID( - b.toPortalId, + b.to, WasabeeMarker.constants.MARKER_TYPE_EXCLUDE ) ) - portals.push(b.toPortalId); + portals.push(b.to); } const reduced = {}; for (const p of portals) { @@ -373,12 +396,10 @@ export function blockerAutomark(operation, first = true) { operation.addMarker(type, wportal, { comment: "auto-marked", zone: zone }); // remove nodes from blocker list - operation.blockers = operation.blockers.filter((b) => { - if (b.fromPortalId == portalId || b.toPortalId == portalId) return false; - return true; - }); + await WasabeeBlocker.removeBlocker(operation, portalId); + // recurse - blockerAutomark(operation, false); + await blockerAutomark(operation, false); if (first) operation.endBatchMode(); } @@ -407,8 +428,6 @@ export async function updateLocalOp(local, remote) { // no changes if (!op.checkChanges()) { - // merge blockers and related portals - remote.mergeBlockers(op); await remote.store(); // if selected op, reload from the new op return remote.ID === so.ID; @@ -504,8 +523,6 @@ export async function syncOp(opID) { const remoteOp = await opPromise(opID); if (remoteOp.lasteditid != localOp.lasteditid) { if (!localOp.localchanged) { - // merge blockers and related portals - remoteOp.mergeBlockers(localOp); await remoteOp.store(); } else { const con = new MergeDialog({ From f6c22a634ae16221b4effe013fdc459579d5b9d3 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 10 Jul 2021 18:58:46 +0200 Subject: [PATCH 023/275] change op.addBlocker --- src/code/crosslinks.js | 8 +------- src/code/model/blocker.js | 4 +--- src/code/model/operation.js | 5 ++--- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/code/crosslinks.js b/src/code/crosslinks.js index c7818825f..dd186dba1 100644 --- a/src/code/crosslinks.js +++ b/src/code/crosslinks.js @@ -188,7 +188,6 @@ function testLink(link, operation) { (link.options.data.oLngE6 / 1e6).toFixed(6), link.options.data.oGuid ); - operation._addPortal(fromPortal); let toPortal = PortalUI.get(link.options.data.dGuid); if (!toPortal) toPortal = WasabeePortal.fake( @@ -196,12 +195,7 @@ function testLink(link, operation) { (link.options.data.dLngE6 / 1e6).toFixed(6), link.options.data.dGuid ); - operation._addPortal(toPortal); - const blocker = new WasabeeLink( - { fromPortalId: fromPortal.id, toPortalId: toPortal.id }, - operation - ); - operation.addBlocker(blocker); // op.update() is called here + operation.addBlocker(fromPortal, toPortal); break; } } diff --git a/src/code/model/blocker.js b/src/code/model/blocker.js index dabef533c..092ef6a5b 100644 --- a/src/code/model/blocker.js +++ b/src/code/model/blocker.js @@ -75,9 +75,7 @@ export default class WasabeeBlocker { } } - static async addBlocker(op, wlink) { - const fromPortal = op.getPortal(wlink.fromPortalId); - const toPortal = op.getPortal(wlink.toPortalId); + static async addBlocker(op, fromPortal, toPortal) { const blocker = new WasabeeBlocker({ opID: op.ID, fromPortal: fromPortal, diff --git a/src/code/model/operation.js b/src/code/model/operation.js index 3eb4e75c4..70ff32399 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -685,9 +685,8 @@ export default class WasabeeOp extends Evented { } } - addBlocker(link) { - if (!link.fromPortalId || !link.toPortalId) return; - WasabeeBlocker.addBlocker(this, link); + addBlocker(fromPortal, toPortal) { + WasabeeBlocker.addBlocker(this, fromPortal, toPortal); } get fakedPortals() { From c6cdc8155dd03d5fd912bd97088daada9d3d64e7 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 10 Jul 2021 22:32:25 +0200 Subject: [PATCH 024/275] update blocker portals --- src/code/crosslinks.js | 1 - src/code/dialogs/blockersList.js | 18 ++++++++++-------- src/code/model/blocker.js | 14 ++++++++++---- src/code/uiCommands.js | 4 +++- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/code/crosslinks.js b/src/code/crosslinks.js index dd186dba1..98765f51d 100644 --- a/src/code/crosslinks.js +++ b/src/code/crosslinks.js @@ -1,5 +1,4 @@ import WasabeePortal from "./model/portal"; -import WasabeeLink from "./model/link"; import WasabeeMarker from "./model/marker"; import { getSelectedOperation } from "./selectedOp"; diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index e4fe4478a..5b0fe96de 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -109,12 +109,13 @@ const BlockerList = WDialog.extend({ content.fields = [ { name: wX("FROM_PORT"), - value: (blocker) => { - return blocker.fromPortal.name; - }, + value: (blocker) => + blocker.fromPortal ? blocker.fromPortal.name : blocker.from, sort: (a, b) => a.localeCompare(b), format: (row, value, blocker) => { - row.appendChild(PortalUI.displayFormat(blocker.fromPortal)); + if (blocker.fromPortal) + row.appendChild(PortalUI.displayFormat(blocker.fromPortal)); + else row.textContent = value; }, }, { @@ -129,12 +130,13 @@ const BlockerList = WDialog.extend({ }, { name: wX("TO_PORT"), - value: (blocker) => { - return blocker.toPortal.name; - }, + value: (blocker) => + blocker.toPortal ? blocker.toPortal.name : blocker.to, sort: (a, b) => a.localeCompare(b), format: (row, value, blocker) => { - row.appendChild(PortalUI.displayFormat(blocker.toPortal)); + if (blocker.toPortal) + row.appendChild(PortalUI.displayFormat(blocker.toPortal)); + else row.textContent = value; }, }, { diff --git a/src/code/model/blocker.js b/src/code/model/blocker.js index 092ef6a5b..c829af212 100644 --- a/src/code/model/blocker.js +++ b/src/code/model/blocker.js @@ -29,6 +29,7 @@ export default class WasabeeBlocker { if (portal.name === portal.id) return; const p = await store.get([op.ID, portal.id]); if (!p) return; + if (p.name === portal.name) return; await store.put({ opID: op.ID, id: portal.id, @@ -87,13 +88,18 @@ export default class WasabeeBlocker { await WasabeeBlocker.addPortal(op, toPortal); } + static async getPortals(op) { + const portals = await ( + await db + ).getAllFromIndex("blockers_portals", "opID", op.ID); + return portals; + } + static async getAll(op) { const blockers = await ( await db ).getAllFromIndex("blockers", "opID", op.ID); - const portals = await ( - await db - ).getAllFromIndex("blockers_portals", "opID", op.ID); + const portals = await WasabeeBlocker.getPortals(op); const portalsMap = new Map(); for (const p of portals) { portalsMap.set(p.id, p); @@ -102,6 +108,6 @@ export default class WasabeeBlocker { b.fromPortal = portalsMap.get(b.from); b.toPortal = portalsMap.get(b.to); } - return blockers.filter((b) => b.fromPortal && b.toPortal); + return blockers; } } diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index 63de31018..a1e80784f 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -130,7 +130,9 @@ export function listenForAddedPortals(newPortal) { if (!newPortal.portal.options.data.title) return; const op = getSelectedOperation(); - op.updatePortal(PortalUI.fromIITC(newPortal.portal)); + const portal = PortalUI.fromIITC(newPortal.portal); + op.updatePortal(portal); + WasabeeBlocker.updatePortal(op, portal); } export function listenForPortalDetails(e) { From bcee6eff3355b0296a38c133ac21a9c3a278ff9b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 15 Jul 2021 16:44:22 +0200 Subject: [PATCH 025/275] clean blockers with ops --- src/code/dialogs/blockersList.js | 2 +- src/code/dialogs/trawl.js | 4 ++-- src/code/model/blocker.js | 6 +++--- src/code/selectedOp.js | 8 +++++++- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index 5b0fe96de..914eb98e3 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -55,7 +55,7 @@ const BlockerList = WDialog.extend({ }; buttons[wX("RESET")] = async () => { const operation = getSelectedOperation(); - await WasabeeBlocker.removeBlockers(operation); + await WasabeeBlocker.removeBlockers(operation.ID); this.update(); operation.update(false); // blockers do not need to be sent to server window.map.fire("wasabee:crosslinks"); diff --git a/src/code/dialogs/trawl.js b/src/code/dialogs/trawl.js index 75a611b67..187a3c0bc 100644 --- a/src/code/dialogs/trawl.js +++ b/src/code/dialogs/trawl.js @@ -231,7 +231,7 @@ const TrawlDialog = WDialog.extend({ L.DomEvent.on(button, "click", async () => { const op = getSelectedOperation(); if (clearMarkers.checked == true) this._clearMarkers(); - await WasabeeBlocker.removeBlockers(op); + await WasabeeBlocker.removeBlockers(op.ID); const points = this._getTrawlPoints(); const td = new TrawlerDialog({ points: points, @@ -248,7 +248,7 @@ const TrawlDialog = WDialog.extend({ crazyButton.textContent = wX("TRAWL_BULK_LOAD"); L.DomEvent.on(crazyButton, "click", async () => { const op = getSelectedOperation(); - await WasabeeBlocker.removeBlockers(op); + await WasabeeBlocker.removeBlockers(op.ID); if (clearMarkers.checked == true) this._clearMarkers(); const points = this._getTrawlPoints(); this._bulkLoad(points, 14); diff --git a/src/code/model/blocker.js b/src/code/model/blocker.js index c829af212..414fbc8a7 100644 --- a/src/code/model/blocker.js +++ b/src/code/model/blocker.js @@ -59,17 +59,17 @@ export default class WasabeeBlocker { await (await db).delete("blockers_portals", [op.ID, portalId]); } - static async removeBlockers(op) { + static async removeBlockers(opID) { let store = (await db).transaction("blockers", "readwrite").store; let cursor = await store .index("opID") - .openKeyCursor(IDBKeyRange.only(op.ID)); + .openKeyCursor(IDBKeyRange.only(opID)); while (cursor) { store.delete(cursor.primaryKey); cursor = await cursor.continue(); } store = (await db).transaction("blockers_portals", "readwrite").store; - cursor = await store.index("opID").openKeyCursor(IDBKeyRange.only(op.ID)); + cursor = await store.index("opID").openKeyCursor(IDBKeyRange.only(opID)); while (cursor) { store.delete(cursor.primaryKey); cursor = await cursor.continue(); diff --git a/src/code/selectedOp.js b/src/code/selectedOp.js index ba891b706..e55873171 100644 --- a/src/code/selectedOp.js +++ b/src/code/selectedOp.js @@ -1,4 +1,5 @@ import WasabeeOp from "./model/operation"; +import WasabeeBlocker from "./model/blocker"; import wX from "./wX"; import { generateId } from "./auxiliar"; @@ -138,6 +139,7 @@ export async function setupLocalStorage() { //** This function removes an operation from the main list */ export async function removeOperation(opID) { await WasabeeOp.delete(opID); + WasabeeBlocker.removeBlockers(opID); // no need to await window.map.fire("wasabee:op:delete", opID); } @@ -172,6 +174,7 @@ export async function resetOps() { const ops = await opsList(); // don't fire event here await Promise.all(ops.map(WasabeeOp.delete)); + ops.map(WasabeeBlocker.removeBlockers); // no need to await } export function hiddenOpsList() { @@ -245,7 +248,10 @@ export async function removeNonOwnedOps() { for (const opID of await opsList()) { const op = await WasabeeOp.load(opID); // don't fire event here - if (!op || !op.isOwnedOp()) await WasabeeOp.delete(opID); + if (!op || !op.isOwnedOp()) { + await WasabeeOp.delete(opID); + WasabeeBlocker.removeBlockers(opID); // no need to await + } } await changeOpIfNeeded(); } From e7a7bc489c9e0c12ccba252f30b71b49ca995213 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 18 Jul 2021 13:33:34 +0200 Subject: [PATCH 026/275] handle fake blocker portals --- src/code/dialogs/blockersList.js | 9 +++++---- src/code/model/blocker.js | 6 +++--- src/code/uiCommands.js | 23 +++++++++++++++++++++-- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index 914eb98e3..91bb5a53a 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -4,7 +4,7 @@ import { getSelectedOperation } from "../selectedOp"; import { listenForAddedPortals, listenForPortalDetails, - loadFaked, + loadBlockerFaked, blockerAutomark, } from "../uiCommands"; import wX from "../wX"; @@ -25,6 +25,7 @@ const BlockerList = WDialog.extend({ addHooks: function () { WDialog.prototype.addHooks.call(this); window.map.on("wasabee:op:select wasabee:op:change", this.update, this); + window.map.on("wasabee:crosslinks:update", this.update, this); window.map.on("wasabee:crosslinks:done", this.update, this); window.addHook("portalAdded", listenForAddedPortals); @@ -35,6 +36,7 @@ const BlockerList = WDialog.extend({ removeHooks: function () { WDialog.prototype.removeHooks.call(this); window.map.off("wasabee:op:select wasabee:op:change", this.update, this); + window.map.off("wasabee:crosslinks:update", this.update, this); window.map.off("wasabee:crosslinks:done", this.update, this); window.removeHook("portalAdded", listenForAddedPortals); @@ -44,7 +46,7 @@ const BlockerList = WDialog.extend({ _displayDialog: async function () { const operation = getSelectedOperation(); this.sortable = await this._getListDialogContent(0, false); // defaults to sorting by op order - loadFaked(operation); + loadBlockerFaked(operation); const buttons = {}; buttons[wX("OK")] = () => { this.closeDialog(); @@ -57,12 +59,11 @@ const BlockerList = WDialog.extend({ const operation = getSelectedOperation(); await WasabeeBlocker.removeBlockers(operation.ID); this.update(); - operation.update(false); // blockers do not need to be sent to server window.map.fire("wasabee:crosslinks"); }; buttons[wX("LOAD PORTALS")] = () => { const operation = getSelectedOperation(); - loadFaked(operation, true); // force + loadBlockerFaked(operation, true); // force }; buttons[wX("TRAWL TITLE")] = () => { const td = new TrawlDialog(); diff --git a/src/code/model/blocker.js b/src/code/model/blocker.js index 414fbc8a7..6f1a1e327 100644 --- a/src/code/model/blocker.js +++ b/src/code/model/blocker.js @@ -26,10 +26,10 @@ export default class WasabeeBlocker { static async updatePortal(op, portal) { const store = (await db).transaction("blockers_portals", "readwrite").store; - if (portal.name === portal.id) return; + if (portal.name === portal.id) return false; const p = await store.get([op.ID, portal.id]); - if (!p) return; - if (p.name === portal.name) return; + if (!p) return false; + if (p.name === portal.name) return false; await store.put({ opID: op.ID, id: portal.id, diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index a1e80784f..83ed65075 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -132,7 +132,9 @@ export function listenForAddedPortals(newPortal) { const op = getSelectedOperation(); const portal = PortalUI.fromIITC(newPortal.portal); op.updatePortal(portal); - WasabeeBlocker.updatePortal(op, portal); + WasabeeBlocker.updatePortal(op, portal).then((r) => { + if (r) window.map.fire("wasabee:crosslinks:update"); + }); } export function listenForPortalDetails(e) { @@ -145,7 +147,9 @@ export function listenForPortalDetails(e) { }); const op = getSelectedOperation(); op.updatePortal(portal); - WasabeeBlocker.updatePortal(op, portal); + WasabeeBlocker.updatePortal(op, portal).then((r) => { + if (r) window.map.fire("wasabee:crosslinks:update"); + }); } // This is what should be called to add to the queue @@ -197,6 +201,7 @@ function pdqDoNext() { window.portalDetail.request(p); } +// load faked op portals export function loadFaked(operation, force = false) { const flag = localStorage[window.plugin.wasabee.static.constants.AUTO_LOAD_FAKED] || @@ -210,6 +215,20 @@ export function loadFaked(operation, force = false) { if (f.length > 0) getPortalDetails(f); } +// load faked blocker portals +export async function loadBlockerFaked(operation, force = false) { + const flag = + localStorage[window.plugin.wasabee.static.constants.AUTO_LOAD_FAKED] || + false; + + // local storage always returns as string + if (flag !== "true" && !force) return; + + const bp = await WasabeeBlocker.getPortals(operation); + const f = bp.filter((p) => p.id === p.name).map((p) => p.id); + if (f.length > 0) getPortalDetails(f); +} + export function sendLocation() { if (!WasabeeMe.isLoggedIn()) return; const sl = From e856a887061ca8ad49067fd61d64ffdbf6e81607 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 18 Jul 2021 14:10:56 +0200 Subject: [PATCH 027/275] remove blockers from op except for blockers event --- src/code/crosslinks.js | 3 ++- src/code/dialogs/markerAddDialog.js | 7 ++++-- src/code/dialogs/markerChangeDialog.js | 3 +++ src/code/model/blocker.js | 6 +++++ src/code/model/marker.js | 14 +++++++++++ src/code/model/operation.js | 35 +++----------------------- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/code/crosslinks.js b/src/code/crosslinks.js index 98765f51d..7c978b5c8 100644 --- a/src/code/crosslinks.js +++ b/src/code/crosslinks.js @@ -1,5 +1,6 @@ import WasabeePortal from "./model/portal"; import WasabeeMarker from "./model/marker"; +import WasabeeBlocker from "./model/blocker"; import { getSelectedOperation } from "./selectedOp"; import PortalUI from "./ui/portal"; @@ -194,7 +195,7 @@ function testLink(link, operation) { (link.options.data.dLngE6 / 1e6).toFixed(6), link.options.data.dGuid ); - operation.addBlocker(fromPortal, toPortal); + WasabeeBlocker.addBlocker(operation, fromPortal, toPortal); break; } } diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index a5da9ae1f..30fcf9e72 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -2,6 +2,7 @@ import { WDialog } from "../leafletClasses"; import WasabeeMe from "../model/me"; import WasabeeTeam from "../model/team"; import WasabeeMarker from "../model/marker"; +import WasabeeBlocker from "../model/blocker"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; @@ -149,9 +150,11 @@ const MarkerAddDialog = WDialog.extend({ }; // XXX remove comment from args in 0.20 - if (operation.addMarker(selectedType, PortalUI.getSelected(), options)) + if (operation.addMarker(selectedType, PortalUI.getSelected(), options)) { + if (WasabeeMarker.isDestructMarkerType(selectedType)) + WasabeeBlocker.removeBlocker(operation, PortalUI.getSelected().id); await this.update(); - else alert(wX("ALREADY_HAS_MARKER")); + } else alert(wX("ALREADY_HAS_MARKER")); localStorage[window.plugin.wasabee.static.constants.LAST_MARKER_KEY] = selectedType; }, diff --git a/src/code/dialogs/markerChangeDialog.js b/src/code/dialogs/markerChangeDialog.js index 308de782a..27c7723a3 100644 --- a/src/code/dialogs/markerChangeDialog.js +++ b/src/code/dialogs/markerChangeDialog.js @@ -2,6 +2,7 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; import WasabeeMarker from "../model/marker"; +import WasabeeBlocker from "../model/blocker"; import PortalUI from "../ui/portal"; @@ -56,6 +57,8 @@ const MarkerChangeDialog = WDialog.extend({ comment: this.options.marker.comment, assign: this.options.marker.assignedTo, }); + if (WasabeeMarker.isDestructMarkerType(this._type.value)) + WasabeeBlocker.removeBlocker(operation, portal.id); operation.endBatchMode(); } this.closeDialog(); diff --git a/src/code/model/blocker.js b/src/code/model/blocker.js index 6f1a1e327..56d6163c4 100644 --- a/src/code/model/blocker.js +++ b/src/code/model/blocker.js @@ -24,11 +24,17 @@ export default class WasabeeBlocker { await store.put(ent); } + // return true if a blocker portal is updated static async updatePortal(op, portal) { const store = (await db).transaction("blockers_portals", "readwrite").store; if (portal.name === portal.id) return false; const p = await store.get([op.ID, portal.id]); if (!p) return false; + if (p.lat !== portal.lat || p.lng !== portal.lng) { + // portal move, drop blockers + await WasabeeBlocker.removeBlocker(op, portal.id); + return true; + } if (p.name === portal.name) return false; await store.put({ opID: op.ID, diff --git a/src/code/model/marker.js b/src/code/model/marker.js index 94c181ae7..ae7e18dea 100644 --- a/src/code/model/marker.js +++ b/src/code/model/marker.js @@ -16,6 +16,12 @@ const markers = { MARKER_TYPE_VIRUS: "UseVirusPortalAlert", }; +const destructMarkerTypes = [ + markers.MARKER_TYPE_DECAY, + markers.MARKER_TYPE_DESTROY, + markers.MARKER_TYPE_VIRUS, +]; + const markerTypes = new Set(Object.values(markers)); const STATE_UNASSIGNED = "pending"; @@ -110,4 +116,12 @@ export default class WasabeeMarker { get state() { return this._state; } + + isDestructMarker() { + return destructMarkerTypes.includes(this.type); + } + + static isDestructMarkerType(type) { + return destructMarkerTypes.includes(type); + } } diff --git a/src/code/model/operation.js b/src/code/model/operation.js index 70ff32399..cb0b450ab 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -1,5 +1,4 @@ import WasabeeLink from "./link"; -import WasabeeBlocker from "./blocker"; import WasabeePortal from "./portal"; import WasabeeMarker from "./marker"; import WasabeeMe from "./me"; @@ -147,7 +146,7 @@ export default class WasabeeOp extends Evented { ID: this.ID, name: this.name, creator: this.creator, - opportals: Array.from(this._idToOpportals.values()), // includes blocker portals + opportals: Array.from(this._idToOpportals.values()), anchors: this.anchors, links: this.links, markers: this.markers, @@ -162,6 +161,7 @@ export default class WasabeeOp extends Evented { toExport() { // round-trip through JSON.stringify to ensure a deep copy const o = new WasabeeOp(JSON.stringify(this)); + // drop +0.21 o.cleanPortalList(); // remove portals which are only relevant to blockers return JSON.stringify(o); } @@ -581,8 +581,6 @@ export default class WasabeeOp extends Evented { for (const m of this.markers) { if (m.portalId == old.id) m.portalId = fake.id; } - // remove blockers on the old portal - WasabeeBlocker.removeBlocker(this, old.id); this._idToOpportals.delete(old.id); // add the new portal so any data related to the real portal (keys) still works @@ -685,10 +683,6 @@ export default class WasabeeOp extends Evented { } } - addBlocker(fromPortal, toPortal) { - WasabeeBlocker.addBlocker(this, fromPortal, toPortal); - } - get fakedPortals() { const c = Array.from(this._idToOpportals.values()).filter((p) => p.faked); return c; @@ -766,21 +760,10 @@ export default class WasabeeOp extends Evented { marker.assign(options.assign); this.markers.push(marker); - // only need this for virus/destroy/decay -- this should be in the marker class - const destructMarkerTypes = [ - WasabeeMarker.constants.MARKER_TYPE_DECAY, - WasabeeMarker.constants.MARKER_TYPE_DESTROY, - WasabeeMarker.constants.MARKER_TYPE_VIRUS, - ]; - if (destructMarkerTypes.includes(markerType)) { - // remove related blockers - WasabeeBlocker.removeBlocker(this, portal.id); - } - this.update(true); // run crosslink to update the layer // XXX: we don't need to check, only redraw, so we need something clever, probably in mapDraw or crosslink.js - if (destructMarkerTypes.includes(markerType)) this.updateBlockers(); + if (marker.isDestructMarker()) this.updateBlockers(); return true; } @@ -862,15 +845,6 @@ export default class WasabeeOp extends Evented { return tmpLinks; } - convertBlockersToObjs(links) { - const tmpLinks = new Array(); - if (!links || links.length == 0) return tmpLinks; - for (const l of links) { - tmpLinks.push(new WasabeeLink(l, this)); - } - return tmpLinks; - } - convertMarkersToObjs(markers) { const tmpMarkers = new Array(); if (!markers || markers.length == 0) return tmpMarkers; @@ -1166,7 +1140,6 @@ export default class WasabeeOp extends Evented { if (oldOp.name != this.name) changes.name = this.name; if (oldOp.color != this.color) changes.color = this.color; if (oldOp.comment != this.comment) changes.comment = this.comment; - // blockers: ignored by the server, handle them later // zones: handle them later for (const [id, p] of this._idToOpportals) { @@ -1267,7 +1240,7 @@ export default class WasabeeOp extends Evented { return count; } - // assume that `this` is a server OP (no blockers, teams/keys are correct) + // assume that `this` is a server OP (teams/keys are correct) applyChanges(changes, op) { const summary = { compatibility: { From 114f86a1b4656a344fe4effdd454a29a7d7c2210 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 18 Jul 2021 16:23:57 +0200 Subject: [PATCH 028/275] sortable: handle [fulfilled] rows Promise.all is async even if all promises are already fulfilled --- src/code/sortable.js | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/code/sortable.js b/src/code/sortable.js index c4b4e2bb4..30a442d0d 100644 --- a/src/code/sortable.js +++ b/src/code/sortable.js @@ -67,6 +67,7 @@ export default class Sortable { // class getters and setter's can't be async, // this lets us build each row as a promise, then resolve them all together + const instantValues = []; const promises = incoming.map(async (obj) => { const row = L.DomUtil.create("tr"); const data = { @@ -105,23 +106,32 @@ export default class Sortable { cell.style.display = "none"; } } + instantValues.push(data); return data; }); // resolve all rows at once // XXX convert to allSettled and check for individual errors rather than failing hard if any row fails // console.log(promises); - this._done = Promise.all(promises).then( - (values) => { - this._items = values; - this.sort(); - return true; - }, - (reject) => { - console.log("rejected", reject); - this._done = false; - } - ); + if (instantValues.length === promises.length) { + // all promises are already fulfilled, dont use async Promise.all + this._items = instantValues; + this.sort(); + this._done = true; + } else { + // always async + this._done = Promise.all(promises).then( + (values) => { + this._items = values; + this.sort(); + return true; + }, + (reject) => { + console.log("rejected", reject); + this._done = false; + } + ); + } } get fields() { From 896bc4f5dda88e080a795e7b6dae836a61edc95f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 18 Jul 2021 16:50:58 +0200 Subject: [PATCH 029/275] wait for async content before creating dialog --- src/code/dialogs/linkListDialog.js | 4 +++- src/code/dialogs/manageTeamDialog.js | 18 +++++++++--------- src/code/dialogs/markerList.js | 4 +++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/code/dialogs/linkListDialog.js b/src/code/dialogs/linkListDialog.js index 8d384d2de..5255d9246 100644 --- a/src/code/dialogs/linkListDialog.js +++ b/src/code/dialogs/linkListDialog.js @@ -45,7 +45,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ return fields.slice(0, 2).concat(linkFields, fields.slice(3)); }, - _displayDialog: function () { + _displayDialog: async function () { const operation = getSelectedOperation(); loadFaked(operation); const links = operation.getLinkListFromPortal(this.options.portal); @@ -61,6 +61,8 @@ const LinkListDialog = OperationChecklistDialog.extend({ this.closeDialog(); }; + await this.sortable.done; + this.createDialog({ title: wX("LINKS2", { portalName: PortalUI.displayName(this.options.portal), diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 23fa464a8..6ffee9f70 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -42,7 +42,7 @@ const ManageTeamDialog = WDialog.extend({ window.map.off("wasabee:logout", this.closeDialog, this); }, - _setupTable: function () { + _setupTable: async function () { const table = new Sortable(); table.fields = [ { @@ -128,8 +128,7 @@ const ManageTeamDialog = WDialog.extend({ ]; table.sortBy = 0; - // async populate - this._refreshTeam(table); + await this._refreshTeam(table); return table; }, @@ -147,19 +146,20 @@ const ManageTeamDialog = WDialog.extend({ } }, - update: function () { - const container = this._dialogContent(); // build the UI + update: async function () { + const container = await this._dialogContent(); // build the UI // this is the correct way to change out a dialog's contents, audit the entire codebase making this change this.setContent(container); this.setTitle(wX("MANAGE_TEAM", { teamName: this.options.team.Name })); }, - _dialogContent: function () { + _dialogContent: async function () { const container = L.DomUtil.create("div", "container"); const list = L.DomUtil.create("div", "list", container); - const table = this._setupTable(); + const table = await this._setupTable(); list.appendChild(table.table); + await table.done; const addlabel = L.DomUtil.create("label", null, container); addlabel.textContent = wX("ADD_AGENT"); @@ -305,8 +305,8 @@ const ManageTeamDialog = WDialog.extend({ return container; }, - _displayDialog: function () { - const container = this._dialogContent(); + _displayDialog: async function () { + const container = await this._dialogContent(); const buttons = {}; buttons[wX("CLOSE")] = () => { this.closeDialog(); diff --git a/src/code/dialogs/markerList.js b/src/code/dialogs/markerList.js index 461583125..72c0fa629 100644 --- a/src/code/dialogs/markerList.js +++ b/src/code/dialogs/markerList.js @@ -8,7 +8,7 @@ const MarkerList = OperationChecklistDialog.extend({ TYPE: "markerList", }, - _displayDialog: function () { + _displayDialog: async function () { const operation = getSelectedOperation(); loadFaked(operation); this.sortable = this.getListDialogContent( @@ -27,6 +27,8 @@ const MarkerList = OperationChecklistDialog.extend({ this.closeDialog(); }; + await this.sortable.done; + this.createDialog({ title: wX("MARKER_LIST", { opName: operation.name }), html: this.sortable.table, From 4d9be5cb299bc95cf8f2c64e5eb0cd5bf0d0de6f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 19 Jul 2021 11:19:43 +0200 Subject: [PATCH 030/275] report db issue (alert + iitc) --- src/code/init.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/code/init.js b/src/code/init.js index d3203d900..cb03ea9ae 100644 --- a/src/code/init.js +++ b/src/code/init.js @@ -40,7 +40,14 @@ window.plugin.wasabee.init = async () => { return; } - Wasabee.idb = await db; + try { + Wasabee.idb = await db; + } catch (e) { + alert("Wasabee: unable to access the storage: " + e.toString()); + plugin_info.error = e; //eslint-disable-line + return; + } + Wasabee._selectedOp = null; // the in-memory working op; Wasabee._updateList = new Map(); Wasabee.portalDetailQueue = new Array(); From aa1b98f8d83a23e232484ea990447c1138de4cb8 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:31:28 +0200 Subject: [PATCH 031/275] remove dead/incompatible code android supports quick only --- src/code/dialogs/authDialog.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index 9759ecf6b..ab862c5cc 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -97,14 +97,6 @@ const AuthDialog = WDialog.extend({ this.gapiAuth.call(this); }); - // XXX this needs to go away - const menus = L.DomUtil.create("div", "options", content); - menus.innerHTML = - "Login Settings:   " + - ": " + - ": "; - if (!this._android) menus.style.display = "none"; - if (!this._android && !this._ios) { const gapiSelectButton = L.DomUtil.create("button", "gapi", content); gapiSelectButton.textContent = wX("AUTH_SELECT_ACCOUNT"); @@ -214,13 +206,7 @@ const AuthDialog = WDialog.extend({ scope: "email profile openid", response_type: "id_token permission", }; - const immediate = document.getElementById("auth-immediate"); - if (immediate && immediate.value != "unset") - options.immediate = immediate.value; - const uxmode = document.getElementById("ux-mode"); - if (uxmode && uxmode.value != "unset") options.ux_mode = uxmode.value; - const gPrompt = document.getElementById("auth-prompt"); - if (gPrompt && gPrompt.value != "unset") options.prompt = gPrompt.value; + window.gapi.auth2.authorize(options, async (response) => { if (response.error) { postToFirebase({ id: "exception", error: response.error }); From 54699258ec6e34c82f77a9bed616d2e4a971347b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:32:11 +0200 Subject: [PATCH 032/275] fix: MM starts from 2 --- src/code/dialogs/multimaxDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/multimaxDialog.js index 483e2367e..cca9b8155 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/multimaxDialog.js @@ -152,7 +152,7 @@ const MultimaxDialog = WDialog.extend({ if (base) this._operation.addLink(pOne, pTwo, { description: commentPrefix + "base", - oder: ++order, + order: ++order, }); if (!Array.isArray(sequence) || !sequence.length) { From 8ceb22f90f79dbe70f027ab551f780afdec155c8 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:13:39 +0200 Subject: [PATCH 033/275] MM: append links --- src/code/dialogs/multimaxDialog.js | 27 ++++++++++++++++++++++++++- src/code/translations/english.json | 1 + src/code/translations/filipino.json | 1 + src/code/translations/french.json | 1 + src/code/translations/german.json | 1 + src/code/translations/italian.json | 1 + src/code/translations/spanish.json | 1 + 7 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/multimaxDialog.js index cca9b8155..42df7f13f 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/multimaxDialog.js @@ -92,6 +92,14 @@ const MultimaxDialog = WDialog.extend({ this._flcheck.type = "checkbox"; this._flcheck.id = "wasabee-multimax-backlink"; + const orderFromEndLabel = L.DomUtil.create("label", null, container); + orderFromEndLabel.textContent = wX("MM_INSERT_ORDER"); + orderFromEndLabel.htmlFor = "wasabee-multimax-insert-order"; + this._orderFromEnd = L.DomUtil.create("input", null, container); + this._orderFromEnd.type = "checkbox"; + this._orderFromEnd.id = "wasabee-multimax-insert-order"; + this._orderFromEnd.checked = true; + // Go button const button = L.DomUtil.create("button", "drawb", container); button.textContent = wX("MULTI_M"); @@ -149,6 +157,18 @@ const MultimaxDialog = WDialog.extend({ window.map.distance(portalsMap.get(a).latLng, portalsMap.get(b).latLng) ); + // shift current op tasks order + if (order < this._operation.nextOrder) { + let diff = sequence.length * 2 + 1; + if (this._flcheck.checked) diff += sequence.length - 1; + for (const l of this._operation.links) { + if (l.opOrder >= order) l.opOrder += diff; + } + for (const m of this._operation.markers) { + if (m.opOrder >= order) m.opOrder += diff; + } + } + if (base) this._operation.addLink(pOne, pTwo, { description: commentPrefix + "base", @@ -202,7 +222,12 @@ const MultimaxDialog = WDialog.extend({ this._operation.startBatchMode(); console.log("starting multimax"); - const length = this.MM(this._anchorOne, this._anchorTwo, portals)[0]; + const length = this.MM( + this._anchorOne, + this._anchorTwo, + portals, + this._orderFromEnd.checked ? this._operation.nextOrder - 1 : 0 + )[0]; console.log("multimax done"); this._operation.endBatchMode(); // save and run crosslinks diff --git a/src/code/translations/english.json b/src/code/translations/english.json index e857f71b1..dc363c9a0 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -196,6 +196,7 @@ "MIN_SRC_PORT_LVL": "Minimum level required on source portal", "MINUTES": " ({minutes} minutes ago)", "MM": "Multimax", + "MM_INSERT_ORDER": "Insert at the end", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Draw", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index 1cbb3df65..f35b34860 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -196,6 +196,7 @@ "MIN_SRC_PORT_LVL": "Pinakamababang level kailangan sa on panimulang portal", "MINUTES": " ({minutes} minutong nakalipas)", "MM": "Multimax", + "MM_INSERT_ORDER": "Insert at the end", "MULTI_M_TITLE": "Gumuhit ng Max Layers", "MULTI_M": "Multimax", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index db4872166..1e179dcba 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -196,6 +196,7 @@ "MIN_SRC_PORT_LVL": "Level minimum requis pour le portail source", "MINUTES": "(il y a {minutes} minute(s))", "MM": "Multimax", + "MM_INSERT_ORDER": "Insert at the end", "MULTI_M_TITLE": "Dessiner le maximum de couches", "MULTI_M": "Draw", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index eac07999a..8b64086e2 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -196,6 +196,7 @@ "MIN_SRC_PORT_LVL": "Minimum level required on source portal", "MINUTES": "vor ({minutes} Minuten)", "MM": "Maximale Feldanzahl", + "MM_INSERT_ORDER": "Insert at the end", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Maximale Feldanzahl", "MULTIMAX": "Maximale Feldanzahl!", diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index 055f43a13..215b7caaa 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -196,6 +196,7 @@ "MIN_SRC_PORT_LVL": "Livello minimo richiesto sul portale d'origine", "MINUTES": " ({minutes} minuti fa)", "MM": "Multimax", + "MM_INSERT_ORDER": "Insert at the end", "MULTI_M_TITLE": "Disegna più strati possibile", "MULTI_M": "Disegna", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index a0efc0981..bfbaec4ce 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -196,6 +196,7 @@ "MIN_SRC_PORT_LVL": "Nivel mínimo requerido para el portal fuente", "MINUTES": "(Hace {minutes} minutos)", "MM": "Multimax", + "MM_INSERT_ORDER": "Insert at the end", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Multimax", "MULTIMAX": "¡Multimax!", From aa0cc5b0edbc58c4fb5581bf1ae9fb46d7feaf01 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:14:51 +0200 Subject: [PATCH 034/275] add gulp task for lang key parity --- gulpfile.js | 34 ++++++++++++++++++++++++++++++ src/code/static.js | 12 +++++------ src/code/translations/french.json | 2 +- src/code/translations/german.json | 4 ++-- src/code/translations/spanish.json | 2 +- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index b6c3bc8a9..adfda1f1e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -12,6 +12,7 @@ const del = require("del"); const webpack = require("webpack"); const PluginError = require("plugin-error"); const prettier = require("gulp-prettier"); +const through2 = require("through2"); const ensureDirectoryExistence = (filePath) => { const dirname = path.dirname(filePath); @@ -158,6 +159,39 @@ gulp.task("buildmeta", (cb) => { }); }); +// locales, key parity +gulp.task("locales", (cb) => { + const english = require("./src/code/translations/english.json"); + function format(buf, ref) { + const parsed = JSON.parse(buf.toString("utf8")); + const result = {}; + for (const key in ref) result[key] = parsed[key] || ref[key]; + return JSON.stringify(result, null, 2) + "\n"; + } + + gulp + .src("./src/code/translations/*.json") + .pipe( + through2.obj(function (file, enc, cb) { + if (file.isBuffer()) { + file.contents = Buffer.from(format(file.contents, english)); + cb(null, file); + } else { + file.contents.pipe( + through2(function (contents) { + file.contents = through2(); + cb(null, file); + file.contents.write(format(contents, english)); + file.contents.end(); + }) + ); + } + }) + ) + .pipe(gulp.dest("./src/code/translations/")); + cb(); +}); + // ESLint gulp.task("eslint", (cb) => { gulp diff --git a/src/code/static.js b/src/code/static.js index 67b1db74c..763c1ef81 100644 --- a/src/code/static.js +++ b/src/code/static.js @@ -86,12 +86,12 @@ W.static = { }; W.static.strings = {}; // empty object, fill it below -W.static.strings.Deutsch = require("./translations/german.json"); -W.static.strings.Espanol = require("./translations/spanish.json"); -W.static.strings.English = require("./translations/english.json"); -W.static.strings.Italiano = require("./translations/italian.json"); -W.static.strings.Tagalog = require("./translations/filipino.json"); -W.static.strings.French = require("./translations/french.json"); +W.static.strings["Deutsch"] = require("./translations/german.json"); +W.static.strings["Espanol"] = require("./translations/spanish.json"); +W.static.strings["English"] = require("./translations/english.json"); +W.static.strings["Italiano"] = require("./translations/italian.json"); +W.static.strings["Tagalog"] = require("./translations/filipino.json"); +W.static.strings["Français"] = require("./translations/french.json"); W.static.defaultOperationColor = "orange"; diff --git a/src/code/translations/french.json b/src/code/translations/french.json index 1e179dcba..6b492ab0c 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -392,7 +392,7 @@ "WASABEE_D_LIST": "Entrer le nombre de clés défensive", "WD BUTTON TITLE": "Enregistrer des clés défensives", "WD BUTTON": "Clés W-D", - "WEBVIEW": "Webview Login (iOS)", + "WEBVIEW VERIFY": "Verify Webview", "WEBVIEW": "Webview Log In (iOS)", "WRITE_SHORT": "RW", "WRITE": "modifier", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index 8b64086e2..007a512e6 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -89,10 +89,10 @@ "DELETE MARKER TITLE": "Markierung löschen", "DELETE PERM DENIED": "Keine Berechtigung zum löschen", "DELETE_ANCHOR": "Löschen", - "DELETED": "Erfolgreich gelöscht", + "DELETE_LINK": "Delete", "DELETE_MARKER": "Delete", "DELETE_OP": "Delete {opName}", - "DELETED": "Successfully deleted.", + "DELETED": "Erfolgreich gelöscht.", "DESCRIP_PLACEHOLD": "Beschreibung (optional)", "DestroyPortalAlert": "Destroy", "DISABLE_SYNC": "Das Standard Synchronisations Plugin ist nicht mit Wasabee kompatibel - Bitte deaktiveren", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index bfbaec4ce..b98364179 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -291,7 +291,7 @@ "SAVELINKS": "Save Links", "SECONDS": "(Hace {seconds} segundos)", "SEL_PORT_FIRST": "¡Por favor, primero seleccionar portal ancla!", - "SEL_SB_ANCHOR ": "Selecciona el área del ancla para hacer acercamiento para añadir a la supernova", + "SEL_SB_ANCHOR": "Selecciona el área del ancla para hacer acercamiento para añadir a la supernova.", "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", "SEL_SB_ANCHOR3": "Please be patient, it can take a bit.", "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", From a17499b766ac39a5d3026a8835209415e95e0f16 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:34:44 +0200 Subject: [PATCH 035/275] MM: refine order insertion --- src/code/dialogs/multimaxDialog.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/multimaxDialog.js index 42df7f13f..e66ee7c38 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/multimaxDialog.js @@ -145,7 +145,7 @@ const MultimaxDialog = WDialog.extend({ pOne, pTwo, portals, - order = 0, + order = 0, // first link is order + 1 base = true, commentPrefix = "multimax " ) { @@ -158,14 +158,17 @@ const MultimaxDialog = WDialog.extend({ ); // shift current op tasks order - if (order < this._operation.nextOrder) { + if (order < this._operation.nextOrder - 1) { let diff = sequence.length * 2 + 1; if (this._flcheck.checked) diff += sequence.length - 1; for (const l of this._operation.links) { - if (l.opOrder >= order) l.opOrder += diff; + // skip base + if (l.toPortalId === pOne.id && l.fromPortalId === pTwo.id) continue; + if (l.fromPortalId === pOne.id && l.toPortalId === pTwo.id) continue; + if (l.opOrder > order) l.opOrder += diff; } for (const m of this._operation.markers) { - if (m.opOrder >= order) m.opOrder += diff; + if (m.opOrder > order) m.opOrder += diff; } } From 5e43ad88706d25c04b53d9824057f0b401f43424 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 2 Aug 2021 20:14:20 +0200 Subject: [PATCH 036/275] merge: mitigate overflow dialog --- src/code/dialogs/mergeDialog.js | 36 +++++++++++++++++---------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index fe619e7a9..02c9af499 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -229,7 +229,7 @@ const MergeDialog = WDialog.extend({ { name: "Entry", value: (e) => e.data.type, - format: async (cell, value, e) => { + format: (cell, value, e) => { const op = e.type === "-" ? origin : operation; if (e.data.type === "link") { cell.appendChild(LinkUI.displayFormat(e.data.link, op)); @@ -243,23 +243,25 @@ const MergeDialog = WDialog.extend({ } if (e.type === "~") { const pre = L.DomUtil.create("code", null, cell); - const diff = []; - for (const [k, v] of e.data.diff) { - let item = e.data.link || e.data.portal || e.data.marker; - let prev = v; - let cur = item[k]; - if (k.endsWith("ortalId")) { - prev = origin.getPortal(prev).name; - cur = operation.getPortal(cur).name; - } else if (k === "assignedTo") { - if (prev !== "") prev = await WasabeeAgent.get(prev); - if (cur !== "") cur = await WasabeeAgent.get(cur); - if (prev) prev = prev.name; - if (cur) cur = cur.name; + (async () => { + const diff = []; + for (const [k, v] of e.data.diff) { + let item = e.data.link || e.data.portal || e.data.marker; + let prev = v; + let cur = item[k]; + if (k.endsWith("ortalId")) { + prev = origin.getPortal(prev).name; + cur = operation.getPortal(cur).name; + } else if (k === "assignedTo") { + if (prev !== "") prev = await WasabeeAgent.get(prev); + if (cur !== "") cur = await WasabeeAgent.get(cur); + if (prev) prev = prev.name; + if (cur) cur = cur.name; + } + diff.push([k, prev, cur]); } - diff.push([k, prev, cur]); - } - pre.textContent = JSON.stringify(diff); + pre.textContent = JSON.stringify(diff); + })(); } }, }, From af284344738bbe2ecaf0986f7ead6568375d6864 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 4 Aug 2021 10:06:29 +0200 Subject: [PATCH 037/275] fix deleted WD keys --- src/code/wd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/wd.js b/src/code/wd.js index 902e9cf99..474810cf1 100644 --- a/src/code/wd.js +++ b/src/code/wd.js @@ -67,7 +67,7 @@ export async function drawWasabeeDkeys() { const list = JSON.parse(data); if (!list || !list.DefensiveKeys || list.DefensiveKeys.length == 0) return; - + window.plugin.wasabee.idb.clear("defensivekeys"); for (const n of list.DefensiveKeys) { try { await window.plugin.wasabee.idb.put("defensivekeys", n); From 118fb3bac9aae38c2dcb66a1f672726c8f747bab Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 4 Aug 2021 10:37:44 +0200 Subject: [PATCH 038/275] fix immediate auth --- src/code/dialogs/authDialog.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index ab862c5cc..f6f481194 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -205,6 +205,7 @@ const AuthDialog = WDialog.extend({ client_id: window.plugin.wasabee.static.constants.OAUTH_CLIENT_ID, scope: "email profile openid", response_type: "id_token permission", + prompt: "none", }; window.gapi.auth2.authorize(options, async (response) => { From 6644b1144ee1160026db685217a62c00a1e13341 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 4 Aug 2021 11:29:55 +0200 Subject: [PATCH 039/275] blocker store migration --- src/code/model/operation.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/code/model/operation.js b/src/code/model/operation.js index cb0b450ab..09450a9dc 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -9,6 +9,9 @@ import { GetWasabeeServer } from "../server"; import { getSelectedOperation } from "../selectedOp"; import db from "../db"; +// 0.20->0.21 blocker migration +import WasabeeBlocker from "./blocker"; + export default class WasabeeOp extends Evented { constructor(obj) { super(); @@ -56,6 +59,17 @@ export default class WasabeeOp extends Evented { if (opportals) for (const p of opportals) this._idToOpportals.set(p.id, p); this.buildCoordsLookupTable(); + // 0.20->0.21 blocker migration + if (obj.blockers) { + for (const blocker of obj.blockers) { + WasabeeBlocker.addBlocker( + this, + this.getPortal(blocker.fromPortalId), + this.getPortal(blocker.toPortalId) + ); + } + } + this.cleanAnchorList(); this.cleanPortalList(); } From b0920be72335f9c1c9beb7c7f2d8e1972ba1f8b3 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Thu, 26 Aug 2021 02:52:57 -0600 Subject: [PATCH 040/275] Adding Portuguese language (#284) --- src/code/static.js | 1 + src/code/translations/portuguese.json | 410 ++++++++++++++++++++++++++ 2 files changed, 411 insertions(+) create mode 100644 src/code/translations/portuguese.json diff --git a/src/code/static.js b/src/code/static.js index 763c1ef81..66ec8495f 100644 --- a/src/code/static.js +++ b/src/code/static.js @@ -92,6 +92,7 @@ W.static.strings["English"] = require("./translations/english.json"); W.static.strings["Italiano"] = require("./translations/italian.json"); W.static.strings["Tagalog"] = require("./translations/filipino.json"); W.static.strings["Français"] = require("./translations/french.json"); +W.static.strings["Português"] = require("./translations/portuguese.json"); W.static.defaultOperationColor = "orange"; diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json new file mode 100644 index 000000000..a1b13e4a8 --- /dev/null +++ b/src/code/translations/portuguese.json @@ -0,0 +1,410 @@ +{ + "acknowledged": "Reconhecido", + "assigned": "Atribuído", + "completed": "Completo", + "pending": "Pendente", + "CapturePortalMarker": "Capturado", + "LetDecayPortalAlert": "Deixar caír", + "DestroyPortalAlert": "Destroir", + "FarmPortalMarker": "Farmar", + "GotoPortalMarker": "Ir para", + "GetKeyPortalMarker": "Retirar Chaves", + "CreateLinkAlert": "Link", + "MeetAgentPortalMarker": "Conhecer Agente", + "OtherPortalAlert": "Otros", + "RechargePortalAlert": "Recharge", + "UpgradePortalAlert": "Upgrade", + "UseVirusPortalAlert": "Usar Virus", + "ExcludeMarker": "Excluir de Auto-Desenhar / Marcar", + "SET_PORTAL_COMMENT": "Definir comentário do portal", + "ABOUT WASABEE-IITC": "Sobre Wasabee-IITC", + "ABOUT_WASABEE": "Sobre Wasabee", + "ADD": "Adicionar", + "ADD1": "Adicionar primeiro link", + "ADD2": "Adicionar segundo link", + "ADD_AGENT": "Adicionar Agente: ", + "ADD_BUTTON_LINKS": "Adicionar todos os links de uma vez.", + "ADD_BL": "Adicionar links oara trás: ", + "ADD LINK TITLE": "Adicionar Links Dialogo", + "ADD_LINKS": "Adicionar Links", + "ADD MARKER TITLE": "Adicionar Marcadores de Dialogo", + "ADD_MARKER": "+ Marcador", + "ADD_MARKER2": "Adicionar Marcador", + "ADD_NEW_OP": "Adicionar Nova Op", + "ADD_SUCC_INSTR": "Adicionar agente, bem sucedido", + "AGENT": "Agente", + "AGENT_STATS": "Agente Stats", + "AGES": " (ages ago)", + "ALREADY_HAS_MARKER": "Este portal já tem um marcador. Escolha um portal diferente.", + "ANCHOR1": "Âncora 1 ", + "ANCHOR2": "Âncora 2 ", + "ANCHOR3": "Âncora 3 ", + "ANCHOR ASSIGNMENT": " Todos os links externos", + "ANCHOR_GMAP": "Google Map", + "ANCHOR_PORTAL": "Âncora Portal ", + "ANCHOR_PORTAL2": "Âncora Portal 2", + "ANCHOR_PORTAL3": "Âncora Portal 3", + "ANCHORS_AS_BOOKMARKS": "Âncora como bookmarks", + "API_KEY": " api key: ", + "ASSIGN": "Atribuir", + "ASSIGNED": "Atribuido", + "ASS_TO": "Atrubuir a:", + "ASSIGN LINK PROMPT": "Atribuir link para: ${value}", + "ASSIGN MARKER PROMPT": "Atrubuir marcador para: ${value}", + "ASSIGN OUTBOUND": "Atribuir links externos", + "ASSIGN OUTBOUND PROMPT": "Atribuir todos os links externos de: ${value}", + "ASSIGNED_ONLY": "Só Atribuir", + "ASSIGNED_ONLY_SHORT": "A", + "AUTH ANDROID": "No Android, tentar primeiro 'rápido'. Se isso falhar, tentar o login principal com 'select_account'..", + "AUTH INCOMPAT": "Você ativou um plugin no TamperMonkey que é incompatível com o Wasabee", + "AUTH IOS": "No iOS, use o 'Login' principal. se isso falhar, faça 'Webview Log in', faça o login; em seguida, use o botão 'Verificar Webview' para concluir o processo.", + "AUTH REQUIRED": "Autentificação Requerida", + "AUTH TOKEN REJECTED": "Envio de token de autenticação rejeitado pelo servidor: ${value}", + "AUTH_SELECT_ACCOUNT": "Selecionar conta", + "AUTODRAWS": "Wasabee Auto-draw Opções", + "AUTO_DRAWS": "Auto-draw", + "AUTOLOAD": "Carregar automaticamente os detalhes do portal em falta", + "AUTOLOAD_RATE": "Taxa de solicitação de detalhes do portal (ms)", + "AUTOMARK": "Auto-Marcar", + "AUTOMARK STOP": "Auto-Marcar interrompido devido a portais não serem carregados", + "AMAZ_TEAM_NAME": "Nome incrível da equipe.", + "BAT_TOAD": "Battle Toads", + "BLOCKER LIST TITLE": "Mostrar todos os blockers", + "BLOCKER TITLE": "Blockers", + "CANCEL": "Cancelar", + "CAPSULE": "Capsula", + "CHANGE SERVER": "Trocar de Servidor", + "CHANGE SERVER PROMPT": "Novo servidro Wasabee", + "CHANGE_WAS_SERVER": "Mudar servidor Wasabee", + "CHECKLIST BUTTON TITLE": "Checklist da Operação", + "CHECKLIST BUTTON": "Checklist", + "CLEAR": "Limpar selecção", + "CLEAR_EVERYTHING": "limpar Portais/Links/Marcadores", + "CLEAR LINKS": "Limpar Links", + "CLEAR MARKERS": "Limpar Markers", + "CLEAROPS BUTTON": "Limpar dados Wasabee", + "CLEAROPS BUTTON TITLE": "limpar TODOS os dados Wasabee", + "CLEAROPS PROMPT": "Isto limpará todas as OPS e dados relacionados a Wasabee. Tudo será restaurado apartir do servidor na próxima sincronização.", + "CLOSE": "Perto", + "COMPLETED": "Completo", + "COMPLETED BY": "Completo por ${value}", + "CON_DEL": "Confirmar Apagar: ${value}", + "COMMENT": "Comentario", + "CONFIRM_DELETE": "Desejas realmente excluir este link: ", + "COUNT": "Contar", + "CREATE_NEW_TEAM": "Criar Nova Equipa", + "CUR_USER_INFO": "Informações do usuário atual", + "DT_FORMAT": "Formato das Ferramentas de Desenho", + "DEFAULT OP NAME": "Nova Op: ${value}", + "DELETE_ANCHOR": "Apagar", + "DELETE ANCHOR PROMPT": "Desejas excluir esta âncora e todos os links associados: ", + "DELETE ANCHOR TITLE": "Apagar Âncora", + "DELETE_LINK": "Apagar", + "DELETE_MARKER": "Apagar", + "DELETE MARKER PROMPT": "Desejas apagar esta âncora: ", + "DELETE MARKER TITLE": "Apagar Marcador", + "DELETE_OP": "Apagar ${value}", + "DELETE PERM DENIED": "Permissão para excluir negada.", + "DELETED": "Excluído com sucesso.", + "DESCRIP_PLACEHOLD": "Descrição (opcional)", + "DISABLED": "Este recurso não está pronto para os usuários", + "DISABLE_SYNC": "O plugin de sincronização de stoque não é compatível com Wassabe. Desativa a sincronização.", + "DONE": "Feito", + "DRAW TOOLS FORMAT": "Formato Draw Tools", + "DUPE_OP": "Duplicar Operação", + "END_PORT": "Portal final ", + "EXPORT": "Exportar: ", + "EXPORT OP": "Exportar Op", + "EXPORT OP TITLE": "Exportar Op Actual", + "FAKED": "Falsificado: [${value}]", + "FANFIELD": "Desenhar", + "FANFIELD2": "Desenhar Fan Field", + "FAN_FIELD3": "Fan Field", + "FANFIELD TITLE": "Fanfield", + "FROM_DEPTH": "da profundidade", + "FROM_1-2": "A Partir da base 1-2", + "FROM_1-3": "A Partir da base 1-3", + "FROM_2-3": "A Partir da base 2-3", + "FROM_PORT": "A Partir do Portal", + "GET_DT_DRAW": "Importar Dezenho DrawTools", + "GET DT": "Obtenha o desenho existente do DrawTools", + "HF_DRAW_BUTTON": "Desenhar", + "HF_DRAW_DEEP_BUTTON": "Desenhar com recursão profunda", + "HF_DEEP_SEARCH": "Pesquisa exaustiva", + "HF_REDRAW_BUTTON": "Redesenhar", + "HG": "Campo Homogêneo", + "H-GEN_INST": "Define portais para a camada externa. Escolhe o número de divisões. Clica para desenhar", + "HOURS": " (${value} horas atrás)", + "HOW_TO_VIDS": "

Vídeos de instruções:

", + "IMP_COMP": "Importação concluída. Encontrada ", + "IMP_DT_OP": "Importar OP Drawtools: ", + "IMPORT_OP": "Importar Operação", + "IMPORT_OP_TITLE": "Importar Op: ${value}", + "IMPORT_OP_SUCCESS": "OP Importada: ${value} successfuly.", + "IMP_NOPE": "A Importação Falhou.", + "IMP_WAS_OP": "Importar Operação Wasabee", + "IMPOSSIBLE": "Impossível", + "INGNAME_GID": "Nome de entrada ou GoogleID", + "INPUT_DT_KEY_COUNT": "Contagem de chaves defensivas de entrada", + "INPUT_SQUAD_NAME": "Insere um nome de esquadrão", + "INVALID REQUEST": "Pedido inválido", + "IOS NEED FAKE UA": "Deves definir um 'Agente de usuário personalizado para visualizações da Web' nas configurações do IITC-Mobile ou o login falhará", + "KEYS": "Chaves", + "KEY_LIST2": "Lista de chaves para operação: ${value}", + "KEY_LIST": "Lista chaves para portal: ${value}", + "KNOWN_BLOCK": "Blockers conhecidos: ${value}", + "LA": "L8+ alguns LA", + "LA DESC": "Dependendo do número e tipo de Link Amps usados, um nível de portal de origem inferior pode ser suficiente.", + "LANG": "Língua", + "LEAVE": "Deixar", + "LINKS": "Links", + "LINKS2": ": Links", + "LINK ASSIGNMENT": "Atribuição de Link", + "LINKS BUTTON TITLE": "Links", + "LOADING": "[a carregar]", + "LOADING1": "a carregar: [${value}]", + "LOAD PORTALS": "Carregar Portais", + "LOC_PROC": "localização processada", + "LOC_UPDATE": "Atualização de localização", + "LOCATION SUB": "Localização registrada", + "LOCFRMSER": " (localmente e do servidor)", + "LOG IN": "Log In", + "LOG_OUT": "Log Out", + "LOG IN QUICK": "Log In (Rápido; para Android)", + "MADRID_WAS_TAKEN": "Madrid Protocol", + "MADRID_TITLE": "Madrid Protocol", + "MADRID": "Desenhar", + "MADRID_NOTSET": "baselink não definido.", + "MADRID_SET_1": "Selecione a região para a ligação de base Âncora 2 à Âncora 3", + "MADRID_SET_2": "Selecione a região para a ligação de base Âncora 3 à Âncora 1", + "MADRID_SET_3": "Selecione a região para a ligação de base Âncora 1 a Âncora 2", + "MANAGE": "Gerenciar", + "MANAGE_TEAM": "Gerenciar ${value}", + "MARKERS BUTTON TITLE": "Marcadores", + "MARKER LIST TITLE": "Lista de Marcadores", + "MARKER LIST": "Marcadores", + "MARKER_LIST": "Lista de Marcadores: ${value}", + "MARKER ASSIGNMENT": " Atribuição de marcador", + "MARKER STATE PROMPT": "Status do marcador", + "MARKER STATE": " Definir estado do marcador", + "MAX": "Fan Field", + "MIN_SRC_PORT_LVL": "Nível mínimo exigido no portal de origem", + "MINUTES": " (${value} minutos atrás)", + "MM": "Multimax", + "MY_CAP_ID": "Minha Capsula ID", + "MY_COUNT": "Minha Conta", + "MULTIMAX": "Multimax!", + "MUST_NOT_BE_EMPTY": "Não deve estar vazio", + "MULTIMAX2": "Multimax", + "MULTI_M_TITLE": "Desenhar camadas máximas", + "MULTI_M": "Desenhar", + "NAME": "Nome: ", + "NAME_REQ": "Nome Requerido", + "NEW_OP": "Nova Operação", + "NEW_TEAM": "Nova Equipa", + "NEW_TEAM_NAME": "Novo nome de Equipa", + "NEW_WAS_SERVER": "Novo servidor Waasbee", + "NOT LOGGED IN": "Não logado: ${value}", + "NOT LOGGED IN SHORT": "Não logado", + "NO": "Não", + "NO_DT_ITEMS": "Nenhum item desenhado do DrawTools foi detectado", + "NO_DATA": "sem dados", + "NO_LABEL": "Nenhum rótulo definido", + "NOT_LOADED": "Não totalmente carregado, tente novamente.", + "NO_PORT_SEL": "Nenhum portal selecionado.", + "NO_TITLE": "Nenhum título definido", + "NOT_SET": "não configurado", + "NO_STOCK_INTEL": "Wasabee não suporta importações de desenho de inteligência de stoque", + "NTNAME": "Nome", + "OK": "OK", + "ON_HAND": "Na Mão", + "ONLY_DT_IMP": " (apenas para importações do DrawTools)", + "OP DELETED": "Operação removida do servidor: ${value}", + "OP PERM DENIED": "Permissão negada para operação: ${value}", + "OP_CHECKLIST": "Lista de verificação de operação: ${value}", + "OP_NAME_UNSET": "O nome da operação não estava definido", + "OP_PERMS": "Permissões de operação", + "OPEN_REQUEST": "[pedido aberto]", + "OPER_NAME": "Nome da Operação: ", + "OPER_COLOR": "Cor de operação: ", + "OPERATIONS": "Operações", + "OPS BUTTON": "Ops", + "OPS BUTTON TITLE": "Operações", + "OP_BUTTON": "Operação", + "OP_SETTINGS_BUTTON": "Op ⚙", + "OP_SETTINGS_TITLE": "Configurações de operação", + "OPTION": "opção", + "ORDER": "Pedido", + "PASTE_INSTRUCT": "Cola uma exportação de desenho Wasabee aqui.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", + "PENDING": "Pendente", + "PERMS": "${value} permissões", + "PICK_DEST_FIRST": "Seleciona um portal de destino primeiro!", + "PICK_TAR_FIRST": "Seleciona um portal de destino primeiro!", + "PICK_TARGETDEST_Portals": "Seleciona primeiro os portais de destino e destino!", + "PLEASE_SELECT_PORTAL": "Seleciona um portal", + "PORTAL": "Portal", + "PORTAL_COUNT": "${value} portais", + "PORTAL KEY LIST": "Lista de chaves para portal ${value}", + "PORT_FAKE": " portais. Falsificado ", + "QD BUTTON END": "Clique para parar de desenhar campos", + "QD END": "FIM", + "QD TITLE": "Camadas de desenho rápido", + "QDBASE": "Link Base", + "QDCANCEL": "Cancelar campos de desenho", + "QDCONT": "Clica num portal espinha para desenhar um campo.", + "QDEND": "Clica novamente no mesmo portal para finalizar o desenho.", + "QDNEXT": "Clica no segundo portal de âncora.", + "QDSTART": "Clica no primeiro portal de âncora.", + "READ": "Ler", + "READ_SHORT": "Ler Abreviado", + "REM_LOC_CP": "Remover cópia local de ${value}", + "REMOVE": "Remover", + "REMOVE_TEAM": "Remover Equipe: ", + "REMOVE_TEAM_CONFIRM_LABEL": "Você deseja remover permanentemente ${value} do servidor Wasabee?", + "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipe ${value}", + "RENAME": "Renomear", + "RENAME_TEAM": "Renomear Equipe: ", + "REQUIRED": "Requerido", + "RESET": "Redefinir", + "REVERSE": "Inverter", + "ROCKS_COM": "enl.rocks comunidade: ", + "ROLE": "Função", + "SEL_SB_ANCHOR": "Seleciona a âncora.", + "SEL_SB_ANCHOR2": "Reduzir o zoom. Verifica se todos os portais foram carregados e clica em desenhar.", + "SEL_SB_ANCHOR3": "Por favor, sê paciente, pode demorar um pouco.", + "SELECT PORTAL": "Selecionar um portal para enviar", + "SECONDS": " (${value} segundos atrás)", + "SEND TARGET": "Enviar alvo", + "SEND TARGET AGENT": "Selecionar o destinatário alvo", + "SEL_SRC_ANC2": "Selecionar a fonte e a âncora 2", + "SEL_SRC_PORT": "Selecionar um portal de origem", + "SELECT_FAN_PORTALS": "Selecionar um portal de âncora, um portal inicial e um portal final e, em seguida, posiciona a visualização sobre a área do campo.", + "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", + "SELECT_INSTRUCTIONS": "Select two anchor portals, then zoom over the spine area.", + "SELECT_MADRID_INSTRUCTIONS": "Selecionar três portais de âncora, amplia a área próxima à âncora selecionada, espera até que os portais sejam carregados (os portais devem aparecer na tela para serem considerados) e selecioner o botão 'definir região da coluna' para os links de base correspondentes.", + "SELECT PORTAL": "Seleciona um portal primeiro", + "SEL_PORT_FIRST": "Selecione primeiro os portais âncora!", + "SELF SWAP": "Não é possível trocar um portal contigo mesmo! Seleciona um portal diferente.", + "SEND ANALYTICS": "Enviar análises anônimas", + "SEND LOCATION": "Enviar localização", + "SEND_LOC": "Enviar localização", + "SEND TARGET CONFIRM": "Queres enviar ${value} alvo para ${option}?", + "SET": "definir", + "SET_3_PORT": "Defina os três portais primeiro!", + "SET_COMMENT": "Definir Comentário", + "SET_LINK_COMMENT": "Definir comentário para o link: ", + "SET_LCOMMENT": "Definir comentário do link", + "SET_MARKER_COMMENT": "Definir comentário para marcador em: ", + "SET_MARKER_TYPE_TITLE": "Alterar o tipo de marcador", + "SET_MCOMMENT": "Definir comentário do marcador: ${value}", + "SET_NEW_OP": "Define o novo nome da operação", + "SET_PORT_COMMENT": "Definir comentário para portal: ", + "SET_PCOMMENT": "Definir comentário do portal: ${value}", + "SET_PORTAL_COMMENT": "Definir comentário do portal", + "SETTINGS": "Configurações do Wasabee", + "SKINS_AVAILABLE": "Existem ${value} skins disponíveis.", + "SKINS_BUTTON": "Configurar Skins", + "SKINS_DESCRIPTION": "Gerenciar as skins disponíveis movendo o tema para a coluna da esquerda. Quanto mais baixo na coluna, maior será a prioridade para o UI.", + "SKINS_MANAGE_TITLE": "Gerenciar skins", + "SOURCE_PORT": "Portal Fonte ", + "SQUAD": "Esquadrão", + "STATE": "Estado", + "STARBURST": "Starburst", + "STARBURST_DRAW": "Desenhar", + "STARBURST TITLE": "Starburst", + "START_PORT": "Portal inicial", + "TEAM STATE": "Partilhar localização", + "SUPPORT_INSTRUCT": "Para obter suporte, por favor, junte-se ao The Wasabee User Telegram Channel", + "SWAP": "Troca", + "SWAP PROMPT": "Queres trocar: ", + "SWAP TITLE": "Trocar Portais", + "SWAP WITH": " com ", + "SYNC": "Download operações disponíveis", + "SYNC DONE": "Download Completo", + "TARDEST_DIFF": "Os portais de destino e destino devem ser diferentes.", + "TEAMS BUTTON TITLE": "Listar equipas Wasabee", + "TEAMS BUTTON": "Equipas", + "NEWOP BUTTON TITLE": "Criar uma nova operação", + "NEWOP BUTTON": "Nova Op", + "TARGET SENT": "Alvo Enviado", + "TEAM": "Equipa", + "TEAM_CREATED": "Equipa ${value} created", + "TEAM_NAME": "Nome Equipa", + "TEAM PERM DENIED": "Permissão negada à equipa: ${value}", + "TITLE": "titulo", + "TRAWL": "Procurar por Blockers", + "TRAWL_AUTOMARK": "Auto-mark blockers depois da procura", + "TRAWL_BULK_LOAD_WARNING": "Este método carrega os dados do bloco o mais rápido possível. Usa por sua conta e risco.", + "TRAWL_BULK_LOAD": "Carregar rapidamente Dados do Bloco", + "TRAWL_CLEAR_MARKERS": "Limpa vírus / destroi marcadores antes da procura", + "TRAWL TITLE": "Trawl Lanes", + "TRAWL WARNING": "Isto carregará os dados do bloco em todos os links desenhados. Este é um processo lento.", + "TRAWLING": "A Varrer os links a procura de blockers, fecha esta caixa de diálogo para parar", + "TRAWL_REMAINING": "${value} Restantes", + "TO_PORT": "Para o Portal", + "TYPE": "Tipo", + "UNASSIGNED": "Não atribuído", + "UNKNOWN": "Desconhecido", + "UPDATED": "Atualizado com sucesso", + "UPDATE HOVER": "UPDATE ${value} no servidor", + "UPDATE HOVER NOT CHANGED": "${value} não mudou localmente", + "UPDATE_CONFLICT_TITLE": "Conflito detectado com o servidor", + "UPDATE_CONFLICT_DESC": "A OP foi modificada no servidor desde a última sincronização. Queres substituir a versão do servidor pela atual?", + "UPLOAD BUTTON HOVER": "UPLOAD ${value} (atualmente não está no servidor)", + "UPLOAD PERM DENIED": "Permissão para upload negada", + "UPLOADED": "Carregado com sucesso", + "USE_SWAP_INSTRUCT": ". Usa o recurso de troca para mover portais falsos para portais reais no mesmo local. Ampliar os portais 'Carregando' na lista de verificação pode forçá-los a carregar.", + "USE_VALID_NAME": "Usa um nome de operação válido", + "UPDATE_COUNT": "Contagem de atualização", + "VRLA": "L8+alguns VRLA", + "VRLA DESC": "Dependendo do número e tipo de Link Amps usados, um nível de portal de origem inferior pode ser suficiente.", + "WASABEE BUTTON TITLE": "Wasabee: É VERDE E FAZ SMURFS CHORAREM.", + "WASABEE_MODE_LABEL": "Modo", + "WASABEE_MODE_BATTLE": "Batalha", + "WASABEE_MODE_DESIGN": "Design", + "WASABEE_MODE_DESC": "No modo de design, as alterações devem ser enviadas manualmente para o servidor; as atribuições feitas não notificarão os agentes; atribuições enviadas do IITC substituirão seu status atual no servidor. No modo de batalha, as alterações serão enviadas automaticamente para o servidor; as atribuições serão enviadas aos agentes via Telegram (se disponível); o status do servidor para atribuições tem prioridade sobre os dados IITC.", + "WD BUTTON": "W-D Chaves", + "WD BUTTON TITLE": "Log de chaves defensivas", + "WEBVIEW": "Login do Webview (iOS)", + "WEBVIEW VERIFY": "Verificar Webview", + "WRITE": "escrita", + "WRITE_SHORT": "RW", + "WSERVER": "Servidor: ${value}", + "YES": "Sim", + "YESNO_DEL": "Tem certeza de que deseja excluir ${value}?", + "LINK STATE PROMPT": "Estado do link", + "LINK STATE": "Definir o status do link", + "D_SHOW_LIST": "Chaves de defesa de entrada", + "WASABEE_D_LIST": "Contagem de chaves defensivas de entrada", + "ONION_WAS_TAKEN": "Cebola", + "ONION": "Desenhar", + "SELECT_ONION_PORTALS": "As camadas são construídas de dentro para fora. Aumenta o zoom para o centro e seleciona o portal inicial, em seguida, diminui o zoom para a área.", + "MAX_SPLITS": "Divisões máximas", + "smallScreen": { + "LOG IN": "Log In", + "LOG_OUT": "Log Out", + "NEWOP BUTTON": "Nova Op", + "CLEAROPS BUTTON": "Limpar", + "TEAMS BUTTON": "Equipas", + "WD BUTTON": "W-D Chaves", + "OPS BUTTON": "Ops", + "CHECKLIST BUTTON": "Verificar", + "MARKER LIST": "Marcadores", + "BLOCKER TITLE": "Blockers", + "KEYS": "Chaves", + "EXPORT OP": "Exportar", + "QD END": "Fim", + "ADD_LINKS": "+ Links", + "MM": "Multi", + "MULTI_M": "Desenhar", + "MULTI_M_TITLE": "Desenhar Maximo de Layers", + "STARBURST": "Estrela", + "STARBURST_DRAW": "Desenhar", + "ADD_MARKER": "+ Marcador", + "MARKERS BUTTON TITLE": "Marcadores", + "FAN_FIELD3": "Fan", + "FANFIELD": "Desenhar", + "FANFIELD2": "Desenhar Fan Field", + "MAX": "Fan" + } +} From f98785c8def63815870cb58cf327aefa62f72de7 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 2 Sep 2021 18:22:33 +0200 Subject: [PATCH 041/275] Build with webpack only (#286) --- .github/workflows/dev.yaml | 2 +- .github/workflows/master.yaml | 2 +- gulpfile.js | 221 +--------------------------------- package.json | 15 +-- plugin.config.json | 5 +- src/code/init.js | 2 + src/code/static.js | 36 +++--- src/code/wX.js | 8 +- src/headers.js | 13 -- src/main.js | 19 --- src/wrapper/afterWrapper.js | 19 --- src/wrapper/pluginEnd.js | 10 -- src/wrapper/pluginStart.js | 6 - webpack.config.js | 154 ++++++++++++++++++++++- 14 files changed, 182 insertions(+), 330 deletions(-) delete mode 100644 src/headers.js delete mode 100644 src/main.js delete mode 100644 src/wrapper/afterWrapper.js delete mode 100644 src/wrapper/pluginEnd.js delete mode 100644 src/wrapper/pluginStart.js diff --git a/.github/workflows/dev.yaml b/.github/workflows/dev.yaml index 7a581c836..d4878e233 100644 --- a/.github/workflows/dev.yaml +++ b/.github/workflows/dev.yaml @@ -13,7 +13,7 @@ jobs: - name: Build 🔧 run: | npm install - npx gulp build-dev + npm run build-dev - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@4.1.1 diff --git a/.github/workflows/master.yaml b/.github/workflows/master.yaml index 1bfc20a6d..46dd26bcf 100644 --- a/.github/workflows/master.yaml +++ b/.github/workflows/master.yaml @@ -13,7 +13,7 @@ jobs: - name: Build 🔧 run: | npm install - npx gulp build-prod + npm run build - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@4.1.1 diff --git a/gulpfile.js b/gulpfile.js index adfda1f1e..4543f1d1d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,164 +1,8 @@ // Requires -const fs = require("fs"); -const path = require("path"); const gulp = require("gulp"); -const injectfile = require("gulp-inject-file"); // https://www.npmjs.com/package/gulp-inject-file -const rename = require("gulp-rename"); // https://www.npmjs.com/package/gulp-rename -const contents = require("gulp-inject-string"); // https://www.npmjs.com/package/gulp-inject-string -const cfg = require("./plugin.config.json"); -const trimlines = require("gulp-trimlines"); -const eslint = require("gulp-eslint"); const del = require("del"); -const webpack = require("webpack"); -const PluginError = require("plugin-error"); -const prettier = require("gulp-prettier"); const through2 = require("through2"); -const ensureDirectoryExistence = (filePath) => { - const dirname = path.dirname(filePath); - if (fs.existsSync(dirname)) return; - - ensureDirectoryExistence(dirname); - fs.mkdirSync(dirname); -}; - -// Config -var status = { - headers: null, - mode: null, -}; - -// status related tasks -gulp.task("set-mode-dev", (cb) => { - status.mode = "dev"; - cb(); -}); - -gulp.task("set-mode-prod", (cb) => { - status.mode = "prod"; - cb(); -}); - -gulp.task("clear", (cb) => { - status.headers = null; - status.mode = null; - cb(); -}); - -// build tasks -gulp.task("buildheaders", (cb) => { - const content = fs.readFileSync(cfg.src.meta, "utf8"); - - let newContent = ""; - for (const l of content.split("\n")) { - let newline = l; - for (const k of Object.keys(cfg.headers.common)) { - if (l.indexOf(`@${k} `) == 3) { - const key = k.padEnd(13); - newline = `// @${key} ${cfg.headers.common[k]}`; - break; - } - } - for (const k of Object.keys(cfg.headers[status.mode])) { - if (l.indexOf(`@${k} `) == 3) { - const key = k.padEnd(13); - newline = `// @${key} ${cfg.headers[status.mode][k]}`; - break; - } - } - newContent += newline + "\n"; - } - - // XXX just append to the version rather than overwriting a fixed string now - const gbd = () => { - const d = new Date(); - let bd = d.getUTCFullYear(); - let t = ("0" + (d.getUTCMonth() + 1)).substr(-2); - bd += t; - t = ("0" + d.getUTCDate()).substr(-2); - bd += t; - t = ("0" + d.getUTCHours()).substr(-2); - bd += t; - t = ("0" + d.getUTCMinutes()).substr(-2); - bd += t; - t = ("0" + d.getUTCSeconds()).substr(-2); - bd += t; - return bd; - }; - newContent = newContent.replace("BUILDDATE", gbd()); - - status.headers = newContent; - - cb(); -}); - -gulp.task("webpack", (callback) => { - const webpackConfig = require("./webpack.config.js"); - if (status.mode === "prod") { - webpackConfig.mode = "production"; - webpackConfig.devtool = "nosources-source-map"; - } - if (status.mode === "dev") { - webpackConfig.mode = "development"; - webpackConfig.devtool = "eval-source-map"; - // webpackConfig.optimization.minimize = true; - } - webpack(webpackConfig, function (err, stats) { - if (err) { - throw new PluginError({ plugin: "webpack", message: err }); - } - - if (stats.hasErrors()) { - throw new PluginError({ - plugin: "webpack", - message: stats.toString({ - // output options - colors: true, - }), - }); - } - - console.log( - stats.toString({ - // output options - colors: true, - }) - ); - - callback(); - }); -}); - -gulp.task("buildplugin", (cb) => { - const destination = cfg.releaseFolder[status.mode]; - - gulp - .src(cfg.src.plugin) - // prepend headers - .pipe(contents.prepend(status.headers)) - // inject files - .pipe( - injectfile({ - pattern: "\\/\\*+\\s*inject:\\s*\\s*\\*+\\/", - }) - ) - // trim leading spaces - .pipe(trimlines({ leading: false })) - // rename and save - .pipe(rename(cfg.pluginName)) - .pipe(gulp.dest(destination)); - cb(); -}); - -gulp.task("buildmeta", (cb) => { - const p = path.join(cfg.releaseFolder[status.mode], cfg.metaName); - - ensureDirectoryExistence(p); - fs.writeFile(p, status.headers, (err) => { - cb(err); - }); -}); - // locales, key parity gulp.task("locales", (cb) => { const english = require("./src/code/translations/english.json"); @@ -192,69 +36,6 @@ gulp.task("locales", (cb) => { cb(); }); -// ESLint -gulp.task("eslint", (cb) => { - gulp - .src([ - "**/*.js", - "!node_modules/**", - "!dist/**", - "!releases/**", - "!src/lib/**", - ]) - .pipe(eslint()) - .pipe(eslint.format()) - .pipe(eslint.failAfterError()); - cb(); -}); - -gulp.task("eslint-fix", () => { - return gulp - .src([ - "**/*.js", - "!node_modules/**", - "!dist/**", - "!releases/**", - "!src/lib/**", - ]) - .pipe(eslint({ fix: true })) - .pipe(eslint.format()) - .pipe(gulp.dest(".")) - .pipe(eslint.failAfterError()); -}); - -gulp.task("prettier", () => { - return gulp - .src([ - "**/*.js", - "!node_modules/**", - "!dist/**", - "!releases/**", - "!src/lib/**", - ]) - .pipe(prettier()) - .pipe(gulp.dest(".")); -}); - -gulp.task( - "build", - gulp.series(["buildheaders", "buildmeta", "webpack", "buildplugin"]) -); - -// eslint-fix already formats the file -gulp.task("format", gulp.series(["eslint-fix"])); -// gulp.task("format", gulp.series(["prettier"])); - -gulp.task( - "build-dev", - gulp.series(["set-mode-dev", "format", "build", "clear"]) -); - -gulp.task( - "build-prod", - gulp.series(["set-mode-prod", "format", "build", "clear"]) -); - -gulp.task("default", gulp.series(["build-dev"])); +gulp.task("default", gulp.series(["locales"])); gulp.task("clean", () => del(["releases/*"])); diff --git a/package.json b/package.json index 173b0f06c..e198dc833 100644 --- a/package.json +++ b/package.json @@ -10,28 +10,25 @@ "eslint": "^7.28.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", + "eslint-webpack-plugin": "^3.0.1", "fancy-log": "^1.3.3", "gulp": "^4.0.2", - "gulp-eslint": "^6.0.0", - "gulp-inject-file": "^0.0.19", - "gulp-inject-string": "^1.1.1", - "gulp-prettier": "^3.0.0", - "gulp-rename": "^2.0.0", - "gulp-trimlines": "^1.0.1", "html-loader": "^2.1.2", "lodash": "^4.17.21", - "plugin-error": "^1.0.1", "prettier": "^2.3.1", "pretty-quick": "^3.1.0", "raw-loader": "^4.0.2", "style-loader": "^2.0.0", + "through2": "^4.0.2", "to-string-loader": "^1.1.6", "url-loader": "^4.1.1", "webpack": "^5.38.1", - "webpack-cli": "^4.7.1" + "webpack-cli": "^4.8.0" }, "scripts": { - "test": "none" + "build": "webpack --progress --mode production", + "build-dev": "webpack --progress --mode development", + "locales": "gulp locales" }, "repository": { "type": "git", diff --git a/plugin.config.json b/plugin.config.json index 90a28d8ed..833280a4b 100644 --- a/plugin.config.json +++ b/plugin.config.json @@ -16,10 +16,7 @@ "namespace": "https://wasabee.rocks/", "description": "Wasabee is not for dating.", "author": "Wasabee Project Team", - "category": "Draw", - "include": "https://intel.ingress.com/*", - "TESTinclude": "/https?:\\/\\/.*\\.ingress\\.com\\/?((intel|mission)?(\\/?(\\?|#).*)?)?/", - "grant": "none" + "category": "Draw" } }, "releaseFolder": { diff --git a/src/code/init.js b/src/code/init.js index cb03ea9ae..59abef6b4 100644 --- a/src/code/init.js +++ b/src/code/init.js @@ -1,3 +1,4 @@ +import statics from "./static"; import { initCrossLinks } from "./crosslinks"; import initServer from "./server"; import { setupLocalStorage, initSelectedOperation } from "./selectedOp"; @@ -21,6 +22,7 @@ import db from "./db"; import polyfill from "./polyfill"; const Wasabee = window.plugin.wasabee; +Wasabee.static = statics; window.plugin.wasabee.init = async () => { // polyfill diff --git a/src/code/static.js b/src/code/static.js index 66ec8495f..5d743d63e 100644 --- a/src/code/static.js +++ b/src/code/static.js @@ -1,7 +1,4 @@ -// this file is loaded by the build system -const W = window.plugin.wasabee || {}; - -W.static = { +const statics = { CSS: { main: require("./css/wasabee.css"), autodraws: require("./css/autodraws.css"), @@ -85,32 +82,32 @@ W.static = { ], }; -W.static.strings = {}; // empty object, fill it below -W.static.strings["Deutsch"] = require("./translations/german.json"); -W.static.strings["Espanol"] = require("./translations/spanish.json"); -W.static.strings["English"] = require("./translations/english.json"); -W.static.strings["Italiano"] = require("./translations/italian.json"); -W.static.strings["Tagalog"] = require("./translations/filipino.json"); -W.static.strings["Français"] = require("./translations/french.json"); -W.static.strings["Português"] = require("./translations/portuguese.json"); +statics.strings = {}; // empty object, fill it below +statics.strings["Deutsch"] = require("./translations/german.json"); +statics.strings["Espanol"] = require("./translations/spanish.json"); +statics.strings["English"] = require("./translations/english.json"); +statics.strings["Italiano"] = require("./translations/italian.json"); +statics.strings["Tagalog"] = require("./translations/filipino.json"); +statics.strings["Français"] = require("./translations/french.json"); +statics.strings["Português"] = require("./translations/portuguese.json"); -W.static.defaultOperationColor = "orange"; +statics.defaultOperationColor = "orange"; -W.static.linkStyle = { +statics.linkStyle = { dashArray: [5, 5, 1, 5], assignedDashArray: [4, 2, 1], opacity: 1, weight: 2, }; -W.static.selfBlockStyle = { +statics.selfBlockStyle = { color: "#ff1111", dashArray: [1, 5], opacity: 4, weight: 3, }; -W.static.backgroundLinkStyle = { +statics.backgroundLinkStyle = { dashArray: [8, 5], opacity: 0.4, weight: 2, @@ -118,10 +115,10 @@ W.static.backgroundLinkStyle = { interactive: false, }; -W.static.anchorTemplate = require("!raw-loader?esModule=false!./images/pin_custom.svg"); +statics.anchorTemplate = require("!raw-loader?esModule=false!./images/pin_custom.svg"); // https://leafletjs.com/reference-1.0.3.html#path -W.static.layerTypes = new Map([ +statics.layerTypes = new Map([ [ "main", { @@ -180,4 +177,5 @@ W.static.layerTypes = new Map([ ], ]); -export const constants = W.static.constants; +export const constants = statics.constants; +export default statics; diff --git a/src/code/wX.js b/src/code/wX.js index a400ee813..4cf9e0b58 100644 --- a/src/code/wX.js +++ b/src/code/wX.js @@ -1,7 +1,9 @@ +import statics from "./static"; + // aliases to make review easier -let strings = window.plugin.wasabee.static.strings; -const defaultLang = window.plugin.wasabee.static.constants.DEFAULT_LANGUAGE; -const localStoreKey = window.plugin.wasabee.static.constants.LANGUAGE_KEY; +let strings = statics.strings; +const defaultLang = statics.constants.DEFAULT_LANGUAGE; +const localStoreKey = statics.constants.LANGUAGE_KEY; const templateRe = /\{ *([\w_ -]+) *\}/g; diff --git a/src/headers.js b/src/headers.js deleted file mode 100644 index 1b853dbab..000000000 --- a/src/headers.js +++ /dev/null @@ -1,13 +0,0 @@ -// ==UserScript== -// @id set -// @name set -// @namespace set -// @version set -// @updateURL set -// @downloadURL set -// @description set -// @author set -// @include https://intel.ingress.com/* -// @category set -// @grant none -// ==/UserScript== diff --git a/src/main.js b/src/main.js deleted file mode 100644 index 5c2fbd415..000000000 --- a/src/main.js +++ /dev/null @@ -1,19 +0,0 @@ -/* eslint-disable */ -function wrapper(plugin_info) { - /* inject: ./wrapper/pluginStart.js */ - - window.plugin.Wasabee = window.plugin.wasabee = {}; - window.plugin.wasabee.info = plugin_info.script; - - // Code injection - let setup = function () { - /* inject: ../dist/static-bundle.js */ - - /* inject: ../dist/init-bundle.js */ - - window.plugin.wasabee.init(); - }; - - /* inject: ./wrapper/pluginEnd.js */ -} -/* inject: ./wrapper/afterWrapper.js */ diff --git a/src/wrapper/afterWrapper.js b/src/wrapper/afterWrapper.js deleted file mode 100644 index 13a3eec1e..000000000 --- a/src/wrapper/afterWrapper.js +++ /dev/null @@ -1,19 +0,0 @@ -//wrapper end - -// inject code into site context -var script = document.createElement("script"); -var info = {}; -if (typeof GM_info !== "undefined" && GM_info && GM_info.script) { - info.script = { - version: GM_info.script.version, - name: GM_info.script.name, - description: GM_info.script.description, - }; -} - -script.appendChild( - document.createTextNode("(" + wrapper + ")(" + JSON.stringify(info) + ");") -); -(document.body || document.head || document.documentElement).appendChild( - script -); diff --git a/src/wrapper/pluginEnd.js b/src/wrapper/pluginEnd.js deleted file mode 100644 index 4585b7e52..000000000 --- a/src/wrapper/pluginEnd.js +++ /dev/null @@ -1,10 +0,0 @@ -// PLUGIN END ---------------------------------------------------------- -setup.info = plugin_info; //add the script info data to the function as a property -if (!window.bootPlugins) { - window.bootPlugins = []; -} -window.bootPlugins.push(setup); -// if IITC has already booted, immediately run the 'setup' function -if (window.iitcLoaded && typeof setup === "function") { - setup(); -} diff --git a/src/wrapper/pluginStart.js b/src/wrapper/pluginStart.js deleted file mode 100644 index e342c8a16..000000000 --- a/src/wrapper/pluginStart.js +++ /dev/null @@ -1,6 +0,0 @@ -// ensure plugin framework is there, even if iitc is not yet loaded -if (typeof window.plugin !== "function") { - window.plugin = function () {}; -} - -// PLUGIN START -------------------------------------------------------- diff --git a/webpack.config.js b/webpack.config.js index 1271d2b77..976029387 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,15 +1,141 @@ const path = require("path"); -const outputPath = path.join(__dirname, "dist"); +const outputPath = path.join(__dirname, "releases"); +const ESLintPlugin = require("eslint-webpack-plugin"); -module.exports = { - mode: "production", +const { ConcatSource } = require("webpack-sources"); +const Compilation = require("webpack/lib/Compilation"); + +const wrapPrefix = ` +function wrapper(plugin_info) { + if (typeof window.plugin !== "function") { + window.plugin = function () {}; + } + + window.plugin.Wasabee = window.plugin.wasabee = {}; + window.plugin.wasabee.info = plugin_info.script; + + // Code injection + function setup () { +`; +const wrapSuffix = ` + window.plugin.wasabee.init(); + }; + + setup.info = plugin_info; //add the script info data to the function as a property + if (!window.bootPlugins) { + window.bootPlugins = []; + } + window.bootPlugins.push(setup); + // if IITC has already booted, immediately run the 'setup' function + if (window.iitcLoaded && typeof setup === "function") { + setup(); + } +} + +var script = document.createElement("script"); +var info = {}; +if (typeof GM_info !== "undefined" && GM_info && GM_info.script) { + info.script = { + version: GM_info.script.version, + name: GM_info.script.name, + description: GM_info.script.description, + }; +} + +script.appendChild( + document.createTextNode("(" + wrapper + ")(" + JSON.stringify(info) + ");") +); +(document.body || document.head || document.documentElement).appendChild( + script +); +`; + +class IITCScript { + constructor(options) { + this.options = options || {}; + this.header = ""; + this.header += "// ==UserScript==\n"; + const keys = [ + "id", + "name", + "namespace", + "version", + "updateURL", + "downloadURL", + "description", + "author", + "match", + "category", + "grant", + ]; + const meta = { + match: "https://intel.ingress.com/*", + grant: "none", + version: "", + }; + Object.assign(meta, options.meta); + meta.version = meta.version.replace( + "BUILDDATE", + new Date() + .toISOString() + .replace(/[^0-9]/g, "") + .slice(0, 14) + ); + keys.forEach((key) => { + Array.prototype.concat + .apply([], meta[key] && [meta[key]]) + .forEach((value) => { + if (value) this.header += `// @${key.padEnd(13)} ${value}\n`; + }); + }); + this.header += "// ==/UserScript==\n\n"; + } + + apply(compiler) { + compiler.hooks.compilation.tap("Userscript", (compilation) => { + compilation.hooks.processAssets.tap( + { + name: "Userscript", + stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE, + }, + () => { + compilation.chunks.forEach((chunk) => { + chunk.files.forEach((file) => { + compilation.updateAsset( + file, + new ConcatSource( + this.header, + wrapPrefix, + compilation.assets[file], + wrapSuffix + ) + ); + }); + }); + if (this.options.withMeta) { + compilation.chunks.forEach((chunk) => { + chunk.files.forEach((file) => { + if (file.match(/user.js$/)) + compilation.emitAsset( + file.replace(/user.js$/, "meta.js"), + new ConcatSource(this.header), + { minimized: true } + ); + }); + }); + } + } + ); + }); + } +} + +const config = { entry: { - static: "./src/code/static.js", init: "./src/code/init.js", }, output: { - path: outputPath, - filename: "[name]-bundle.js", + filename: "wasabee.user.js", }, resolve: { modules: ["node_modules"], @@ -36,4 +162,20 @@ module.exports = { }, ], }, + plugins: [new ESLintPlugin({ fix: true })], +}; + +module.exports = (env, argv) => { + const pluginConfig = require("./plugin.config.json"); + const meta = pluginConfig.headers.common; + if (argv.mode === "development") { + config.output.path = path.join(outputPath, "dev"); + config.devtool = "eval-source-map"; + Object.assign(meta, pluginConfig.headers.dev); + } else { + config.output.path = path.join(outputPath, "prod"); + Object.assign(meta, pluginConfig.headers.prod); + } + config.plugins.push(new IITCScript({ meta: meta, withMeta: true })); + return config; }; From d7af2013511204b47686ce758e8d4f0b48dd52a1 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 2 Sep 2021 18:27:30 +0200 Subject: [PATCH 042/275] protuguese: key parity/order --- src/code/translations/portuguese.json | 317 ++++++++++++++------------ 1 file changed, 169 insertions(+), 148 deletions(-) diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index a1b13e4a8..bc5b97fc7 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -1,385 +1,406 @@ { - "acknowledged": "Reconhecido", - "assigned": "Atribuído", - "completed": "Completo", - "pending": "Pendente", - "CapturePortalMarker": "Capturado", - "LetDecayPortalAlert": "Deixar caír", - "DestroyPortalAlert": "Destroir", - "FarmPortalMarker": "Farmar", - "GotoPortalMarker": "Ir para", - "GetKeyPortalMarker": "Retirar Chaves", - "CreateLinkAlert": "Link", - "MeetAgentPortalMarker": "Conhecer Agente", - "OtherPortalAlert": "Otros", - "RechargePortalAlert": "Recharge", - "UpgradePortalAlert": "Upgrade", - "UseVirusPortalAlert": "Usar Virus", - "ExcludeMarker": "Excluir de Auto-Desenhar / Marcar", - "SET_PORTAL_COMMENT": "Definir comentário do portal", "ABOUT WASABEE-IITC": "Sobre Wasabee-IITC", "ABOUT_WASABEE": "Sobre Wasabee", - "ADD": "Adicionar", - "ADD1": "Adicionar primeiro link", - "ADD2": "Adicionar segundo link", + "acknowledged": "Reconhecido", + "ADD LINK TITLE": "Adicionar Links Dialogo", + "ADD MARKER TITLE": "Adicionar Marcadores de Dialogo", "ADD_AGENT": "Adicionar Agente: ", - "ADD_BUTTON_LINKS": "Adicionar todos os links de uma vez.", "ADD_BL": "Adicionar links oara trás: ", - "ADD LINK TITLE": "Adicionar Links Dialogo", + "ADD_BUTTON_LINKS": "Adicionar todos os links de uma vez.", "ADD_LINKS": "Adicionar Links", - "ADD MARKER TITLE": "Adicionar Marcadores de Dialogo", "ADD_MARKER": "+ Marcador", - "ADD_MARKER2": "Adicionar Marcador", "ADD_NEW_OP": "Adicionar Nova Op", "ADD_SUCC_INSTR": "Adicionar agente, bem sucedido", - "AGENT": "Agente", + "ADD_ZONE": "Add Zone", + "ADD": "Adicionar", + "ADD1": "Adicionar primeiro link", + "ADD2": "Adicionar segundo link", "AGENT_STATS": "Agente Stats", + "AGENT": "Agente", "AGES": " (ages ago)", "ALREADY_HAS_MARKER": "Este portal já tem um marcador. Escolha um portal diferente.", - "ANCHOR1": "Âncora 1 ", - "ANCHOR2": "Âncora 2 ", - "ANCHOR3": "Âncora 3 ", + "AMAZ_TEAM_NAME": "Nome incrível da equipe.", "ANCHOR ASSIGNMENT": " Todos os links externos", "ANCHOR_GMAP": "Google Map", "ANCHOR_PORTAL": "Âncora Portal ", "ANCHOR_PORTAL2": "Âncora Portal 2", "ANCHOR_PORTAL3": "Âncora Portal 3", + "ANCHOR1": "Âncora 1 ", + "ANCHOR2": "Âncora 2 ", + "ANCHOR3": "Âncora 3 ", "ANCHORS_AS_BOOKMARKS": "Âncora como bookmarks", "API_KEY": " api key: ", - "ASSIGN": "Atribuir", - "ASSIGNED": "Atribuido", "ASS_TO": "Atrubuir a:", "ASSIGN LINK PROMPT": "Atribuir link para: ${value}", "ASSIGN MARKER PROMPT": "Atrubuir marcador para: ${value}", - "ASSIGN OUTBOUND": "Atribuir links externos", "ASSIGN OUTBOUND PROMPT": "Atribuir todos os links externos de: ${value}", - "ASSIGNED_ONLY": "Só Atribuir", + "ASSIGN OUTBOUND": "Atribuir links externos", + "ASSIGN": "Atribuir", "ASSIGNED_ONLY_SHORT": "A", + "ASSIGNED_ONLY": "Só Atribuir", + "assigned": "Atribuído", + "ASSIGNED": "Atribuido", "AUTH ANDROID": "No Android, tentar primeiro 'rápido'. Se isso falhar, tentar o login principal com 'select_account'..", "AUTH INCOMPAT": "Você ativou um plugin no TamperMonkey que é incompatível com o Wasabee", "AUTH IOS": "No iOS, use o 'Login' principal. se isso falhar, faça 'Webview Log in', faça o login; em seguida, use o botão 'Verificar Webview' para concluir o processo.", "AUTH REQUIRED": "Autentificação Requerida", "AUTH TOKEN REJECTED": "Envio de token de autenticação rejeitado pelo servidor: ${value}", "AUTH_SELECT_ACCOUNT": "Selecionar conta", - "AUTODRAWS": "Wasabee Auto-draw Opções", "AUTO_DRAWS": "Auto-draw", - "AUTOLOAD": "Carregar automaticamente os detalhes do portal em falta", + "AUTODRAWS": "Wasabee Auto-draw Opções", "AUTOLOAD_RATE": "Taxa de solicitação de detalhes do portal (ms)", - "AUTOMARK": "Auto-Marcar", + "AUTOLOAD": "Carregar automaticamente os detalhes do portal em falta", "AUTOMARK STOP": "Auto-Marcar interrompido devido a portais não serem carregados", - "AMAZ_TEAM_NAME": "Nome incrível da equipe.", + "AUTOMARK": "Auto-Marcar", "BAT_TOAD": "Battle Toads", "BLOCKER LIST TITLE": "Mostrar todos os blockers", "BLOCKER TITLE": "Blockers", "CANCEL": "Cancelar", "CAPSULE": "Capsula", - "CHANGE SERVER": "Trocar de Servidor", + "CapturePortalMarker": "Capturado", "CHANGE SERVER PROMPT": "Novo servidro Wasabee", + "CHANGE SERVER": "Trocar de Servidor", "CHANGE_WAS_SERVER": "Mudar servidor Wasabee", "CHECKLIST BUTTON TITLE": "Checklist da Operação", "CHECKLIST BUTTON": "Checklist", - "CLEAR": "Limpar selecção", - "CLEAR_EVERYTHING": "limpar Portais/Links/Marcadores", "CLEAR LINKS": "Limpar Links", "CLEAR MARKERS": "Limpar Markers", - "CLEAROPS BUTTON": "Limpar dados Wasabee", + "CLEAR_EVERYTHING": "limpar Portais/Links/Marcadores", + "CLEAR": "Limpar selecção", "CLEAROPS BUTTON TITLE": "limpar TODOS os dados Wasabee", + "CLEAROPS BUTTON": "Limpar dados Wasabee", "CLEAROPS PROMPT": "Isto limpará todas as OPS e dados relacionados a Wasabee. Tudo será restaurado apartir do servidor na próxima sincronização.", "CLOSE": "Perto", - "COMPLETED": "Completo", + "COMMENT": "Comentario", "COMPLETED BY": "Completo por ${value}", + "completed": "Completo", + "COMPLETED": "Completo", "CON_DEL": "Confirmar Apagar: ${value}", - "COMMENT": "Comentario", "CONFIRM_DELETE": "Desejas realmente excluir este link: ", "COUNT": "Contar", "CREATE_NEW_TEAM": "Criar Nova Equipa", + "CreateLinkAlert": "Link", "CUR_USER_INFO": "Informações do usuário atual", - "DT_FORMAT": "Formato das Ferramentas de Desenho", + "D_SHOW_LIST": "Chaves de defesa de entrada", "DEFAULT OP NAME": "Nova Op: ${value}", - "DELETE_ANCHOR": "Apagar", "DELETE ANCHOR PROMPT": "Desejas excluir esta âncora e todos os links associados: ", "DELETE ANCHOR TITLE": "Apagar Âncora", - "DELETE_LINK": "Apagar", - "DELETE_MARKER": "Apagar", "DELETE MARKER PROMPT": "Desejas apagar esta âncora: ", "DELETE MARKER TITLE": "Apagar Marcador", - "DELETE_OP": "Apagar ${value}", "DELETE PERM DENIED": "Permissão para excluir negada.", + "DELETE_ANCHOR": "Apagar", + "DELETE_LINK": "Apagar", + "DELETE_MARKER": "Apagar", + "DELETE_OP": "Apagar ${value}", "DELETED": "Excluído com sucesso.", "DESCRIP_PLACEHOLD": "Descrição (opcional)", - "DISABLED": "Este recurso não está pronto para os usuários", + "DestroyPortalAlert": "Destroir", "DISABLE_SYNC": "O plugin de sincronização de stoque não é compatível com Wassabe. Desativa a sincronização.", + "DISABLED": "Este recurso não está pronto para os usuários", "DONE": "Feito", "DRAW TOOLS FORMAT": "Formato Draw Tools", + "DT_FORMAT": "Formato das Ferramentas de Desenho", "DUPE_OP": "Duplicar Operação", "END_PORT": "Portal final ", - "EXPORT": "Exportar: ", - "EXPORT OP": "Exportar Op", + "ExcludeMarker": "Excluir de Auto-Desenhar / Marcar", "EXPORT OP TITLE": "Exportar Op Actual", + "EXPORT OP": "Exportar Op", + "EXPORT": "Exportar: ", "FAKED": "Falsificado: [${value}]", - "FANFIELD": "Desenhar", - "FANFIELD2": "Desenhar Fan Field", "FAN_FIELD3": "Fan Field", "FANFIELD TITLE": "Fanfield", - "FROM_DEPTH": "da profundidade", + "FANFIELD": "Desenhar", + "FANFIELD2": "Desenhar Fan Field", + "FarmPortalMarker": "Farmar", "FROM_1-2": "A Partir da base 1-2", "FROM_1-3": "A Partir da base 1-3", "FROM_2-3": "A Partir da base 2-3", + "FROM_DEPTH": "da profundidade", "FROM_PORT": "A Partir do Portal", - "GET_DT_DRAW": "Importar Dezenho DrawTools", "GET DT": "Obtenha o desenho existente do DrawTools", + "GET_DT_DRAW": "Importar Dezenho DrawTools", + "GetKeyPortalMarker": "Retirar Chaves", + "GotoPortalMarker": "Ir para", + "H-GEN_INST": "Define portais para a camada externa. Escolhe o número de divisões. Clica para desenhar", + "HF_DEEP_SEARCH": "Pesquisa exaustiva", "HF_DRAW_BUTTON": "Desenhar", "HF_DRAW_DEEP_BUTTON": "Desenhar com recursão profunda", - "HF_DEEP_SEARCH": "Pesquisa exaustiva", "HF_REDRAW_BUTTON": "Redesenhar", "HG": "Campo Homogêneo", - "H-GEN_INST": "Define portais para a camada externa. Escolhe o número de divisões. Clica para desenhar", "HOURS": " (${value} horas atrás)", "HOW_TO_VIDS": "

Vídeos de instruções:

", "IMP_COMP": "Importação concluída. Encontrada ", "IMP_DT_OP": "Importar OP Drawtools: ", - "IMPORT_OP": "Importar Operação", - "IMPORT_OP_TITLE": "Importar Op: ${value}", - "IMPORT_OP_SUCCESS": "OP Importada: ${value} successfuly.", "IMP_NOPE": "A Importação Falhou.", "IMP_WAS_OP": "Importar Operação Wasabee", + "IMPORT_OP_SUCCESS": "OP Importada: ${value} successfuly.", + "IMPORT_OP_TITLE": "Importar Op: ${value}", + "IMPORT_OP": "Importar Operação", "IMPOSSIBLE": "Impossível", "INGNAME_GID": "Nome de entrada ou GoogleID", "INPUT_DT_KEY_COUNT": "Contagem de chaves defensivas de entrada", "INPUT_SQUAD_NAME": "Insere um nome de esquadrão", "INVALID REQUEST": "Pedido inválido", "IOS NEED FAKE UA": "Deves definir um 'Agente de usuário personalizado para visualizações da Web' nas configurações do IITC-Mobile ou o login falhará", - "KEYS": "Chaves", "KEY_LIST2": "Lista de chaves para operação: ${value}", - "KEY_LIST": "Lista chaves para portal: ${value}", + "KEYS": "Chaves", "KNOWN_BLOCK": "Blockers conhecidos: ${value}", - "LA": "L8+ alguns LA", "LA DESC": "Dependendo do número e tipo de Link Amps usados, um nível de portal de origem inferior pode ser suficiente.", + "LA": "L8+ alguns LA", "LANG": "Língua", "LEAVE": "Deixar", - "LINKS": "Links", - "LINKS2": ": Links", + "LetDecayPortalAlert": "Deixar caír", "LINK ASSIGNMENT": "Atribuição de Link", + "LINK STATE PROMPT": "Estado do link", + "LINK STATE": "Definir o status do link", "LINKS BUTTON TITLE": "Links", + "LINKS": "Links", + "LINKS2": ": Links", + "LOAD PORTALS": "Carregar Portais", "LOADING": "[a carregar]", "LOADING1": "a carregar: [${value}]", - "LOAD PORTALS": "Carregar Portais", "LOC_PROC": "localização processada", "LOC_UPDATE": "Atualização de localização", "LOCATION SUB": "Localização registrada", "LOCFRMSER": " (localmente e do servidor)", + "LOG IN QUICK": "Log In (Rápido; para Android)", "LOG IN": "Log In", "LOG_OUT": "Log Out", - "LOG IN QUICK": "Log In (Rápido; para Android)", - "MADRID_WAS_TAKEN": "Madrid Protocol", - "MADRID_TITLE": "Madrid Protocol", - "MADRID": "Desenhar", - "MADRID_NOTSET": "baselink não definido.", "MADRID_SET_1": "Selecione a região para a ligação de base Âncora 2 à Âncora 3", "MADRID_SET_2": "Selecione a região para a ligação de base Âncora 3 à Âncora 1", "MADRID_SET_3": "Selecione a região para a ligação de base Âncora 1 a Âncora 2", - "MANAGE": "Gerenciar", + "MADRID_TITLE": "Madrid Protocol", + "MADRID_WAS_TAKEN": "Madrid Protocol", + "MADRID": "Desenhar", "MANAGE_TEAM": "Gerenciar ${value}", - "MARKERS BUTTON TITLE": "Marcadores", + "MANAGE": "Gerenciar", + "MARKER ASSIGNMENT": " Atribuição de marcador", "MARKER LIST TITLE": "Lista de Marcadores", "MARKER LIST": "Marcadores", - "MARKER_LIST": "Lista de Marcadores: ${value}", - "MARKER ASSIGNMENT": " Atribuição de marcador", "MARKER STATE PROMPT": "Status do marcador", "MARKER STATE": " Definir estado do marcador", + "MARKER_LIST": "Lista de Marcadores: ${value}", + "MARKERS BUTTON TITLE": "Marcadores", + "MAX_SPLITS": "Divisões máximas", "MAX": "Fan Field", + "MeetAgentPortalMarker": "Conhecer Agente", + "MERGE ON UPDATE": "Merge on update", + "MERGE_CHANGES_LOCAL": "Local changes", + "MERGE_CHANGES_MERGE": "Merge result", + "MERGE_CHANGES_REMOTE": "Remote changes", + "MERGE_LOCAL": "Keep local", + "MERGE_MESSAGE": "It seems that {opName} has local changes. Do you want to merge your modifications with the server OP, use the server version or keep the local version?", + "MERGE_REBASE": "Merge", + "MERGE_REPLACE": "Use server", + "MERGE_TITLE": "Merge local&remote OP", "MIN_SRC_PORT_LVL": "Nível mínimo exigido no portal de origem", "MINUTES": " (${value} minutos atrás)", "MM": "Multimax", - "MY_CAP_ID": "Minha Capsula ID", - "MY_COUNT": "Minha Conta", - "MULTIMAX": "Multimax!", - "MUST_NOT_BE_EMPTY": "Não deve estar vazio", - "MULTIMAX2": "Multimax", + "MM_INSERT_ORDER": "Insert at the end", "MULTI_M_TITLE": "Desenhar camadas máximas", "MULTI_M": "Desenhar", - "NAME": "Nome: ", + "MULTIMAX": "Multimax!", + "MULTIMAX2": "Multimax", + "MUST_NOT_BE_EMPTY": "Não deve estar vazio", + "MY_CAP_ID": "Minha Capsula ID", + "MY_COUNT": "Minha Conta", "NAME_REQ": "Nome Requerido", + "NAME": "Nome: ", "NEW_OP": "Nova Operação", - "NEW_TEAM": "Nova Equipa", "NEW_TEAM_NAME": "Novo nome de Equipa", + "NEW_TEAM": "Nova Equipa", "NEW_WAS_SERVER": "Novo servidor Waasbee", - "NOT LOGGED IN": "Não logado: ${value}", - "NOT LOGGED IN SHORT": "Não logado", - "NO": "Não", - "NO_DT_ITEMS": "Nenhum item desenhado do DrawTools foi detectado", + "NEWOP BUTTON TITLE": "Criar uma nova operação", + "NEWOP BUTTON": "Nova Op", "NO_DATA": "sem dados", + "NO_DT_ITEMS": "Nenhum item desenhado do DrawTools foi detectado", "NO_LABEL": "Nenhum rótulo definido", - "NOT_LOADED": "Não totalmente carregado, tente novamente.", "NO_PORT_SEL": "Nenhum portal selecionado.", + "NO_STOCK_INTEL": "Wasabee não suporta importações de desenho de inteligência de stoque", "NO_TITLE": "Nenhum título definido", + "NO": "Não", + "NOT LOGGED IN SHORT": "Não logado", + "NOT LOGGED IN": "Não logado: ${value}", + "NOT_LOADED": "Não totalmente carregado, tente novamente.", "NOT_SET": "não configurado", - "NO_STOCK_INTEL": "Wasabee não suporta importações de desenho de inteligência de stoque", "NTNAME": "Nome", "OK": "OK", "ON_HAND": "Na Mão", + "ONION_WAS_TAKEN": "Cebola", + "ONION": "Desenhar", "ONLY_DT_IMP": " (apenas para importações do DrawTools)", "OP DELETED": "Operação removida do servidor: ${value}", "OP PERM DENIED": "Permissão negada para operação: ${value}", + "OP_BUTTON": "Operação", "OP_CHECKLIST": "Lista de verificação de operação: ${value}", "OP_NAME_UNSET": "O nome da operação não estava definido", "OP_PERMS": "Permissões de operação", + "OP_SETTINGS_BUTTON": "Op ⚙", + "OP_SETTINGS_TITLE": "Configurações de operação", "OPEN_REQUEST": "[pedido aberto]", - "OPER_NAME": "Nome da Operação: ", "OPER_COLOR": "Cor de operação: ", + "OPER_NAME": "Nome da Operação: ", "OPERATIONS": "Operações", - "OPS BUTTON": "Ops", "OPS BUTTON TITLE": "Operações", - "OP_BUTTON": "Operação", - "OP_SETTINGS_BUTTON": "Op ⚙", - "OP_SETTINGS_TITLE": "Configurações de operação", - "OPTION": "opção", + "OPS BUTTON": "Ops", "ORDER": "Pedido", + "OtherPortalAlert": "Otros", "PASTE_INSTRUCT": "Cola uma exportação de desenho Wasabee aqui.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", + "pending": "Pendente", "PENDING": "Pendente", "PERMS": "${value} permissões", "PICK_DEST_FIRST": "Seleciona um portal de destino primeiro!", "PICK_TAR_FIRST": "Seleciona um portal de destino primeiro!", "PICK_TARGETDEST_Portals": "Seleciona primeiro os portais de destino e destino!", "PLEASE_SELECT_PORTAL": "Seleciona um portal", - "PORTAL": "Portal", - "PORTAL_COUNT": "${value} portais", - "PORTAL KEY LIST": "Lista de chaves para portal ${value}", "PORT_FAKE": " portais. Falsificado ", + "PORTAL KEY LIST": "Lista de chaves para portal ${value}", + "PORTAL_COUNT": "${value} portais", + "PORTAL": "Portal", + "QD BUTTON CHANGE COLOR": "Click to change next links color", "QD BUTTON END": "Clique para parar de desenhar campos", + "QD BUTTON TOGGLE MODE": "Click to change draw mode", + "QD CHANGE COLOR": "Change color", "QD END": "FIM", "QD TITLE": "Camadas de desenho rápido", + "QD TOGGLE MODE": "Change mode", "QDBASE": "Link Base", "QDCANCEL": "Cancelar campos de desenho", "QDCONT": "Clica num portal espinha para desenhar um campo.", "QDEND": "Clica novamente no mesmo portal para finalizar o desenho.", "QDNEXT": "Clica no segundo portal de âncora.", "QDSTART": "Clica no primeiro portal de âncora.", - "READ": "Ler", "READ_SHORT": "Ler Abreviado", + "READ": "Ler", + "RechargePortalAlert": "Recharge", + "REFERENCE_TIME": "Reference Time: ", "REM_LOC_CP": "Remover cópia local de ${value}", - "REMOVE": "Remover", - "REMOVE_TEAM": "Remover Equipe: ", "REMOVE_TEAM_CONFIRM_LABEL": "Você deseja remover permanentemente ${value} do servidor Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipe ${value}", - "RENAME": "Renomear", + "REMOVE_TEAM": "Remover Equipe: ", + "REMOVE": "Remover", "RENAME_TEAM": "Renomear Equipe: ", + "RENAME": "Renomear", "REQUIRED": "Requerido", "RESET": "Redefinir", "REVERSE": "Inverter", "ROCKS_COM": "enl.rocks comunidade: ", "ROLE": "Função", + "SAVELINKS TITLE": "Save Links", + "SAVELINKS_DRAW": "Save Links", + "SAVELINKS": "Save Links", + "SECONDS": " (${value} segundos atrás)", + "SEL_PORT_FIRST": "Selecione primeiro os portais âncora!", "SEL_SB_ANCHOR": "Seleciona a âncora.", "SEL_SB_ANCHOR2": "Reduzir o zoom. Verifica se todos os portais foram carregados e clica em desenhar.", "SEL_SB_ANCHOR3": "Por favor, sê paciente, pode demorar um pouco.", - "SELECT PORTAL": "Selecionar um portal para enviar", - "SECONDS": " (${value} segundos atrás)", - "SEND TARGET": "Enviar alvo", - "SEND TARGET AGENT": "Selecionar o destinatário alvo", + "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", "SEL_SRC_ANC2": "Selecionar a fonte e a âncora 2", "SEL_SRC_PORT": "Selecionar um portal de origem", + "SELECT PORTAL": "Seleciona um portal primeiro", "SELECT_FAN_PORTALS": "Selecionar um portal de âncora, um portal inicial e um portal final e, em seguida, posiciona a visualização sobre a área do campo.", "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", "SELECT_INSTRUCTIONS": "Select two anchor portals, then zoom over the spine area.", "SELECT_MADRID_INSTRUCTIONS": "Selecionar três portais de âncora, amplia a área próxima à âncora selecionada, espera até que os portais sejam carregados (os portais devem aparecer na tela para serem considerados) e selecioner o botão 'definir região da coluna' para os links de base correspondentes.", - "SELECT PORTAL": "Seleciona um portal primeiro", - "SEL_PORT_FIRST": "Selecione primeiro os portais âncora!", + "SELECT_ONION_PORTALS": "As camadas são construídas de dentro para fora. Aumenta o zoom para o centro e seleciona o portal inicial, em seguida, diminui o zoom para a área.", "SELF SWAP": "Não é possível trocar um portal contigo mesmo! Seleciona um portal diferente.", "SEND ANALYTICS": "Enviar análises anônimas", "SEND LOCATION": "Enviar localização", - "SEND_LOC": "Enviar localização", + "SEND TARGET AGENT": "Selecionar o destinatário alvo", "SEND TARGET CONFIRM": "Queres enviar ${value} alvo para ${option}?", - "SET": "definir", + "SEND TARGET": "Enviar alvo", + "SEND_LOC": "Enviar localização", "SET_3_PORT": "Defina os três portais primeiro!", "SET_COMMENT": "Definir Comentário", - "SET_LINK_COMMENT": "Definir comentário para o link: ", "SET_LCOMMENT": "Definir comentário do link", + "SET_LINK_COMMENT": "Definir comentário para o link: ", + "SET_LINKS_ZONES": "Set Links to Zones ", "SET_MARKER_COMMENT": "Definir comentário para marcador em: ", "SET_MARKER_TYPE_TITLE": "Alterar o tipo de marcador", + "SET_MARKERS_ZONES": "Set Markers to Zones", "SET_MCOMMENT": "Definir comentário do marcador: ${value}", "SET_NEW_OP": "Define o novo nome da operação", - "SET_PORT_COMMENT": "Definir comentário para portal: ", "SET_PCOMMENT": "Definir comentário do portal: ${value}", + "SET_PORT_COMMENT": "Definir comentário para portal: ", "SET_PORTAL_COMMENT": "Definir comentário do portal", + "SET": "definir", "SETTINGS": "Configurações do Wasabee", "SKINS_AVAILABLE": "Existem ${value} skins disponíveis.", "SKINS_BUTTON": "Configurar Skins", "SKINS_DESCRIPTION": "Gerenciar as skins disponíveis movendo o tema para a coluna da esquerda. Quanto mais baixo na coluna, maior será a prioridade para o UI.", "SKINS_MANAGE_TITLE": "Gerenciar skins", + "SKIP_CONFIRM_ALWAYS": "Never ask (use with caution)", + "SKIP_CONFIRM_ENTITY": "Only ask for team/op", + "SKIP_CONFIRM_NEVER": "Always ask", + "SKIP_CONFIRM": "Skip confirmation", "SOURCE_PORT": "Portal Fonte ", "SQUAD": "Esquadrão", - "STATE": "Estado", - "STARBURST": "Starburst", - "STARBURST_DRAW": "Desenhar", "STARBURST TITLE": "Starburst", + "STARBURST_DRAW": "Desenhar", + "STARBURST": "Starburst", "START_PORT": "Portal inicial", - "TEAM STATE": "Partilhar localização", + "STATE": "Estado", "SUPPORT_INSTRUCT": "Para obter suporte, por favor, junte-se ao The Wasabee User Telegram Channel", - "SWAP": "Troca", "SWAP PROMPT": "Queres trocar: ", "SWAP TITLE": "Trocar Portais", "SWAP WITH": " com ", - "SYNC": "Download operações disponíveis", + "SWAP": "Troca", "SYNC DONE": "Download Completo", + "SYNC": "Download operações disponíveis", "TARDEST_DIFF": "Os portais de destino e destino devem ser diferentes.", - "TEAMS BUTTON TITLE": "Listar equipas Wasabee", - "TEAMS BUTTON": "Equipas", - "NEWOP BUTTON TITLE": "Criar uma nova operação", - "NEWOP BUTTON": "Nova Op", "TARGET SENT": "Alvo Enviado", - "TEAM": "Equipa", + "TEAM PERM DENIED": "Permissão negada à equipa: ${value}", + "TEAM STATE": "Partilhar localização", "TEAM_CREATED": "Equipa ${value} created", "TEAM_NAME": "Nome Equipa", - "TEAM PERM DENIED": "Permissão negada à equipa: ${value}", + "TEAM": "Equipa", + "TEAMS BUTTON TITLE": "Listar equipas Wasabee", + "TEAMS BUTTON": "Equipas", "TITLE": "titulo", - "TRAWL": "Procurar por Blockers", + "TO_PORT": "Para o Portal", + "TRAWL SKIP TILES": "Trawl Skip Tiles", + "TRAWL TITLE": "Trawl Lanes", + "TRAWL WARNING": "Isto carregará os dados do bloco em todos os links desenhados. Este é um processo lento.", "TRAWL_AUTOMARK": "Auto-mark blockers depois da procura", "TRAWL_BULK_LOAD_WARNING": "Este método carrega os dados do bloco o mais rápido possível. Usa por sua conta e risco.", "TRAWL_BULK_LOAD": "Carregar rapidamente Dados do Bloco", "TRAWL_CLEAR_MARKERS": "Limpa vírus / destroi marcadores antes da procura", - "TRAWL TITLE": "Trawl Lanes", - "TRAWL WARNING": "Isto carregará os dados do bloco em todos os links desenhados. Este é um processo lento.", - "TRAWLING": "A Varrer os links a procura de blockers, fecha esta caixa de diálogo para parar", "TRAWL_REMAINING": "${value} Restantes", - "TO_PORT": "Para o Portal", + "TRAWL": "Procurar por Blockers", + "TRAWLING": "A Varrer os links a procura de blockers, fecha esta caixa de diálogo para parar", "TYPE": "Tipo", "UNASSIGNED": "Não atribuído", "UNKNOWN": "Desconhecido", - "UPDATED": "Atualizado com sucesso", - "UPDATE HOVER": "UPDATE ${value} no servidor", "UPDATE HOVER NOT CHANGED": "${value} não mudou localmente", - "UPDATE_CONFLICT_TITLE": "Conflito detectado com o servidor", + "UPDATE HOVER": "UPDATE ${value} no servidor", + "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "A OP foi modificada no servidor desde a última sincronização. Queres substituir a versão do servidor pela atual?", + "UPDATE_CONFLICT_TITLE": "Conflito detectado com o servidor", + "UPDATE_COUNT": "Contagem de atualização", + "UPDATED": "Atualizado com sucesso", + "UpgradePortalAlert": "Upgrade", "UPLOAD BUTTON HOVER": "UPLOAD ${value} (atualmente não está no servidor)", "UPLOAD PERM DENIED": "Permissão para upload negada", "UPLOADED": "Carregado com sucesso", + "USE PANES ON MOBILE": "Use panes (need reload)", "USE_SWAP_INSTRUCT": ". Usa o recurso de troca para mover portais falsos para portais reais no mesmo local. Ampliar os portais 'Carregando' na lista de verificação pode forçá-los a carregar.", "USE_VALID_NAME": "Usa um nome de operação válido", - "UPDATE_COUNT": "Contagem de atualização", - "VRLA": "L8+alguns VRLA", + "UseVirusPortalAlert": "Usar Virus", "VRLA DESC": "Dependendo do número e tipo de Link Amps usados, um nível de portal de origem inferior pode ser suficiente.", + "VRLA": "L8+alguns VRLA", "WASABEE BUTTON TITLE": "Wasabee: É VERDE E FAZ SMURFS CHORAREM.", - "WASABEE_MODE_LABEL": "Modo", - "WASABEE_MODE_BATTLE": "Batalha", - "WASABEE_MODE_DESIGN": "Design", - "WASABEE_MODE_DESC": "No modo de design, as alterações devem ser enviadas manualmente para o servidor; as atribuições feitas não notificarão os agentes; atribuições enviadas do IITC substituirão seu status atual no servidor. No modo de batalha, as alterações serão enviadas automaticamente para o servidor; as atribuições serão enviadas aos agentes via Telegram (se disponível); o status do servidor para atribuições tem prioridade sobre os dados IITC.", - "WD BUTTON": "W-D Chaves", + "WASABEE_D_LIST": "Contagem de chaves defensivas de entrada", "WD BUTTON TITLE": "Log de chaves defensivas", - "WEBVIEW": "Login do Webview (iOS)", + "WD BUTTON": "W-D Chaves", "WEBVIEW VERIFY": "Verificar Webview", - "WRITE": "escrita", + "WEBVIEW": "Login do Webview (iOS)", "WRITE_SHORT": "RW", + "WRITE": "escrita", "WSERVER": "Servidor: ${value}", "YES": "Sim", "YESNO_DEL": "Tem certeza de que deseja excluir ${value}?", - "LINK STATE PROMPT": "Estado do link", - "LINK STATE": "Definir o status do link", - "D_SHOW_LIST": "Chaves de defesa de entrada", - "WASABEE_D_LIST": "Contagem de chaves defensivas de entrada", - "ONION_WAS_TAKEN": "Cebola", - "ONION": "Desenhar", - "SELECT_ONION_PORTALS": "As camadas são construídas de dentro para fora. Aumenta o zoom para o centro e seleciona o portal inicial, em seguida, diminui o zoom para a área.", - "MAX_SPLITS": "Divisões máximas", + "ZONE_DRAW": "Click to set the zone boundaries", + "ZONE": "Zone", "smallScreen": { "LOG IN": "Log In", "LOG_OUT": "Log Out", From 7be145c3a7884a925152db64f138158f45c9c2ca Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Sep 2021 22:40:31 +0200 Subject: [PATCH 043/275] merge: fix users importing remote op --- src/code/dialogs/mergeDialog.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index 02c9af499..77c25d49e 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -60,7 +60,13 @@ const MergeDialog = WDialog.extend({ _displayDialog: function () { this._opRebase = new WasabeeOp(this.options.opRemote); - const origin = new WasabeeOp(this.options.opOwn.fetchedOp); + const origin = new WasabeeOp( + // while merge should only occurs with server ops, it appears users succeed to merge + // with local ops. This is a failsafe for those edge-cases + this.options.opOwn.fetchedOp + ? this.options.opOwn.fetchedOp + : this.options.opOwn.toExport() + ); const changes = this.options.opOwn.changes(origin); const summary = this._opRebase.applyChanges(changes, this.options.opOwn); this._opRebase.cleanAll(); From 3bb6baa1777915de35635bb7793e93d738e78b26 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Sep 2021 23:03:19 +0200 Subject: [PATCH 044/275] update/upload: add UI feedback --- src/code/buttons/uploadButton.js | 4 ++++ src/code/css/toolbar.css | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/code/buttons/uploadButton.js b/src/code/buttons/uploadButton.js index ec8f0f067..c43469f87 100644 --- a/src/code/buttons/uploadButton.js +++ b/src/code/buttons/uploadButton.js @@ -38,6 +38,7 @@ const UploadButton = WButton.extend({ } try { + this.button.classList.add("loading"); const r = await uploadOpPromise(); // switch to the new version in local store -- uploadOpPromise stores it await makeSelectedOperation(r.ID); @@ -55,6 +56,7 @@ const UploadButton = WButton.extend({ console.error(e); alert(`Upload + Update Failed: ${e.toString()}`); } + this.button.classList.remove("loading"); } }, }); @@ -122,6 +124,7 @@ const UploadButton = WButton.extend({ if (operation.isServerOp()) { try { if (force) delete operation.lasteditid; + this.button.classList.add("loading"); const success = await updateOpPromise(operation); if (success) { operation.localchanged = false; @@ -158,6 +161,7 @@ const UploadButton = WButton.extend({ console.error(e); alert(`Update Failed: ${e.toString()}`); } + this.button.classList.remove("loading"); return; } }, diff --git a/src/code/css/toolbar.css b/src/code/css/toolbar.css index 09a07589b..fbb5fae18 100644 --- a/src/code/css/toolbar.css +++ b/src/code/css/toolbar.css @@ -129,7 +129,8 @@ /*background-image: url(../images/toolbar_sync.png)*/ background-image: url(../images/toolbar_download.svg) } -.wasabee-toolbar-sync.loading { +.wasabee-toolbar-sync.loading, +.wasabee-toolbar-upload.loading { background-image: url(../images/loading.gif) } From 24ab8470c53dd09191ef47e6336021c54addc505 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Sep 2021 23:15:57 +0200 Subject: [PATCH 045/275] build: add scot build --- package.json | 1 + plugin.config.json | 7 ++++++- webpack.config.js | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e198dc833..f60d37b3d 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "scripts": { "build": "webpack --progress --mode production", "build-dev": "webpack --progress --mode development", + "build-scot": "webpack --progress --mode development --env scot", "locales": "gulp locales" }, "repository": { diff --git a/plugin.config.json b/plugin.config.json index 833280a4b..f4e05872d 100644 --- a/plugin.config.json +++ b/plugin.config.json @@ -6,9 +6,14 @@ "version": "0.20.BUILDDATE" }, "dev": { + "downloadURL": "https://cdn2.wasabee.rocks/iitcplugin/latest/dev/wasabee.user.js", + "updateURL": "https://cdn2.wasabee.rocks/iitcplugin/latest/dev/wasabee.meta.js", + "version": "0.20.BUILDDATE-dev" + }, + "scot": { "downloadURL": "https://am.wasabee.rocks/static/dev/wasabee.user.js", "updateURL": "https://am.wasabee.rocks/static/dev/wasabee.meta.js", - "version": "0.20.BUILDDATE-dev" + "version": "0.20.BUILDDATE-scot" }, "common": { "id": "Wasabee.user.js", diff --git a/webpack.config.js b/webpack.config.js index 976029387..1635fe532 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -168,7 +168,11 @@ const config = { module.exports = (env, argv) => { const pluginConfig = require("./plugin.config.json"); const meta = pluginConfig.headers.common; - if (argv.mode === "development") { + if (argv.mode === "development" && env.scot) { + config.output.path = path.join(outputPath, "scot"); + config.devtool = "eval-source-map"; + Object.assign(meta, pluginConfig.headers.scot); + } else if (argv.mode === "development") { config.output.path = path.join(outputPath, "dev"); config.devtool = "eval-source-map"; Object.assign(meta, pluginConfig.headers.dev); From a33a55cfed802b15d5d4241b9121546ca6ea9362 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 4 Oct 2021 20:50:55 +0200 Subject: [PATCH 046/275] don't import to duplicate --- src/code/dialogs/importDialog.js | 18 ++++++++++++++---- src/code/translations/english.json | 2 +- src/code/translations/filipino.json | 2 +- src/code/translations/french.json | 2 +- src/code/translations/german.json | 2 +- src/code/translations/italian.json | 2 +- src/code/translations/portuguese.json | 2 +- src/code/translations/spanish.json | 2 +- 8 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/code/dialogs/importDialog.js b/src/code/dialogs/importDialog.js index 84f40ca5f..3b3ee1bd9 100644 --- a/src/code/dialogs/importDialog.js +++ b/src/code/dialogs/importDialog.js @@ -141,12 +141,22 @@ const ImportDialog = WDialog.extend({ try { const data = JSON.parse(string); const importedOp = new WasabeeOp(data); - await importedOp.store(); - await makeSelectedOperation(importedOp.ID); - alert(wX("IMPORT_OP_SUCCESS", { opName: importedOp.name })); + const localOp = await WasabeeOp.load(importedOp.ID); + if (localOp) { + alert( + wX("IMP_NOPE", { + error: "op already exists, either delete it or duplicate", + }) + ); + await makeSelectedOperation(importedOp.ID); + } else { + await importedOp.store(); + await makeSelectedOperation(importedOp.ID); + alert(wX("IMPORT_OP_SUCCESS", { opName: importedOp.name })); + } } catch (e) { console.error("WasabeeTools: failed to import data", e); - alert(wX("IMP_NOPE")); + alert(wX("IMP_NOPE", { error: "data invalid" })); } }, diff --git a/src/code/translations/english.json b/src/code/translations/english.json index dc363c9a0..ba723d58c 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -131,7 +131,7 @@ "HOW_TO_VIDS": "

How-To Videos:

", "IMP_COMP": "Import Complete. Found ", "IMP_DT_OP": "Imported Drawtools Op: ", - "IMP_NOPE": "Import Failed.", + "IMP_NOPE": "Import Failed: {error}", "IMP_WAS_OP": "Import Wasabee Operation", "IMPORT_OP_SUCCESS": "Imported Operation: {opName} successfuly.", "IMPORT_OP_TITLE": "Import Op: {date}", diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index f35b34860..e225e35b9 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -131,7 +131,7 @@ "HOW_TO_VIDS": "

How-To Videos:

", "IMP_COMP": "Natapos ang Pag Import. ", "IMP_DT_OP": "Na-Import na Drawtools Op: ", - "IMP_NOPE": "Pag-I-Import Hindi Matagumpay.", + "IMP_NOPE": "Pag-I-Import Hindi Matagumpay: {error}", "IMP_WAS_OP": "I-Import ang Wasabee operasyon", "IMPORT_OP_SUCCESS": "Na-Import na Operasyon: {opName} Matagumpay.", "IMPORT_OP_TITLE": "Na-Import na Op: {date}", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index 6b492ab0c..c5f04f410 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -131,7 +131,7 @@ "HOW_TO_VIDS": "

Tuto:

", "IMP_COMP": "Importation reussi. ", "IMP_DT_OP": "Op Drawtools: ", - "IMP_NOPE": "Echec de l'importation", + "IMP_NOPE": "Echec de l'importation: {error}", "IMP_WAS_OP": "Importer les opérations Wasabee", "IMPORT_OP_SUCCESS": "Importer l'opération : {opName} Reussi.", "IMPORT_OP_TITLE": "Importer l'opération : {date}", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index 007a512e6..e04d4b99d 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -131,7 +131,7 @@ "HOW_TO_VIDS": "

Erklärungsvideos:

", "IMP_COMP": "Import Komplett. Gefunden ", "IMP_DT_OP": "Importierte Drawtools Op: ", - "IMP_NOPE": "Import Fehlgeschlagen.", + "IMP_NOPE": "Import Fehlgeschlagen: {error}", "IMP_WAS_OP": "Importiere Wasabee Operation", "IMPORT_OP_SUCCESS": "Importierte Operation: {opName}. Erfolgreich.", "IMPORT_OP_TITLE": "Importierte Op: {date}", diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index 215b7caaa..8f4b86800 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -131,7 +131,7 @@ "HOW_TO_VIDS": "

Video tutorial:

", "IMP_COMP": "Importazione Completata. Trovato ", "IMP_DT_OP": "Importata Operazione Drawtools: ", - "IMP_NOPE": "Importazione Fallita.", + "IMP_NOPE": "Importazione Fallita: {error}", "IMP_WAS_OP": "Importa Operazione Wasabee", "IMPORT_OP_SUCCESS": "Importata Operazione: {opName} con successo.", "IMPORT_OP_TITLE": "Importa Op: {date}", diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index bc5b97fc7..0ad05434f 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -131,7 +131,7 @@ "HOW_TO_VIDS": "

Vídeos de instruções:

", "IMP_COMP": "Importação concluída. Encontrada ", "IMP_DT_OP": "Importar OP Drawtools: ", - "IMP_NOPE": "A Importação Falhou.", + "IMP_NOPE": "A Importação Falhou: {error}", "IMP_WAS_OP": "Importar Operação Wasabee", "IMPORT_OP_SUCCESS": "OP Importada: ${value} successfuly.", "IMPORT_OP_TITLE": "Importar Op: ${value}", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index b98364179..07e069366 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -131,7 +131,7 @@ "HOW_TO_VIDS": "

Videos de Cómo Se Hace:

", "IMP_COMP": "Importación Completa. Se encontró", "IMP_DT_OP": "Op en Drawtools Importada", - "IMP_NOPE": "Importación Falló.", + "IMP_NOPE": "Importación Falló: {error}", "IMP_WAS_OP": "Importar Operación Wasabee", "IMPORT_OP_SUCCESS": "Operación {opName} Importada Exitosamente.", "IMPORT_OP_TITLE": "Importar Op {date}", From 186bce1219f2a0875890c61a96afed791f30b2db Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:35:44 +0200 Subject: [PATCH 047/275] MM: factor UI part --- src/code/dialogs/madrid.js | 189 +++++++++-------------------- src/code/dialogs/multimaxDialog.js | 161 ++++++++++++------------ 2 files changed, 136 insertions(+), 214 deletions(-) diff --git a/src/code/dialogs/madrid.js b/src/code/dialogs/madrid.js index b7f286366..a8bdb7094 100644 --- a/src/code/dialogs/madrid.js +++ b/src/code/dialogs/madrid.js @@ -9,8 +9,6 @@ import { import wX from "../wX"; import MultimaxDialog from "./multimaxDialog"; -import PortalUI from "../ui/portal"; - // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX const MadridDialog = MultimaxDialog.extend({ @@ -20,143 +18,67 @@ const MadridDialog = MultimaxDialog.extend({ needWritePermission: true, - // addHooks inherited from MultimaxDialog - _displayDialog: function () { - const container = L.DomUtil.create("div", "container"); - const description = L.DomUtil.create("div", "desc", container); - description.textContent = wX("SELECT_INSTRUCTIONS"); - - const anchorOneLabel = L.DomUtil.create("label", null, container); - anchorOneLabel.textContent = wX("ANCHOR1"); - const anchorOneButton = L.DomUtil.create("button", null, container); - anchorOneButton.textContent = wX("SET"); - this._anchorOneDisplay = L.DomUtil.create("span", null, container); - if (this._anchorOne) { - this._anchorOneDisplay.appendChild( - PortalUI.displayFormat(this._anchorOne, this._smallScreen) - ); - } else { - this._anchorOneDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(anchorOneButton, "click", () => { - this._anchorOne = PortalUI.getSelected(); - if (this._anchorOne) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = - JSON.stringify(this._anchorOne); - this._anchorOneDisplay.textContent = ""; - this._anchorOneDisplay.appendChild( - PortalUI.displayFormat(this._anchorOne, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); - - const setOneLabel = L.DomUtil.create("div", "set_label", container); - setOneLabel.textContent = wX("MADRID_SET_1"); - const setOneButton = L.DomUtil.create("button", null, container); - setOneButton.textContent = wX("SET"); - this._setOneDisplay = L.DomUtil.create("span", null, container); - if (this._portalSetOne) { - this._setOneDisplay.textContent = wX("PORTAL_COUNT", { - count: this._portalSetOne.length, + _addSetZone: function (text, thisKey, container) { + const label = L.DomUtil.create("div", "set_label", container); + label.textContent = text; + const button = L.DomUtil.create("button", null, container); + button.textContent = wX("SET"); + const display = L.DomUtil.create("span", null, container); + if (this[thisKey]) { + display.textContent = wX("PORTAL_COUNT", { + count: this[thisKey].length, }); } else { - this._setOneDisplay.textContent = wX("NOT_SET"); + display.textContent = wX("NOT_SET"); } - L.DomEvent.on(setOneButton, "click", () => { - this._portalSetOne = getAllPortalsOnScreen(getSelectedOperation()); + L.DomEvent.on(button, "click", () => { + this[thisKey] = getAllPortalsOnScreen(getSelectedOperation()); // XXX this is not enough, need to cache them in case IITC purges them - this._setOneDisplay.textContent = wX("PORTAL_COUNT", { - count: this._portalSetOne.length, + display.textContent = wX("PORTAL_COUNT", { + count: this[thisKey].length, }); }); + }, - const anchorTwoLabel = L.DomUtil.create("label", null, container); - anchorTwoLabel.textContent = wX("ANCHOR2"); - const anchorTwoButton = L.DomUtil.create("button", null, container); - anchorTwoButton.textContent = wX("SET"); - this._anchorTwoDisplay = L.DomUtil.create("span", null, container); - if (this._anchorTwo) { - this._anchorTwoDisplay.appendChild( - PortalUI.displayFormat(this._anchorTwo, this._smallScreen) - ); - } else { - this._anchorTwoDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(anchorTwoButton, "click", () => { - this._anchorTwo = PortalUI.getSelected(); - if (this._anchorTwo) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY] = - JSON.stringify(this._anchorTwo); - this._anchorTwoDisplay.textContent = ""; - this._anchorTwoDisplay.appendChild( - PortalUI.displayFormat(this._anchorTwo, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); + _buildContent: function () { + const container = L.DomUtil.create("div", "container"); + const description = L.DomUtil.create("div", "desc", container); + description.textContent = wX("SELECT_INSTRUCTIONS"); - const setTwoLabel = L.DomUtil.create("div", "set_label", container); - setTwoLabel.textContent = wX("MADRID_SET_2"); - const setTwoButton = L.DomUtil.create("button", null, container); - setTwoButton.textContent = wX("SET"); - this._setTwoDisplay = L.DomUtil.create("span", null, container); - if (this._portalSetTwo) { - this._setTwoDisplay.textContent = wX("PORTAL_COUNT", { - count: this._portalSetTwo.length, - }); - } else { - this._setTwoDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(setTwoButton, "click", () => { - this._portalSetTwo = getAllPortalsOnScreen(getSelectedOperation()); - // XXX cache - this._setTwoDisplay.textContent = wX("PORTAL_COUNT", { - count: this._portalSetTwo.length, - }); - }); + this._addSetPortal( + wX("ANCHOR1"), + "_anchorOne", + container, + window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY + ); + this._addSetZone(wX("MADRID_SET_1"), "_portalSetOne", container); + + this._addSetPortal( + wX("ANCHOR2"), + "_anchorTwo", + container, + window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY + ); + this._addSetZone(wX("MADRID_SET_2"), "_portalSetTwo", container); const anchorThreeLabel = L.DomUtil.create("label", null, container); anchorThreeLabel.textContent = wX("ANCHOR3"); const anchorThreeDisplay = L.DomUtil.create("span", null, container); anchorThreeDisplay.textContent = "Auto-determined"; + this._addSetZone(wX("MADRID_SET_3"), "_portalSetThree", container); - const setThreeLabel = L.DomUtil.create("div", "set_label", container); - setThreeLabel.textContent = wX("MADRID_SET_3"); - const setThreeButton = L.DomUtil.create("button", null, container); - setThreeButton.textContent = wX("SET"); - this._setThreeDisplay = L.DomUtil.create("span", null, container); - if (this._portalSetThree) { - this._setThreeDisplay.textContent = wX("PORTAL_COUNT", { - count: this._portalSetThree.length, - }); - } else { - this._setThreeDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(setThreeButton, "click", () => { - this._portalSetThree = getAllPortalsOnScreen(getSelectedOperation()); - // XXX cache - this._setThreeDisplay.textContent = wX("PORTAL_COUNT", { - count: this._portalSetThree.length, - }); - }); - - //Add backlinks after all the rest is set up - const fllabel = L.DomUtil.create("label", null, container); - fllabel.textContent = wX("ADD_BL"); - fllabel.htmlFor = "wasabee-madrid-backlink"; - this._flcheck = L.DomUtil.create("input", null, container); - this._flcheck.type = "checkbox"; - this._flcheck.id = "wasabee-madrid-backlink"; - - const balancedLabel = L.DomUtil.create("label", null, container); - balancedLabel.textContent = "Balanced"; - balancedLabel.htmlFor = "wasabee-madrid-balanced"; - this._balancedcheck = L.DomUtil.create("input", null, container); - this._balancedcheck.type = "checkbox"; - this._balancedcheck.id = "wasabee-madrid-balanced"; + this._addCheckbox( + wX("ADD_BL"), + "wasabee-madrid-backlink", + "_flcheck", + container + ); + this._addCheckbox( + "Balanced", // wX + "wasabee-madrid-balanced", + "_balancedcheck", + container + ); const newLine = L.DomUtil.create("label", "newline", container); const dividerBeforeDraw = L.DomUtil.create("span", null, container); @@ -178,6 +100,13 @@ const MadridDialog = MultimaxDialog.extend({ // this.closeDialog(); }); + return container; + }, + + // addHooks inherited from MultimaxDialog + _displayDialog: function () { + const container = this._buildContent(); + const buttons = {}; buttons[wX("CLOSE")] = () => { this.closeDialog(); @@ -207,16 +136,6 @@ const MadridDialog = MultimaxDialog.extend({ this._urp = testPortal(); }, - getSpine: function (pOne, pTwo, portals) { - const portalsMap = new Map(portals.map((p) => [p.id, p])); - const poset = this.buildPOSet(pOne, pTwo, portals); - const sequence = this.longestSequence(poset, null, (a, b) => - window.map.distance(portalsMap.get(a).latLng, portalsMap.get(b).latLng) - ); - - return sequence.map((id) => portalsMap.get(id)); - }, - doBalancedMadrid: function () { // Calculate the multimax if ( diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/multimaxDialog.js index e66ee7c38..9e3504945 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/multimaxDialog.js @@ -25,80 +25,80 @@ const MultimaxDialog = WDialog.extend({ this._displayDialog(); }, - _displayDialog: function () { - const container = L.DomUtil.create("div", "container"); - const description = L.DomUtil.create("div", "desc", container); - description.textContent = wX("SELECT_INSTRUCTIONS"); - - const description2 = L.DomUtil.create("div", "desc", container); - description2.textContent = wX("SEL_SB_ANCHOR2"); - - const anchorOneLabel = L.DomUtil.create("label", null, container); - anchorOneLabel.textContent = wX("ANCHOR1"); - const anchorOneButton = L.DomUtil.create("button", null, container); - anchorOneButton.textContent = wX("SET"); - this._anchorOneDisplay = L.DomUtil.create("span", null, container); - if (this._anchorOne) { - this._anchorOneDisplay.appendChild( - PortalUI.displayFormat(this._anchorOne, this._smallScreen) + _addSetPortal: function (text, thisKey, container, storageKey) { + const label = L.DomUtil.create("label", null, container); + label.textContent = text; + const button = L.DomUtil.create("button", null, container); + button.textContent = wX("SET"); + const display = L.DomUtil.create("span", null, container); + if (this[thisKey]) { + display.appendChild( + PortalUI.displayFormat(this[thisKey], this._smallScreen) ); } else { - this._anchorOneDisplay.textContent = wX("NOT_SET"); + display.textContent = wX("NOT_SET"); } - L.DomEvent.on(anchorOneButton, "click", () => { - this._anchorOne = PortalUI.getSelected(); - if (this._anchorOne) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = - JSON.stringify(this._anchorOne); - this._anchorOneDisplay.textContent = ""; - this._anchorOneDisplay.appendChild( - PortalUI.displayFormat(this._anchorOne, this._smallScreen) + L.DomEvent.on(button, "click", () => { + this[thisKey] = PortalUI.getSelected(); + if (this[thisKey]) { + if (storageKey) + localStorage[storageKey] = JSON.stringify(this[thisKey]); + display.textContent = ""; + display.appendChild( + PortalUI.displayFormat(this[thisKey], this._smallScreen) ); } else { + display.textContent = wX("NOT_SET"); alert(wX("PLEASE_SELECT_PORTAL")); } }); + }, - const anchorTwoLabel = L.DomUtil.create("label", null, container); - anchorTwoLabel.textContent = wX("ANCHOR2"); - const anchorTwoButton = L.DomUtil.create("button", null, container); - anchorTwoButton.textContent = wX("SET"); - this._anchorTwoDisplay = L.DomUtil.create("span", null, container); - if (this._anchorTwo) { - this._anchorTwoDisplay.appendChild( - PortalUI.displayFormat(this._anchorTwo, this._smallScreen) - ); - } else { - this._anchorTwoDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(anchorTwoButton, "click", () => { - this._anchorTwo = PortalUI.getSelected(); - if (this._anchorTwo) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY] = - JSON.stringify(this._anchorTwo); - this._anchorTwoDisplay.textContent = ""; - this._anchorTwoDisplay.appendChild( - PortalUI.displayFormat(this._anchorTwo, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); + _addCheckbox: function (text, id, thisKey, container, defaultValue) { + const label = L.DomUtil.create("label", null, container); + label.textContent = text; + label.htmlFor = id; + this[thisKey] = L.DomUtil.create("input", null, container); + this[thisKey].type = "checkbox"; + this[thisKey].id = id; + this[thisKey].checked = defaultValue; + }, + + _buildContent: function () { + const container = L.DomUtil.create("div", "container"); + const description = L.DomUtil.create("div", "desc", container); + description.textContent = wX("SELECT_INSTRUCTIONS"); + + const description2 = L.DomUtil.create("div", "desc", container); + description2.textContent = wX("SEL_SB_ANCHOR2"); - const fllabel = L.DomUtil.create("label", null, container); - fllabel.textContent = wX("ADD_BL"); - fllabel.htmlFor = "wasabee-multimax-backlink"; - this._flcheck = L.DomUtil.create("input", null, container); - this._flcheck.type = "checkbox"; - this._flcheck.id = "wasabee-multimax-backlink"; - - const orderFromEndLabel = L.DomUtil.create("label", null, container); - orderFromEndLabel.textContent = wX("MM_INSERT_ORDER"); - orderFromEndLabel.htmlFor = "wasabee-multimax-insert-order"; - this._orderFromEnd = L.DomUtil.create("input", null, container); - this._orderFromEnd.type = "checkbox"; - this._orderFromEnd.id = "wasabee-multimax-insert-order"; - this._orderFromEnd.checked = true; + this._addSetPortal( + wX("ANCHOR1"), + "_anchorOne", + container, + window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY + ); + this._addSetPortal( + wX("ANCHOR2"), + "_anchorTwo", + container, + window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY + ); + + this._addCheckbox( + wX("ADD_BL"), + "wasabee-multimax-backlink", + "_flcheck", + container + ); + + this._addCheckbox( + wX("MM_INSERT_ORDER"), + "wasabee-multimax-insert-order", + "_orderFromEnd", + container, + true + ); // Go button const button = L.DomUtil.create("button", "drawb", container); @@ -109,6 +109,12 @@ const MultimaxDialog = WDialog.extend({ // this.closeDialog(); }); + return container; + }, + + _displayDialog: function () { + const container = this._buildContent(); + const buttons = {}; buttons[wX("CLOSE")] = () => { this.closeDialog(); @@ -129,8 +135,6 @@ const MultimaxDialog = WDialog.extend({ initialize: function (options) { WDialog.prototype.initialize.call(this, options); - this.title = wX("MULTI_M"); - this.label = wX("MULTI_M"); let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; if (p) this._anchorOne = new WasabeePortal(p); p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; @@ -138,6 +142,16 @@ const MultimaxDialog = WDialog.extend({ this._urp = L.latLng(testPortal()); }, + getSpine: function (pOne, pTwo, portals) { + const portalsMap = new Map(portals.map((p) => [p.id, p])); + const poset = this.buildPOSet(pOne, pTwo, portals); + const sequence = this.longestSequence(poset, null, (a, b) => + window.map.distance(portalsMap.get(a).latLng, portalsMap.get(b).latLng) + ); + + return sequence.map((id) => portalsMap.get(id)); + }, + /* Calculate, given two anchors and a set of portals, the deepest sequence of nested fields. */ @@ -149,13 +163,7 @@ const MultimaxDialog = WDialog.extend({ base = true, commentPrefix = "multimax " ) { - const portalsMap = new Map(portals.map((p) => [p.id, p])); - - const poset = this.buildPOSet(pOne, pTwo, portals); - - const sequence = this.longestSequence(poset, null, (a, b) => - window.map.distance(portalsMap.get(a).latLng, portalsMap.get(b).latLng) - ); + const sequence = this.getSpine(pOne, pTwo, portals); // shift current op tasks order if (order < this._operation.nextOrder - 1) { @@ -185,12 +193,7 @@ const MultimaxDialog = WDialog.extend({ let prev = null; - for (const node of sequence) { - const p = portalsMap.get(node); - if (!p) { - console.log("skipping: " + node); - continue; - } + for (const p of sequence) { this._operation.addLink(p, pOne, { description: commentPrefix + "link", order: ++order, From 09e9d1cfb90d412e0759f96c3e13d66590f13e0e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Sep 2021 12:20:45 +0200 Subject: [PATCH 048/275] add flipflop --- src/code/css/autodraws.css | 7 + src/code/dialogs/autodraws.js | 9 + src/code/dialogs/fanfield.js | 106 +++---- src/code/dialogs/flipflop.js | 380 ++++++++++++++++++++++++++ src/code/translations/english.json | 5 + src/code/translations/filipino.json | 5 + src/code/translations/french.json | 5 + src/code/translations/german.json | 5 + src/code/translations/italian.json | 5 + src/code/translations/portuguese.json | 5 + src/code/translations/spanish.json | 5 + 11 files changed, 491 insertions(+), 46 deletions(-) create mode 100644 src/code/dialogs/flipflop.js diff --git a/src/code/css/autodraws.css b/src/code/css/autodraws.css index 79843b2d5..2ec5e9949 100644 --- a/src/code/css/autodraws.css +++ b/src/code/css/autodraws.css @@ -11,6 +11,7 @@ } .wasabee-dialog-fanfield .container, +.wasabee-dialog-flipflop .container, .wasabee-dialog-homogeneous .container, .wasabee-dialog-link .container, .wasabee-dialog-madrid .container, @@ -22,9 +23,11 @@ grid-gap: 0.2em 0.5em; align-items: center; grid-template-columns: minmax(min-content, 10em) min-content auto; + max-width: 700px; } .wasabee-dialog-fanfield label, +.wasabee-dialog-flipflop label, .wasabee-dialog-link label, .wasabee-dialog-madrid label, .wasabee-dialog-multimax label, @@ -35,6 +38,7 @@ } .wasabee-dialog-fanfield button, +.wasabee-dialog-flipflop button, .wasabee-dialog-homogeneous button, .wasabee-dialog-link button, .wasabee-dialog-madrid button, @@ -53,6 +57,8 @@ .wasabee-dialog-link .drawb, .wasabee-dialog-fanfield .drawb, +.wasabee-dialog-flipflop .drawb, +.wasabee-dialog-onion .drawb, .wasabee-dialog-madrid .drawb, .wasabee-dialog-multimax .drawb, .wasabee-dialog-onion .drawb, @@ -62,6 +68,7 @@ } .wasabee-dialog-fanfield .desc, +.wasabee-dialog-flipflop .desc, .wasabee-dialog-madrid .desc, .wasabee-dialog-multimax .desc, .wasabee-dialog-onion .desc, diff --git a/src/code/dialogs/autodraws.js b/src/code/dialogs/autodraws.js index 83999ef6e..4acb8e0b2 100644 --- a/src/code/dialogs/autodraws.js +++ b/src/code/dialogs/autodraws.js @@ -7,6 +7,7 @@ import SaveLinksDialog from "../dialogs/saveLinks"; import OnionfieldDialog from "../dialogs/onionfield"; import HomogeneousDialog from "../dialogs/homogeneous"; import MadridDialog from "../dialogs/madrid"; +import FlipFlopDialog from "../dialogs/flipflop"; // This file documents the minimum requirements of a dialog in wasabee const AutodrawsDialog = WDialog.extend({ @@ -76,6 +77,14 @@ const AutodrawsDialog = WDialog.extend({ sl.enable(); }, }, + { + text: wX("FLIP_FLOP_NAME"), + callback: () => { + this.closeDialog(); + const ff = new FlipFlopDialog(); + ff.enable(); + }, + }, ]; }, diff --git a/src/code/dialogs/fanfield.js b/src/code/dialogs/fanfield.js index 7dc8b4d44..6a5c2aaf7 100644 --- a/src/code/dialogs/fanfield.js +++ b/src/code/dialogs/fanfield.js @@ -8,6 +8,59 @@ import wX from "../wX"; import PortalUI from "../ui/portal"; +export function angle(a, p) { + if (a.id == p.id) throw Error("same portal"); + if (a.latLng.lng == p.latLng.lng) { + if (a.latLng.lat > p.latLng.lat) return 0; + else return Math.PI; + } + const link = new GeodesicLine(a.latLng, p.latLng); + return link.bearing(); +} + +export function sortPortalsByAngle(anchor, portals, start, end) { + const startAngle = angle(anchor, start); + const endAngle = angle(anchor, end); + + // swap start/end if more than 180° + let invert = false; + if ( + (((endAngle - startAngle) % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI) > + Math.PI + ) { + invert = true; + } + + const good = new Map(); + for (const p of portals) { + if (p.id == anchor.id) continue; + const pAngle = angle(anchor, p); + + good.set(pAngle, p); // what are the odds of two having EXACTLY the same angle? + } + // add start and end portals just in case + good.set(startAngle, start); + good.set(endAngle, end); + + const sorted = new Array(...good.entries()) + .sort((a, b) => a[0] - b[0]) + .map((v) => v[1]); + + if (invert) { + sorted.reverse(); + } + // Build the sequence of portals between start/end + const slice = new Array(); + let s = 0; + for (s = 0; sorted[s].id != start.id; s++); + for (; sorted[s % sorted.length].id != end.id; s++) { + slice.push(sorted[s % sorted.length]); + } + slice.push(end); + + return slice; +} + const FanfieldDialog = WDialog.extend({ statics: { TYPE: "FanfieldDialog", @@ -149,48 +202,14 @@ const FanfieldDialog = WDialog.extend({ return; } - const startAngle = this._angle(this._anchor, this._start); - const endAngle = this._angle(this._anchor, this._end); - - // swap start/end if more than 180° - this._invert = false; - if ( - (((endAngle - startAngle) % (2 * Math.PI)) + 2 * Math.PI) % - (2 * Math.PI) > - Math.PI - ) { - this._invert = true; - } - - const good = new Map(); const op = getSelectedOperation(); - for (const p of getAllPortalsOnScreen(op)) { - if (p.id == this._anchor.id) continue; - const pAngle = this._angle(this._anchor, p); - - good.set(pAngle, p); // what are the odds of two having EXACTLY the same angle? - } - // add start and end portals just in case - good.set(startAngle, this._start); - good.set(endAngle, this._end); - - const sorted = new Array(...good.entries()) - .sort((a, b) => a[0] - b[0]) - .map((v) => v[1]); - - if (this._invert) { - sorted.reverse(); - } - // Build the sequence of portals between start/end - const slice = new Array(); - let start = 0; - for (start = 0; sorted[start].id != this._start.id; start++); - for (; sorted[start % sorted.length].id != this._end.id; start++) { - slice.push(sorted[start % sorted.length]); - } - slice.push(this._end); - - this._draw(slice); + const steps = sortPortalsByAngle( + this._anchor, + getAllPortalsOnScreen(op), + this._start, + this._end + ); + this._draw(steps); }, // draw takes the sorted list of poratls and draws the links @@ -253,11 +272,6 @@ const FanfieldDialog = WDialog.extend({ // too many parameters for wX(); alert(`Fanfield found ${order} links and ${fields} fields for ${ap} AP`); }, - - _angle: function (a, p) { - const link = new GeodesicLine(a.latLng, p.latLng); - return link.bearing(); - }, }); export default FanfieldDialog; diff --git a/src/code/dialogs/flipflop.js b/src/code/dialogs/flipflop.js new file mode 100644 index 000000000..bd1f34f92 --- /dev/null +++ b/src/code/dialogs/flipflop.js @@ -0,0 +1,380 @@ +import { WDialog } from "../leafletClasses"; +import wX from "../wX"; +import { getSelectedOperation } from "../selectedOp"; +import { getAllPortalsOnScreen, clearAllLinks } from "../uiCommands"; + +import WasabeePortal from "../model/portal"; +import WasabeeMarker from "../model/marker"; +import PortalUI from "../ui/portal"; + +import { angle } from "./fanfield"; +import { greatCircleArcIntersectByLatLngs } from "../crosslinks"; + +function selectAngleInterval(anchor, portalsSorted, start, end) { + const startAngle = angle(anchor, start); + const endAngle = angle(anchor, end); + + // swap start/end if more than 180° + if ( + (((endAngle - startAngle) % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI) > + Math.PI + ) { + [start, end] = [end, start]; + } + + // Build the sequence of portals between start/end + const slice = new Array(); + let s = 0; + for (s = 0; portalsSorted[s].id != start.id; s++); + for (; portalsSorted[s % portalsSorted.length].id != end.id; s++) { + slice.push(portalsSorted[s % portalsSorted.length]); + } + slice.push(end); + + return slice; +} + +function sortPortalsByAngle(anchor, portals) { + const good = new Map(); + for (const p of portals) { + if (p.id == anchor.id) continue; + const pAngle = angle(anchor, p); + good.set(pAngle, p); + } + + const sorted = new Array(...good.entries()) + .sort((a, b) => a[0] - b[0]) + .map((v) => v[1]); + + return sorted; +} + +function fastFan(anchor, two, three, portalsSorted, offset, revSortAngle) { + const res = []; + const inserted = [two, three]; + if (revSortAngle.get(two.id) > revSortAngle.get(three.id)) inserted.reverse(); + for (let i = offset; i < portalsSorted.length; i++) { + const p = portalsSorted[i]; + if (!revSortAngle.has(p.id)) continue; + let prev = inserted.length - 1; + let next = 0; + while ( + prev >= 0 && + revSortAngle.get(inserted[prev].id) > revSortAngle.get(p.id) + ) + prev--; + while ( + next < inserted.length && + revSortAngle.get(inserted[next].id) < revSortAngle.get(p.id) + ) + next++; + if ( + !greatCircleArcIntersectByLatLngs( + anchor, + p, + inserted[prev], + inserted[next] + ) + ) { + res.push([p, inserted[prev], inserted[next]]); + inserted.splice(prev + 1, 0, p); + } + } + return res; +} + +// now that the formerly external mm functions are in the class, some of the logic can be cleaned up +// to not require passing values around when we can get them from this.XXX +const FlipFlopDialog = WDialog.extend({ + statics: { + TYPE: "madridDialog", + }, + + needWritePermission: true, + + initialize: function (options) { + WDialog.prototype.initialize.call(this, options); + let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; + if (p) this._anchorOne = new WasabeePortal(p); + }, + + addHooks: function () { + WDialog.prototype.addHooks.call(this); + this._displayDialog(); + }, + + _addSetPortal: function (text, thisKey, container, storageKey) { + const label = L.DomUtil.create("label", null, container); + label.textContent = text; + const button = L.DomUtil.create("button", null, container); + button.textContent = wX("SET"); + const display = L.DomUtil.create("span", null, container); + if (this[thisKey]) { + display.appendChild( + PortalUI.displayFormat(this[thisKey], this._smallScreen) + ); + } else { + display.textContent = wX("NOT_SET"); + } + L.DomEvent.on(button, "click", () => { + this[thisKey] = PortalUI.getSelected(); + if (this[thisKey]) { + if (storageKey) + localStorage[storageKey] = JSON.stringify(this[thisKey]); + display.textContent = ""; + display.appendChild( + PortalUI.displayFormat(this[thisKey], this._smallScreen) + ); + } else { + display.textContent = wX("NOT_SET"); + alert(wX("PLEASE_SELECT_PORTAL")); + } + }); + }, + + _buildContent: function () { + const container = L.DomUtil.create("div", "container"); + const description = L.DomUtil.create("div", "desc", container); + description.textContent = wX("FLIP_FLOP_DESC"); + + const description2 = L.DomUtil.create("div", "desc", container); + description2.textContent = wX("FLIP_FLOP_INSTRUCTION"); + + this._addSetPortal( + wX("ANCHOR1"), + "_anchorOne", + container, + window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY + ); + + L.DomUtil.create("label", null, container).textContent = "#SBUL"; + this._nbSbul = L.DomUtil.create("input", null, container); + this._nbSbul.type = "number"; + this._nbSbul.value = 2; + this._nbSbul.size = 1; + this._nbSbul.min = 0; + this._nbSbul.max = 4; + + // Go button + const button = L.DomUtil.create("button", "drawb", container); + button.textContent = wX("FANFIELD"); + L.DomEvent.on(button, "click", () => { + const total = this.doFanGun(); + alert(`Flip flop: found ${total} links`); + }); + + return container; + }, + + _displayDialog: function () { + const container = this._buildContent(); + + const buttons = {}; + buttons[wX("CLOSE")] = () => { + this.closeDialog(); + }; + buttons[wX("FLIP_FLOP_FIND_ANCHORS")] = () => { + this.findOtherAnchors(); + }; + buttons[wX("CLEAR LINKS")] = () => { + clearAllLinks(getSelectedOperation()); + }; + + this.createDialog({ + title: wX("FLIP_FLOP_TITLE"), + html: container, + width: "auto", + dialogClass: "flipflop", + buttons: buttons, + id: "flipflop", + }); + }, + + findOtherAnchors: function () { + if (!this.best) return; + + this._operation = getSelectedOperation(); + const portals = getAllPortalsOnScreen(this._operation); + + const sequencePortals = this.best.steps.map((s) => s[0]); + const linkedPortals = sequencePortals.concat([ + this.best.two, + this.best.three, + ]); + const portalsMatch = []; + for (const a of portals) { + let match = true; + + // check distance order + for (const [p, p1, p2] of this.best.steps) { + if ( + a.latLng.distanceTo(p.latLng) > a.latLng.distanceTo(p1.latLng) || + a.latLng.distanceTo(p.latLng) > a.latLng.distanceTo(p2.latLng) + ) { + match = false; + break; + } + } + if (!match) continue; + + // check angle order + const sortedAngle = sortPortalsByAngle(a, linkedPortals); + const interval = selectAngleInterval( + a, + sortedAngle, + this.best.two, + this.best.three + ); + const angleSort = interval.map((p) => p.id); + let i = 0, + j = 0; + while (i < angleSort.length && j < this.best.angleSort.length) { + if (this.best.angleSort[j] === angleSort[i]) i++; + j++; + } + match = i == angleSort.length; + + if (match) portalsMatch.push(a); + } + for (const a of portalsMatch) { + this._operation.addMarker(WasabeeMarker.constants.MARKER_TYPE_LINK, a, { + comment: "flipflop anchor", + }); + } + }, + + getDistances: function (anchor, portals) { + if (this.distCache && this.distCache.has(anchor.id)) + return this.distCache.get(anchor.id); + const dists = new Map( + portals.map((p) => [p.id, p.latLng.distanceTo(anchor.latLng)]) + ); + if (this.distCache) this.distCache.set(anchor.id, dists); + return dists; + }, + + createFanLinks: function (one, two, three, steps, order = 0) { + this._operation.addLink(two, three, { + description: "flipflop origin", + order: order + 1, + }); + for (const [p, a, b] of steps) { + this._operation.addLink(p, a, { + description: "flipflop origin", + order: order + 1, + }); + this._operation.addLink(p, b, { + description: "flipflop origin", + order: order + 1, + }); + } + + order++; + this._operation.addLink(one, two, { + description: "flipflop fire", + order: ++order, + }); + this._operation.addLink(one, three, { + description: "flipflop fire", + order: ++order, + }); + for (const s of steps) { + const p = s[0]; + this._operation.addLink(one, p, { + description: "flipflop fire", + order: ++order, + }); + } + }, + + doFanGun: function () { + // Calculate the multimax + if (!this._anchorOne) { + alert(wX("INVALID REQUEST")); + return 0; + } + + this._operation = getSelectedOperation(); + const portals = getAllPortalsOnScreen(this._operation).filter( + (p) => p.id != this._anchorOne.id + ); + + const nbSbul = + +this._nbSbul.value < 0 + ? 0 + : +this._nbSbul.value > 4 + ? 4 + : +this._nbSbul.value; + + console.log("starting fastfan"); + this.distCache = new Map(); + const distances = this.getDistances(this._anchorOne, portals); + portals.sort((a, b) => distances.get(b.id) - distances.get(a.id)); + + const sortedAngle = sortPortalsByAngle(this._anchorOne, portals); + + const best = { + two: null, + three: null, + steps: [], + }; + const maxSteps = 8 * (nbSbul + 1) - 2; + + for (let i = 0; i < portals.length; i++) { + const pTwo = portals[i]; + for (let j = i + 1; j < portals.length; j++) { + const pThree = portals[j]; + const interval = selectAngleInterval( + this._anchorOne, + sortedAngle, + pTwo, + pThree + ); + const revAngleSort = new Map(interval.map((p, i) => [p.id, i])); + const res = fastFan( + this._anchorOne, + pTwo, + pThree, + portals, + j + 1, + revAngleSort + ); + if (best.steps.length < res.length) { + best.steps = res; + best.two = pTwo; + best.three = pThree; + best.angleSort = interval.map((p) => p.id); + if (best.steps.length >= maxSteps) break; + } + } + if (best.steps.length >= maxSteps) break; + } + + if (best.steps.length > maxSteps) + best.steps = best.steps.slice(0, maxSteps); + + // Calculate the multimax + if (!best.steps.length) { + alert(wX("INVALID REQUEST")); + return 0; + } + + this.best = best; + + this._operation.startBatchMode(); + this.createFanLinks( + this._anchorOne, + best.two, + best.three, + best.steps, + this._operation.nextOrder - 1 + ); + console.log("fastfan done"); + + this._operation.endBatchMode(); // save and run crosslinks + + return best.steps.length + 2; + }, +}); + +export default FlipFlopDialog; diff --git a/src/code/translations/english.json b/src/code/translations/english.json index ba723d58c..8194f39ab 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -112,6 +112,11 @@ "FANFIELD": "Draw", "FANFIELD2": "Draw Fan Field", "FarmPortalMarker": "Farm", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "from base 1-2", "FROM_1-3": "from base 1-3", "FROM_2-3": "from base 2-3", diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index e225e35b9..a4a0734fa 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -112,6 +112,11 @@ "FANFIELD": "Guhit", "FANFIELD2": "Iguhit ang Fanfield", "FarmPortalMarker": "Farm", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "from base 1-2", "FROM_1-3": "from base 1-3", "FROM_2-3": "from base 2-3", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index c5f04f410..8f96253ea 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -112,6 +112,11 @@ "FANFIELD": "Draw", "FANFIELD2": "Draw Fan Field", "FarmPortalMarker": "Farm", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "depuis la base 1-2", "FROM_1-3": "depuis la base 1-3", "FROM_2-3": "depuis la base 2-3", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index e04d4b99d..daf4d0876 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -112,6 +112,11 @@ "FANFIELD": "Fächerfeld!", "FANFIELD2": "Fächerfeld", "FarmPortalMarker": "Farm", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "from base 1-2", "FROM_1-3": "from base 1-3", "FROM_2-3": "from base 2-3", diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index 8f4b86800..90c46a88d 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -112,6 +112,11 @@ "FANFIELD": "Fanfield!", "FANFIELD2": "Fanfield", "FarmPortalMarker": "Farmare", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "dalla base 1-2", "FROM_1-3": "dalla base 1-3", "FROM_2-3": "dalla base 2-3", diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index 0ad05434f..a8e330757 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -112,6 +112,11 @@ "FANFIELD": "Desenhar", "FANFIELD2": "Desenhar Fan Field", "FarmPortalMarker": "Farmar", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "A Partir da base 1-2", "FROM_1-3": "A Partir da base 1-3", "FROM_2-3": "A Partir da base 2-3", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index 07e069366..2cca0cb09 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -112,6 +112,11 @@ "FANFIELD": "¡Dibujar!", "FANFIELD2": "Fanfield", "FarmPortalMarker": "Farmear", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "from base 1-2", "FROM_1-3": "from base 1-3", "FROM_2-3": "from base 2-3", From 1c4ddbe6c4f8013b06242bddb93254d2134c44c6 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 8 Oct 2021 15:23:04 +0200 Subject: [PATCH 049/275] add pr artifact --- .github/workflows/pr.yaml | 26 ++++++++++++++++++++++++++ package.json | 1 + plugin.config.json | 3 +++ webpack.config.js | 23 +++++++++++++++-------- 4 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/pr.yaml diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 000000000..7e23861e7 --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,26 @@ +name: Pull request artifacts +on: + pull_request: + branches: [dev] +jobs: + build-and-deploy-dev: + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2.3.1 + + - name: Build + env: + PR_NUMBER: ${{ github.event.number }} + run: | + npm install + npm run build-pr + + - name: Pull request artifacts + uses: gavv/pull-request-artifacts@v1.0.0 + with: + commit: ${{ github.event.pull_request.head.sha }} + repo-token: ${{ secrets.GITHUB_TOKEN }} + artifacts-branch: artifacts + artifacts: | + releases/dev/wasabee.user.js diff --git a/package.json b/package.json index f60d37b3d..02f67b3b8 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "build": "webpack --progress --mode production", "build-dev": "webpack --progress --mode development", "build-scot": "webpack --progress --mode development --env scot", + "build-pr": "webpack --progress --mode development --env pr=${PR_NUMBER}", "locales": "gulp locales" }, "repository": { diff --git a/plugin.config.json b/plugin.config.json index f4e05872d..22b852d52 100644 --- a/plugin.config.json +++ b/plugin.config.json @@ -10,6 +10,9 @@ "updateURL": "https://cdn2.wasabee.rocks/iitcplugin/latest/dev/wasabee.meta.js", "version": "0.20.BUILDDATE-dev" }, + "pr": { + "version": "0.20-pr" + }, "scot": { "downloadURL": "https://am.wasabee.rocks/static/dev/wasabee.user.js", "updateURL": "https://am.wasabee.rocks/static/dev/wasabee.meta.js", diff --git a/webpack.config.js b/webpack.config.js index 1635fe532..fa7a7cb9f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -168,14 +168,21 @@ const config = { module.exports = (env, argv) => { const pluginConfig = require("./plugin.config.json"); const meta = pluginConfig.headers.common; - if (argv.mode === "development" && env.scot) { - config.output.path = path.join(outputPath, "scot"); - config.devtool = "eval-source-map"; - Object.assign(meta, pluginConfig.headers.scot); - } else if (argv.mode === "development") { - config.output.path = path.join(outputPath, "dev"); - config.devtool = "eval-source-map"; - Object.assign(meta, pluginConfig.headers.dev); + if (argv.mode === "development") { + if(env.scot) { + config.output.path = path.join(outputPath, "scot"); + config.devtool = "eval-source-map"; + Object.assign(meta, pluginConfig.headers.scot); + } else if(env.pr) { + config.output.path = path.join(outputPath, "dev"); + config.devtool = "inline-source-map"; + Object.assign(meta, pluginConfig.headers.pr); + meta.version += env.pr; + } else if (argv.mode === "development") { + config.output.path = path.join(outputPath, "dev"); + config.devtool = "eval-source-map"; + Object.assign(meta, pluginConfig.headers.dev); + } } else { config.output.path = path.join(outputPath, "prod"); Object.assign(meta, pluginConfig.headers.prod); From 559f3a5786746b7e8d49e6302b8aa90e8f80c1a4 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:35:50 +0200 Subject: [PATCH 050/275] fix agent/link ui --- src/code/ui/agent.js | 5 ++++- src/code/ui/link.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index ab00db528..8287f7629 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -132,11 +132,14 @@ const WLAgent = L.Marker.extend({ zoom: zoom, }); - window.registerMarkerForOMS(this); this.bindPopup((layer) => layer._getPopup(), { className: "wasabee-popup", closeButton: false, }); + + this.off("click", this._openPopup); + window.registerMarkerForOMS(this); + this.on("spiderfiedclick", this._openPopup); }, update: function () { diff --git a/src/code/ui/link.js b/src/code/ui/link.js index 5587d42dc..0411d6c81 100644 --- a/src/code/ui/link.js +++ b/src/code/ui/link.js @@ -114,8 +114,8 @@ const WLLink = L.GeodesicPolyline.extend({ L.DomUtil.create("div", "enl", div).textContent = link.description; L.DomUtil.create("div", "enl", div).textContent = "# " + link.throwOrderPos; const buttonset = L.DomUtil.create("div", "buttonset", div); - const del = L.DomUtil.create("button", null, buttonset); if (operation.canWrite()) { + const del = L.DomUtil.create("button", null, buttonset); del.textContent = wX("DELETE_LINK"); L.DomEvent.on(del, "click", (ev) => { L.DomEvent.stop(ev); From c75a15db28cbf38a7015da2a87ac420e11a7c51b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 23 Oct 2021 22:18:09 +0200 Subject: [PATCH 051/275] fix: flipflop full rethrow --- src/code/dialogs/flipflop.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/code/dialogs/flipflop.js b/src/code/dialogs/flipflop.js index bd1f34f92..13b64b76c 100644 --- a/src/code/dialogs/flipflop.js +++ b/src/code/dialogs/flipflop.js @@ -225,6 +225,8 @@ const FlipFlopDialog = WDialog.extend({ this.best.two, this.best.three ); + if (interval.length !== linkedPortals.length) continue; + const angleSort = interval.map((p) => p.id); let i = 0, j = 0; From 40613e404ecf713a35945a70bb3d87e764fb578c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 25 Oct 2021 10:09:56 +0200 Subject: [PATCH 052/275] fix build_pr --- .github/workflows/pr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 7e23861e7..ff20ad907 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -1,6 +1,6 @@ name: Pull request artifacts on: - pull_request: + pull_request_target: branches: [dev] jobs: build-and-deploy-dev: From b46171db22270ec0f2455fc9f730a792bc9a21d8 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 27 Oct 2021 21:03:30 +0200 Subject: [PATCH 053/275] fix: wild agent.timeSinceFormat --- src/code/dialogs/onlineAgentList.js | 2 +- src/code/ui/agent.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/code/dialogs/onlineAgentList.js b/src/code/dialogs/onlineAgentList.js index a13469387..b681023df 100644 --- a/src/code/dialogs/onlineAgentList.js +++ b/src/code/dialogs/onlineAgentList.js @@ -55,7 +55,7 @@ const OnlineAgentList = WDialog.extend({ value: (agent) => agent.date, sort: (a, b) => a.localeCompare(b), format: (cell, value, agent) => { - if (agent) cell.textContent = agent.timeSinceformat(); + if (agent) cell.textContent = AgentUI.timeSinceformat(agent); }, }, { diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index 8287f7629..6927d821a 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -245,4 +245,5 @@ const WLAgent = L.Marker.extend({ export default { formatDisplay, WLAgent, + timeSinceformat, }; From 34b5855ea9cd938b918bf0f9f2103b972f6eb339 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 3 Nov 2021 18:44:51 +0100 Subject: [PATCH 054/275] fix: pr artifact --- .github/workflows/pr-build.yaml | 23 +++++++++++++++++++++++ .github/workflows/pr-comment.yaml | 25 +++++++++++++++++++++++++ .github/workflows/pr.yaml | 26 -------------------------- 3 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/pr-build.yaml create mode 100644 .github/workflows/pr-comment.yaml delete mode 100644 .github/workflows/pr.yaml diff --git a/.github/workflows/pr-build.yaml b/.github/workflows/pr-build.yaml new file mode 100644 index 000000000..a45f8040c --- /dev/null +++ b/.github/workflows/pr-build.yaml @@ -0,0 +1,23 @@ +name: Pull request build +on: + pull_request: + branches: [dev] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2.3.1 + + - name: Build + env: + PR_NUMBER: ${{ github.event.number }} + run: | + npm install + npm run build-pr + + - uses: actions/upload-artifact@v2 + with: + name: pr + path: releases/dev/wasabee.user.js diff --git a/.github/workflows/pr-comment.yaml b/.github/workflows/pr-comment.yaml new file mode 100644 index 000000000..5a1b8b60d --- /dev/null +++ b/.github/workflows/pr-comment.yaml @@ -0,0 +1,25 @@ +name: Pull request Comment +on: + workflow_run: + workflows: ["Pull request build"] + types: + - completed +jobs: + comment: + runs-on: ubuntu-latest + if: > + ${{ github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' }} + steps: + - uses: actions/download-artifact@v2 + with: + name: pr + + - name: Pull request artifacts + uses: gavv/pull-request-artifacts@v1.0.0 + with: + commit: ${{ github.event.pull_request.head.sha }} + repo-token: ${{ secrets.GITHUB_TOKEN }} + artifacts-branch: artifacts + artifacts: | + wasabee.user.js diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml deleted file mode 100644 index ff20ad907..000000000 --- a/.github/workflows/pr.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: Pull request artifacts -on: - pull_request_target: - branches: [dev] -jobs: - build-and-deploy-dev: - runs-on: ubuntu-latest - steps: - - name: Checkout 🛎️ - uses: actions/checkout@v2.3.1 - - - name: Build - env: - PR_NUMBER: ${{ github.event.number }} - run: | - npm install - npm run build-pr - - - name: Pull request artifacts - uses: gavv/pull-request-artifacts@v1.0.0 - with: - commit: ${{ github.event.pull_request.head.sha }} - repo-token: ${{ secrets.GITHUB_TOKEN }} - artifacts-branch: artifacts - artifacts: | - releases/dev/wasabee.user.js From beabd133935fb0e8687da7199eb0f14a51c89d32 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 9 Jun 2021 00:04:47 +0200 Subject: [PATCH 055/275] operation.getzone --- src/code/model/operation.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/code/model/operation.js b/src/code/model/operation.js index 09450a9dc..75af4ece0 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -1059,6 +1059,13 @@ export default class WasabeeOp extends Evented { return i; } + getZone(zoneID) { + for (const z of this.zones) { + if (z.id == zoneID) return z; + } + return null; + } + zoneName(zoneID) { if (zoneID == "0") // All zone From eafa9a373316633414385690902c6cc13b8bce99 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 9 Jun 2021 00:04:57 +0200 Subject: [PATCH 056/275] multimax: select spine from keys/zones --- src/code/dialogs/multimaxDialog.js | 128 ++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/multimaxDialog.js index 9e3504945..38e764a85 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/multimaxDialog.js @@ -1,5 +1,6 @@ import { WDialog } from "../leafletClasses"; import WasabeePortal from "../model/portal"; +import WasabeeMarker from "../model/marker"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; import { @@ -22,7 +23,77 @@ const MultimaxDialog = WDialog.extend({ addHooks: function () { WDialog.prototype.addHooks.call(this); + window.map.on("wasabee:op:select", this.closeDialog, this); + window.map.on("wasabee:op:change", this._opChange, this); + this._mapRefreshHook = this._updatePortalSet.bind(this); + window.addHook("mapDataRefreshEnd", this._mapRefreshHook); + + this._operation = getSelectedOperation(); + this._displayDialog(); + this._updatePortalSet(); + }, + + removeHooks: function () { + WDialog.prototype.removeHooks.call(this); + window.map.off("wasabee:op:select", this.closeDialog, this); + window.map.off("wasabee:op:change", this._opChange, this); + window.removeHook("mapDataRefreshEnd", this._mapRefreshHook); + }, + + _opChange: function () { + this._operation = getSelectedOperation(); + this._updatePortalSet(); + }, + + _initPortalSet: function (setKey, zone, keys) { + const portalSet = this._portalSets[setKey]; + portalSet.zone = zone; + portalSet.keys = keys; + portalSet.portals = []; + }, + + _updatePortalSet: function () { + for (const setKey in this._portalSets) { + const portalSet = this._portalSets[setKey]; + if (portalSet.keys) { + const keys = this._operation.markers.filter( + (m) => m.type === WasabeeMarker.constants.MARKER_TYPE_KEY + ); + portalSet.portals = keys.map((m) => + this._operation.getPortal(m.portalId) + ); + + if (portalSet.zone) { + const zone = this._operation.getZone(portalSet.zone); + if (zone) { + //failsafe + portalSet.portals = portalSet.portals.filter((p) => + zone.contains(p.latLng) + ); + } + } + } else { + const portals = getAllPortalsOnScreen(this._operation); + if (portalSet.zone == 0) portalSet.portals = portals; + else { + const ids = new Set(portalSet.portals.map((p) => p.id)); + for (const p of portals) { + if (!ids.has(p.id)) portalSet.portals.push(p); + } + const zone = this._operation.getZone(portalSet.zone); + if (zone) { + // filter all, if zone shape changed + portalSet.portals = portalSet.portals.filter((p) => + zone.contains(p.latLng) + ); + } + } + } + portalSet.display.textContent = wX("PORTAL_COUNT", { + count: portalSet.portals.length, + }); + } }, _addSetPortal: function (text, thisKey, container, storageKey) { @@ -64,6 +135,55 @@ const MultimaxDialog = WDialog.extend({ this[thisKey].checked = defaultValue; }, + _addSelectSet: function (text, setKey, container, defaultValue) { + const label = L.DomUtil.create("label", null, container); + label.textContent = text; + const select = L.DomUtil.create("select", null, container); + const display = L.DomUtil.create("span", null, container); + display.textContent = wX("NOT_SET"); + { + const o = L.DomUtil.create("option", null, select); + o.textContent = "All visible portals"; + o.value = "all"; + o.selected = defaultValue == o.value; + } + { + const o = L.DomUtil.create("option", null, select); + o.textContent = "All Key Portals"; + o.value = "keys"; + o.selected = defaultValue == o.value; + } + for (const zone of this._operation.zones) { + const o = L.DomUtil.create("option", null, select); + o.textContent = zone.name; + o.value = zone.id; + o.selected = defaultValue == o.value; + } + for (const zone of this._operation.zones) { + const o = L.DomUtil.create("option", null, select); + o.textContent = "Keys in " + zone.name; + o.value = "keys" + zone.id; + o.selected = defaultValue == o.value; + } + L.DomEvent.on(select, "change", (ev) => { + L.DomEvent.stop(ev); + const keys = select.value.slice(0, 4) === "keys"; + const zone = + select.value === "all" || select.value === "keys" + ? 0 + : +(keys ? select.value.slice(4) : select.value); + this._initPortalSet(setKey, zone, keys); + this._updatePortalSet(); + }); + + this._portalSets[setKey] = { + portals: [], + zone: 0, + keys: false, + display: display, + }; + }, + _buildContent: function () { const container = L.DomUtil.create("div", "container"); const description = L.DomUtil.create("div", "desc", container); @@ -100,6 +220,8 @@ const MultimaxDialog = WDialog.extend({ true ); + this._addSelectSet("Spine region", "spine", container, "all"); + // Go button const button = L.DomUtil.create("button", "drawb", container); button.textContent = wX("MULTI_M"); @@ -140,6 +262,7 @@ const MultimaxDialog = WDialog.extend({ p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; if (p) this._anchorTwo = new WasabeePortal(p); this._urp = L.latLng(testPortal()); + this._portalSets = {}; }, getSpine: function (pOne, pTwo, portals) { @@ -216,11 +339,10 @@ const MultimaxDialog = WDialog.extend({ doMultimax: function () { // this._operation is OK here - this._operation = getSelectedOperation(); - const portals = getAllPortalsOnScreen(this._operation); + const portals = this._portalSets.spine.portals; // Calculate the multimax - if (!this._anchorOne || !this._anchorTwo || !portals) { + if (!this._anchorOne || !this._anchorTwo || !portals.length) { alert(wX("INVALID REQUEST")); return 0; } From 751bfd7219e92f0f61d91e5ca22c087de7d8eb64 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 3 Nov 2021 14:14:51 +0100 Subject: [PATCH 057/275] fix: zone interactive --- src/code/ui/zone.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/ui/zone.js b/src/code/ui/zone.js index 72f204506..7184d5faa 100644 --- a/src/code/ui/zone.js +++ b/src/code/ui/zone.js @@ -2,7 +2,6 @@ const zoneShape = { stroke: false, opacity: 0.7, fill: true, - interactive: false, }; const WLZone = L.LayerGroup.extend({ @@ -21,6 +20,7 @@ const WLZone = L.LayerGroup.extend({ layer = L.polygon(zone.points, { color: zone.color, shapeOptions: zoneShape, + interactive: false, }); L.LayerGroup.prototype.initialize.call(this, [layer]); }, From f1134daa8312a3071ae20dbdf28d9805fd42fae9 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 3 Nov 2021 14:15:32 +0100 Subject: [PATCH 058/275] madrid: use portals selection from multimax --- src/code/dialogs/madrid.js | 99 ++++++++++++++------------------------ 1 file changed, 36 insertions(+), 63 deletions(-) diff --git a/src/code/dialogs/madrid.js b/src/code/dialogs/madrid.js index a8bdb7094..fd9874b2b 100644 --- a/src/code/dialogs/madrid.js +++ b/src/code/dialogs/madrid.js @@ -1,11 +1,5 @@ -import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; import { getSelectedOperation } from "../selectedOp"; -import { - getAllPortalsOnScreen, - testPortal, - clearAllLinks, -} from "../uiCommands"; +import { clearAllLinks } from "../uiCommands"; import wX from "../wX"; import MultimaxDialog from "./multimaxDialog"; @@ -18,28 +12,6 @@ const MadridDialog = MultimaxDialog.extend({ needWritePermission: true, - _addSetZone: function (text, thisKey, container) { - const label = L.DomUtil.create("div", "set_label", container); - label.textContent = text; - const button = L.DomUtil.create("button", null, container); - button.textContent = wX("SET"); - const display = L.DomUtil.create("span", null, container); - if (this[thisKey]) { - display.textContent = wX("PORTAL_COUNT", { - count: this[thisKey].length, - }); - } else { - display.textContent = wX("NOT_SET"); - } - L.DomEvent.on(button, "click", () => { - this[thisKey] = getAllPortalsOnScreen(getSelectedOperation()); - // XXX this is not enough, need to cache them in case IITC purges them - display.textContent = wX("PORTAL_COUNT", { - count: this[thisKey].length, - }); - }); - }, - _buildContent: function () { const container = L.DomUtil.create("div", "container"); const description = L.DomUtil.create("div", "desc", container); @@ -51,7 +23,7 @@ const MadridDialog = MultimaxDialog.extend({ container, window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY ); - this._addSetZone(wX("MADRID_SET_1"), "_portalSetOne", container); + this._addSelectSet(wX("MADRID_SET_1"), "setOne", container, "all"); this._addSetPortal( wX("ANCHOR2"), @@ -59,13 +31,13 @@ const MadridDialog = MultimaxDialog.extend({ container, window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY ); - this._addSetZone(wX("MADRID_SET_2"), "_portalSetTwo", container); + this._addSelectSet(wX("MADRID_SET_2"), "setTwo", container, "all"); const anchorThreeLabel = L.DomUtil.create("label", null, container); anchorThreeLabel.textContent = wX("ANCHOR3"); const anchorThreeDisplay = L.DomUtil.create("span", null, container); anchorThreeDisplay.textContent = "Auto-determined"; - this._addSetZone(wX("MADRID_SET_3"), "_portalSetThree", container); + this._addSelectSet(wX("MADRID_SET_3"), "setThree", container, "all"); this._addCheckbox( wX("ADD_BL"), @@ -125,48 +97,43 @@ const MadridDialog = MultimaxDialog.extend({ }); }, - initialize: function (options) { - WDialog.prototype.initialize.call(this, options); - this.title = wX("MADRID"); - this.label = wX("MADRID"); - let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; - if (p) this._anchorOne = new WasabeePortal(p); - p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; - if (p) this._anchorTwo = new WasabeePortal(p); - this._urp = testPortal(); - }, - doBalancedMadrid: function () { // Calculate the multimax if ( !this._anchorOne || !this._anchorTwo || - !this._portalSetOne || - !this._portalSetTwo || - !this._portalSetThree + !this._portalSets.setOne.portals.length || + !this._portalSets.setTwo.portals.length || + !this._portalSets.setThree.portals.length ) { alert(wX("INVALID REQUEST")); return 0; } // the set 1 must contain anchor 1 (first back link) - if (this._portalSetOne.find((p) => this._anchorOne.id == p.id) == undefined) - this._portalSetOne.push(this._anchorOne); + if ( + this._portalSets.setOne.portals.find((p) => this._anchorOne.id == p.id) == + undefined + ) + this._portalSets.setOne.portals.push(this._anchorOne); // the set 2 must contain anchor 2 (first back link) - if (this._portalSetTwo.find((p) => this._anchorTwo.id == p.id) == undefined) - this._portalSetTwo.push(this._anchorTwo); + if ( + this._portalSets.setTwo.portals.find((p) => this._anchorTwo.id == p.id) == + undefined + ) + this._portalSets.setTwo.portals.push(this._anchorTwo); const spineThree = this.getSpine( this._anchorOne, this._anchorTwo, - this._portalSetThree + this._portalSets.setThree.portals ); const lastThree = spineThree[spineThree.length - 1]; const spineOne = this.getSpine( this._anchorTwo, lastThree, - this._portalSetOne.filter( + this._portalSets.setOne.portals.filter( (p) => this._anchorOne.id == p.id || this.fieldCoversPortal(this._anchorTwo, lastThree, p, this._anchorOne) @@ -177,7 +144,7 @@ const MadridDialog = MultimaxDialog.extend({ const spineTwo = this.getSpine( lastThree, lastOne, - this._portalSetTwo.filter( + this._portalSets.setTwo.portals.filter( (p) => this._anchorTwo.id == p.id || this.fieldCoversPortal(lastThree, lastOne, p, this._anchorTwo) @@ -251,9 +218,9 @@ const MadridDialog = MultimaxDialog.extend({ if ( !this._anchorOne || !this._anchorTwo || - !this._portalSetOne || - !this._portalSetTwo || - !this._portalSetThree + !this._portalSets.setOne.portals.length || + !this._portalSets.setTwo.portals.length || + !this._portalSets.setThree.portals.length ) { alert(wX("INVALID REQUEST")); return 0; @@ -268,7 +235,7 @@ const MadridDialog = MultimaxDialog.extend({ const [len1, order1, last1] = this.MM( this._anchorOne, this._anchorTwo, - this._portalSetThree, + this._portalSets.setThree.portals, 1, false, "madrid protocol " @@ -277,13 +244,16 @@ const MadridDialog = MultimaxDialog.extend({ const newThree = last1; // the set 1 must contain anchor 1 (first back link) - if (this._portalSetOne.find((p) => this._anchorOne.id == p.id) == undefined) - this._portalSetOne.push(this._anchorOne); + if ( + this._portalSets.setOne.portals.find((p) => this._anchorOne.id == p.id) == + undefined + ) + this._portalSets.setOne.portals.push(this._anchorOne); const [len2, order2, last2] = this.MM( this._anchorTwo, newThree, - this._portalSetOne.filter( + this._portalSets.setOne.portals.filter( (p) => this._anchorOne.id == p.id || this.fieldCoversPortal(this._anchorTwo, newThree, p, this._anchorOne) @@ -297,13 +267,16 @@ const MadridDialog = MultimaxDialog.extend({ // _anchorOne is no longer useful, use last2 const newOne = last2; // the set 2 must contain anchor 2 (first back link) - if (this._portalSetTwo.find((p) => this._anchorTwo.id == p.id) == undefined) - this._portalSetTwo.push(this._anchorTwo); + if ( + this._portalSets.setTwo.portals.find((p) => this._anchorTwo.id == p.id) == + undefined + ) + this._portalSets.setTwo.portals.push(this._anchorTwo); const len3 = this.MM( newThree, newOne, - this._portalSetTwo.filter( + this._portalSets.setTwo.portals.filter( (p) => this._anchorTwo.id == p.id || this.fieldCoversPortal(newThree, newOne, p, this._anchorTwo) From 008ebf5200c79ec6305e8c40e2435705b21b1641 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 3 Nov 2021 14:25:56 +0100 Subject: [PATCH 059/275] add xW --- src/code/dialogs/multimaxDialog.js | 8 ++++---- src/code/translations/english.json | 4 ++++ src/code/translations/filipino.json | 4 ++++ src/code/translations/french.json | 4 ++++ src/code/translations/german.json | 4 ++++ src/code/translations/italian.json | 4 ++++ src/code/translations/portuguese.json | 4 ++++ src/code/translations/spanish.json | 4 ++++ 8 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/multimaxDialog.js index 38e764a85..7eb8632ac 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/multimaxDialog.js @@ -143,13 +143,13 @@ const MultimaxDialog = WDialog.extend({ display.textContent = wX("NOT_SET"); { const o = L.DomUtil.create("option", null, select); - o.textContent = "All visible portals"; + o.textContent = wX("MM_SET_ALL_PORTALS"); o.value = "all"; o.selected = defaultValue == o.value; } { const o = L.DomUtil.create("option", null, select); - o.textContent = "All Key Portals"; + o.textContent = wX("MM_SET_ALL_KEYS"); o.value = "keys"; o.selected = defaultValue == o.value; } @@ -161,7 +161,7 @@ const MultimaxDialog = WDialog.extend({ } for (const zone of this._operation.zones) { const o = L.DomUtil.create("option", null, select); - o.textContent = "Keys in " + zone.name; + o.textContent = wX("MM_SET_KEYS_ZONE", { zoneName: zone.name }); o.value = "keys" + zone.id; o.selected = defaultValue == o.value; } @@ -220,7 +220,7 @@ const MultimaxDialog = WDialog.extend({ true ); - this._addSelectSet("Spine region", "spine", container, "all"); + this._addSelectSet(wX("MM_SPINE"), "spine", container, "all"); // Go button const button = L.DomUtil.create("button", "drawb", container); diff --git a/src/code/translations/english.json b/src/code/translations/english.json index 8194f39ab..69d1e30f5 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -202,6 +202,10 @@ "MINUTES": " ({minutes} minutes ago)", "MM": "Multimax", "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Draw", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index a4a0734fa..2a23a89bb 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -202,6 +202,10 @@ "MINUTES": " ({minutes} minutong nakalipas)", "MM": "Multimax", "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Gumuhit ng Max Layers", "MULTI_M": "Multimax", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index 8f96253ea..23e8eca91 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -202,6 +202,10 @@ "MINUTES": "(il y a {minutes} minute(s))", "MM": "Multimax", "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Dessiner le maximum de couches", "MULTI_M": "Draw", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index daf4d0876..f158eeea3 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -202,6 +202,10 @@ "MINUTES": "vor ({minutes} Minuten)", "MM": "Maximale Feldanzahl", "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Maximale Feldanzahl", "MULTIMAX": "Maximale Feldanzahl!", diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index 90c46a88d..cd414aa62 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -202,6 +202,10 @@ "MINUTES": " ({minutes} minuti fa)", "MM": "Multimax", "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Disegna più strati possibile", "MULTI_M": "Disegna", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index a8e330757..f9f0fcd96 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -202,6 +202,10 @@ "MINUTES": " (${value} minutos atrás)", "MM": "Multimax", "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Desenhar camadas máximas", "MULTI_M": "Desenhar", "MULTIMAX": "Multimax!", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index 2cca0cb09..b77b0f737 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -202,6 +202,10 @@ "MINUTES": "(Hace {minutes} minutos)", "MM": "Multimax", "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Multimax", "MULTIMAX": "¡Multimax!", From 239a14749950c5692ac657c78eabf39935570f61 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 3 Nov 2021 16:43:14 +0100 Subject: [PATCH 060/275] move autodraws --- src/code/dialogs/autodraws.js | 16 ++++++++-------- src/code/dialogs/{ => autodraws}/fanfield.js | 16 ++++++++-------- src/code/dialogs/{ => autodraws}/flipflop.js | 16 ++++++++-------- src/code/dialogs/{ => autodraws}/homogeneous.js | 14 +++++++------- src/code/dialogs/{ => autodraws}/madrid.js | 6 +++--- .../dialogs/{ => autodraws}/multimaxDialog.js | 16 ++++++++-------- src/code/dialogs/{ => autodraws}/onionfield.js | 16 ++++++++-------- src/code/dialogs/{ => autodraws}/saveLinks.js | 12 ++++++------ src/code/dialogs/{ => autodraws}/starburst.js | 12 ++++++------ 9 files changed, 62 insertions(+), 62 deletions(-) rename src/code/dialogs/{ => autodraws}/fanfield.js (95%) rename src/code/dialogs/{ => autodraws}/flipflop.js (96%) rename src/code/dialogs/{ => autodraws}/homogeneous.js (98%) rename src/code/dialogs/{ => autodraws}/madrid.js (98%) rename src/code/dialogs/{ => autodraws}/multimaxDialog.js (97%) rename src/code/dialogs/{ => autodraws}/onionfield.js (96%) rename src/code/dialogs/{ => autodraws}/saveLinks.js (91%) rename src/code/dialogs/{ => autodraws}/starburst.js (91%) diff --git a/src/code/dialogs/autodraws.js b/src/code/dialogs/autodraws.js index 4acb8e0b2..4403ba4e3 100644 --- a/src/code/dialogs/autodraws.js +++ b/src/code/dialogs/autodraws.js @@ -1,13 +1,13 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; -import MultimaxDialog from "../dialogs/multimaxDialog"; -import FanfieldDialog from "../dialogs/fanfield"; -import StarburstDialog from "../dialogs/starburst"; -import SaveLinksDialog from "../dialogs/saveLinks"; -import OnionfieldDialog from "../dialogs/onionfield"; -import HomogeneousDialog from "../dialogs/homogeneous"; -import MadridDialog from "../dialogs/madrid"; -import FlipFlopDialog from "../dialogs/flipflop"; +import MultimaxDialog from "./autodraws/multimaxDialog"; +import FanfieldDialog from "./autodraws/fanfield"; +import StarburstDialog from "./autodraws/starburst"; +import SaveLinksDialog from "./autodraws/saveLinks"; +import OnionfieldDialog from "./autodraws/onionfield"; +import HomogeneousDialog from "./autodraws/homogeneous"; +import MadridDialog from "./autodraws/madrid"; +import FlipFlopDialog from "./autodraws/flipflop"; // This file documents the minimum requirements of a dialog in wasabee const AutodrawsDialog = WDialog.extend({ diff --git a/src/code/dialogs/fanfield.js b/src/code/dialogs/autodraws/fanfield.js similarity index 95% rename from src/code/dialogs/fanfield.js rename to src/code/dialogs/autodraws/fanfield.js index 6a5c2aaf7..2f0124fa6 100644 --- a/src/code/dialogs/fanfield.js +++ b/src/code/dialogs/autodraws/fanfield.js @@ -1,12 +1,12 @@ -import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; -import { getSelectedOperation } from "../selectedOp"; -import { greatCircleArcIntersect, GeodesicLine } from "../crosslinks"; -import WasabeeLink from "../model/link"; -import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; -import wX from "../wX"; +import { WDialog } from "../../leafletClasses"; +import WasabeePortal from "../../model/portal"; +import { getSelectedOperation } from "../../selectedOp"; +import { greatCircleArcIntersect, GeodesicLine } from "../../crosslinks"; +import WasabeeLink from "../../model/link"; +import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; +import wX from "../../wX"; -import PortalUI from "../ui/portal"; +import PortalUI from "../../ui/portal"; export function angle(a, p) { if (a.id == p.id) throw Error("same portal"); diff --git a/src/code/dialogs/flipflop.js b/src/code/dialogs/autodraws/flipflop.js similarity index 96% rename from src/code/dialogs/flipflop.js rename to src/code/dialogs/autodraws/flipflop.js index 13b64b76c..e06cb92fa 100644 --- a/src/code/dialogs/flipflop.js +++ b/src/code/dialogs/autodraws/flipflop.js @@ -1,14 +1,14 @@ -import { WDialog } from "../leafletClasses"; -import wX from "../wX"; -import { getSelectedOperation } from "../selectedOp"; -import { getAllPortalsOnScreen, clearAllLinks } from "../uiCommands"; +import { WDialog } from "../../leafletClasses"; +import wX from "../../wX"; +import { getSelectedOperation } from "../../selectedOp"; +import { getAllPortalsOnScreen, clearAllLinks } from "../../uiCommands"; -import WasabeePortal from "../model/portal"; -import WasabeeMarker from "../model/marker"; -import PortalUI from "../ui/portal"; +import WasabeePortal from "../../model/portal"; +import WasabeeMarker from "../../model/marker"; +import PortalUI from "../../ui/portal"; import { angle } from "./fanfield"; -import { greatCircleArcIntersectByLatLngs } from "../crosslinks"; +import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; function selectAngleInterval(anchor, portalsSorted, start, end) { const startAngle = angle(anchor, start); diff --git a/src/code/dialogs/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js similarity index 98% rename from src/code/dialogs/homogeneous.js rename to src/code/dialogs/autodraws/homogeneous.js index 6910ee5b6..ae79ad81e 100644 --- a/src/code/dialogs/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -1,16 +1,16 @@ -import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; -import { getSelectedOperation } from "../selectedOp"; -import { greatCircleArcIntersectByLatLngs } from "../crosslinks"; +import { WDialog } from "../../leafletClasses"; +import WasabeePortal from "../../model/portal"; +import { getSelectedOperation } from "../../selectedOp"; +import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; // import WasabeeLink from "../model/link"; import { clearAllLinks, getAllPortalsOnScreen, testPortal, -} from "../uiCommands"; -import wX from "../wX"; +} from "../../uiCommands"; +import wX from "../../wX"; -import PortalUI from "../ui/portal"; +import PortalUI from "../../ui/portal"; const HomogeneousDialog = WDialog.extend({ statics: { diff --git a/src/code/dialogs/madrid.js b/src/code/dialogs/autodraws/madrid.js similarity index 98% rename from src/code/dialogs/madrid.js rename to src/code/dialogs/autodraws/madrid.js index fd9874b2b..4b64c9b1a 100644 --- a/src/code/dialogs/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -1,6 +1,6 @@ -import { getSelectedOperation } from "../selectedOp"; -import { clearAllLinks } from "../uiCommands"; -import wX from "../wX"; +import { getSelectedOperation } from "../../selectedOp"; +import { clearAllLinks } from "../../uiCommands"; +import wX from "../../wX"; import MultimaxDialog from "./multimaxDialog"; // now that the formerly external mm functions are in the class, some of the logic can be cleaned up diff --git a/src/code/dialogs/multimaxDialog.js b/src/code/dialogs/autodraws/multimaxDialog.js similarity index 97% rename from src/code/dialogs/multimaxDialog.js rename to src/code/dialogs/autodraws/multimaxDialog.js index 7eb8632ac..5d5612686 100644 --- a/src/code/dialogs/multimaxDialog.js +++ b/src/code/dialogs/autodraws/multimaxDialog.js @@ -1,16 +1,16 @@ -import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; -import WasabeeMarker from "../model/marker"; -import { getSelectedOperation } from "../selectedOp"; -import wX from "../wX"; +import { WDialog } from "../../leafletClasses"; +import WasabeePortal from "../../model/portal"; +import WasabeeMarker from "../../model/marker"; +import { getSelectedOperation } from "../../selectedOp"; +import wX from "../../wX"; import { getAllPortalsOnScreen, testPortal, clearAllLinks, -} from "../uiCommands"; -import { greatCircleArcIntersectByLatLngs } from "../crosslinks"; +} from "../../uiCommands"; +import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; -import PortalUI from "../ui/portal"; +import PortalUI from "../../ui/portal"; // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX diff --git a/src/code/dialogs/onionfield.js b/src/code/dialogs/autodraws/onionfield.js similarity index 96% rename from src/code/dialogs/onionfield.js rename to src/code/dialogs/autodraws/onionfield.js index e53514680..27eb87212 100644 --- a/src/code/dialogs/onionfield.js +++ b/src/code/dialogs/autodraws/onionfield.js @@ -1,12 +1,12 @@ -import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; -import { getSelectedOperation } from "../selectedOp"; -import { greatCircleArcIntersect } from "../crosslinks"; -import WasabeeLink from "../model/link"; -import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; -import wX from "../wX"; +import { WDialog } from "../../leafletClasses"; +import WasabeePortal from "../../model/portal"; +import { getSelectedOperation } from "../../selectedOp"; +import { greatCircleArcIntersect } from "../../crosslinks"; +import WasabeeLink from "../../model/link"; +import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; +import wX from "../../wX"; -import PortalUI from "../ui/portal"; +import PortalUI from "../../ui/portal"; const OnionfieldDialog = WDialog.extend({ statics: { diff --git a/src/code/dialogs/saveLinks.js b/src/code/dialogs/autodraws/saveLinks.js similarity index 91% rename from src/code/dialogs/saveLinks.js rename to src/code/dialogs/autodraws/saveLinks.js index efe8fe4f7..8c03760cf 100644 --- a/src/code/dialogs/saveLinks.js +++ b/src/code/dialogs/autodraws/saveLinks.js @@ -1,10 +1,10 @@ -import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; -import { getSelectedOperation } from "../selectedOp"; -import { clearAllLinks, getAllPortalsLinked } from "../uiCommands"; -import wX from "../wX"; +import { WDialog } from "../../leafletClasses"; +import WasabeePortal from "../../model/portal"; +import { getSelectedOperation } from "../../selectedOp"; +import { clearAllLinks, getAllPortalsLinked } from "../../uiCommands"; +import wX from "../../wX"; -import PortalUI from "../ui/portal"; +import PortalUI from "../../ui/portal"; const SaveLinksDialog = WDialog.extend({ statics: { diff --git a/src/code/dialogs/starburst.js b/src/code/dialogs/autodraws/starburst.js similarity index 91% rename from src/code/dialogs/starburst.js rename to src/code/dialogs/autodraws/starburst.js index 3eb9fb109..483af5eba 100644 --- a/src/code/dialogs/starburst.js +++ b/src/code/dialogs/autodraws/starburst.js @@ -1,10 +1,10 @@ -import { WDialog } from "../leafletClasses"; -import WasabeePortal from "../model/portal"; -import { getSelectedOperation } from "../selectedOp"; -import { clearAllLinks, getAllPortalsOnScreen } from "../uiCommands"; -import wX from "../wX"; +import { WDialog } from "../../leafletClasses"; +import WasabeePortal from "../../model/portal"; +import { getSelectedOperation } from "../../selectedOp"; +import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; +import wX from "../../wX"; -import PortalUI from "../ui/portal"; +import PortalUI from "../../ui/portal"; const StarburstDialog = WDialog.extend({ statics: { From 172b75aa456e5f8612ed685c568963be2e655b1f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 3 Nov 2021 17:00:43 +0100 Subject: [PATCH 061/275] autodraw: factor common UI parts --- src/code/css/autodraws.css | 15 +- src/code/dialogs/autodraws/fanfield.js | 127 ++++--------- src/code/dialogs/autodraws/flipflop.js | 40 +--- src/code/dialogs/autodraws/homogeneous.js | 148 ++++----------- src/code/dialogs/autodraws/madrid.js | 2 - src/code/dialogs/autodraws/multimaxDialog.js | 190 ++----------------- src/code/dialogs/autodraws/onionfield.js | 65 ++----- src/code/dialogs/autodraws/saveLinks.js | 60 ++---- src/code/dialogs/autodraws/starburst.js | 62 ++---- src/code/dialogs/autodraws/tools.js | 182 ++++++++++++++++++ 10 files changed, 322 insertions(+), 569 deletions(-) create mode 100644 src/code/dialogs/autodraws/tools.js diff --git a/src/code/css/autodraws.css b/src/code/css/autodraws.css index 2ec5e9949..61427428b 100644 --- a/src/code/css/autodraws.css +++ b/src/code/css/autodraws.css @@ -77,16 +77,16 @@ grid-column: 1 / 4; } -.wasabee-dialog-starburst .desc2, -.wasabee-dialog-fanfield .desc2 { - grid-column: 1 / 3; +.wasabee-dialog-starburst .desc.secondary, +.wasabee-dialog-fanfield .desc.secondary { + color: lightgrey; } .wasabee-dialog-homogeneous .desc { grid-column: 1 / 5; } -.wasabee-dialog-homogeneous .portal { +.wasabee-dialog-homogeneous .set-portal-display { grid-column: 3 / 5; } @@ -98,10 +98,3 @@ grid-column: 4; } -.wasabee-dialog-madrid .set_label { - grid-column: 1 / 4; -} - -.wasabee-dialog-starburst .desc2 { - color: lightgrey; -} diff --git a/src/code/dialogs/autodraws/fanfield.js b/src/code/dialogs/autodraws/fanfield.js index 2f0124fa6..f0a188bae 100644 --- a/src/code/dialogs/autodraws/fanfield.js +++ b/src/code/dialogs/autodraws/fanfield.js @@ -1,4 +1,4 @@ -import { WDialog } from "../../leafletClasses"; +import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { greatCircleArcIntersect, GeodesicLine } from "../../crosslinks"; @@ -6,8 +6,6 @@ import WasabeeLink from "../../model/link"; import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; -import PortalUI from "../../ui/portal"; - export function angle(a, p) { if (a.id == p.id) throw Error("same portal"); if (a.latLng.lng == p.latLng.lng) { @@ -61,13 +59,23 @@ export function sortPortalsByAngle(anchor, portals, start, end) { return slice; } -const FanfieldDialog = WDialog.extend({ +const FanfieldDialog = AutoDraw.extend({ statics: { TYPE: "FanfieldDialog", }, + initialize: function (options) { + AutoDraw.prototype.initialize.call(this, options); + let p = localStorage["wasabee-anchor-1"]; + if (p) this._anchor = new WasabeePortal(p); + p = localStorage["wasabee-fanfield-start"]; + if (p) this._start = new WasabeePortal(p); + p = localStorage["wasabee-fanfield-end"]; + if (p) this._end = new WasabeePortal(p); + }, + addHooks: function () { - WDialog.prototype.addHooks.call(this); + AutoDraw.prototype.addHooks.call(this); this._displayDialog(); }, @@ -76,85 +84,26 @@ const FanfieldDialog = WDialog.extend({ const description = L.DomUtil.create("div", "desc", container); description.textContent = wX("SELECT_FAN_PORTALS"); - const anchorLabel = L.DomUtil.create("label", null, container); - anchorLabel.textContent = wX("ANCHOR_PORTAL"); - const anchorButton = L.DomUtil.create("button", null, container); - anchorButton.textContent = wX("SET"); - this._anchorDisplay = L.DomUtil.create("span", null, container); - if (this._anchor) { - this._anchorDisplay.appendChild( - PortalUI.displayFormat(this._anchor, this._smallScreen) - ); - } else { - this._anchorDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(anchorButton, "click", (ev) => { - L.DomEvent.stop(ev); - this._anchor = PortalUI.getSelected(); - if (this._anchor) { - localStorage["wasabee-anchor-1"] = JSON.stringify(this._anchor); - this._anchorDisplay.textContent = ""; - this._anchorDisplay.appendChild( - PortalUI.displayFormat(this._anchor, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); - - const startLabel = L.DomUtil.create("label", null, container); - startLabel.textContent = wX("START_PORT"); - const startButton = L.DomUtil.create("button", null, container); - startButton.textContent = wX("SET"); - this._startDisplay = L.DomUtil.create("span", null, container); - if (this._start) { - this._startDisplay.appendChild( - PortalUI.displayFormat(this._start, this._smallScreen) - ); - } else { - this._startDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(startButton, "click", (ev) => { - L.DomEvent.stop(ev); - this._start = PortalUI.getSelected(); - if (this._start) { - localStorage["wasabee-fanfield-start"] = JSON.stringify(this._start); - this._startDisplay.textContent = ""; - this._startDisplay.appendChild( - PortalUI.displayFormat(this._start, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); - - const endLabel = L.DomUtil.create("label", null, container); - endLabel.textContent = wX("END_PORT"); - const endButton = L.DomUtil.create("button", null, container); - endButton.textContent = wX("SET"); - this._endDisplay = L.DomUtil.create("span", null, container); - if (this._end) { - this._endDisplay.appendChild( - PortalUI.displayFormat(this._end, this._smallScreen) - ); - } else { - this._endDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(endButton, "click", (ev) => { - L.DomEvent.stop(ev); - this._end = PortalUI.getSelected(); - if (this._end) { - localStorage["wasabee-fanfield-end"] = JSON.stringify(this._end); - this._endDisplay.textContent = ""; - this._endDisplay.appendChild( - PortalUI.displayFormat(this._end, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); + this._addSetPortal( + wX("ANCHOR_PORTAL"), + "_anchor", + container, + "wasabee-anchor-1" + ); + this._addSetPortal( + wX("START_PORT"), + "_start", + container, + "wasabee-fanfield-start" + ); + this._addSetPortal( + wX("END_PORT"), + "_end", + container, + "wasabee-fanfield-end" + ); - const description2 = L.DomUtil.create("div", "desc2", container); + const description2 = L.DomUtil.create("div", "desc secondary", container); description2.textContent = wX("SELECT_FAN_PORTALS2"); // Bottom buttons bar @@ -183,18 +132,6 @@ const FanfieldDialog = WDialog.extend({ }); }, - initialize: function (options) { - WDialog.prototype.initialize.call(this, options); - this.title = wX("FAN_FIELD3"); - this.label = wX("FAN_FIELD3"); - let p = localStorage["wasabee-anchor-1"]; - if (p) this._anchor = new WasabeePortal(p); - p = localStorage["wasabee-fanfield-start"]; - if (p) this._start = new WasabeePortal(p); - p = localStorage["wasabee-fanfield-end"]; - if (p) this._end = new WasabeePortal(p); - }, - // fanfiled determines the portals between start/end and their angle (and order) fanfield: function () { if (!this._anchor || !this._start || !this._end) { diff --git a/src/code/dialogs/autodraws/flipflop.js b/src/code/dialogs/autodraws/flipflop.js index e06cb92fa..9eeea0531 100644 --- a/src/code/dialogs/autodraws/flipflop.js +++ b/src/code/dialogs/autodraws/flipflop.js @@ -1,11 +1,10 @@ -import { WDialog } from "../../leafletClasses"; +import { AutoDraw } from "./tools"; import wX from "../../wX"; import { getSelectedOperation } from "../../selectedOp"; import { getAllPortalsOnScreen, clearAllLinks } from "../../uiCommands"; import WasabeePortal from "../../model/portal"; import WasabeeMarker from "../../model/marker"; -import PortalUI from "../../ui/portal"; import { angle } from "./fanfield"; import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; @@ -85,53 +84,22 @@ function fastFan(anchor, two, three, portalsSorted, offset, revSortAngle) { // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX -const FlipFlopDialog = WDialog.extend({ +const FlipFlopDialog = AutoDraw.extend({ statics: { TYPE: "madridDialog", }, - needWritePermission: true, - initialize: function (options) { - WDialog.prototype.initialize.call(this, options); + AutoDraw.prototype.initialize.call(this, options); let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; if (p) this._anchorOne = new WasabeePortal(p); }, addHooks: function () { - WDialog.prototype.addHooks.call(this); + AutoDraw.prototype.addHooks.call(this); this._displayDialog(); }, - _addSetPortal: function (text, thisKey, container, storageKey) { - const label = L.DomUtil.create("label", null, container); - label.textContent = text; - const button = L.DomUtil.create("button", null, container); - button.textContent = wX("SET"); - const display = L.DomUtil.create("span", null, container); - if (this[thisKey]) { - display.appendChild( - PortalUI.displayFormat(this[thisKey], this._smallScreen) - ); - } else { - display.textContent = wX("NOT_SET"); - } - L.DomEvent.on(button, "click", () => { - this[thisKey] = PortalUI.getSelected(); - if (this[thisKey]) { - if (storageKey) - localStorage[storageKey] = JSON.stringify(this[thisKey]); - display.textContent = ""; - display.appendChild( - PortalUI.displayFormat(this[thisKey], this._smallScreen) - ); - } else { - display.textContent = wX("NOT_SET"); - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); - }, - _buildContent: function () { const container = L.DomUtil.create("div", "container"); const description = L.DomUtil.create("div", "desc", container); diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index ae79ad81e..c6113ba9e 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -1,4 +1,4 @@ -import { WDialog } from "../../leafletClasses"; +import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; @@ -12,14 +12,26 @@ import wX from "../../wX"; import PortalUI from "../../ui/portal"; -const HomogeneousDialog = WDialog.extend({ +const HomogeneousDialog = AutoDraw.extend({ statics: { TYPE: "HomogeneousDialog", }, - needWritePermission: true, + initialize: function (options) { + AutoDraw.prototype.initialize.call(this, options); + let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; + if (p) this._anchorOne = new WasabeePortal(p); + p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; + if (p) this._anchorTwo = new WasabeePortal(p); + p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_THREE_KEY]; + if (p) this._anchorThree = new WasabeePortal(p); + + this._urp = L.latLng(testPortal()); + this._failed = 0; + }, addHooks: function () { + AutoDraw.prototype.addHooks.call(this); this._layerGroup = new L.LayerGroup(); window.addLayerGroup("Wasabee H-G Debug", this._layerGroup, true); this._displayDialog(); @@ -27,7 +39,7 @@ const HomogeneousDialog = WDialog.extend({ removeHooks: function () { window.removeLayerGroup(this._layerGroup); - WDialog.prototype.removeHooks.call(this); + AutoDraw.prototype.removeHooks.call(this); }, _displayDialog: function () { @@ -35,86 +47,24 @@ const HomogeneousDialog = WDialog.extend({ const description2 = L.DomUtil.create("div", "desc", container); description2.textContent = wX("H-GEN_INST"); - const anchorLabelOne = L.DomUtil.create("label", null, container); - anchorLabelOne.textContent = wX("ANCHOR_PORTAL"); - const anchorButtonOne = L.DomUtil.create("button", null, container); - anchorButtonOne.textContent = wX("SET"); - this._anchorDisplayOne = L.DomUtil.create("span", "portal", container); - if (this._anchorOne) { - this._anchorDisplayOne.appendChild( - PortalUI.displayFormat(this._anchorOne, this._smallScreen) - ); - } else { - this._anchorDisplayOne.textContent = wX("NOT_SET"); - } - L.DomEvent.on(anchorButtonOne, "click", (ev) => { - L.DomEvent.stop(ev); - this._anchorOne = PortalUI.getSelected(); - if (this._anchorOne) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = - JSON.stringify(this._anchorOne); - this._anchorDisplayOne.textContent = ""; - this._anchorDisplayOne.appendChild( - PortalUI.displayFormat(this._anchorOne, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); - - const anchorLabelTwo = L.DomUtil.create("label", null, container); - anchorLabelTwo.textContent = wX("ANCHOR_PORTAL2"); - const anchorButtonTwo = L.DomUtil.create("button", null, container); - anchorButtonTwo.textContent = wX("SET"); - this._anchorDisplayTwo = L.DomUtil.create("span", "portal", container); - if (this._anchorTwo) { - this._anchorDisplayTwo.appendChild( - PortalUI.displayFormat(this._anchorTwo, this._smallScreen) - ); - } else { - this._anchorDisplayTwo.textContent = wX("NOT_SET"); - } - L.DomEvent.on(anchorButtonTwo, "click", (ev) => { - L.DomEvent.stop(ev); - this._anchorTwo = PortalUI.getSelected(); - if (this._anchorTwo) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY] = - JSON.stringify(this._anchorTwo); - this._anchorDisplayTwo.textContent = ""; - this._anchorDisplayTwo.appendChild( - PortalUI.displayFormat(this._anchorTwo, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); - - const anchorLabelThree = L.DomUtil.create("label", null, container); - anchorLabelThree.textContent = wX("ANCHOR_PORTAL3"); - const anchorButtonThree = L.DomUtil.create("button", null, container); - anchorButtonThree.textContent = wX("SET"); - this._anchorDisplayThree = L.DomUtil.create("span", "portal", container); - if (this._anchorThree) { - this._anchorDisplayThree.appendChild( - PortalUI.displayFormat(this._anchorThree, this._smallScreen) - ); - } else { - this._anchorDisplayThree.textContent = wX("NOT_SET"); - } - L.DomEvent.on(anchorButtonThree, "click", (ev) => { - L.DomEvent.stop(ev); - this._anchorThree = PortalUI.getSelected(); - if (this._anchorThree) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_THREE_KEY] = - JSON.stringify(this._anchorThree); - this._anchorDisplayThree.textContent = ""; - this._anchorDisplayThree.appendChild( - PortalUI.displayFormat(this._anchorThree, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); + this._addSetPortal( + wX("ANCHOR_PORTAL"), + "_anchorOne", + container, + window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY + ); + this._addSetPortal( + wX("ANCHOR_PORTAL2"), + "_anchorTwo", + container, + window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY + ); + this._addSetPortal( + wX("ANCHOR_PORTAL3"), + "_anchorThree", + container, + window.plugin.wasabee.static.constants.ANCHOR_THREE_KEY + ); const depthLabel = L.DomUtil.create("label", null, container); depthLabel.textContent = wX("MAX_SPLITS"); @@ -141,12 +91,13 @@ const HomogeneousDialog = WDialog.extend({ orderOption.textContent = text; } - const fullSearchLabel = L.DomUtil.create("label", null, container); - fullSearchLabel.textContent = wX("HF_DEEP_SEARCH"); - fullSearchLabel.htmlFor = "wasabee-homogeneous-deep"; - this._fullSearchCheck = L.DomUtil.create("input", null, container); - this._fullSearchCheck.type = "checkbox"; - this._fullSearchCheck.id = "wasabee-homogeneous-deep"; + this._addCheckbox( + wX("HF_DEEP_SEARCH"), + "wasabee-homogeneous-deep", + "_fullSearch", + container, + false + ); const spanRedraw = L.DomUtil.create("div", null, container); this._redrawButton = L.DomUtil.create("button", null, spanRedraw); @@ -164,7 +115,7 @@ const HomogeneousDialog = WDialog.extend({ L.DomEvent.on(drawButton, "click", (ev) => { L.DomEvent.stop(ev); this._operation = getSelectedOperation(); - if (this._fullSearchCheck.checked) this.hdeepfield.call(this); + if (this._fullSearch) this.hdeepfield.call(this); else this.hfield.call(this); }); @@ -186,21 +137,6 @@ const HomogeneousDialog = WDialog.extend({ }); }, - initialize: function (options) { - WDialog.prototype.initialize.call(this, options); - this.title = "Homogeneous"; - this.label = "Homogeneous"; - let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; - if (p) this._anchorOne = new WasabeePortal(p); - p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; - if (p) this._anchorTwo = new WasabeePortal(p); - p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_THREE_KEY]; - if (p) this._anchorThree = new WasabeePortal(p); - - this._urp = L.latLng(testPortal()); - this._failed = 0; - }, - hfield: function () { this._failed = 0; this._layerGroup.clearLayers(); diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index 4b64c9b1a..0f1b2a82d 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -10,8 +10,6 @@ const MadridDialog = MultimaxDialog.extend({ TYPE: "madridDialog", }, - needWritePermission: true, - _buildContent: function () { const container = L.DomUtil.create("div", "container"); const description = L.DomUtil.create("div", "desc", container); diff --git a/src/code/dialogs/autodraws/multimaxDialog.js b/src/code/dialogs/autodraws/multimaxDialog.js index 5d5612686..55c60795e 100644 --- a/src/code/dialogs/autodraws/multimaxDialog.js +++ b/src/code/dialogs/autodraws/multimaxDialog.js @@ -1,189 +1,33 @@ -import { WDialog } from "../../leafletClasses"; +import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; -import WasabeeMarker from "../../model/marker"; import { getSelectedOperation } from "../../selectedOp"; import wX from "../../wX"; -import { - getAllPortalsOnScreen, - testPortal, - clearAllLinks, -} from "../../uiCommands"; +import { testPortal, clearAllLinks } from "../../uiCommands"; import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; -import PortalUI from "../../ui/portal"; - // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX -const MultimaxDialog = WDialog.extend({ +const MultimaxDialog = AutoDraw.extend({ statics: { TYPE: "multimaxDialog", }, - needWritePermission: true, + initialize: function (options) { + AutoDraw.prototype.initialize.call(this, options); + let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; + if (p) this._anchorOne = new WasabeePortal(p); + p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; + if (p) this._anchorTwo = new WasabeePortal(p); + this._urp = L.latLng(testPortal()); + }, addHooks: function () { - WDialog.prototype.addHooks.call(this); - window.map.on("wasabee:op:select", this.closeDialog, this); - window.map.on("wasabee:op:change", this._opChange, this); - this._mapRefreshHook = this._updatePortalSet.bind(this); - window.addHook("mapDataRefreshEnd", this._mapRefreshHook); - - this._operation = getSelectedOperation(); + AutoDraw.prototype.addHooks.call(this); this._displayDialog(); this._updatePortalSet(); }, - removeHooks: function () { - WDialog.prototype.removeHooks.call(this); - window.map.off("wasabee:op:select", this.closeDialog, this); - window.map.off("wasabee:op:change", this._opChange, this); - window.removeHook("mapDataRefreshEnd", this._mapRefreshHook); - }, - - _opChange: function () { - this._operation = getSelectedOperation(); - this._updatePortalSet(); - }, - - _initPortalSet: function (setKey, zone, keys) { - const portalSet = this._portalSets[setKey]; - portalSet.zone = zone; - portalSet.keys = keys; - portalSet.portals = []; - }, - - _updatePortalSet: function () { - for (const setKey in this._portalSets) { - const portalSet = this._portalSets[setKey]; - if (portalSet.keys) { - const keys = this._operation.markers.filter( - (m) => m.type === WasabeeMarker.constants.MARKER_TYPE_KEY - ); - portalSet.portals = keys.map((m) => - this._operation.getPortal(m.portalId) - ); - - if (portalSet.zone) { - const zone = this._operation.getZone(portalSet.zone); - if (zone) { - //failsafe - portalSet.portals = portalSet.portals.filter((p) => - zone.contains(p.latLng) - ); - } - } - } else { - const portals = getAllPortalsOnScreen(this._operation); - if (portalSet.zone == 0) portalSet.portals = portals; - else { - const ids = new Set(portalSet.portals.map((p) => p.id)); - for (const p of portals) { - if (!ids.has(p.id)) portalSet.portals.push(p); - } - const zone = this._operation.getZone(portalSet.zone); - if (zone) { - // filter all, if zone shape changed - portalSet.portals = portalSet.portals.filter((p) => - zone.contains(p.latLng) - ); - } - } - } - portalSet.display.textContent = wX("PORTAL_COUNT", { - count: portalSet.portals.length, - }); - } - }, - - _addSetPortal: function (text, thisKey, container, storageKey) { - const label = L.DomUtil.create("label", null, container); - label.textContent = text; - const button = L.DomUtil.create("button", null, container); - button.textContent = wX("SET"); - const display = L.DomUtil.create("span", null, container); - if (this[thisKey]) { - display.appendChild( - PortalUI.displayFormat(this[thisKey], this._smallScreen) - ); - } else { - display.textContent = wX("NOT_SET"); - } - L.DomEvent.on(button, "click", () => { - this[thisKey] = PortalUI.getSelected(); - if (this[thisKey]) { - if (storageKey) - localStorage[storageKey] = JSON.stringify(this[thisKey]); - display.textContent = ""; - display.appendChild( - PortalUI.displayFormat(this[thisKey], this._smallScreen) - ); - } else { - display.textContent = wX("NOT_SET"); - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); - }, - - _addCheckbox: function (text, id, thisKey, container, defaultValue) { - const label = L.DomUtil.create("label", null, container); - label.textContent = text; - label.htmlFor = id; - this[thisKey] = L.DomUtil.create("input", null, container); - this[thisKey].type = "checkbox"; - this[thisKey].id = id; - this[thisKey].checked = defaultValue; - }, - - _addSelectSet: function (text, setKey, container, defaultValue) { - const label = L.DomUtil.create("label", null, container); - label.textContent = text; - const select = L.DomUtil.create("select", null, container); - const display = L.DomUtil.create("span", null, container); - display.textContent = wX("NOT_SET"); - { - const o = L.DomUtil.create("option", null, select); - o.textContent = wX("MM_SET_ALL_PORTALS"); - o.value = "all"; - o.selected = defaultValue == o.value; - } - { - const o = L.DomUtil.create("option", null, select); - o.textContent = wX("MM_SET_ALL_KEYS"); - o.value = "keys"; - o.selected = defaultValue == o.value; - } - for (const zone of this._operation.zones) { - const o = L.DomUtil.create("option", null, select); - o.textContent = zone.name; - o.value = zone.id; - o.selected = defaultValue == o.value; - } - for (const zone of this._operation.zones) { - const o = L.DomUtil.create("option", null, select); - o.textContent = wX("MM_SET_KEYS_ZONE", { zoneName: zone.name }); - o.value = "keys" + zone.id; - o.selected = defaultValue == o.value; - } - L.DomEvent.on(select, "change", (ev) => { - L.DomEvent.stop(ev); - const keys = select.value.slice(0, 4) === "keys"; - const zone = - select.value === "all" || select.value === "keys" - ? 0 - : +(keys ? select.value.slice(4) : select.value); - this._initPortalSet(setKey, zone, keys); - this._updatePortalSet(); - }); - - this._portalSets[setKey] = { - portals: [], - zone: 0, - keys: false, - display: display, - }; - }, - _buildContent: function () { const container = L.DomUtil.create("div", "container"); const description = L.DomUtil.create("div", "desc", container); @@ -255,16 +99,6 @@ const MultimaxDialog = WDialog.extend({ }); }, - initialize: function (options) { - WDialog.prototype.initialize.call(this, options); - let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; - if (p) this._anchorOne = new WasabeePortal(p); - p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; - if (p) this._anchorTwo = new WasabeePortal(p); - this._urp = L.latLng(testPortal()); - this._portalSets = {}; - }, - getSpine: function (pOne, pTwo, portals) { const portalsMap = new Map(portals.map((p) => [p.id, p])); const poset = this.buildPOSet(pOne, pTwo, portals); diff --git a/src/code/dialogs/autodraws/onionfield.js b/src/code/dialogs/autodraws/onionfield.js index 27eb87212..42f739b71 100644 --- a/src/code/dialogs/autodraws/onionfield.js +++ b/src/code/dialogs/autodraws/onionfield.js @@ -1,4 +1,4 @@ -import { WDialog } from "../../leafletClasses"; +import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { greatCircleArcIntersect } from "../../crosslinks"; @@ -6,17 +6,20 @@ import WasabeeLink from "../../model/link"; import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; -import PortalUI from "../../ui/portal"; - -const OnionfieldDialog = WDialog.extend({ +const OnionfieldDialog = AutoDraw.extend({ statics: { TYPE: "OnionDialog", }, - needWritePermission: true, + initialize: function (options) { + AutoDraw.prototype.initialize.call(this, options); + const p = + localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; + if (p) this._anchor = new WasabeePortal(p); + }, addHooks: function () { - WDialog.prototype.addHooks.call(this); + AutoDraw.prototype.addHooks.call(this); this._displayDialog(); }, @@ -27,41 +30,12 @@ const OnionfieldDialog = WDialog.extend({ const description3 = L.DomUtil.create("div", "desc", container); description3.textContent = wX("SEL_SB_ANCHOR2"); - const dividerBeforePortals = L.DomUtil.create("span", null, container); - dividerBeforePortals.textContent = ""; - - const anchorLabel = L.DomUtil.create("label", null, container); - anchorLabel.textContent = wX("ANCHOR_PORTAL"); - const anchorButton = L.DomUtil.create("button", null, container); - anchorButton.textContent = wX("SET"); - this._anchorDisplay = L.DomUtil.create("span", null, container); - if (this._anchor) { - this._anchorDisplay.appendChild( - PortalUI.displayFormat(this._anchor, this._smallScreen) - ); - } else { - this._anchorDisplay.textContent = wX("NOT_SET"); - } - L.DomEvent.on(anchorButton, "click", (ev) => { - L.DomEvent.stop(ev); - this._anchor = PortalUI.getSelected(); - if (this._anchor) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = - JSON.stringify(this._anchor); - this._anchorDisplay.textContent = ""; - this._anchorDisplay.appendChild( - PortalUI.displayFormat(this._anchor, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); - const dividerBeforeDraw = L.DomUtil.create("span", null, container); - dividerBeforeDraw.textContent = ""; - - // Bottom buttons bar - const placeholder = L.DomUtil.create("label", "placeholder", container); - placeholder.textContent = "\u2063"; + this._addSetPortal( + wX("ANCHOR_PORTAL"), + "_anchor", + container, + window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY + ); // Go button const button = L.DomUtil.create("button", "drawb", container); @@ -87,15 +61,6 @@ const OnionfieldDialog = WDialog.extend({ }); }, - initialize: function (options) { - WDialog.prototype.initialize.call(this, options); - this.title = "Onion/Rose"; - this.label = "Onion/Rose"; - const p = - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; - if (p) this._anchor = new WasabeePortal(p); - }, - onion: function () { // this._operation is OK here this._operation = getSelectedOperation(); diff --git a/src/code/dialogs/autodraws/saveLinks.js b/src/code/dialogs/autodraws/saveLinks.js index 8c03760cf..bad5da83b 100644 --- a/src/code/dialogs/autodraws/saveLinks.js +++ b/src/code/dialogs/autodraws/saveLinks.js @@ -1,20 +1,23 @@ -import { WDialog } from "../../leafletClasses"; +import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { clearAllLinks, getAllPortalsLinked } from "../../uiCommands"; import wX from "../../wX"; -import PortalUI from "../../ui/portal"; - -const SaveLinksDialog = WDialog.extend({ +const SaveLinksDialog = AutoDraw.extend({ statics: { TYPE: "SaveLinksDialog", }, - needWritePermission: true, + initialize: function (options) { + AutoDraw.prototype.initialize.call(this, options); + const p = + localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; + if (p) this._anchor = new WasabeePortal(p); + }, addHooks: function () { - WDialog.prototype.addHooks.call(this); + AutoDraw.prototype.addHooks.call(this); this._displayDialog(); }, @@ -24,38 +27,12 @@ const SaveLinksDialog = WDialog.extend({ const description = L.DomUtil.create("div", "desc", container); description.textContent = wX("SEL_SL_ANCHOR"); - //anchor portal text - const anchorLabel = L.DomUtil.create("label", null, container); - anchorLabel.textContent = wX("ANCHOR_PORTAL"); - - //Set Button - const anchorButton = L.DomUtil.create("button", null, container); - anchorButton.textContent = wX("SET"); - this._anchorDisplay = L.DomUtil.create("div", "anchor", container); - - //do magic - if (this._anchor) { - this._anchorDisplay.appendChild( - PortalUI.displayFormat(this._anchor, this._smallScreen) - ); - } else { - this._anchorDisplay.textContent = wX("NOT_SET"); - } - - L.DomEvent.on(anchorButton, "click", (ev) => { - L.DomEvent.stop(ev); - this._anchor = PortalUI.getSelected(); - if (this._anchor) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = - JSON.stringify(this._anchor); - this._anchorDisplay.textContent = ""; - this._anchorDisplay.appendChild( - PortalUI.displayFormat(this._anchor, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); + this._addSetPortal( + wX("ANCHOR_PORTAL"), + "_anchor", + container, + window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY + ); const button = L.DomUtil.create("button", "drawb", container); button.textContent = wX("SAVELINKS_DRAW"); @@ -82,13 +59,6 @@ const SaveLinksDialog = WDialog.extend({ }); }, - initialize: function (options) { - WDialog.prototype.initialize.call(this, options); - const p = - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; - if (p) this._anchor = new WasabeePortal(p); - }, - saveLinks: function () { if (!this._anchor) { alert("Select an anchor portal"); diff --git a/src/code/dialogs/autodraws/starburst.js b/src/code/dialogs/autodraws/starburst.js index 483af5eba..503e7d0ab 100644 --- a/src/code/dialogs/autodraws/starburst.js +++ b/src/code/dialogs/autodraws/starburst.js @@ -1,20 +1,23 @@ -import { WDialog } from "../../leafletClasses"; +import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; -import PortalUI from "../../ui/portal"; - -const StarburstDialog = WDialog.extend({ +const StarburstDialog = AutoDraw.extend({ statics: { TYPE: "StarburstDialog", }, - needWritePermission: true, + initialize: function (options) { + AutoDraw.prototype.initialize.call(this, options); + const p = + localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; + if (p) this._anchor = new WasabeePortal(p); + }, addHooks: function () { - WDialog.prototype.addHooks.call(this); + AutoDraw.prototype.addHooks.call(this); this._displayDialog(); }, @@ -24,40 +27,14 @@ const StarburstDialog = WDialog.extend({ const description = L.DomUtil.create("div", "desc", container); description.textContent = wX("SEL_SB_ANCHOR"); - //anchor portal text - const anchorLabel = L.DomUtil.create("label", null, container); - anchorLabel.textContent = wX("ANCHOR_PORTAL"); - - //Set Button - const anchorButton = L.DomUtil.create("button", null, container); - anchorButton.textContent = wX("SET"); - this._anchorDisplay = L.DomUtil.create("div", "anchor", container); - - //do magic - if (this._anchor) { - this._anchorDisplay.appendChild( - PortalUI.displayFormat(this._anchor, this._smallScreen) - ); - } else { - this._anchorDisplay.textContent = wX("NOT_SET"); - } - - L.DomEvent.on(anchorButton, "click", (ev) => { - L.DomEvent.stop(ev); - this._anchor = PortalUI.getSelected(); - if (this._anchor) { - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = - JSON.stringify(this._anchor); - this._anchorDisplay.textContent = ""; - this._anchorDisplay.appendChild( - PortalUI.displayFormat(this._anchor, this._smallScreen) - ); - } else { - alert(wX("PLEASE_SELECT_PORTAL")); - } - }); + this._addSetPortal( + wX("ANCHOR_PORTAL"), + "_anchor", + container, + window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY + ); - const description2 = L.DomUtil.create("div", "desc2", container); + const description2 = L.DomUtil.create("div", "desc secondary", container); description2.textContent = wX("SEL_SB_ANCHOR2"); const button = L.DomUtil.create("button", "drawb", container); @@ -85,13 +62,6 @@ const StarburstDialog = WDialog.extend({ }); }, - initialize: function (options) { - WDialog.prototype.initialize.call(this, options); - const p = - localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; - if (p) this._anchor = new WasabeePortal(p); - }, - starburst: function () { if (!this._anchor) { alert("Select an anchor portal"); diff --git a/src/code/dialogs/autodraws/tools.js b/src/code/dialogs/autodraws/tools.js new file mode 100644 index 000000000..2460798c2 --- /dev/null +++ b/src/code/dialogs/autodraws/tools.js @@ -0,0 +1,182 @@ +import { WDialog } from "../../leafletClasses"; +import WasabeeMarker from "../../model/marker"; +import { getSelectedOperation } from "../../selectedOp"; +import wX from "../../wX"; +import { getAllPortalsOnScreen } from "../../uiCommands"; + +import PortalUI from "../../ui/portal"; + +// now that the formerly external mm functions are in the class, some of the logic can be cleaned up +// to not require passing values around when we can get them from this.XXX +export const AutoDraw = WDialog.extend({ + statics: { + TYPE: "autodraw", + }, + + needWritePermission: true, + + initialize: function (options) { + WDialog.prototype.initialize.call(this, options); + this._portalSets = {}; + }, + + addHooks: function () { + WDialog.prototype.addHooks.call(this); + window.map.on("wasabee:op:select wasabee:op:change", this._opChange, this); + + this._mapRefreshHook = this._updatePortalSet.bind(this); + window.addHook("mapDataRefreshEnd", this._mapRefreshHook); + + this._operation = getSelectedOperation(); + }, + + removeHooks: function () { + WDialog.prototype.removeHooks.call(this); + window.map.off("wasabee:op:select wasabee:op:change", this._opChange, this); + + window.removeHook("mapDataRefreshEnd", this._mapRefreshHook); + }, + + _opChange: function () { + this._operation = getSelectedOperation(); + this._updatePortalSet(); + }, + + _initPortalSet: function (setKey, zone, keys) { + const portalSet = this._portalSets[setKey]; + portalSet.zone = zone; + portalSet.keys = keys; + portalSet.portals = []; + }, + + _updatePortalSet: function () { + for (const setKey in this._portalSets) { + const portalSet = this._portalSets[setKey]; + if (portalSet.keys) { + const keys = this._operation.markers.filter( + (m) => m.type === WasabeeMarker.constants.MARKER_TYPE_KEY + ); + portalSet.portals = keys.map((m) => + this._operation.getPortal(m.portalId) + ); + + if (portalSet.zone) { + const zone = this._operation.getZone(portalSet.zone); + if (zone) { + //failsafe + portalSet.portals = portalSet.portals.filter((p) => + zone.contains(p.latLng) + ); + } + } + } else { + const portals = getAllPortalsOnScreen(this._operation); + if (portalSet.zone == 0) portalSet.portals = portals; + else { + const ids = new Set(portalSet.portals.map((p) => p.id)); + for (const p of portals) { + if (!ids.has(p.id)) portalSet.portals.push(p); + } + const zone = this._operation.getZone(portalSet.zone); + if (zone) { + // filter all, if zone shape changed + portalSet.portals = portalSet.portals.filter((p) => + zone.contains(p.latLng) + ); + } + } + } + portalSet.display.textContent = wX("PORTAL_COUNT", { + count: portalSet.portals.length, + }); + } + }, + + _addSetPortal: function (text, thisKey, container, storageKey) { + const label = L.DomUtil.create("label", "set-portal-label", container); + label.textContent = text; + const button = L.DomUtil.create("button", "set-portal-button", container); + button.textContent = wX("SET"); + const display = L.DomUtil.create("span", "set-portal-display", container); + if (this[thisKey]) { + display.appendChild( + PortalUI.displayFormat(this[thisKey], this._smallScreen) + ); + } else { + display.textContent = wX("NOT_SET"); + } + L.DomEvent.on(button, "click", () => { + this[thisKey] = PortalUI.getSelected(); + if (this[thisKey]) { + if (storageKey) + localStorage[storageKey] = JSON.stringify(this[thisKey]); + display.textContent = ""; + display.appendChild( + PortalUI.displayFormat(this[thisKey], this._smallScreen) + ); + } else { + display.textContent = wX("NOT_SET"); + alert(wX("PLEASE_SELECT_PORTAL")); + } + }); + }, + + _addCheckbox: function (text, id, thisKey, container, defaultValue) { + const label = L.DomUtil.create("label", "checkbox-label", container); + label.textContent = text; + label.htmlFor = id; + this[thisKey] = L.DomUtil.create("input", "checkbox-input", container); + this[thisKey].type = "checkbox"; + this[thisKey].id = id; + this[thisKey].checked = defaultValue; + }, + + _addSelectSet: function (text, setKey, container, defaultValue) { + const label = L.DomUtil.create("label", "select-set-label", container); + label.textContent = text; + const select = L.DomUtil.create("select", "select-set-input", container); + const display = L.DomUtil.create("span", "select-set-display", container); + display.textContent = wX("NOT_SET"); + { + const o = L.DomUtil.create("option", null, select); + o.textContent = wX("MM_SET_ALL_PORTALS"); + o.value = "all"; + o.selected = defaultValue == o.value; + } + { + const o = L.DomUtil.create("option", null, select); + o.textContent = wX("MM_SET_ALL_KEYS"); + o.value = "keys"; + o.selected = defaultValue == o.value; + } + for (const zone of this._operation.zones) { + const o = L.DomUtil.create("option", null, select); + o.textContent = zone.name; + o.value = zone.id; + o.selected = defaultValue == o.value; + } + for (const zone of this._operation.zones) { + const o = L.DomUtil.create("option", null, select); + o.textContent = wX("MM_SET_KEYS_ZONE", { zoneName: zone.name }); + o.value = "keys" + zone.id; + o.selected = defaultValue == o.value; + } + L.DomEvent.on(select, "change", (ev) => { + L.DomEvent.stop(ev); + const keys = select.value.slice(0, 4) === "keys"; + const zone = + select.value === "all" || select.value === "keys" + ? 0 + : +(keys ? select.value.slice(4) : select.value); + this._initPortalSet(setKey, zone, keys); + this._updatePortalSet(); + }); + + this._portalSets[setKey] = { + portals: [], + zone: 0, + keys: false, + display: display, + }; + }, +}); From 856d4eff753decdbb694494f89a0b286be5ea71a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 3 Nov 2021 18:00:19 +0100 Subject: [PATCH 062/275] fanfield/flipflop: select portals --- src/code/dialogs/autodraws/fanfield.js | 8 +++++--- src/code/dialogs/autodraws/flipflop.js | 9 +++++---- src/code/translations/english.json | 1 + src/code/translations/filipino.json | 1 + src/code/translations/french.json | 1 + src/code/translations/german.json | 1 + src/code/translations/italian.json | 1 + src/code/translations/portuguese.json | 1 + src/code/translations/spanish.json | 1 + 9 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/code/dialogs/autodraws/fanfield.js b/src/code/dialogs/autodraws/fanfield.js index f0a188bae..a50b42db4 100644 --- a/src/code/dialogs/autodraws/fanfield.js +++ b/src/code/dialogs/autodraws/fanfield.js @@ -3,7 +3,7 @@ import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { greatCircleArcIntersect, GeodesicLine } from "../../crosslinks"; import WasabeeLink from "../../model/link"; -import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; +import { clearAllLinks } from "../../uiCommands"; import wX from "../../wX"; export function angle(a, p) { @@ -77,6 +77,7 @@ const FanfieldDialog = AutoDraw.extend({ addHooks: function () { AutoDraw.prototype.addHooks.call(this); this._displayDialog(); + this._updatePortalSet(); }, _displayDialog: function () { @@ -103,6 +104,8 @@ const FanfieldDialog = AutoDraw.extend({ "wasabee-fanfield-end" ); + this._addSelectSet(wX("AUTODRAW_PORTALS_SET"), "set", container, "all"); + const description2 = L.DomUtil.create("div", "desc secondary", container); description2.textContent = wX("SELECT_FAN_PORTALS2"); @@ -139,10 +142,9 @@ const FanfieldDialog = AutoDraw.extend({ return; } - const op = getSelectedOperation(); const steps = sortPortalsByAngle( this._anchor, - getAllPortalsOnScreen(op), + this._portalSets["set"].portals, this._start, this._end ); diff --git a/src/code/dialogs/autodraws/flipflop.js b/src/code/dialogs/autodraws/flipflop.js index 9eeea0531..b2021c6f3 100644 --- a/src/code/dialogs/autodraws/flipflop.js +++ b/src/code/dialogs/autodraws/flipflop.js @@ -115,6 +115,8 @@ const FlipFlopDialog = AutoDraw.extend({ window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY ); + this._addSelectSet(wX("AUTODRAW_PORTALS_SET"), "set", container, "all"); + L.DomUtil.create("label", null, container).textContent = "#SBUL"; this._nbSbul = L.DomUtil.create("input", null, container); this._nbSbul.type = "number"; @@ -265,7 +267,7 @@ const FlipFlopDialog = AutoDraw.extend({ } this._operation = getSelectedOperation(); - const portals = getAllPortalsOnScreen(this._operation).filter( + const portals = this._portalSets["set"].portals.filter( (p) => p.id != this._anchorOne.id ); @@ -309,7 +311,7 @@ const FlipFlopDialog = AutoDraw.extend({ j + 1, revAngleSort ); - if (best.steps.length < res.length) { + if (!best.two || best.steps.length < res.length) { best.steps = res; best.two = pTwo; best.three = pThree; @@ -323,8 +325,7 @@ const FlipFlopDialog = AutoDraw.extend({ if (best.steps.length > maxSteps) best.steps = best.steps.slice(0, maxSteps); - // Calculate the multimax - if (!best.steps.length) { + if (!best.two) { alert(wX("INVALID REQUEST")); return 0; } diff --git a/src/code/translations/english.json b/src/code/translations/english.json index 69d1e30f5..2dbfa9f53 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -48,6 +48,7 @@ "AUTH_SELECT_ACCOUNT": "Select account", "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", + "AUTODRAW_PORTALS_SET": "Portals", "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", "AUTOLOAD": "Automatically Load Missing Portal Details", "AUTOMARK STOP": "Auto-Mark stopped due to portals not being loaded", diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index 2a23a89bb..789b5763c 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -48,6 +48,7 @@ "AUTH_SELECT_ACCOUNT": "Select account", "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", + "AUTODRAW_PORTALS_SET": "Portals", "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", "AUTOLOAD": "Automatically Load Missing Portal Details", "AUTOMARK STOP": "Itinigil ang pag Auto-Mark dahil hindi maiload ang mga portals", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index 23e8eca91..c8effcc06 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -48,6 +48,7 @@ "AUTH_SELECT_ACCOUNT": "Sélectionner le compte", "AUTO_DRAWS": "Auto-Draw", "AUTODRAWS": "Choix d'Auto-draw", + "AUTODRAW_PORTALS_SET": "Portals", "AUTOLOAD_RATE": "Délai entre deux requêtes", "AUTOLOAD": "Charger automatiquement les données manquantes de portails", "AUTOMARK STOP": "Le processus d'Auto-Mark s'est arrêté suite à l'absence de donnée pour certains portails.", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index f158eeea3..2cf6eae59 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -48,6 +48,7 @@ "AUTH_SELECT_ACCOUNT": "Select account", "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", + "AUTODRAW_PORTALS_SET": "Portals", "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", "AUTOLOAD": "Automatically Load Missing Portal Details", "AUTOMARK STOP": "Automatische Markierung gestoppt - Portale nicht vollständig geladen.", diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index cd414aa62..01dafd9f8 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -48,6 +48,7 @@ "AUTH_SELECT_ACCOUNT": "Seleziona account", "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Opzioni Wasabee Auto-draw", + "AUTODRAW_PORTALS_SET": "Portals", "AUTOLOAD_RATE": "Frequenza Richiesta dettagli Portali (ms)", "AUTOLOAD": "Carica Automaticamente Dettagli dei Portali Mancanti", "AUTOMARK STOP": "Auto-Mark interrotto, i portali non sono caricati", diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index f9f0fcd96..67b0bcf1b 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -48,6 +48,7 @@ "AUTH_SELECT_ACCOUNT": "Selecionar conta", "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Opções", + "AUTODRAW_PORTALS_SET": "Portals", "AUTOLOAD_RATE": "Taxa de solicitação de detalhes do portal (ms)", "AUTOLOAD": "Carregar automaticamente os detalhes do portal em falta", "AUTOMARK STOP": "Auto-Marcar interrompido devido a portais não serem carregados", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index b77b0f737..c204d713a 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -48,6 +48,7 @@ "AUTH_SELECT_ACCOUNT": "Select account", "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", + "AUTODRAW_PORTALS_SET": "Portals", "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", "AUTOLOAD": "Automatically Load Missing Portal Details", "AUTOMARK STOP": "El Marcado-Automático se detuvo debido a que los portales no estaban cargado", From a740804233fc160bc18647f509ed1ce84b4ff796 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 25 Oct 2021 09:43:33 +0200 Subject: [PATCH 063/275] agent: use intelname when available + display name origin (intel/rocks/V) --- src/code/css/wasabee.css | 8 +++++++ src/code/dialogs/agentDialog.js | 30 ++++++++++++++++---------- src/code/dialogs/assignDialog.js | 2 +- src/code/dialogs/checklist.js | 2 +- src/code/dialogs/keyListPortal.js | 2 +- src/code/dialogs/manageTeamDialog.js | 8 +++---- src/code/dialogs/markerAddDialog.js | 2 +- src/code/dialogs/onlineAgentList.js | 6 +++--- src/code/dialogs/opsDialog.js | 4 ++-- src/code/dialogs/sendTargetDialog.js | 2 +- src/code/dialogs/teamMembershipList.js | 8 +++---- src/code/model/agent.js | 10 ++++++++- src/code/ui/agent.js | 30 +++++++++++++++++++++----- src/code/ui/marker.js | 4 ++-- src/code/wd.js | 2 +- 15 files changed, 80 insertions(+), 40 deletions(-) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index f2629261c..dad395df9 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -52,6 +52,14 @@ } // .wasabee-table td.menu { position: relative; min-height: 20px; min-width: 24px; } +.wasabee-dialog-agent ul { + padding-left: 0; +} + +.wasabee-dialog-agent li { + list-style: none; +} + /* defined in agent.js, always on an -- can this be pruned ? */ .wasabee-agent-label a { text-shadow: 1px 1px #000, 1px -1px #000, -1px 1px #000, -1px -1px #000, diff --git a/src/code/dialogs/agentDialog.js b/src/code/dialogs/agentDialog.js index 7f646b1d3..c6afdd01d 100644 --- a/src/code/dialogs/agentDialog.js +++ b/src/code/dialogs/agentDialog.js @@ -18,23 +18,31 @@ const AgentDialog = WDialog.extend({ _displayDialog: async function () { const html = L.DomUtil.create("div", null); - const agent = L.DomUtil.create("div", null, html); try { const data = await WasabeeAgent.get(this.options.gid); - const name = L.DomUtil.create("h2", "enl, wasabee-agent-label", agent); - name.textContent = data.name; - const vLabel = L.DomUtil.create("label", null, agent); - vLabel.textContent = "V Verified: "; - L.DomUtil.create("div", null, vLabel).textContent = data.Vverified; - const rocksLabel = L.DomUtil.create("label", null, agent); - rocksLabel.textContent = "Rocks Verified: "; - L.DomUtil.create("div", null, rocksLabel).textContent = data.rocks; - const img = L.DomUtil.create("img", null, agent); + L.DomUtil.create("h2", "wasabee-agent-label", html).textContent = + data.getName(); + + const ul = L.DomUtil.create("ul", "", html); + const rows = [ + ["Server name: ", data.name], + ["V name: ", data.vname], + ["V verified: ", data.Vverified], + ["Rocks name: ", data.rocksname], + ["Rocks Verified: ", data.rocks], + ]; + for (const [label, value] of rows) { + const li = L.DomUtil.create("li", "", ul); + L.DomUtil.create("label", null, li).textContent = label; + L.DomUtil.create("span", null, li).textContent = value; + } + + const img = L.DomUtil.create("img", null, html); img.src = data.pic; } catch (e) { console.error(e); - agent.innerHTML = e.toString(); + html.innerHTML = e.toString(); } const buttons = {}; diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index 7c3bd7e15..9d66bf8a2 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -128,7 +128,7 @@ const AssignDialog = WDialog.extend({ alreadyAdded.push(a.id); option = L.DomUtil.create("option"); option.value = a.id; - option.textContent = a.name; + option.textContent = a.getName(); if (a.id == current) option.selected = true; menu.appendChild(option); } diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index abb5dde1d..63e5c6cc3 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -212,7 +212,7 @@ const OperationChecklistDialog = WDialog.extend({ value: async (thing) => { if (thing.assignedTo != null && thing.assignedTo != "") { const agent = await WasabeeAgent.get(thing.assignedTo); - if (agent != null) return agent.name; + if (agent != null) return agent.getName(); return "GID: [" + thing.assignedTo + "]"; } return ". . ."; diff --git a/src/code/dialogs/keyListPortal.js b/src/code/dialogs/keyListPortal.js index c6f095d20..f32c9ec2d 100644 --- a/src/code/dialogs/keyListPortal.js +++ b/src/code/dialogs/keyListPortal.js @@ -81,7 +81,7 @@ const KeyListPortal = WDialog.extend({ sort: (a, b) => a.localeCompare(b), format: async (cell, value, key) => { const agent = await WasabeeAgent.get(key.gid); - cell.textContent = agent ? agent.name : key.gid; + cell.textContent = agent ? agent.getName() : key.gid; }, }, { diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 6ffee9f70..c26301122 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -47,12 +47,10 @@ const ManageTeamDialog = WDialog.extend({ table.fields = [ { name: wX("AGENT"), - value: (agent) => agent.name, + value: (agent) => agent.getName(), sort: (a, b) => a.localeCompare(b), - format: async (cell, value, agent) => - cell.appendChild( - await AgentUI.formatDisplay(agent, this.options.team.id) - ), + format: (cell, value, agent) => + cell.appendChild(AgentUI.formatDisplay(agent)), }, { name: wX("TEAM STATE"), diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index 30fcf9e72..25dc3375b 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -182,7 +182,7 @@ const MarkerAddDialog = WDialog.extend({ alreadyAdded.add(a.id); option = L.DomUtil.create("option"); option.value = a.id; - option.textContent = a.name; + option.textContent = a.getName(); menu.appendChild(option); } } diff --git a/src/code/dialogs/onlineAgentList.js b/src/code/dialogs/onlineAgentList.js index b681023df..10eb12295 100644 --- a/src/code/dialogs/onlineAgentList.js +++ b/src/code/dialogs/onlineAgentList.js @@ -45,10 +45,10 @@ const OnlineAgentList = WDialog.extend({ this._table.fields = [ { name: wX("AGENT"), - value: (agent) => agent.name, + value: (agent) => agent.getName(), sort: (a, b) => a.localeCompare(b), - format: async (cell, value, agent) => - cell.appendChild(await AgentUI.formatDisplay(agent)), + format: (cell, value, agent) => + cell.appendChild(AgentUI.formatDisplay(agent)), }, { name: "Last Seen", diff --git a/src/code/dialogs/opsDialog.js b/src/code/dialogs/opsDialog.js index 93136e810..5cdfc4e38 100644 --- a/src/code/dialogs/opsDialog.js +++ b/src/code/dialogs/opsDialog.js @@ -281,8 +281,8 @@ const OpsDialog = WDialog.extend({ }; if (sum.currentserver) { const agent = await WasabeeAgent.get(tmpOp.creator); - sum.owner = agent.name; - sum.ownerDisplay = await AgentUI.formatDisplay(agent); + sum.owner = agent.getName(); + sum.ownerDisplay = AgentUI.formatDisplay(agent); } else { sum.owner = window.PLAYER.nickname; } diff --git a/src/code/dialogs/sendTargetDialog.js b/src/code/dialogs/sendTargetDialog.js index 518a7e7cc..1e3937dfb 100644 --- a/src/code/dialogs/sendTargetDialog.js +++ b/src/code/dialogs/sendTargetDialog.js @@ -106,7 +106,7 @@ const SendTargetDialog = WDialog.extend({ alreadyAdded.push(a.id); option = L.DomUtil.create("option"); option.value = a.id; - option.textContent = a.name; + option.textContent = a.getName(); if (a.id == current) option.selected = true; menu.appendChild(option); } diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index a6df0068b..69aa80628 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -53,12 +53,10 @@ const TeamMembershipList = WDialog.extend({ table.fields = [ { name: wX("AGENT"), - value: (agent) => agent.name, + value: (agent) => agent.getName(), sort: (a, b) => a.localeCompare(b), - format: async (cell, value, agent) => - cell.appendChild( - await AgentUI.formatDisplay(agent, this.options.teamID) - ), + format: (cell, value, agent) => + cell.appendChild(AgentUI.formatDisplay(agent)), }, { name: wX("SQUAD"), diff --git a/src/code/model/agent.js b/src/code/model/agent.js index bf2332b21..92b63beda 100644 --- a/src/code/model/agent.js +++ b/src/code/model/agent.js @@ -20,7 +20,7 @@ export default class WasabeeAgent { this.name = obj.name; this.vname = obj.vname; this.rocksname = obj.rocksname; - this.intelname = obj.intelname; + this.intelname = obj.intelname !== "unset" ? obj.intelname : null; this.intelfaction = obj.intelfaction; this.level = obj.level ? Number(obj.level) : 0; this.enlid = obj.enlid ? obj.enlid : null; @@ -53,6 +53,14 @@ export default class WasabeeAgent { this._updateCache(); } + getName() { + if (this.Vverified && this.vname) return this.vname; + if (this.rocks && this.rocksname) return this.rocksname; + if (this.intelname) return this.intelname; + return this.name; + } + + // deprecated async getTeamName(teamID = 0) { if (teamID == 0) return this.name; diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index 6927d821a..bfbad6584 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -7,7 +7,7 @@ import wX from "../wX"; import WasabeeAgent from "../model/agent"; -async function formatDisplay(agent, teamID = 0) { +function formatDisplay(agent) { const display = L.DomUtil.create("a", "wasabee-agent-label"); if (agent.Vverified || agent.rocks) { L.DomUtil.addClass(display, "enl"); @@ -20,7 +20,27 @@ async function formatDisplay(agent, teamID = 0) { const ad = new AgentDialog({ gid: agent.id }); ad.enable(); }); - display.textContent = await agent.getTeamName(teamID); + + let prefix = ""; + if (agent.Vverified) prefix += "V"; + else if (agent.vname === agent.name) prefix += "v"; + if (agent.rocks) prefix += "R"; + else if (agent.rocksname === agent.name) prefix += "r"; + if (agent.intelname) { + // no identity source exept intel + if (!agent.rocksname && !agent.vname) prefix += "I"; + // no verified source + else if (!agent.rocks && !agent.Vverified) prefix += "I"; + // match server preference + else if (agent.intelname === agent.name) prefix += "I"; + // match server preference, in lower case + else if (agent.intelname.toLowerCase() === agent.name.toLowerCase()) + prefix += "i"; + } + + display.textContent = prefix + ? `[${prefix}] ` + agent.getName() + : agent.getName(); return display; } @@ -119,7 +139,7 @@ const WLAgent = L.Marker.extend({ initialize: function (agent) { const zoom = window.map.getZoom(); L.Marker.prototype.initialize.call(this, agent.latLng, { - title: agent.name, + title: agent.getName(), icon: L.divIcon({ className: "wasabee-agent-icon", iconSize: iconSize(zoom), @@ -163,7 +183,7 @@ const WLAgent = L.Marker.extend({ const content = L.DomUtil.create("div", "wasabee-agent-popup"); const title = L.DomUtil.create("div", "desc", content); title.id = agent.id; - title.textContent = agent.name; + title.textContent = agent.getName(); WasabeeAgent.get(this.options.id) .then(formatDisplay) @@ -185,7 +205,7 @@ const WLAgent = L.Marker.extend({ title: wX("SEND TARGET"), label: wX("SEND TARGET CONFIRM", { portalName: PortalUI.displayName(selectedPortal), - agent: agent.name, + agent: agent.getName(), }), type: "agent", callback: async () => { diff --git a/src/code/ui/marker.js b/src/code/ui/marker.js index c7dd426a7..7a1158776 100644 --- a/src/code/ui/marker.js +++ b/src/code/ui/marker.js @@ -107,7 +107,7 @@ const WLMarker = PortalUI.WLPortal.extend({ try { const a = await WasabeeAgent.get(marker.assignedTo); assignment.textContent = wX("ASS_TO"); // FIXME convert formatDisplay to html and add as value to wX - if (a) assignment.appendChild(await AgentUI.formatDisplay(a)); + if (a) assignment.appendChild(AgentUI.formatDisplay(a)); else assignment.textContent += " " + marker.assignedTo; } catch (err) { console.error(err); @@ -117,7 +117,7 @@ const WLMarker = PortalUI.WLPortal.extend({ try { const a = await WasabeeAgent.get(marker.completedID); assignment.innerHTML = wX("COMPLETED BY", { - agentName: a ? a.name : marker.completedID, + agentName: a ? a.getName() : marker.completedID, }); } catch (e) { console.error(e); diff --git a/src/code/wd.js b/src/code/wd.js index 474810cf1..c4b9b5498 100644 --- a/src/code/wd.js +++ b/src/code/wd.js @@ -155,7 +155,7 @@ async function getMarkerPopup(PortalID) { const a = await WasabeeAgent.get(dk.GID); const li = L.DomUtil.create("li", null, ul); if (a) { - li.appendChild(await AgentUI.formatDisplay(a)); + li.appendChild(AgentUI.formatDisplay(a)); } else { const fake = L.DomUtil.create("span", null, li); fake.textContent = wX("LOADING"); From e9979c690eb103fb7c48bea1148a62c24722c6d0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 11 Nov 2021 10:32:15 +0100 Subject: [PATCH 064/275] fix: send target broken on anchor --- src/code/dialogs/sendTargetDialog.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/code/dialogs/sendTargetDialog.js b/src/code/dialogs/sendTargetDialog.js index 518a7e7cc..4f723d07e 100644 --- a/src/code/dialogs/sendTargetDialog.js +++ b/src/code/dialogs/sendTargetDialog.js @@ -50,18 +50,22 @@ const SendTargetDialog = WDialog.extend({ const operation = getSelectedOperation(); if (this.options.target instanceof WasabeeMarker) { - const portal = operation.getPortal(this.options.target.portalId); + this._portal = operation.getPortal(this.options.target.portalId); this._targettype = this.options.target.type; - divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); + divtitle.appendChild( + PortalUI.displayFormat(this._portal, this._smallScreen) + ); const t = L.DomUtil.create("label", null); t.textContent = wX("SEND TARGET AGENT"); menu.prepend(t); } if (this.options.target instanceof WasabeePortal) { - const portal = this.options.target; + this._portal = this.options.target; this._targettype = "anchor"; - divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); + divtitle.appendChild( + PortalUI.displayFormat(this._portal, this._smallScreen) + ); const t = L.DomUtil.create("label", null); t.textContent = wX("SEND TARGET AGENT"); menu.prepend(t); @@ -120,13 +124,11 @@ const SendTargetDialog = WDialog.extend({ }, _sendTarget: function () { - if (!this._value) { + if (!this._value || !this._portal) { this.closeDialog(); return; } - const operation = getSelectedOperation(); - const portal = operation.getPortal(this.options.target.portalId); - targetPromise(this._value, portal, this._targettype) + targetPromise(this._value, this._portal, this._targettype) .then(() => { alert(wX("TARGET SENT")); this.closeDialog(); From d9a519d553058844095e1fa48bf433078935ca5c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 16 Nov 2021 20:40:26 +0100 Subject: [PATCH 065/275] fix: assign dialog without title --- src/code/dialogs/assignDialog.js | 59 +++++++++++++------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index 9d66bf8a2..003e67dad 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -32,13 +32,11 @@ const AssignDialog = WDialog.extend({ this.closeDialog(); }; - // create container then setup asynchronously - this._html = L.DomUtil.create("div", "container"); - this._setup(); + const html = this._buildContent(); this.createDialog({ title: this._name, - html: this._html, + html: html, width: "auto", dialogClass: "assign", buttons: buttons, @@ -46,12 +44,15 @@ const AssignDialog = WDialog.extend({ }); }, - _setup: async function () { + _buildContent: function () { + const html = L.DomUtil.create("div", "container"); + const target = this.options.target; const operation = getSelectedOperation(); this._targetID = target.ID; - const divtitle = L.DomUtil.create("div", "desc", this._html); - const menu = await this._getAgentMenu(target.assignedTo); + + const divtitle = L.DomUtil.create("div", "desc", html); + const menu = L.DomUtil.create("div", "wasabee-agent-menu", html); if (target instanceof WasabeeLink) { const portal = operation.getPortal(target.fromPortalId); @@ -62,9 +63,8 @@ const AssignDialog = WDialog.extend({ divtitle.appendChild( LinkUI.displayFormat(target, operation, this._smallScreen) ); - const t = L.DomUtil.create("label", null); + const t = L.DomUtil.create("label", null, menu); t.textContent = wX("LINK ASSIGNMENT"); - menu.prepend(t); } if (target instanceof WasabeeMarker) { @@ -74,9 +74,8 @@ const AssignDialog = WDialog.extend({ portalName: PortalUI.displayName(portal), }); divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); - const t = L.DomUtil.create("label", null); + const t = L.DomUtil.create("label", null, menu); t.textContent = wX("MARKER ASSIGNMENT"); - menu.prepend(t); } if (target instanceof WasabeePortal) { @@ -86,36 +85,27 @@ const AssignDialog = WDialog.extend({ portalName: PortalUI.displayName(portal), }); divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); - const t = L.DomUtil.create("label", null); + const t = L.DomUtil.create("label", null, menu); t.textContent = wX("ANCHOR ASSIGNMENT"); - menu.prepend(t); - } - - this._html.appendChild(menu); - }, - - _buildContent: function () { - const content = L.DomUtil.create("div"); - if (typeof this._label == "string") { - content.textContent = this._label; - } else { - content.appendChild(this._label); } - return content; - }, - _getAgentMenu: async function (current) { - const container = L.DomUtil.create("div", "wasabee-agent-menu"); - const menu = L.DomUtil.create("select", null, container); - let option = menu.appendChild(L.DomUtil.create("option", null)); + const select = L.DomUtil.create("select", null, menu); + const option = L.DomUtil.create("option", null, select); option.value = ""; option.textContent = wX("UNASSIGNED"); - const alreadyAdded = new Array(); - menu.addEventListener("change", (value) => { + L.DomEvent.on(select, "change", (value) => { this.localAssign(value); }); + this._populateAgentSelect(select, target.assignedTo); + + return html; + }, + + _populateAgentSelect: async function (select, current) { + const alreadyAdded = new Array(); + const me = await WasabeeMe.waitGet(); for (const t of getSelectedOperation().teamlist) { if (me.teamJoined(t.teamid) == false) continue; @@ -126,19 +116,16 @@ const AssignDialog = WDialog.extend({ for (const a of agents) { if (!alreadyAdded.includes(a.id)) { alreadyAdded.push(a.id); - option = L.DomUtil.create("option"); + const option = L.DomUtil.create("option", "", select); option.value = a.id; option.textContent = a.getName(); if (a.id == current) option.selected = true; - menu.appendChild(option); } } } catch (e) { console.error(e); } } - - return container; }, localAssign: function (value) { From 72ec58688bae0af711989dcd1dda218b39c861ea Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 20 Nov 2021 15:49:12 +0100 Subject: [PATCH 066/275] fix: assign all outbound links --- src/code/dialogs/assignDialog.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index 003e67dad..7cd1bbb92 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -137,11 +137,9 @@ const AssignDialog = WDialog.extend({ operation.assignLink(this._targetID, value.srcElement.value); } if (this._type == "Anchor") { - const links = operation.getLinkListFromPortal( - operation.getPortal(this._targetID) - ); + const links = operation.getLinkListFromPortal(this.options.target); for (const l of links) { - if (l.fromPortalId == this._targetID) { + if (l.fromPortalId == this.options.target.id) { operation.assignLink(l.ID, value.srcElement.value); } } From 049016346bac7ad87f39998f173922c44d08828b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 9 Nov 2021 22:42:05 +0100 Subject: [PATCH 067/275] types --- package.json | 11 +- src/code/addButtons.d.ts | 2 + src/code/auxiliar.d.ts | 3 + src/code/buttons/linkButton.d.ts | 6 + src/code/buttons/markerButton.d.ts | 4 + src/code/buttons/opButton.d.ts | 4 + src/code/buttons/quickdrawButton.d.ts | 6 + src/code/buttons/syncButton.d.ts | 4 + src/code/buttons/uploadButton.d.ts | 6 + src/code/buttons/wasabeeButton.d.ts | 4 + src/code/crosslinks.d.ts | 22 ++ src/code/db.d.ts | 58 ++++ src/code/dialogs/about.d.ts | 3 + src/code/dialogs/agentDialog.d.ts | 9 + src/code/dialogs/assignDialog.d.ts | 13 + src/code/dialogs/authDialog.d.ts | 3 + src/code/dialogs/autodraws.d.ts | 7 + src/code/dialogs/autodraws/fanfield.d.ts | 11 + src/code/dialogs/autodraws/flipflop.d.ts | 8 + src/code/dialogs/autodraws/homogeneous.d.ts | 14 + src/code/dialogs/autodraws/madrid.d.ts | 6 + .../dialogs/autodraws/multimaxDialog.d.ts | 26 ++ src/code/dialogs/autodraws/onionfield.d.ts | 10 + src/code/dialogs/autodraws/saveLinks.d.ts | 7 + src/code/dialogs/autodraws/starburst.d.ts | 7 + src/code/dialogs/autodraws/tools.d.ts | 43 +++ src/code/dialogs/blockersList.d.ts | 4 + src/code/dialogs/checklist.d.ts | 16 + src/code/dialogs/confirmDialog.d.ts | 13 + src/code/dialogs/defensiveKeysDialog.d.ts | 4 + src/code/dialogs/exportDialog.d.ts | 4 + src/code/dialogs/importDialog.d.ts | 4 + src/code/dialogs/keyListPortal.d.ts | 10 + src/code/dialogs/keysList.d.ts | 4 + src/code/dialogs/linkDialog.d.ts | 4 + src/code/dialogs/linkListDialog.d.ts | 12 + src/code/dialogs/manageTeamDialog.d.ts | 11 + src/code/dialogs/markerAddDialog.d.ts | 4 + src/code/dialogs/markerChangeDialog.d.ts | 11 + src/code/dialogs/markerList.d.ts | 4 + src/code/dialogs/mergeDialog.d.ts | 13 + src/code/dialogs/newopDialog.d.ts | 4 + src/code/dialogs/onlineAgentList.d.ts | 4 + src/code/dialogs/opPerms.d.ts | 4 + src/code/dialogs/opSettings.d.ts | 4 + src/code/dialogs/opsDialog.d.ts | 4 + src/code/dialogs/promptDialog.d.ts | 20 ++ src/code/dialogs/sendTargetDialog.d.ts | 12 + src/code/dialogs/setCommentDialog.d.ts | 14 + src/code/dialogs/settingsDialog.d.ts | 4 + src/code/dialogs/skinDialog.d.ts | 3 + src/code/dialogs/stateDialog.d.ts | 12 + src/code/dialogs/teamListDialog.d.ts | 4 + src/code/dialogs/teamMembershipList.d.ts | 10 + src/code/dialogs/trawl.d.ts | 4 + src/code/dialogs/wasabeeDlist.d.ts | 4 + src/code/dialogs/zoneDialog.d.ts | 14 + src/code/dialogs/zoneSetColor.d.ts | 11 + src/code/firebaseSupport.d.ts | 2 + src/code/index.d.ts | 13 + src/code/init.d.ts | 1 + src/code/leafletClasses.d.ts | 95 ++++++ src/code/mapDrawing.d.ts | 7 + src/code/model/agent.d.ts | 29 ++ src/code/model/blocker.d.ts | 24 ++ src/code/model/evented.d.ts | 12 + src/code/model/index.d.ts | 10 + src/code/model/link.d.ts | 38 +++ src/code/model/marker.d.ts | 47 +++ src/code/model/me.d.ts | 48 +++ src/code/model/operation.d.ts | 202 +++++++++++++ src/code/model/portal.d.ts | 24 ++ src/code/model/team.d.ts | 15 + src/code/model/team.js | 7 +- src/code/model/zone.d.ts | 21 ++ src/code/polyfill.d.ts | 1 + src/code/selectedOp.d.ts | 17 ++ src/code/server.d.ts | 68 +++++ src/code/skin.d.ts | 3 + src/code/sortable.d.ts | 41 +++ src/code/static.d.ts | 3 + src/code/toolbox.d.ts | 1 + src/code/ui/agent.d.ts | 25 ++ src/code/ui/anchor.d.ts | 14 + src/code/ui/link.d.ts | 22 ++ src/code/ui/marker.d.ts | 18 ++ src/code/ui/portal.d.ts | 40 +++ src/code/ui/zone.d.ts | 8 + src/code/uiCommands.d.ts | 25 ++ src/code/wX.d.ts | 3 + src/code/wd.d.ts | 15 + src/types/iitc/LICENSE | 21 ++ src/types/iitc/README.md | 21 ++ src/types/iitc/core/android.d.ts | 57 ++++ src/types/iitc/core/artifact.d.ts | 44 +++ src/types/iitc/core/boot.d.ts | 46 +++ src/types/iitc/core/chat.d.ts | 138 +++++++++ src/types/iitc/core/constants.d.ts | 115 ++++++++ src/types/iitc/core/data_cache.d.ts | 30 ++ src/types/iitc/core/dialog.d.ts | 105 +++++++ src/types/iitc/core/entity_decode.d.ts | 25 ++ src/types/iitc/core/entity_info.d.ts | 9 + .../iitc/core/extract_niantic_parameters.d.ts | 10 + src/types/iitc/core/game_status.d.ts | 6 + src/types/iitc/core/hooks.d.ts | 279 ++++++++++++++++++ src/types/iitc/core/idle.d.ts | 20 ++ src/types/iitc/core/iitctypes.d.ts | 148 ++++++++++ src/types/iitc/core/inteltypes.d.ts | 58 ++++ src/types/iitc/core/location.d.ts | 13 + src/types/iitc/core/main.d.ts | 87 ++++++ src/types/iitc/core/map_data_calc_tools.d.ts | 59 ++++ src/types/iitc/core/map_data_debug.d.ts | 36 +++ src/types/iitc/core/map_data_render.d.ts | 66 +++++ src/types/iitc/core/map_data_request.d.ts | 159 ++++++++++ src/types/iitc/core/ornaments.d.ts | 36 +++ src/types/iitc/core/panes.d.ts | 8 + src/types/iitc/core/player_names.d.ts | 8 + src/types/iitc/core/portal_data.d.ts | 61 ++++ src/types/iitc/core/portal_detail.d.ts | 23 ++ .../iitc/core/portal_detail_display.d.ts | 26 ++ .../core/portal_detail_display_tools.d.ts | 57 ++++ src/types/iitc/core/portal_highlighter.d.ts | 29 ++ src/types/iitc/core/portal_info.d.ts | 93 ++++++ src/types/iitc/core/portal_marker.d.ts | 16 + src/types/iitc/core/redeeming.d.ts | 25 ++ src/types/iitc/core/region_scoreboard.d.ts | 15 + src/types/iitc/core/request_handling.d.ts | 37 +++ src/types/iitc/core/search.d.ts | 72 +++++ src/types/iitc/core/send_request.d.ts | 28 ++ src/types/iitc/core/smartphone.d.ts | 24 ++ src/types/iitc/core/utils_file.d.ts | 11 + src/types/iitc/core/utils_misc.d.ts | 146 +++++++++ src/types/iitc/index.d.ts | 58 ++++ src/types/iitc/package.json | 26 ++ src/types/leafletExtentions/index.d.ts | 39 +++ tsconfig.json | 28 ++ 136 files changed, 3857 insertions(+), 7 deletions(-) create mode 100644 src/code/addButtons.d.ts create mode 100644 src/code/auxiliar.d.ts create mode 100644 src/code/buttons/linkButton.d.ts create mode 100644 src/code/buttons/markerButton.d.ts create mode 100644 src/code/buttons/opButton.d.ts create mode 100644 src/code/buttons/quickdrawButton.d.ts create mode 100644 src/code/buttons/syncButton.d.ts create mode 100644 src/code/buttons/uploadButton.d.ts create mode 100644 src/code/buttons/wasabeeButton.d.ts create mode 100644 src/code/crosslinks.d.ts create mode 100644 src/code/db.d.ts create mode 100644 src/code/dialogs/about.d.ts create mode 100644 src/code/dialogs/agentDialog.d.ts create mode 100644 src/code/dialogs/assignDialog.d.ts create mode 100644 src/code/dialogs/authDialog.d.ts create mode 100644 src/code/dialogs/autodraws.d.ts create mode 100644 src/code/dialogs/autodraws/fanfield.d.ts create mode 100644 src/code/dialogs/autodraws/flipflop.d.ts create mode 100644 src/code/dialogs/autodraws/homogeneous.d.ts create mode 100644 src/code/dialogs/autodraws/madrid.d.ts create mode 100644 src/code/dialogs/autodraws/multimaxDialog.d.ts create mode 100644 src/code/dialogs/autodraws/onionfield.d.ts create mode 100644 src/code/dialogs/autodraws/saveLinks.d.ts create mode 100644 src/code/dialogs/autodraws/starburst.d.ts create mode 100644 src/code/dialogs/autodraws/tools.d.ts create mode 100644 src/code/dialogs/blockersList.d.ts create mode 100644 src/code/dialogs/checklist.d.ts create mode 100644 src/code/dialogs/confirmDialog.d.ts create mode 100644 src/code/dialogs/defensiveKeysDialog.d.ts create mode 100644 src/code/dialogs/exportDialog.d.ts create mode 100644 src/code/dialogs/importDialog.d.ts create mode 100644 src/code/dialogs/keyListPortal.d.ts create mode 100644 src/code/dialogs/keysList.d.ts create mode 100644 src/code/dialogs/linkDialog.d.ts create mode 100644 src/code/dialogs/linkListDialog.d.ts create mode 100644 src/code/dialogs/manageTeamDialog.d.ts create mode 100644 src/code/dialogs/markerAddDialog.d.ts create mode 100644 src/code/dialogs/markerChangeDialog.d.ts create mode 100644 src/code/dialogs/markerList.d.ts create mode 100644 src/code/dialogs/mergeDialog.d.ts create mode 100644 src/code/dialogs/newopDialog.d.ts create mode 100644 src/code/dialogs/onlineAgentList.d.ts create mode 100644 src/code/dialogs/opPerms.d.ts create mode 100644 src/code/dialogs/opSettings.d.ts create mode 100644 src/code/dialogs/opsDialog.d.ts create mode 100644 src/code/dialogs/promptDialog.d.ts create mode 100644 src/code/dialogs/sendTargetDialog.d.ts create mode 100644 src/code/dialogs/setCommentDialog.d.ts create mode 100644 src/code/dialogs/settingsDialog.d.ts create mode 100644 src/code/dialogs/skinDialog.d.ts create mode 100644 src/code/dialogs/stateDialog.d.ts create mode 100644 src/code/dialogs/teamListDialog.d.ts create mode 100644 src/code/dialogs/teamMembershipList.d.ts create mode 100644 src/code/dialogs/trawl.d.ts create mode 100644 src/code/dialogs/wasabeeDlist.d.ts create mode 100644 src/code/dialogs/zoneDialog.d.ts create mode 100644 src/code/dialogs/zoneSetColor.d.ts create mode 100644 src/code/firebaseSupport.d.ts create mode 100644 src/code/index.d.ts create mode 100644 src/code/init.d.ts create mode 100644 src/code/leafletClasses.d.ts create mode 100644 src/code/mapDrawing.d.ts create mode 100644 src/code/model/agent.d.ts create mode 100644 src/code/model/blocker.d.ts create mode 100644 src/code/model/evented.d.ts create mode 100644 src/code/model/index.d.ts create mode 100644 src/code/model/link.d.ts create mode 100644 src/code/model/marker.d.ts create mode 100644 src/code/model/me.d.ts create mode 100644 src/code/model/operation.d.ts create mode 100644 src/code/model/portal.d.ts create mode 100644 src/code/model/team.d.ts create mode 100644 src/code/model/zone.d.ts create mode 100644 src/code/polyfill.d.ts create mode 100644 src/code/selectedOp.d.ts create mode 100644 src/code/server.d.ts create mode 100644 src/code/skin.d.ts create mode 100644 src/code/sortable.d.ts create mode 100644 src/code/static.d.ts create mode 100644 src/code/toolbox.d.ts create mode 100644 src/code/ui/agent.d.ts create mode 100644 src/code/ui/anchor.d.ts create mode 100644 src/code/ui/link.d.ts create mode 100644 src/code/ui/marker.d.ts create mode 100644 src/code/ui/portal.d.ts create mode 100644 src/code/ui/zone.d.ts create mode 100644 src/code/uiCommands.d.ts create mode 100644 src/code/wX.d.ts create mode 100644 src/code/wd.d.ts create mode 100755 src/types/iitc/LICENSE create mode 100755 src/types/iitc/README.md create mode 100755 src/types/iitc/core/android.d.ts create mode 100755 src/types/iitc/core/artifact.d.ts create mode 100755 src/types/iitc/core/boot.d.ts create mode 100755 src/types/iitc/core/chat.d.ts create mode 100755 src/types/iitc/core/constants.d.ts create mode 100755 src/types/iitc/core/data_cache.d.ts create mode 100755 src/types/iitc/core/dialog.d.ts create mode 100755 src/types/iitc/core/entity_decode.d.ts create mode 100755 src/types/iitc/core/entity_info.d.ts create mode 100755 src/types/iitc/core/extract_niantic_parameters.d.ts create mode 100755 src/types/iitc/core/game_status.d.ts create mode 100755 src/types/iitc/core/hooks.d.ts create mode 100755 src/types/iitc/core/idle.d.ts create mode 100755 src/types/iitc/core/iitctypes.d.ts create mode 100755 src/types/iitc/core/inteltypes.d.ts create mode 100755 src/types/iitc/core/location.d.ts create mode 100755 src/types/iitc/core/main.d.ts create mode 100755 src/types/iitc/core/map_data_calc_tools.d.ts create mode 100755 src/types/iitc/core/map_data_debug.d.ts create mode 100755 src/types/iitc/core/map_data_render.d.ts create mode 100755 src/types/iitc/core/map_data_request.d.ts create mode 100755 src/types/iitc/core/ornaments.d.ts create mode 100755 src/types/iitc/core/panes.d.ts create mode 100755 src/types/iitc/core/player_names.d.ts create mode 100755 src/types/iitc/core/portal_data.d.ts create mode 100755 src/types/iitc/core/portal_detail.d.ts create mode 100755 src/types/iitc/core/portal_detail_display.d.ts create mode 100755 src/types/iitc/core/portal_detail_display_tools.d.ts create mode 100755 src/types/iitc/core/portal_highlighter.d.ts create mode 100755 src/types/iitc/core/portal_info.d.ts create mode 100755 src/types/iitc/core/portal_marker.d.ts create mode 100755 src/types/iitc/core/redeeming.d.ts create mode 100755 src/types/iitc/core/region_scoreboard.d.ts create mode 100755 src/types/iitc/core/request_handling.d.ts create mode 100755 src/types/iitc/core/search.d.ts create mode 100755 src/types/iitc/core/send_request.d.ts create mode 100755 src/types/iitc/core/smartphone.d.ts create mode 100755 src/types/iitc/core/utils_file.d.ts create mode 100755 src/types/iitc/core/utils_misc.d.ts create mode 100755 src/types/iitc/index.d.ts create mode 100755 src/types/iitc/package.json create mode 100755 src/types/leafletExtentions/index.d.ts create mode 100644 tsconfig.json diff --git a/package.json b/package.json index 02f67b3b8..e41f0dd41 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,10 @@ "main": "gulpfile.js", "private": true, "devDependencies": { + "@types/jquery": "^3.5.8", + "@types/jqueryui": "^1.12.16", + "@types/leaflet": "^1.7.5", + "@types/spectrum": "^1.8.2", "css-loader": "^5.2.6", "del": "^6.0.0", "eslint": "^7.28.0", @@ -21,6 +25,8 @@ "style-loader": "^2.0.0", "through2": "^4.0.2", "to-string-loader": "^1.1.6", + "tslib": "^2.3.1", + "typescript": "^4.4.4", "url-loader": "^4.1.1", "webpack": "^5.38.1", "webpack-cli": "^4.8.0" @@ -48,5 +54,6 @@ "geodesy": "^2.2.1", "idb": "^6.1.2", "sortablejs": "^1.12.0" - } -} + }, + "typings": "src/code/index.d.ts" +} \ No newline at end of file diff --git a/src/code/addButtons.d.ts b/src/code/addButtons.d.ts new file mode 100644 index 000000000..e091ae441 --- /dev/null +++ b/src/code/addButtons.d.ts @@ -0,0 +1,2 @@ +export declare function addButtons(): void; +export default addButtons; diff --git a/src/code/auxiliar.d.ts b/src/code/auxiliar.d.ts new file mode 100644 index 000000000..9054b1b9c --- /dev/null +++ b/src/code/auxiliar.d.ts @@ -0,0 +1,3 @@ +export declare function generateId(len?: number): string; +export declare function newColors(incoming: any): any; +export declare function convertColorToHex(color: any, on_error?: string): any; diff --git a/src/code/buttons/linkButton.d.ts b/src/code/buttons/linkButton.d.ts new file mode 100644 index 000000000..d351c36ae --- /dev/null +++ b/src/code/buttons/linkButton.d.ts @@ -0,0 +1,6 @@ +import { WButton } from "../leafletClasses"; + +declare class LinkButton extends WButton { + needWritePermission: true; +} +export default LinkButton; diff --git a/src/code/buttons/markerButton.d.ts b/src/code/buttons/markerButton.d.ts new file mode 100644 index 000000000..f69f25a78 --- /dev/null +++ b/src/code/buttons/markerButton.d.ts @@ -0,0 +1,4 @@ +import { WButton } from "../leafletClasses"; + +declare class MarkerButton extends WButton {} +export default MarkerButton; diff --git a/src/code/buttons/opButton.d.ts b/src/code/buttons/opButton.d.ts new file mode 100644 index 000000000..8f8cc2859 --- /dev/null +++ b/src/code/buttons/opButton.d.ts @@ -0,0 +1,4 @@ +import { WButton } from "../leafletClasses"; + +declare class OpButton extends WButton {} +export default OpButton; diff --git a/src/code/buttons/quickdrawButton.d.ts b/src/code/buttons/quickdrawButton.d.ts new file mode 100644 index 000000000..afbd5f109 --- /dev/null +++ b/src/code/buttons/quickdrawButton.d.ts @@ -0,0 +1,6 @@ +import { WButton } from "../leafletClasses"; + +declare class QuickdrawButton extends WButton { + needWritePermission: true; +} +export default QuickdrawButton; diff --git a/src/code/buttons/syncButton.d.ts b/src/code/buttons/syncButton.d.ts new file mode 100644 index 000000000..c18959463 --- /dev/null +++ b/src/code/buttons/syncButton.d.ts @@ -0,0 +1,4 @@ +import { WButton } from "../leafletClasses"; + +declare class SyncButton extends WButton {} +export default SyncButton; diff --git a/src/code/buttons/uploadButton.d.ts b/src/code/buttons/uploadButton.d.ts new file mode 100644 index 000000000..41205bbe2 --- /dev/null +++ b/src/code/buttons/uploadButton.d.ts @@ -0,0 +1,6 @@ +import { WButton } from "../leafletClasses"; + +declare class UploadButton extends WButton { + needWritePermission: true; +} +export default UploadButton; diff --git a/src/code/buttons/wasabeeButton.d.ts b/src/code/buttons/wasabeeButton.d.ts new file mode 100644 index 000000000..31db031db --- /dev/null +++ b/src/code/buttons/wasabeeButton.d.ts @@ -0,0 +1,4 @@ +import { WButton } from "../leafletClasses"; + +declare class WasabeeButton extends WButton {} +export default WasabeeButton; diff --git a/src/code/crosslinks.d.ts b/src/code/crosslinks.d.ts new file mode 100644 index 000000000..859fa8b9d --- /dev/null +++ b/src/code/crosslinks.d.ts @@ -0,0 +1,22 @@ +import * as L from "leaflet"; +interface LLC extends L.LatLng { + _cartesian?: [number, number, number]; +} +export declare function greatCircleArcIntersectByLatLngs(a0: LLC, a1: LLC, b0: LLC, b1: LLC): boolean; +export declare function greatCircleArcIntersect(existing: any, drawn: any): boolean; +export declare function checkAllLinks(): void; +export declare function initCrossLinks(): void; +export declare class GeodesicLine { + lat1: number; + lat2: number; + lng1: number; + lng2: number; + sinLat1CosLat2: number; + sinLat2CosLat1: number; + cosLat1CosLat2SinDLng: number; + constructor(start: L.LatLng, end: L.LatLng); + isMeridian(): boolean; + latAtLng(lng: any): number; + bearing(): number; +} +export {}; diff --git a/src/code/db.d.ts b/src/code/db.d.ts new file mode 100644 index 000000000..a0c64d7ef --- /dev/null +++ b/src/code/db.d.ts @@ -0,0 +1,58 @@ +import { DBSchema } from "idb"; +import type WasabeeAgent from "./model/agent"; +import type { IBlockerPortal } from "./model/blocker"; +import type WasabeeBlocker from "./model/blocker"; +import type { ILocalOp } from "./model/operation"; +import type WasabeeTeam from "./model/team"; +import type { WDKey } from "./wd"; +interface WasabeeDB extends DBSchema { + agents: { + key: GoogleID; + value: WasabeeAgent; + indexes: { + date: string; + fetched: string; + }; + }; + teams: { + key: TeamID; + value: WasabeeTeam; + indexes: { + fetched: string; + }; + }; + defensivekeys: { + key: [GoogleID, PortalID]; + value: WDKey; + indexes: { + PortalID: string; + Count: number; + }; + }; + operations: { + key: OpID; + value: ILocalOp; + indexes: { + fetched: string; + server: string; + }; + }; + blockers: { + key: [OpID, PortalID, PortalID]; + value: WasabeeBlocker; + indexes: { + opID: OpID; + from: PortalID; + to: PortalID; + }; + }; + blockers_portals: { + key: [OpID, PortalID]; + value: IBlockerPortal; + indexes: { + opID: OpID; + }; + }; +} +declare const db: Promise>; +export default db; diff --git a/src/code/dialogs/about.d.ts b/src/code/dialogs/about.d.ts new file mode 100644 index 000000000..30c9f0e60 --- /dev/null +++ b/src/code/dialogs/about.d.ts @@ -0,0 +1,3 @@ +import { WDialog } from "../leafletClasses"; +declare class AboutDialog extends WDialog {} +export default AboutDialog; diff --git a/src/code/dialogs/agentDialog.d.ts b/src/code/dialogs/agentDialog.d.ts new file mode 100644 index 000000000..c6872b750 --- /dev/null +++ b/src/code/dialogs/agentDialog.d.ts @@ -0,0 +1,9 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +interface AgentDialogOptions extends WDialogOptions { + gid: string; +} +declare class AgentDialog extends WDialog { + options: AgentDialogOptions; + constructor(options: AgentDialogOptions); +} +export default AgentDialog; diff --git a/src/code/dialogs/assignDialog.d.ts b/src/code/dialogs/assignDialog.d.ts new file mode 100644 index 000000000..39240323c --- /dev/null +++ b/src/code/dialogs/assignDialog.d.ts @@ -0,0 +1,13 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +import WasabeeLink from "../model/link"; +import WasabeeMarker from "../model/marker"; +import WasabeePortal from "../model/portal"; +interface AssignDialogOptions extends WDialogOptions { + target: WasabeeLink | WasabeeMarker | WasabeePortal; +} +declare class AssignDialog extends WDialog { + needWritePermission: true; + options: AssignDialogOptions; + constructor(options: AssignDialogOptions); +} +export default AssignDialog; diff --git a/src/code/dialogs/authDialog.d.ts b/src/code/dialogs/authDialog.d.ts new file mode 100644 index 000000000..16459ee4a --- /dev/null +++ b/src/code/dialogs/authDialog.d.ts @@ -0,0 +1,3 @@ +import { WDialog } from "../leafletClasses"; +declare class AuthDialog extends WDialog {} +export default AuthDialog; diff --git a/src/code/dialogs/autodraws.d.ts b/src/code/dialogs/autodraws.d.ts new file mode 100644 index 000000000..2571cf38c --- /dev/null +++ b/src/code/dialogs/autodraws.d.ts @@ -0,0 +1,7 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; + +declare class AutodrawsDialog extends WDialog { + needWritePermission: true; + constructor(options?: WDialogOptions); +} +export default AutodrawsDialog; diff --git a/src/code/dialogs/autodraws/fanfield.d.ts b/src/code/dialogs/autodraws/fanfield.d.ts new file mode 100644 index 000000000..e8602aaa2 --- /dev/null +++ b/src/code/dialogs/autodraws/fanfield.d.ts @@ -0,0 +1,11 @@ +import type WasabeePortal from "../../model/portal"; +import type { AutoDraw } from "./tools"; + +export function angle(a: WasabeePortal, p: WasabeePortal): number; + +export default class FanfieldDialog extends AutoDraw { + _anchor: WasabeePortal; + _start: WasabeePortal; + _end: WasabeePortal; + constructor(); +} diff --git a/src/code/dialogs/autodraws/flipflop.d.ts b/src/code/dialogs/autodraws/flipflop.d.ts new file mode 100644 index 000000000..14908f7f2 --- /dev/null +++ b/src/code/dialogs/autodraws/flipflop.d.ts @@ -0,0 +1,8 @@ +import type WasabeePortal from "../../model/portal"; +import type { AutoDraw } from "./tools"; + +export default class FlipFlopDialog extends AutoDraw { + _anchorOne: WasabeePortal; + _nbSbul: HTMLInputElement; + constructor(); +} diff --git a/src/code/dialogs/autodraws/homogeneous.d.ts b/src/code/dialogs/autodraws/homogeneous.d.ts new file mode 100644 index 000000000..b219dddb0 --- /dev/null +++ b/src/code/dialogs/autodraws/homogeneous.d.ts @@ -0,0 +1,14 @@ +import { AutoDraw } from "./tools"; +import WasabeePortal from "../../model/portal"; + +export default class HomogeneousDialog extends AutoDraw { + _anchorOne: WasabeePortal; + _anchorTwo: WasabeePortal; + _anchorThree: WasabeePortal; + depthMenu: HTMLSelectElement; + orderMenu: HTMLSelectElement; + _fullSearch: boolean; + _urp: L.LatLng; + + constructor(); +} diff --git a/src/code/dialogs/autodraws/madrid.d.ts b/src/code/dialogs/autodraws/madrid.d.ts new file mode 100644 index 000000000..0b59c490a --- /dev/null +++ b/src/code/dialogs/autodraws/madrid.d.ts @@ -0,0 +1,6 @@ +import MultimaxDialog from "./multimaxDialog"; + +export default class MadridDialog extends MultimaxDialog { + _balancedcheck: boolean; + constructor(); +} diff --git a/src/code/dialogs/autodraws/multimaxDialog.d.ts b/src/code/dialogs/autodraws/multimaxDialog.d.ts new file mode 100644 index 000000000..fa8064003 --- /dev/null +++ b/src/code/dialogs/autodraws/multimaxDialog.d.ts @@ -0,0 +1,26 @@ +import { AutoDraw } from "./tools"; +import WasabeePortal from "../../model/portal"; + +export default class MultimaxDialog extends AutoDraw { + _anchorOne: WasabeePortal; + _anchorTwo: WasabeePortal; + _flcheck: boolean; + _orderFromEnd: boolean; + _urp: L.LatLng; + + constructor(); + MM( + pOne: WasabeePortal, + pTwo: WasabeePortal, + portals: WasabeePortal[], + order?: number, + base?: boolean, + commentPrefix?: string + ): any[]; + fieldCoversPortal(a: any, b: any, c: any, p: any): boolean; + getSpine( + one: WasabeePortal, + two: WasabeePortal, + portals: WasabeePortal[] + ): WasabeePortal[]; +} diff --git a/src/code/dialogs/autodraws/onionfield.d.ts b/src/code/dialogs/autodraws/onionfield.d.ts new file mode 100644 index 000000000..22aeefdb8 --- /dev/null +++ b/src/code/dialogs/autodraws/onionfield.d.ts @@ -0,0 +1,10 @@ +import { AutoDraw } from "./tools"; +import WasabeePortal from "../../model/portal"; + +export default class OnionfieldDialog extends AutoDraw { + _anchor: WasabeePortal; + _colors: string[]; + _colorIterator: number; + _color: string; + constructor(); +} diff --git a/src/code/dialogs/autodraws/saveLinks.d.ts b/src/code/dialogs/autodraws/saveLinks.d.ts new file mode 100644 index 000000000..edc63c92e --- /dev/null +++ b/src/code/dialogs/autodraws/saveLinks.d.ts @@ -0,0 +1,7 @@ +import { AutoDraw } from "./tools"; +import WasabeePortal from "../../model/portal"; + +export default class SaveLinksDialog extends AutoDraw { + _anchor: WasabeePortal; + constructor(); +} diff --git a/src/code/dialogs/autodraws/starburst.d.ts b/src/code/dialogs/autodraws/starburst.d.ts new file mode 100644 index 000000000..e8db36576 --- /dev/null +++ b/src/code/dialogs/autodraws/starburst.d.ts @@ -0,0 +1,7 @@ +import { AutoDraw } from "./tools"; +import WasabeePortal from "../../model/portal"; + +export default class StarburstDialog extends AutoDraw { + _anchor: WasabeePortal; + constructor(); +} diff --git a/src/code/dialogs/autodraws/tools.d.ts b/src/code/dialogs/autodraws/tools.d.ts new file mode 100644 index 000000000..55f257d89 --- /dev/null +++ b/src/code/dialogs/autodraws/tools.d.ts @@ -0,0 +1,43 @@ +import { WDialog, WDialogOptions } from "../../leafletClasses"; +import WasabeeOp from "../../model/operation"; +import WasabeePortal from "../../model/portal"; + +export class AutoDraw extends WDialog { + needWritePermission: true; + _operation: WasabeeOp; + _portalSets: { + [name: string]: { + zone: ZoneID; + keys: boolean; + portals: WasabeePortal[]; + display: HTMLSpanElement; + }; + }; + _mapRefreshHook: () => void; + + constructor(options?: WDialogOptions); + initialize(options?: WDialogOptions): void; + + _opChange(): void; + _initPortalSet(setKey: string, zone: ZoneID, keys: boolean): void; + _updatePortalSet(): void; + _addSetPortal( + text: string, + thisKey: string, + container: HTMLDivElement, + storageKey: string + ): void; + _addCheckbox( + text: string, + id: string, + thisKey: string, + container: HTMLDivElement, + defaultValue: boolean + ): void; + _addSelectSet( + text: string, + setKey: string, + container: HTMLDivElement, + defaultValue: string + ): void; +} diff --git a/src/code/dialogs/blockersList.d.ts b/src/code/dialogs/blockersList.d.ts new file mode 100644 index 000000000..b766b0455 --- /dev/null +++ b/src/code/dialogs/blockersList.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class BlockerList extends WDialog {} +export default BlockerList; diff --git a/src/code/dialogs/checklist.d.ts b/src/code/dialogs/checklist.d.ts new file mode 100644 index 000000000..566dbb037 --- /dev/null +++ b/src/code/dialogs/checklist.d.ts @@ -0,0 +1,16 @@ +import { WDialog } from "../leafletClasses"; +import WasabeeLink from "../model/link"; +import WasabeeMarker from "../model/marker"; +import Sortable, { SortableField } from "../sortable"; +import type WasabeeOp from "../model/operation"; + +declare class OperationChecklistDialog extends WDialog { + getFields(operation: WasabeeOp): SortableField[]; + getListDialogContent( + operation: WasabeeOp, + items: Array, + sortBy: number, + sortAsc: boolean + ): Sortable; +} +export default OperationChecklistDialog; diff --git a/src/code/dialogs/confirmDialog.d.ts b/src/code/dialogs/confirmDialog.d.ts new file mode 100644 index 000000000..19bf3be6f --- /dev/null +++ b/src/code/dialogs/confirmDialog.d.ts @@ -0,0 +1,13 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +interface ConfirmDialogOptions extends WDialogOptions { + title: string; + label: string | HTMLElement; + type?: "agent" | "anchor" | "link" | "marker" | "zone" | "operation" | "team"; + callback?: () => void; + cancelCallback?: () => void; +} +declare class ConfirmDialog extends WDialog { + options: ConfirmDialogOptions; + constructor(options: ConfirmDialogOptions); +} +export default ConfirmDialog; diff --git a/src/code/dialogs/defensiveKeysDialog.d.ts b/src/code/dialogs/defensiveKeysDialog.d.ts new file mode 100644 index 000000000..fefb41941 --- /dev/null +++ b/src/code/dialogs/defensiveKeysDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class DefensiveKeysDialog extends WDialog {} +export default DefensiveKeysDialog; diff --git a/src/code/dialogs/exportDialog.d.ts b/src/code/dialogs/exportDialog.d.ts new file mode 100644 index 000000000..dc569b067 --- /dev/null +++ b/src/code/dialogs/exportDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class ExportDialog extends WDialog {} +export default ExportDialog; diff --git a/src/code/dialogs/importDialog.d.ts b/src/code/dialogs/importDialog.d.ts new file mode 100644 index 000000000..c958e3577 --- /dev/null +++ b/src/code/dialogs/importDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class ImportDialog extends WDialog {} +export default ImportDialog; diff --git a/src/code/dialogs/keyListPortal.d.ts b/src/code/dialogs/keyListPortal.d.ts new file mode 100644 index 000000000..929aa196b --- /dev/null +++ b/src/code/dialogs/keyListPortal.d.ts @@ -0,0 +1,10 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; + +interface KeyListPortalOptions extends WDialogOptions { + portalID: string; +} +declare class KeyListPortal extends WDialog { + options: KeyListPortalOptions; + constructor(options: KeyListPortalOptions); +} +export default KeyListPortal; diff --git a/src/code/dialogs/keysList.d.ts b/src/code/dialogs/keysList.d.ts new file mode 100644 index 000000000..7a2e890cb --- /dev/null +++ b/src/code/dialogs/keysList.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class KeysList extends WDialog {} +export default KeysList; diff --git a/src/code/dialogs/linkDialog.d.ts b/src/code/dialogs/linkDialog.d.ts new file mode 100644 index 000000000..52647e178 --- /dev/null +++ b/src/code/dialogs/linkDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; + +declare class LinkDialog extends WDialog {} +export default LinkDialog; diff --git a/src/code/dialogs/linkListDialog.d.ts b/src/code/dialogs/linkListDialog.d.ts new file mode 100644 index 000000000..23f07fd47 --- /dev/null +++ b/src/code/dialogs/linkListDialog.d.ts @@ -0,0 +1,12 @@ +import OperationChecklistDialog from "./checklist"; +import type { WDialogOptions } from "../leafletClasses"; +import type WasabeePortal from "../model/portal"; + +interface LinkListDialogOptions extends WDialogOptions { + portal: WasabeePortal; +} +declare class LinkListDialog extends OperationChecklistDialog { + options: LinkListDialogOptions; + constructor(options: LinkListDialogOptions); +} +export default LinkListDialog; diff --git a/src/code/dialogs/manageTeamDialog.d.ts b/src/code/dialogs/manageTeamDialog.d.ts new file mode 100644 index 000000000..71c9d1a55 --- /dev/null +++ b/src/code/dialogs/manageTeamDialog.d.ts @@ -0,0 +1,11 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +import { MeTeam } from "../model/me"; + +interface ManageTeamDialogOptions extends WDialogOptions { + team: MeTeam; +} +declare class ManageTeamDialog extends WDialog { + options: ManageTeamDialogOptions; + constructor(options: ManageTeamDialogOptions); +} +export default ManageTeamDialog; diff --git a/src/code/dialogs/markerAddDialog.d.ts b/src/code/dialogs/markerAddDialog.d.ts new file mode 100644 index 000000000..7d6b926d5 --- /dev/null +++ b/src/code/dialogs/markerAddDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class MarkerAddDialog extends WDialog {} +export default MarkerAddDialog; diff --git a/src/code/dialogs/markerChangeDialog.d.ts b/src/code/dialogs/markerChangeDialog.d.ts new file mode 100644 index 000000000..773648b1b --- /dev/null +++ b/src/code/dialogs/markerChangeDialog.d.ts @@ -0,0 +1,11 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +import WasabeeMarker from "../model/marker"; + +interface MarkerChangeDialogOptions extends WDialogOptions { + marker: WasabeeMarker; +} +declare class MarkerChangeDialog extends WDialog { + options: MarkerChangeDialogOptions; + constructor(options: MarkerChangeDialogOptions); +} +export default MarkerChangeDialog; diff --git a/src/code/dialogs/markerList.d.ts b/src/code/dialogs/markerList.d.ts new file mode 100644 index 000000000..01f8fd582 --- /dev/null +++ b/src/code/dialogs/markerList.d.ts @@ -0,0 +1,4 @@ +import OperationChecklistDialog from "./checklist"; + +declare class MarkerList extends OperationChecklistDialog {} +export default MarkerList; diff --git a/src/code/dialogs/mergeDialog.d.ts b/src/code/dialogs/mergeDialog.d.ts new file mode 100644 index 000000000..1f786d89a --- /dev/null +++ b/src/code/dialogs/mergeDialog.d.ts @@ -0,0 +1,13 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +import WasabeeOp from "../model/operation"; +interface MergeDialogOptions extends WDialogOptions { + title?: string; + opOwn: WasabeeOp; + opRemote: WasabeeOp; + updateCallback?: (op: WasabeeOp) => void; +} +declare class MergeDialog extends WDialog { + options: MergeDialogOptions; + constructor(options: MergeDialogOptions); +} +export default MergeDialog; diff --git a/src/code/dialogs/newopDialog.d.ts b/src/code/dialogs/newopDialog.d.ts new file mode 100644 index 000000000..a60fd39b2 --- /dev/null +++ b/src/code/dialogs/newopDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class NewopDialog extends WDialog {} +export default NewopDialog; diff --git a/src/code/dialogs/onlineAgentList.d.ts b/src/code/dialogs/onlineAgentList.d.ts new file mode 100644 index 000000000..9dae4a871 --- /dev/null +++ b/src/code/dialogs/onlineAgentList.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class OnlineAgentList extends WDialog {} +export default OnlineAgentList; diff --git a/src/code/dialogs/opPerms.d.ts b/src/code/dialogs/opPerms.d.ts new file mode 100644 index 000000000..0afac860c --- /dev/null +++ b/src/code/dialogs/opPerms.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class OpPermList extends WDialog {} +export default OpPermList; diff --git a/src/code/dialogs/opSettings.d.ts b/src/code/dialogs/opSettings.d.ts new file mode 100644 index 000000000..9c1678786 --- /dev/null +++ b/src/code/dialogs/opSettings.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class OpSettingDialog extends WDialog {} +export default OpSettingDialog; diff --git a/src/code/dialogs/opsDialog.d.ts b/src/code/dialogs/opsDialog.d.ts new file mode 100644 index 000000000..2bb768d25 --- /dev/null +++ b/src/code/dialogs/opsDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class OpsDialog extends WDialog {} +export default OpsDialog; diff --git a/src/code/dialogs/promptDialog.d.ts b/src/code/dialogs/promptDialog.d.ts new file mode 100644 index 000000000..9255f6d07 --- /dev/null +++ b/src/code/dialogs/promptDialog.d.ts @@ -0,0 +1,20 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; + +interface PromptDialogOptions extends WDialogOptions { + title: string; + label: string; + placeholder?: string; + current?: string; + suggestions?: { + text: string; + value: string; + }[]; + callback?: () => void; + cancelCallback?: () => void; +} +declare class PromptDialog extends WDialog { + inputField: HTMLInputElement; + options: PromptDialogOptions; + constructor(options: PromptDialogOptions); +} +export default PromptDialog; diff --git a/src/code/dialogs/sendTargetDialog.d.ts b/src/code/dialogs/sendTargetDialog.d.ts new file mode 100644 index 000000000..2bddfa7ad --- /dev/null +++ b/src/code/dialogs/sendTargetDialog.d.ts @@ -0,0 +1,12 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +import WasabeeMarker from "../model/marker"; +import WasabeePortal from "../model/portal"; + +interface SendTargetDialogOptions extends WDialogOptions { + target: WasabeeMarker | WasabeePortal; +} +declare class SendTargetDialog extends WDialog { + options: SendTargetDialogOptions; + constructor(options: SendTargetDialogOptions); +} +export default SendTargetDialog; diff --git a/src/code/dialogs/setCommentDialog.d.ts b/src/code/dialogs/setCommentDialog.d.ts new file mode 100644 index 000000000..066928b55 --- /dev/null +++ b/src/code/dialogs/setCommentDialog.d.ts @@ -0,0 +1,14 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +import WasabeePortal from "../model/portal"; +import WasabeeLink from "../model/link"; +import WasabeeMarker from "../model/marker"; +import type WasabeeOp from "../model/operation"; +interface SetCommentDialogOptions extends WDialogOptions { + target: WasabeeMarker | WasabeeLink | WasabeePortal; + operation: WasabeeOp; +} +export declare class SetCommentDialog extends WDialog { + options: SetCommentDialogOptions; + constructor(options: SetCommentDialogOptions); +} +export default SetCommentDialog; diff --git a/src/code/dialogs/settingsDialog.d.ts b/src/code/dialogs/settingsDialog.d.ts new file mode 100644 index 000000000..c52b9dd9a --- /dev/null +++ b/src/code/dialogs/settingsDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class SettingsDialog extends WDialog {} +export default SettingsDialog; diff --git a/src/code/dialogs/skinDialog.d.ts b/src/code/dialogs/skinDialog.d.ts new file mode 100644 index 000000000..02bdeb001 --- /dev/null +++ b/src/code/dialogs/skinDialog.d.ts @@ -0,0 +1,3 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +declare class SkinDialog extends WDialog {} +export default SkinDialog; diff --git a/src/code/dialogs/stateDialog.d.ts b/src/code/dialogs/stateDialog.d.ts new file mode 100644 index 000000000..4310debff --- /dev/null +++ b/src/code/dialogs/stateDialog.d.ts @@ -0,0 +1,12 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +import WasabeeLink from "../model/link"; +import WasabeeMarker from "../model/marker"; +interface StateDialogOptions extends WDialogOptions { + target: WasabeeMarker | WasabeeLink; + opID: string; +} +declare class StateDialog extends WDialog { + options: StateDialogOptions; + constructor(options: StateDialogOptions); +} +export default StateDialog; diff --git a/src/code/dialogs/teamListDialog.d.ts b/src/code/dialogs/teamListDialog.d.ts new file mode 100644 index 000000000..883317201 --- /dev/null +++ b/src/code/dialogs/teamListDialog.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class TeamListDialog extends WDialog {} +export default TeamListDialog; diff --git a/src/code/dialogs/teamMembershipList.d.ts b/src/code/dialogs/teamMembershipList.d.ts new file mode 100644 index 000000000..ce212b909 --- /dev/null +++ b/src/code/dialogs/teamMembershipList.d.ts @@ -0,0 +1,10 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; + +interface TeamMembershipListOptions extends WDialogOptions { + teamID: string; +} +declare class TeamMembershipList extends WDialog { + options: TeamMembershipListOptions; + constructor(options: TeamMembershipListOptions); +} +export default TeamMembershipList; diff --git a/src/code/dialogs/trawl.d.ts b/src/code/dialogs/trawl.d.ts new file mode 100644 index 000000000..617a8332c --- /dev/null +++ b/src/code/dialogs/trawl.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class TrawlDialog extends WDialog {} +export default TrawlDialog; diff --git a/src/code/dialogs/wasabeeDlist.d.ts b/src/code/dialogs/wasabeeDlist.d.ts new file mode 100644 index 000000000..8b6520f10 --- /dev/null +++ b/src/code/dialogs/wasabeeDlist.d.ts @@ -0,0 +1,4 @@ +import { WDialog } from "../leafletClasses"; + +declare class WasabeeDList extends WDialog {} +export default WasabeeDList; diff --git a/src/code/dialogs/zoneDialog.d.ts b/src/code/dialogs/zoneDialog.d.ts new file mode 100644 index 000000000..d625cd983 --- /dev/null +++ b/src/code/dialogs/zoneDialog.d.ts @@ -0,0 +1,14 @@ +import { WDialog } from "../leafletClasses"; + +declare class ZoneDialog extends WDialog { + ZonedrawHandler: ZonedrawHandler; +} +export default ZoneDialog; + +interface ZonedrawHandlerOptions { + parent: ZoneDialog; +} +declare class ZonedrawHandler extends L.Handler { + zoneID: number; + constructor(options: ZonedrawHandlerOptions); +} diff --git a/src/code/dialogs/zoneSetColor.d.ts b/src/code/dialogs/zoneSetColor.d.ts new file mode 100644 index 000000000..efaeb6905 --- /dev/null +++ b/src/code/dialogs/zoneSetColor.d.ts @@ -0,0 +1,11 @@ +import { WDialog, WDialogOptions } from "../leafletClasses"; +import type WasabeeZone from "../model/zone"; + +interface ZoneSetColorDialogOptions extends WDialogOptions { + zone: WasabeeZone; +} +declare class ZoneSetColorDialog extends WDialog { + options: ZoneSetColorDialogOptions; + constructor(options: ZoneSetColorDialogOptions); +} +export default ZoneSetColorDialog; diff --git a/src/code/firebaseSupport.d.ts b/src/code/firebaseSupport.d.ts new file mode 100644 index 000000000..466c320fb --- /dev/null +++ b/src/code/firebaseSupport.d.ts @@ -0,0 +1,2 @@ +export declare function initFirebase(): void; +export declare function postToFirebase(message: any): void; diff --git a/src/code/index.d.ts b/src/code/index.d.ts new file mode 100644 index 000000000..d0439ddfc --- /dev/null +++ b/src/code/index.d.ts @@ -0,0 +1,13 @@ +/// + +export {}; + +declare global { + type OpID = string; + type PortalID = string; + type TeamID = string; + type LinkID = string; + type MarkerID = string; + type GoogleID = string; + type ZoneID = number; +} diff --git a/src/code/init.d.ts b/src/code/init.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/src/code/init.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/src/code/leafletClasses.d.ts b/src/code/leafletClasses.d.ts new file mode 100644 index 000000000..0442203eb --- /dev/null +++ b/src/code/leafletClasses.d.ts @@ -0,0 +1,95 @@ +/// +/// + +export declare class WTooltip extends L.Class { + _pane: HTMLElement; + _container: HTMLDivElement; + constructor(); + dispose(): void; + updateContent(labelText: any): this; + updatePosition(latlng: L.LatLngExpression): this; + showAsError(): this; + removeError(): this; +} +declare type WPaneOptions = { + paneId: string; + paneName: string; + default?: () => WDialog; +}; +export declare class WPane extends L.Handler { + options: WPaneOptions; + _dialog: WDialog; + _container: HTMLDivElement; + constructor(options: WPaneOptions); + addHooks(): void; + removeHooks(): void; +} +export interface WDialogOptions { + [propName: string]: unknown; +} +export declare class WDialog extends L.Handler { + needWritePermission: boolean; // todo: set static + usePane: boolean; + paneId: string; + options: WDialogOptions; + _smallScreen: boolean; + _dialog: JQuery | null; + _container: HTMLDivElement; + _header: HTMLDivElement; + _content: HTMLDivElement; + _buttons: HTMLDivElement; + constructor(options?: WDialogOptions); + initialize(options?: WDialogOptions); + addHooks(): void; + removeHooks(): void; + onOpChange(): void; + enable(): any; + update(): void; + createDialog(options: DialogOptions): void; + setTitle(title: string): void; + setContent(content: HTMLElement | string): void; + closeDialog(): void; + _isMobile(): boolean; +} +export interface ButtonsControlOptions extends L.ControlOptions { + buttons: Map; + container: HTMLElement; +} +export declare class ButtonsControl extends L.Control { + options: ButtonsControlOptions; + constructor(options: ButtonsControlOptions); + onAdd(): HTMLDivElement; + onRemove(): void; + update(): void; + disableAllExcept(name: any): void; +} +export declare type ButtonOptions = { + text?: string; + html?: HTMLElement; + title?: string; + container?: HTMLElement; + callback: () => void; + context: unknown; + buttonImage?: string; + className?: string; + img?: string; +}; +export declare class WButton extends L.Class { + title: string; + type: string; + needWritePermission: boolean; + _enabled: boolean; + actionsContainer: HTMLElement; + control: ButtonsControl; + button: HTMLAnchorElement; + _container: HTMLElement; + constructor(container: HTMLElement); + update(): void; + _toggleActions(): void; + setControl(control: any): void; + disable(): void; + enable(): void; + _createButton(options: ButtonOptions): HTMLAnchorElement; + _createSubActions(buttons: ButtonOptions[]): HTMLUListElement; +} +export {}; diff --git a/src/code/mapDrawing.d.ts b/src/code/mapDrawing.d.ts new file mode 100644 index 000000000..01953e7f1 --- /dev/null +++ b/src/code/mapDrawing.d.ts @@ -0,0 +1,7 @@ +import * as L from "leaflet"; +export declare function drawMap(): void; +export declare function drawBackgroundOps(opIDs?: string[]): Promise; +export declare function drawBackgroundOp(operation: any, layerGroup?: L.LayerGroup, style?: L.PathOptions): void; +export declare function drawAgents(): Promise; +export declare function drawSingleTeam(teamID: string, layerMap?: Map, alreadyDone?: string[]): Promise; +export declare function drawSingleAgent(gid: any): Promise; diff --git a/src/code/model/agent.d.ts b/src/code/model/agent.d.ts new file mode 100644 index 000000000..40b3b92d8 --- /dev/null +++ b/src/code/model/agent.d.ts @@ -0,0 +1,29 @@ +import * as L from "leaflet"; +export default class WasabeeAgent { + id: string; + name: string; + vname: string; + rocksname: string; + intelname: string; + intelfaction: string; + level: number; + enlid: string; + pic: string; + Vverified: boolean; + blacklisted: boolean; + rocks: boolean; + lat: number; + lng: number; + date: string; + ShareWD?: boolean; + LoadWD?: boolean; + squad?: string; + state?: boolean; + fetched: number; + cached?: boolean; + constructor(obj: any); + getTeamName(teamID?: number): Promise; + _updateCache(): Promise; + get latLng(): L.LatLng; + static get(gid: string, maxAgeSeconds?: number): Promise; +} diff --git a/src/code/model/blocker.d.ts b/src/code/model/blocker.d.ts new file mode 100644 index 000000000..ec8ade609 --- /dev/null +++ b/src/code/model/blocker.d.ts @@ -0,0 +1,24 @@ +import type WasabeeOp from "./operation"; +import type WasabeePortal from "./portal"; +export interface IBlockerPortal { + opID: OpID; + id: PortalID; + name: string; + lat: string; + lng: string; +} +export default class WasabeeBlocker { + opID: string; + from: string; + to: string; + fromPortal?: IBlockerPortal; + toPortal?: IBlockerPortal; + constructor(obj: any); + static addPortal(op: WasabeeOp, portal: WasabeePortal): Promise; + static updatePortal(op: WasabeeOp, portal: WasabeePortal): Promise; + static removeBlocker(op: WasabeeOp, portalId: string): Promise; + static removeBlockers(opID: string): Promise; + static addBlocker(op: WasabeeOp, fromPortal: WasabeePortal, toPortal: WasabeePortal): Promise; + static getPortals(op: WasabeeOp): Promise; + static getAll(op: WasabeeOp): Promise; +} diff --git a/src/code/model/evented.d.ts b/src/code/model/evented.d.ts new file mode 100644 index 000000000..889d79964 --- /dev/null +++ b/src/code/model/evented.d.ts @@ -0,0 +1,12 @@ +export default class Evented { + _events: { + [propName: string]: Array<{ + fct: (data: unknown) => void; + context: unknown; + }>; + }; + constructor(); + on(event: string, func: (data: unknown) => void, context?: unknown): this; + off(event: string, func: (data: unknown) => void, context?: unknown): this; + fire(event: string, data?: unknown): this; +} diff --git a/src/code/model/index.d.ts b/src/code/model/index.d.ts new file mode 100644 index 000000000..a1fa7fb2a --- /dev/null +++ b/src/code/model/index.d.ts @@ -0,0 +1,10 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// diff --git a/src/code/model/link.d.ts b/src/code/model/link.d.ts new file mode 100644 index 000000000..430485bf2 --- /dev/null +++ b/src/code/model/link.d.ts @@ -0,0 +1,38 @@ +import type WasabeeOp from "./operation"; +export default class WasabeeLink { + ID: string; + fromPortalId: string; + toPortalId: string; + description?: string; + assignedTo?: string; + throwOrderPos: number; + color: string; + completed: boolean; + zone: number; + constructor(obj: any); + assign(gid: any): void; + toJSON(): { + ID: string; + fromPortalId: string; + toPortalId: string; + description: string; + assignedTo: string; + throwOrderPos: number; + color: string; + completed: boolean; + zone: number; + }; + get comment(): string; + set comment(c: string); + get opOrder(): number; + set opOrder(o: number); + setOrder(o: number | string): void; + get state(): "pending" | "completed" | "assigned"; + set state(s: string); + get portalId(): string; + getLatLngs(operation: WasabeeOp): any[]; + get latLngs(): any[]; + setColor(color: string, operation: WasabeeOp): void; + getColor(operation: WasabeeOp): string; + length(operation: WasabeeOp): number; +} diff --git a/src/code/model/marker.d.ts b/src/code/model/marker.d.ts new file mode 100644 index 000000000..f688b712a --- /dev/null +++ b/src/code/model/marker.d.ts @@ -0,0 +1,47 @@ +export default class WasabeeMarker { + ID: string; + portalId: string; + type: string; + comment?: string; + order: number; + completedID: boolean; + assignedTo: string; + zone: number; + _state: "pending" | "assigned" | "acknowledged" | "completed"; + static get markerTypes(): Set; + static get constants(): { + MARKER_TYPE_CAPTURE: string; + MARKER_TYPE_DECAY: string; + MARKER_TYPE_EXCLUDE: string; + MARKER_TYPE_DESTROY: string; + MARKER_TYPE_FARM: string; + MARKER_TYPE_GOTO: string; + MARKER_TYPE_KEY: string; + MARKER_TYPE_LINK: string; + MARKER_TYPE_MEETAGENT: string; + MARKER_TYPE_OTHER: string; + MARKER_TYPE_RECHARGE: string; + MARKER_TYPE_UPGRADE: string; + MARKER_TYPE_VIRUS: string; + }; + constructor(obj: any); + toJSON(): { + ID: string; + portalId: string; + type: string; + comment: string; + state: "pending" | "completed" | "assigned" | "acknowledged"; + completedID: boolean; + assignedTo: string; + order: number; + zone: number; + }; + get opOrder(): number; + set opOrder(o: number); + setOrder(o: number | string): void; + assign(gid: any): void; + set state(state: "pending" | "completed" | "assigned" | "acknowledged"); + get state(): "pending" | "completed" | "assigned" | "acknowledged"; + isDestructMarker(): boolean; + static isDestructMarkerType(type: any): boolean; +} diff --git a/src/code/model/me.d.ts b/src/code/model/me.d.ts new file mode 100644 index 000000000..443c8c926 --- /dev/null +++ b/src/code/model/me.d.ts @@ -0,0 +1,48 @@ +export interface MeTeam { + ID: string; + Name: string; + RocksComm: string; + RocksKey: string; + JoinLinkToken: string; + ShareWD: "On" | "Off"; + LoadWD: "On" | "Off"; + State: "On" | "Off"; + Owner: string; + VTeam: string; + VTeamRole: string; +} +interface MeOp { + ID: string; +} +export default class WasabeeMe { + GoogleID: string; + name: string; + vname: string; + rocksname: string; + intelname: string; + level: number; + Teams: Array; + Ops: Array; + fetched: number; + Vverified: boolean; + blacklisted: boolean; + enlid: string; + pic: string; + intelfaction: string; + querytoken: string; + _teamMap: Map; + constructor(data: any); + static maxCacheAge(): number; + toJSON(): this; + store(): void; + remove(): void; + static localGet(): WasabeeMe; + static isLoggedIn(): boolean; + static cacheGet(): WasabeeMe; + static waitGet(force?: boolean): Promise; + static purge(): Promise; + teamJoined(teamID: any): boolean; + teamEnabled(teamID: any): boolean; + makeTeamMap(): void; +} +export {}; diff --git a/src/code/model/operation.d.ts b/src/code/model/operation.d.ts new file mode 100644 index 000000000..ddde21a5b --- /dev/null +++ b/src/code/model/operation.d.ts @@ -0,0 +1,202 @@ +import * as L from "leaflet"; +import WasabeeLink from "./link"; +import WasabeePortal from "./portal"; +import WasabeeMarker from "./marker"; +import WasabeeZone from "./zone"; +import Evented from "./evented"; +export declare type KeyOnHand = { + portalId: PortalID; + gid: GoogleID; + capsule: string; + onhand: number; +}; +export declare type OpPermItem = { + role: "read" | "write" | "assignonly"; + teamid: string; + zone: number; +}; +interface IOperation { + ID: OpID; + name: string; + creator: string | GoogleID; + opportals: WasabeePortal[]; + anchors: string[]; + links: WasabeeLink[]; + markers: WasabeeMarker[]; + color: string; + comment: string; + zones: WasabeeZone[]; + referencetime: string; +} +export interface IServerOp extends IOperation { + creator: GoogleID; + teamlist: OpPermItem[]; + keysonhand: KeyOnHand[]; + lasteditid: string; + fetched: string; + modified: string; +} +export interface ILocalOp extends IOperation { + teamlist: OpPermItem[]; + keysonhand: KeyOnHand[]; + lasteditid: string; + fetched: string; + fetchedOp: string; + server: string; + localchanged: boolean; + remoteChanged: boolean; + background: boolean; + stored: number; +} +export default class WasabeeOp extends Evented implements IOperation { + ID: string; + name: string; + creator: string; + anchors: string[]; + links: WasabeeLink[]; + markers: WasabeeMarker[]; + color: string; + comment: string; + zones: WasabeeZone[]; + referencetime: string; + teamlist: OpPermItem[]; + keysonhand: KeyOnHand[]; + lasteditid: string; + fetched: string; + fetchedOp: string; + localchanged: boolean; + remoteChanged: boolean; + server: string; + blockers: WasabeeLink[]; + background: boolean; + stored: number; + _idToOpportals: Map; + _coordsToOpportals: Map; + _dirtyCoordsTable: boolean; + _batchmode: boolean; + constructor(obj: any); + static load(opID: any): Promise; + static delete(opID: any): Promise; + static migrate(opID: any): Promise; + store(): Promise; + toJSON(): IOperation; + toExport(): string; + get opportals(): WasabeePortal[]; + buildCoordsLookupTable(): void; + getColor(): string; + containsPortal(portal: any): boolean; + getPortalByLatLng(lat: any, lng: any): WasabeePortal; + containsLinkFromTo(fromPortalId: any, toPortalId: any): boolean; + containsLink(link: any): boolean; + containsMarker(portal: any, markerType: any): boolean; + containsMarkerByID(portalID: any, markerType: any): boolean; + getPortalMarkers(portal: any): Map; + getLinkByPortalIDs(portalId1: any, portalId2: any): WasabeeLink; + getLink(portal1: any, portal2: any): WasabeeLink; + getLinkListFromPortal(portal: any): WasabeeLink[]; + getPortal(portalID: any): WasabeePortal; + getMarker(markerID: any): WasabeeMarker; + removeAnchor(portalId: any): void; + removeMarker(marker: any): void; + setMarkerComment(marker: any, comment: any): void; + setMarkerState(markerID: any, state: any): void; + setLinkComment(link: any, comment: any): void; + setLinkState(linkID: any, state: any): void; + setLinkColor(linkID: any, color: any): void; + setLinkOrder(linkID: any, order: any): void; + setMarkerOrder(markerID: any, order: any): void; + setPortalComment(portal: any, comment: any): void; + setPortalHardness(portal: any, hardness: any): void; + removeLink(startPortal: any, endPortal: any): void; + reverseLink(startPortalID: any, endPortalID: any): void; + cleanAll(): void; + cleanAnchorList(): void; + cleanPortalList(): void; + addPortal(portal: any): void; + _addPortal(portal: any): boolean; + updatePortal(portal: any): boolean; + _updatePortal(portal: any): boolean; + addLink(fromPortal: WasabeePortal, toPortal: WasabeePortal, options?: { + description?: string; + order?: number; + color?: string; + replace?: boolean; + }): WasabeeLink; + containsAnchor(portalId: string): boolean; + addAnchor(portal: WasabeePortal): void; + get fakedPortals(): WasabeePortal[]; + _swapPortal(originalPortal: WasabeePortal, newPortal: WasabeePortal): void; + swapPortal(originalPortal: WasabeePortal, newPortal: WasabeePortal): void; + addMarker(markerType: string, portal: WasabeePortal, options: any): boolean; + assignMarker(id: any, gid: any): void; + assignLink(id: any, gid: any): void; + clearAllItems(): void; + clearAllLinks(): void; + clearAllMarkers(): void; + update(updateLocalchanged?: boolean): void; + updateBlockers(): void; + startBatchMode(): void; + endBatchMode(): void; + convertLinksToObjs(links: any): any[]; + convertMarkersToObjs(markers: any): any[]; + convertPortalsToObjs(portals: any): any[]; + convertZonesToObjs(zones: any): any[]; + get mbr(): L.LatLngBounds; + canWriteServer(): boolean; + canWrite(): boolean; + getPermission(): "write" | "read" | "assignonly"; + isOnCurrentServer(): boolean; + isServerOp(): boolean; + isOwnedOp(): boolean; + get nextOrder(): number; + keyOnHand(portalId: any, gid: any, onhand: any, capsule: any): void; + KeysOnHandForPortal(portalId: any): number; + KeysRequiredForPortal(portalId: any): number; + zoneName(zoneID: any): any; + setZone(thing: any, zoneID: any): void; + removeZone(zoneID: any): void; + removeZonePoints(zoneID: any): void; + renameZone(zoneID: any, name: any): void; + addZone(): number; + addZonePoint(zoneID: number, latlng: L.LatLng): void; + changes(origin?: WasabeeOp): { + addition: any[]; + edition: any[]; + deletion: any[]; + name: any; + color: any; + comment: any; + }; + checkChanges(): boolean; + mergeZones(op: any): number; + applyChanges(changes: any, op: any): { + compatibility: { + ok: boolean; + rewrite: { + link: number; + marker: number; + }; + }; + addition: { + link: number; + marker: number; + zone: number; + ignored: number; + }; + deletion: { + link: number; + marker: number; + }; + edition: { + portal: number; + link: number; + marker: number; + assignment: number; + duplicate: number; + singlePortalLink: number; + removed: number; + }; + }; + determineZone(latlng: any): number; +} +export { }; diff --git a/src/code/model/portal.d.ts b/src/code/model/portal.d.ts new file mode 100644 index 000000000..349ecff92 --- /dev/null +++ b/src/code/model/portal.d.ts @@ -0,0 +1,24 @@ +import * as L from "leaflet"; +export default class WasabeePortal { + id: string; + name: string; + lat: string; + lng: string; + comment: string; + hardness: string; + _latLng: L.LatLng; + constructor(obj: any); + toJSON(): { + id: string; + name: string; + lat: string; + lng: string; + comment: string; + hardness: string; + }; + get latLng(): L.LatLng; + static fake(lat: string | number, lng: string | number, id?: string, name?: string): WasabeePortal; + get faked(): boolean; + get loading(): boolean; + get pureFaked(): boolean; +} diff --git a/src/code/model/team.d.ts b/src/code/model/team.d.ts new file mode 100644 index 000000000..e7c6fcd33 --- /dev/null +++ b/src/code/model/team.d.ts @@ -0,0 +1,15 @@ +import WasabeeAgent from "./agent"; +export default class WasabeeTeam { + fetched: number; + id: string; + name: string; + rc: string; + rk: string; + jlt: string; + agents: Array; + _a: Array; + constructor(data: any); + getAgents(): WasabeeAgent[]; + _updateCache(): Promise; + static get(teamID: any, maxAgeSeconds?: number): Promise; +} diff --git a/src/code/model/team.js b/src/code/model/team.js index b8c1b4e2b..7a0c7747b 100644 --- a/src/code/model/team.js +++ b/src/code/model/team.js @@ -52,11 +52,8 @@ export default class WasabeeTeam { static async get(teamID, maxAgeSeconds = 60) { const cached = await (await db).get("teams", teamID); if (cached) { - const t = new WasabeeTeam(cached); - if (t.fetched > Date.now() - 1000 * maxAgeSeconds) { - t.cached = true; - return t; - } + if (cached.fetched + maxAgeSeconds * 1000 > Date.now()) + return new WasabeeTeam(cached); } if (!WasabeeMe.isLoggedIn()) return null; diff --git a/src/code/model/zone.d.ts b/src/code/model/zone.d.ts new file mode 100644 index 000000000..911650855 --- /dev/null +++ b/src/code/model/zone.d.ts @@ -0,0 +1,21 @@ +export default class WasabeeZone { + id: number; + name: string; + color: string; + points: Array; + constructor(obj: any); + toJSON(): { + id: number; + name: string; + color: string; + points: zonePoint[]; + }; + contains(latlng: any): boolean; +} +declare class zonePoint { + position: number; + lat: number; + lng: number; + constructor(obj: any); +} +export {}; diff --git a/src/code/polyfill.d.ts b/src/code/polyfill.d.ts new file mode 100644 index 000000000..5fcaa65e1 --- /dev/null +++ b/src/code/polyfill.d.ts @@ -0,0 +1 @@ +export default function polyfill(): void; diff --git a/src/code/selectedOp.d.ts b/src/code/selectedOp.d.ts new file mode 100644 index 000000000..b4fb3d92a --- /dev/null +++ b/src/code/selectedOp.d.ts @@ -0,0 +1,17 @@ +import WasabeeOp from "./model/operation"; +export declare function getSelectedOperation(): WasabeeOp; +export declare function initSelectedOperation(): Promise; +export declare function changeOpIfNeeded(): Promise; +export declare function loadNewDefaultOp(): Promise; +export declare function makeSelectedOperation(opID: any): Promise; +export declare function setupLocalStorage(): Promise; +export declare function removeOperation(opID: any): Promise; +export declare function showOperation(opID: any): void; +export declare function hideOperation(opID: any): void; +export declare function resetHiddenOps(): void; +export declare function resetOps(): Promise; +export declare function hiddenOpsList(): any; +export declare function setOpBackground(opID: any, background: any): Promise; +export declare function opsList(hidden?: boolean): Promise; +export declare function duplicateOperation(opID: any): Promise; +export declare function removeNonOwnedOps(): Promise; diff --git a/src/code/server.d.ts b/src/code/server.d.ts new file mode 100644 index 000000000..ad7e1ea57 --- /dev/null +++ b/src/code/server.d.ts @@ -0,0 +1,68 @@ +import WasabeeOp from "./model/operation"; +import WasabeeMarker from "./model/marker"; +import type WasabeeLink from "./model/link"; +import type WasabeePortal from "./model/portal"; +import type { WDKey } from "./wd"; +interface IServerUpdate { + updateID?: string; +} +export default function (): any; +export declare function uploadOpPromise(): Promise; +export declare function updateOpPromise(operation: WasabeeOp): Promise; +export declare function deleteOpPromise(opID: OpID): Promise; +export declare function statOpPromise(opID: OpID): Promise; +export declare function teamPromise(teamid: TeamID): Promise; +export declare function opPromise(opID: OpID): Promise; +export declare function mePromise(): Promise; +export declare function agentPromise(GID: GoogleID): Promise; +export declare function assignMarkerPromise(opID: OpID, markerID: MarkerID, agentID: GoogleID): Promise; +export declare function assignLinkPromise(opID: OpID, linkID: LinkID, agentID: GoogleID): Promise; +export declare function targetPromise(agentID: GoogleID, portal: WasabeePortal, type?: string): Promise; +export declare function routePromise(agentID: GoogleID, portal: WasabeePortal): Promise; +export declare function SendAccessTokenAsync(accessToken: string): Promise; +export declare function SetTeamState(teamID: TeamID, state: "On" | "Off"): Promise; +export declare function SetTeamShareWD(teamID: TeamID, state: "On" | "Off"): Promise; +export declare function SetTeamLoadWD(teamID: TeamID, state: "On" | "Off"): Promise; +export declare function SetMarkerState(opID: OpID, markerID: MarkerID, state: string): Promise; +export declare function SetLinkState(opID: OpID, linkID: LinkID, state: string): Promise; +export declare function opKeyPromise(opID: OpID, portalID: PortalID, onhand: number, capsule: string): Promise; +export declare function dKeyPromise(json: string): Promise; +export declare function dKeyBulkPromise(json: string): Promise; +export declare function dKeylistPromise(): Promise<{ + DefensiveKeys: WDKey[]; +}>; +export declare function locationPromise(lat: number, lng: number): Promise; +export declare function logoutPromise(): Promise; +export declare function addPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; +export declare function delPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; +export declare function leaveTeamPromise(teamID: TeamID): Promise; +export declare function removeAgentFromTeamPromise(agentID: GoogleID, teamID: TeamID): Promise; +export declare function setAgentTeamSquadPromise(agentID: GoogleID, teamID: TeamID, squad: string): Promise; +export declare function addAgentToTeamPromise(agentID: GoogleID, teamID: TeamID): Promise; +export declare function renameTeamPromise(teamID: TeamID, name: string): Promise; +export declare function rocksPromise(teamID: TeamID, community: string, apikey: string): Promise; +export declare function newTeamPromise(name: string): Promise; +export declare function deleteTeamPromise(teamID: TeamID): Promise; +export declare function oneTimeToken(token: string): Promise; +export declare function GetWasabeeServer(): any; +export declare function GetUpdateList(): any; +export declare function SetWasabeeServer(server: string): void; +export declare function sendTokenToWasabee(token: string): Promise; +export declare function getCustomTokenFromServer(): Promise; +export declare function loadConfig(): Promise; +export declare function changeTeamOwnerPromise(teamID: TeamID, newOwner: GoogleID): Promise; +export declare function createJoinLinkPromise(teamID: TeamID): Promise<{ + Key: string; +}>; +export declare function deleteJoinLinkPromise(teamID: TeamID): Promise; +export declare function setAssignmentStatus(op: WasabeeOp, object: WasabeeLink | WasabeeMarker, completed: boolean): Promise; +export declare function sendAnnounce(teamID: TeamID, message: string): Promise; +export declare function pullRocks(teamID: TeamID): Promise; +export declare function reverseLinkDirection(opID: OpID, linkID: LinkID): Promise; +export declare function setOpInfo(opID: OpID, info: any): Promise; +export declare function setMarkerComment(opID: OpID, markerID: MarkerID, comment: string): Promise; +export declare function setLinkComment(opID: OpID, linkID: LinkID, desc: string): Promise; +export declare function setLinkZone(opID: OpID, linkID: LinkID, zone: ZoneID): Promise; +export declare function setMarkerZone(opID: OpID, markerID: MarkerID, zone: ZoneID): Promise; +export declare function setIntelID(name: string, faction: string, querytoken: string): Promise; +export { }; diff --git a/src/code/skin.d.ts b/src/code/skin.d.ts new file mode 100644 index 000000000..aea4270eb --- /dev/null +++ b/src/code/skin.d.ts @@ -0,0 +1,3 @@ +export declare function initSkin(): void; +export declare function changeSkin(names: any): boolean; +export declare function addToColorList(color: any): void; diff --git a/src/code/sortable.d.ts b/src/code/sortable.d.ts new file mode 100644 index 000000000..d51f3ea87 --- /dev/null +++ b/src/code/sortable.d.ts @@ -0,0 +1,41 @@ +interface SortableItem { + obj: T; + row: HTMLTableRowElement; + index: number; + values: unknown[]; + sortValues: unknown[]; +} +export interface SortableField { + name: string; + className?: string; + value: (thing: T) => unknown; + sortValue?: (value: unknown, thing: T) => unknown; + sort?: (a: unknown, b: unknown, aobj?: T, bobj?: T) => number; + format?: (cell: HTMLTableCellElement, value: unknown, thing?: T) => void; + smallScreenHide?: boolean; +} +export default class Sortable { + _items: Array>; + _fields: Array>; + _sortBy: number; + _sortAsc: boolean; + _table: HTMLTableElement; + _head: HTMLTableSectionElement; + _body: HTMLTableSectionElement; + _smallScreen: boolean; + _done: Promise | boolean; + constructor(); + get sortBy(): number; + set sortBy(property: number); + get sortAsc(): boolean; + set sortAsc(b: boolean); + get table(): HTMLTableElement; + get items(): T[]; + set items(incoming: T[]); + get fields(): SortableField[]; + set fields(value: SortableField[]); + get done(): boolean | Promise; + renderHead(): void; + sort(): void; +} +export {}; diff --git a/src/code/static.d.ts b/src/code/static.d.ts new file mode 100644 index 000000000..683a3dd8d --- /dev/null +++ b/src/code/static.d.ts @@ -0,0 +1,3 @@ +declare const statics: any; +export declare const constants: any; +export default statics; diff --git a/src/code/toolbox.d.ts b/src/code/toolbox.d.ts new file mode 100644 index 000000000..1a0053459 --- /dev/null +++ b/src/code/toolbox.d.ts @@ -0,0 +1 @@ +export declare function setupToolbox(): void; diff --git a/src/code/ui/agent.d.ts b/src/code/ui/agent.d.ts new file mode 100644 index 000000000..40d8b0f32 --- /dev/null +++ b/src/code/ui/agent.d.ts @@ -0,0 +1,25 @@ +import WasabeeAgent from "../model/agent"; + +declare function formatDisplay( + agent: WasabeeAgent, + teamID?: number | string +): HTMLAnchorElement; +declare function timeSinceformat(agent: WasabeeAgent): string; + +interface WLAgentOptions extends L.MarkerOptions { + agent: WasabeeAgent; + id: string; + zoom: number; +} +declare class WLAgent extends L.Marker { + options: WLAgentOptions; + constructor(agent: WasabeeAgent); + update(): this; + _getPopup(): HTMLDivElement; +} +declare const _default: { + formatDisplay: typeof formatDisplay; + timeSinceformat: typeof timeSinceformat; + WLAgent: typeof WLAgent; +}; +export default _default; diff --git a/src/code/ui/anchor.d.ts b/src/code/ui/anchor.d.ts new file mode 100644 index 000000000..246d0391e --- /dev/null +++ b/src/code/ui/anchor.d.ts @@ -0,0 +1,14 @@ +import type WasabeeOp from "../model/operation"; +import PortalUI from "./portal"; + +declare class WLAnchor extends PortalUI.WLPortal { + constructor(portalId: string, operation: WasabeeOp); + _popupContent(): any; + _linksButton(container: any): void; + _swapButton(container: any): void; + _deleteAction(): void; +} +declare const _default: { + WLAnchor: typeof WLAnchor; +}; +export default _default; diff --git a/src/code/ui/link.d.ts b/src/code/ui/link.d.ts new file mode 100644 index 000000000..b866e9184 --- /dev/null +++ b/src/code/ui/link.d.ts @@ -0,0 +1,22 @@ +import type WasabeeOp from "../model/operation"; +import type WasabeeLink from "../model/link"; +declare function displayFormat( + link: WasabeeLink, + operation: WasabeeOp, + smallScreen?: boolean +): HTMLDivElement; +declare function minLevel( + link: WasabeeLink, + operation: WasabeeOp +): HTMLSpanElement; +declare class WLLink extends L.GeodesicPolyline { + _wlink: WasabeeLink; + constructor(link: WasabeeLink, operation: WasabeeOp); + _getPopup(): HTMLDivElement; +} +declare const _default: { + displayFormat: typeof displayFormat; + minLevel: typeof minLevel; + WLLink: typeof WLLink; +}; +export default _default; diff --git a/src/code/ui/marker.d.ts b/src/code/ui/marker.d.ts new file mode 100644 index 000000000..51fee7a00 --- /dev/null +++ b/src/code/ui/marker.d.ts @@ -0,0 +1,18 @@ +import PortalUI from "./portal"; +import type WasabeeMarker from "../model/marker"; +declare class WLMarker extends PortalUI.WLPortal { + state: string; + constructor(marker: WasabeeMarker); + setState(state: string): void; + _popupContent(): any; + _popupMarkerComment(container: any, marker: any, canWrite: any): void; + _popupAssignState(container: any, marker: any): Promise; + _stateButton(container: any, marker: any): void; + _deleteAction(): void; + _setComment(ev: any): void; + _setMarkerType(ev: any): void; +} +declare const _default: { + WLMarker: typeof WLMarker; +}; +export default _default; diff --git a/src/code/ui/portal.d.ts b/src/code/ui/portal.d.ts new file mode 100644 index 000000000..14f5530f2 --- /dev/null +++ b/src/code/ui/portal.d.ts @@ -0,0 +1,40 @@ +import WasabeePortal from "../model/portal"; +import { IITC } from "../../types/iitc"; + +declare function fromIITC(p: IITC.Portal): WasabeePortal; +declare function team(portal: any): string; +declare function displayName(portal: any): any; +declare function displayFormat( + portal: any, + shortName?: boolean +): HTMLAnchorElement; +declare function get(id: any): WasabeePortal; +declare function getSelected(): WasabeePortal; +interface WLPortalOptions extends L.MarkerOptions { + portalId: string; + title?: string; + id: string; +} +declare class WLPortal extends L.Marker { + type: string; + options: WLPortalOptions; + constructor(options: WLPortalOptions); + _popupContent(): HTMLDivElement; + _popupPortalComments(container: any, portal: any, canWrite: any): void; + _setPortalComment(ev: any): void; + _assignButton(container: any, text: any, target: any): void; + _deleteAction(): void; + _deleteButton(container: any, text: any): void; + _sendTargetButton(container: any, text: any, target: any): void; + _mapButton(container: any, text: any): void; +} +declare const _default: { + fromIITC: typeof fromIITC; + displayName: typeof displayName; + displayFormat: typeof displayFormat; + get: typeof get; + getSelected: typeof getSelected; + team: typeof team; + WLPortal: typeof WLPortal; +}; +export default _default; diff --git a/src/code/ui/zone.d.ts b/src/code/ui/zone.d.ts new file mode 100644 index 000000000..124d69c35 --- /dev/null +++ b/src/code/ui/zone.d.ts @@ -0,0 +1,8 @@ +import type WasabeeZone from "../model/zone"; +declare class WLZone extends L.LayerGroup { + constructor(zone: WasabeeZone); +} +declare const _default: { + WLZone: typeof WLZone; +}; +export default _default; diff --git a/src/code/uiCommands.d.ts b/src/code/uiCommands.d.ts new file mode 100644 index 000000000..b62d1ae10 --- /dev/null +++ b/src/code/uiCommands.d.ts @@ -0,0 +1,25 @@ +export declare function addPortal(operation: any, portal: any): void; +export declare function swapPortal(operation: any, portal: any): void; +export declare function deletePortal(operation: any, portal: any): void; +export declare function deleteMarker(operation: any, marker: any, portal: any): void; +export declare function clearAllItems(operation: any): void; +export declare function clearAllLinks(operation: any): void; +export declare function clearAllMarkers(operation: any): void; +export declare function listenForAddedPortals(newPortal: any): void; +export declare function listenForPortalDetails(e: any): void; +export declare function getPortalDetails(guid: any): void; +export declare function loadFaked(operation: any, force?: boolean): void; +export declare function loadBlockerFaked(operation: any, force?: boolean): Promise; +export declare function sendLocation(): void; +export declare function getAllPortalsOnScreen(operation: any): any[]; +export declare function getAllPortalsLinked(operation: any, originPortal: any): any[]; +export declare function testPortal(recursed?: boolean): any; +export declare function blockerAutomark(operation: any, first?: boolean): Promise; +export declare function zoomToOperation(operation: any): void; +export declare function updateLocalOp(local: any, remote: any): Promise; +export declare function fullSync(): Promise; +export declare function syncOp(opID: any): Promise; +export declare function deleteLocalOp(opname: any, opid: any): void; +export declare function resetCaches(): Promise; +export declare function setMarkersToZones(): void; +export declare function setLinksToZones(): void; diff --git a/src/code/wX.d.ts b/src/code/wX.d.ts new file mode 100644 index 000000000..49bf52ccf --- /dev/null +++ b/src/code/wX.d.ts @@ -0,0 +1,3 @@ +export declare function wX(key: string, data?: object): any; +export declare function getLanguage(): any; +export default wX; diff --git a/src/code/wd.d.ts b/src/code/wd.d.ts new file mode 100644 index 000000000..6e961e1ee --- /dev/null +++ b/src/code/wd.d.ts @@ -0,0 +1,15 @@ +export declare type WDKey = { + Name: string; + PortalID: string; + GID: string; + Lat: string; + Lng: string; + Count: number; + CapID: string; +}; +export declare function initWasabeeD(): void; +export declare function getAllWasabeeDkeys(): Promise; +export declare function getAgentWasabeeDkeys(gid: string): Promise; +export declare function getAllPortalWasabeeDkeys(portalid: string): Promise; +export declare function getAgentPortalWasabeeDkeys(gid: string, portalid: string): Promise; +export declare function drawWasabeeDkeys(): Promise; diff --git a/src/types/iitc/LICENSE b/src/types/iitc/LICENSE new file mode 100755 index 000000000..9e841e7a2 --- /dev/null +++ b/src/types/iitc/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/src/types/iitc/README.md b/src/types/iitc/README.md new file mode 100755 index 000000000..b54336725 --- /dev/null +++ b/src/types/iitc/README.md @@ -0,0 +1,21 @@ +# Installation + +> `npm install --save @types/iitc` + +# Summary + +This package contains type definitions for IITC (Ingress Intel Total Conversation) (https://github.com/IITC-CE/ingress-intel-total-conversion). + +# Details + +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/iitc. + +### Additional Details + +- Last updated: Tue, 07 Sep 2021 07:31:40 GMT +- Dependencies: [@types/leaflet](https://npmjs.com/package/@types/leaflet), [@types/spectrum](https://npmjs.com/package/@types/spectrum), [@types/jquery](https://npmjs.com/package/@types/jquery), [@types/jqueryui](https://npmjs.com/package/@types/jqueryui) +- Global values: none + +# Credits + +These definitions were written by [McBen](https://github.com/McBen). diff --git a/src/types/iitc/core/android.d.ts b/src/types/iitc/core/android.d.ts new file mode 100755 index 000000000..cd471b666 --- /dev/null +++ b/src/types/iitc/core/android.d.ts @@ -0,0 +1,57 @@ +export {}; + +declare global { + class Android { + saveFile(filename: string, mime: string, content: string): void; + + // open dialog to send geo intent for navigation apps like gmaps or waze etc... + intentPosLink( + lat: number, + lng: number, + zoom: number, + title: string, + isPortal: boolean + ): void; + + // share a string to the IITC share activity. only uses the share tab. + shareString(text: string): void; + + // disable javascript injection while spinner is enabled prevent the spinner from closing automatically + spinnerEnabled(enable: boolean): void; + + copy(text: string): void; + + getVersionCode(): number; + getVersionName(): string; + + addPane( + id: string, + label: string, + icon?: string /*= "ic_action_new_event"*/ + ): void; + switchToPane(id: string): void; + + dialogFocused(id: string): void; + dialogOpened(id: string, open: boolean): void; + + setLayers(base_layer: string, overlay_layer: string): void; + + addPortalHighlighter(name: string): void; + setActiveHighlighter(name: string): void; + + // IITC-Version check plugin + updateIitc(fileUrl: string): void; + + showZoom(): boolean; + setFollowMode(follow: boolean): void; + + setProgress(progress: number): void; + + getFileRequestUrlPrefix(): string; + setPermalink(href: string): void; + + reloadIITC(clearCache?: boolean /*= false*/): void; + } + + var android: Android; +} diff --git a/src/types/iitc/core/artifact.d.ts b/src/types/iitc/core/artifact.d.ts new file mode 100755 index 000000000..a3e9ceb00 --- /dev/null +++ b/src/types/iitc/core/artifact.d.ts @@ -0,0 +1,44 @@ +import * as L from "leaflet"; + +export {}; + +declare global { + class Artifact { + // private _layer: L.LayerGroup; + REFRESH_JITTER: number; // 2 minute random period so not all users refresh at once + REFRESH_SUCCESS: number; // 60 minutes on success + REFRESH_FAILURE: number; // 2 minute retry on failure + portalInfo: {}; + artifactTypes: { [type: string]: any }; + entities: []; + + setup(): void; + requestData(): void; + idleResume(): void; + // private handleSuccess(data): void; + // private handleFailure(data): void; + // private processData(data): void; + // private processResult(portals): void; + clearData(): void; + + getArtifactTypes(): string[]; + isArtifact(type: string): boolean; + + /** used to render portals that would otherwise be below the visible level */ + getArtifactEntities(): []; + getInterestingPortals(): string[]; + + /** quick test for portal being relevant to artifacts - of any type */ + isInterestingPortal(guid: string): boolean; + + /** get the artifact data for a specified artifact id (e.g. 'jarvis'), if it exists - otherwise returns something 'false' */ + getPortalData(guid: string, artifactId: any): any; + + updateLayer(): void; + + /** show artifact dialog */ + showArtifactList(): void; + } + + var artifact: Artifact; +} diff --git a/src/types/iitc/core/boot.d.ts b/src/types/iitc/core/boot.d.ts new file mode 100755 index 000000000..d643d0dae --- /dev/null +++ b/src/types/iitc/core/boot.d.ts @@ -0,0 +1,46 @@ +export {}; + +declare global { + function setupLargeImagePreview(): void; + + /** + * adds listeners to the layer chooser such that a long press hides + * all custom layers except the long pressed one. + */ + function setupLayerChooserSelectOne(): void; + + /** Setup the function to record the on/off status of overlay layerGroups */ + function setupLayerChooserStatusRecorder(): void; + + function setupStyles(): void; + function setupIcons(): void; + function createDefaultBaseMapLayers(): void; + function setupMap(): void; + + /** adds a base layer to the map. done separately from the above, so that plugins that add base layers can be the default */ + function setMapBaseLayer(): void; + + /** + * renders player details into the website. Since the player info is + * included as inline script in the original site, the data is static + * and cannot be updated. + */ + function setupPlayerStat(): void; + + function setupSidebarToggle(): void; + function setupTooltips(): void; + function setupLayerChooserApi(): void; + function extendLeaflet(): void; + + // BOOTING /////////////////////////////////////////////////////////// + function prepPluginsToLoad(): void; + function boot(): void; + + /** + * OMS doesn't cancel the original click event, so the topmost marker will get a click event while spiderfying. + * Also, OMS only supports a global callback for all managed markers. Therefore, we will use a custom event that gets fired + * for each marker. + */ + function setupOMS(): void; + function registerMarkerForOMS(marker: L.Marker): void; +} diff --git a/src/types/iitc/core/chat.d.ts b/src/types/iitc/core/chat.d.ts new file mode 100755 index 000000000..e6e96c987 --- /dev/null +++ b/src/types/iitc/core/chat.d.ts @@ -0,0 +1,138 @@ +import { Intel } from "./inteltypes"; + +export {}; + +declare global { + type ChatChannels = "all" | "faction" | "alerts"; + + class Chat { + /** @return name of active tab */ + getActive(): string; + + /** Expand or collapse chat window */ + toggle(): void; + + handleTabCompletion(): void; + + genPostData( + channel: ChatChannels, + storageHash: chatStorage, + getOlderMsgs: boolean + ): any; + + // faction + _faction: chatStorage; + _requestFactionRunning: boolean; + requestFaction(getOlderMsgs: boolean, isRetry: boolean): void; + handleFaction(data: any, olderMsgs: boolean): void; + renderFaction(oldMsgsWereAdded: boolean): void; + + // all + _public: chatStorage; + _requestPublicRunning: boolean; + requestPublic(getOlderMsgs: boolean, isRetry: boolean): void; + handlePublic(data: any, olderMsgs: boolean): void; + renderPublic(oldMsgsWereAdded: boolean): void; + + // alerts + _alerts: chatStorage; + _requestAlertsRunning: boolean; + requestAlerts(getOlderMsgs: boolean, isRetry: boolean): void; + handleAlerts(data: any, olderMsgs: boolean): void; + renderAlerts(oldMsgsWereAdded: boolean): void; + + /** if user clicked a agent name */ + nicknameClicked(event: MouseEvent, nickname: string): void; + + /** store incoming data */ + writeDataToHash( + newData: any, + storageHash: chatStorage, + isPublicChannel: boolean, + isOlderMsgs: boolean + ): void; + + /** Override portal names that are used over and over, such as 'US Post Office' */ + getChatPortalName(markup: Intel.MarkUpPortalType): string; + + /** + * renders data from the data-hash to the element defined by the given + * ID. Set 3rd argument to true if it is likely that old data has been + * added. Latter is only required for scrolling. + */ + renderData( + data: any, + element: "chatfaction" | "chatall" | "chatalerts", + likelyWereOldMsgs: boolean + ): void; + + renderDivider(text: string): string; + + renderMsg( + msg: string, + nick: string, + time: number, + team: 0 | 1 | 2, + msgToPlayer: boolean, + systemNarrowcast: boolean + ): string; + + /** add nickname to chat-input line */ + addNickname(nick: string): void; + + tabToChannel(tab: ChatChannels | string): ChatChannels; + + /** + * called by plugins (or other things?) that need to monitor COMM data streams when the user is not viewing them + * instance: a unique string identifying the plugin requesting background COMM + * channel: either 'all', 'faction' or (soon) 'alerts' - others possible in the future + * flag: true for data wanted, false for not wanted + */ + backgroundChannelData( + instance: string, + channel: ChatChannels, + flag: boolean + ): void; + + backgroundInstanceChannel: {}; // [instance][channel] = flag; + + request(): void; + + /** + * checks if there are enough messages in the selected chat tab and + * loads more if not. + */ + needMoreMessages(): void; + + /** activate a chat tab */ + show(tab: ChatChannels): void; + + chooseTab(tab: ChatChannels): void; + + /** mouse event handler */ + chooser(event: MouseEvent): void; + + /** contains the logic to keep the correct scroll position. */ + keepScrollPosition( + box: JQuery, + scrollBefore: number, + isOldMsgs: boolean + ): void; + + /** init */ + setup(): void; + setupTime(): void; + setupPosting(): void; + + /** send current message of current chat to server */ + postMsg(): void; + } + + interface chatStorage { + data: {}; + oldestTimestamp: number; + newestTimestamp: number; + } + + var chat: Chat; +} diff --git a/src/types/iitc/core/constants.d.ts b/src/types/iitc/core/constants.d.ts new file mode 100755 index 000000000..86be064d6 --- /dev/null +++ b/src/types/iitc/core/constants.d.ts @@ -0,0 +1,115 @@ +import { IITC, PortalGUID } from "./iitctypes"; + +export {}; + +declare global { + const script_info: any; + const iitcBuildDate: string; + + // CONFIG OPTIONS //////////////////////////////////////////////////// + const REFRESH: number; /** @default = 30; // refresh view every 30s (base time) */ + const ZOOM_LEVEL_ADJ: number; /** @default = 5; // add 5 seconds per zoom level */ + const ON_MOVE_REFRESH: number; /** @default = 2.5; //refresh time to use after a movement event */ + const MINIMUM_OVERRIDE_REFRESH: number; /** @default = 10; //limit on refresh time since previous refresh, limiting repeated move refresh rate */ + const REFRESH_GAME_SCORE: number; /** @default = 15 * 60; // refresh game score every 15 minutes */ + const MAX_IDLE_TIME: number; /** @default = 15 * 60; // stop updating map after 15min idling */ + const HIDDEN_SCROLLBAR_ASSUMED_WIDTH: number; /** @default = 20; */ + const SIDEBAR_WIDTH: number; /** @default = 300; */ + + // how many pixels to the top before requesting new data + const CHAT_REQUEST_SCROLL_TOP: number; /** @default = 200; */ + const CHAT_SHRINKED: number; /** @default = 60; */ + + // Minimum area to zoom ratio that field MU's will display + const FIELD_MU_DISPLAY_AREA_ZOOM_RATIO: number; /** @default 0.001; */ + + // Point tolerance for displaying MU's + const FIELD_MU_DISPLAY_POINT_TOLERANCE: number; /** @default = 60 */ + + const COLOR_SELECTED_PORTAL: string; /** @default '#f0f' */ + + /** + * Team colors + * @default ['#FF6600','#0088FF','#03DC03'] + */ + const COLORS: [string, string, string]; + const COLORS_LVL: string[]; /** @default ['#000',...,'#9627F4'] */ + const COLORS_MOD: {}; /** @default {VERY_RARE:'#b08cff',RARE:'#73a8ff',COMMON:'#8cffbf'} */ + + const MOD_TYPE: {}; // { RES_SHIELD: 'Shield', MULTIHACK: 'Multi-hack', FORCE_AMP: 'Force Amp', HEATSINK: 'Heat Sink', TURRET: 'Turret', LINK_AMPLIFIER: 'Link Amp' }; + + // circles around a selected portal that show from where you can hack + // it and how far the portal reaches (i.e. how far links may be made + // from this portal) + const ACCESS_INDICATOR_COLOR: string; // = 'orange'; + const RANGE_INDICATOR_COLOR: string; // = 'red' + + // min zoom for intel map - should match that used by stock intel + const MIN_ZOOM: number; // = 3; + + // used when zoom level is not specified explicitly (must contain all the portals) + const DEFAULT_ZOOM: number; // = 15; + + const DEFAULT_PORTAL_IMG: string; // '//commondatastorage.googleapis.com/ingress.com/img/default-portal-image.png'; + const NOMINATIM: string; // '//nominatim.openstreetmap.org/search?format=json&polygon_geojson=1&q='; + + // INGRESS CONSTANTS ///////////////////////////////////////////////// + // http://decodeingress.me/2012/11/18/ingress-portal-levels-and-link-range/ + const RESO_NRG: number[]; /** @default [0,1000,1500,2000,2500,3000,4000,5000,6000] */ + const HACK_RANGE: number; /** @default 40 in meters, max. distance from portal to be able to access it */ + const OCTANTS: string[]; /** @default ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE'] */ + const OCTANTS_ARROW: string[]; /** @default ['→', '↗', '↑', '↖', '←', '↙', '↓', '↘'] */ + const DESTROY_RESONATOR: number; /** @default 75 AP for destroying portal */ + const DESTROY_LINK: number; /** @default 187 AP for destroying link */ + const DESTROY_FIELD: number; /** @default 750 AP for destroying field */ + const CAPTURE_PORTAL: number; /** @default 500 AP for capturing a portal */ + const DEPLOY_RESONATOR: number; /** @default 125 AP for deploying a resonator */ + const COMPLETION_BONUS: number; /** @default 250; AP for deploying all resonators on portal */ + const UPGRADE_ANOTHERS_RESONATOR: number; /** @default 65; AP for upgrading another's resonator */ + const MAX_PORTAL_LEVEL: number; /** @default 8 */ + const MAX_RESO_PER_PLAYER: number[]; /** @default [0, 8, 4, 4, 4, 2, 2, 1, 1] */ + + // OTHER MORE-OR-LESS CONSTANTS ////////////////////////////////////// + /** Team constants */ + const TEAM_ENL: number; /** @default 2 */ + const TEAM_RES: number; /** @default 1 */ + const TEAM_NONE: number; /** @default 0 */ + + /** Team CSS = ['none', 'res', 'enl'] */ + const TEAM_TO_CSS: [string, string, string]; + + /** ['Neutral', 'Resistance', 'Enlightened'] */ + const TEAM_NAMES: [string, string, string]; + + // STORAGE /////////////////////////////////////////////////////////// + // global constiables used for storage. Most likely READ ONLY. Proper + // way would be to encapsulate them in an anonymous function and write + // getters/setters, but if you are careful enough, this works. + var refreshTimeout: any; // = undefined; + var urlPortal: any; // = null; + var urlPortalLL: any; // = null; + + /** guid of current selected portal */ + var selectedPortal: PortalGUID | null; + + var portalRangeIndicator: any; // = null; + var portalAccessIndicator: any; // = null; + var mapRunsUserAction: any; // = false; + + const portalsFactionLayers: L.LayerGroup; + const linksFactionLayers: L.LayerGroup; + const fieldsFactionLayers: L.LayerGroup; + + /** list of all loaded portals */ + var portals: { [guid: string /* PortalGUID */]: IITC.Portal }; + + /** list of all loaded links */ + var links: { [guid: string /* LinkGUID */]: IITC.Link }; + + /** list of all fields */ + var fields: { [guid: string /* FieldGUID */]: IITC.Field }; + + // contain current status(on/off) of overlay layerGroups. + // But you should use isLayerGroupDisplayed(name) to check the status + var overlayStatus: {}; +} diff --git a/src/types/iitc/core/data_cache.d.ts b/src/types/iitc/core/data_cache.d.ts new file mode 100755 index 000000000..bf74866f2 --- /dev/null +++ b/src/types/iitc/core/data_cache.d.ts @@ -0,0 +1,30 @@ +/** cache for map data tiles. */ +export class DataCache { + /** + * if younger than this, use data in the cache rather than fetching from the server + * @default 180 + */ + REQUEST_CACHE_FRESH_AGE: number; + + /** + * maximum cache age. entries are deleted from the cache after this time + * @default 300 + */ + REQUEST_CACHE_MAX_AGE: number; + + /** if more than this many entries, expire early */ + REQUEST_CACHE_MAX_ITEMS: number; + /** or more than this total size */ + REQUEST_CACHE_MAX_CHARS: number; + + store(key: string, data: any, freshTime?: number): void; + remove(key: string): void; + get(key: string): any; + getTime(key: string): number; + getFresh(key: string): boolean | undefined; + startExpireInterval(periodInSecond: number): void; + stopExpireInterval(): void; + private runExpire(): void; + + debug(): string; +} diff --git a/src/types/iitc/core/dialog.d.ts b/src/types/iitc/core/dialog.d.ts new file mode 100755 index 000000000..0a4993b0b --- /dev/null +++ b/src/types/iitc/core/dialog.d.ts @@ -0,0 +1,105 @@ +import "jqueryui"; + +declare global { + /** The global ID of onscreen dialogs. */ + var DIALOG_ID: number; + + /** All onscreen dialogs, keyed by their ID. */ + var DIALOGS: {}; + + /** The number of dialogs on screen. */ + var DIALOG_COUNT: number; + + /** The dialog that has focus. */ + var DIALOG_FOCUS: any; + + /** + * Controls how quickly the slide toggle animation + * should play for dialog collapsing and expanding. + * @default 100 + */ + var DIALOG_SLIDE_DURATION: number; + + /** Create and show dialog */ + function dialog(data: DialogOptions): JQuery; + + // see https://jqueryui.com/dialog/ + interface DialogOptions { + /** If set only one dialog can be open */ + id?: string | undefined; + + /** Dialog title */ + title?: string | undefined; + + /** + * Dialog contents - converted by convertTextToTableMagic + * \n will be line breaks \t will be table fields + */ + text?: string | undefined; + + /** Dialog contents (if no text) */ + html?: string | HTMLElement | JQuery | undefined; + + dialogClass?: string | undefined; + classes?: any; + + /** + * single dialog + * default: false + */ + modal?: boolean | undefined; + + /** + * moveable dialog + * default: true + */ + draggable?: boolean | undefined; + + /** + * resizeable dialog (won't work in iitc out-of-the-box) + * default: false + */ + resizable?: boolean | undefined; + + /** position, see: https://api.jqueryui.com/position/ */ + position?: any; + + /** size */ + height?: string | number | undefined; + width?: string | number | undefined; + maxHeight?: string | undefined; + maxWidth?: string | undefined; + minHeight?: string | undefined; + minWidth?: string | undefined; + + autoOpen?: boolean | undefined; + closeOnEscape?: boolean | undefined; + hide?: any; + appendTo?: any; + + /** Specifies the text for the close button */ + closeText?: string | undefined; + + closeCallback?: any; + collapseCallback?: any; + expandCallback?: any; + collapseExpandCallback?: any; + focusCallback?: any; + blurCallback?: any; + + buttons?: + | JQueryUI.ButtonOptions[] + | { [key: string]: () => void } + | undefined; + } + + /** custom alert box */ + function alert( + text: string | HTMLElement, + isHTML?: boolean, + closeCallback?: any + ): JQuery; + + /** init */ + function setupDialogs(): void; +} diff --git a/src/types/iitc/core/entity_decode.d.ts b/src/types/iitc/core/entity_decode.d.ts new file mode 100755 index 000000000..9873be997 --- /dev/null +++ b/src/types/iitc/core/entity_decode.d.ts @@ -0,0 +1,25 @@ +import { IITC } from "./iitctypes"; + +export {}; + +declare global { + /** + * decode the on-network array entity format into an object format closer to that used before + * makes much more sense as an object, means that existing code didn't need to change, and it's what the + * stock intel site does internally too (the array format is only on the network) + */ + class DecodeArray { + portalSummary( + data: any[] + ): IITC.PortalData | IITC.PortalDataCore | undefined; + portalDetail(data: any[]): IITC.PortalDataDetail | undefined; + } + + // private but exposed: + // function parseMod(arr: null | any[]): IITC.Mod | null; + // function parseResonator(arr: null | any[]): IITC.Resonator | null; + // function parseArtifactBrief(arr: null | any[]): { fragment: any, target: any }; + // function parseArtifactDetail(arr: null | any[]): IITC.ArtifactDetail | null; + + var decodeArray: DecodeArray; +} diff --git a/src/types/iitc/core/entity_info.d.ts b/src/types/iitc/core/entity_info.d.ts new file mode 100755 index 000000000..5ee1681ac --- /dev/null +++ b/src/types/iitc/core/entity_info.d.ts @@ -0,0 +1,9 @@ +import { IITC } from "./iitctypes"; + +declare global { + /** + * given the entity detail data, returns the team the entity belongs to. Uses TEAM_* enum values. + */ + function getTeam(details: IITC.PortalData): 0 | 1 | 2; + function teamStringToId(teamStr: string): 0 | 1 | 2; +} diff --git a/src/types/iitc/core/extract_niantic_parameters.d.ts b/src/types/iitc/core/extract_niantic_parameters.d.ts new file mode 100755 index 000000000..586044e78 --- /dev/null +++ b/src/types/iitc/core/extract_niantic_parameters.d.ts @@ -0,0 +1,10 @@ +export {}; + +declare global { + /** + * as of 2014-08-14, Niantic have returned to minifying the javascript. This means we no longer get the nemesis object + * and it's various member objects, functions, etc. + * so we need to extract some essential parameters from the code for IITC to use + */ + function extractFromStock(): void; +} diff --git a/src/types/iitc/core/game_status.d.ts b/src/types/iitc/core/game_status.d.ts new file mode 100755 index 000000000..644e7a6ff --- /dev/null +++ b/src/types/iitc/core/game_status.d.ts @@ -0,0 +1,6 @@ +export {}; + +declare global { + /** MindUnit display */ + function updateGameScore(data?: JQuery.jqXHR): void; +} diff --git a/src/types/iitc/core/hooks.d.ts b/src/types/iitc/core/hooks.d.ts new file mode 100755 index 000000000..cb483b2c1 --- /dev/null +++ b/src/types/iitc/core/hooks.d.ts @@ -0,0 +1,279 @@ +import { IITC } from "./iitctypes"; +import { Intel } from "./inteltypes"; + +declare global { + /** + * register a callback for an event + * called when portal on map is selected/unselected + */ + function addHook( + event: "portalSelected", + callback: (e: EventPortalSelected) => void + ): void; + + /** + * register a callback for an event + * this hook runs after data for any of the public chats has been received and processed, but not + * yet been displayed. The data hash contains both the unprocessed raw ajax response as well as the processed + * chat data that is going to be used for display. + */ + function addHook( + event: "publicChatDataAvailable", + callback: (e: EventPublicChatDataAvailable) => void + ): void; + + /** + * register a callback for an event + * this hook runs after data for the faction chat has been received and processed, but not yet been + * displayed. The data hash contains both the unprocessed raw ajax response as well as the processed chat data + * that is going to be used for display. + */ + function addHook( + event: "factionChatDataAvailable", + callback: (e: EventFactionChatDataAvailable) => void + ): void; + + /** + * register a callback for an event + * fired after the details in the sidebar have been (re-)rendered Provides data about the portal + * that has been selected. + */ + function addHook( + event: "portalDetailsUpdated", + callback: (e: EventPortalDetailsUpdated) => void + ): void; + + /** + * register a callback for an event + * called when the set of artifacts (including targets) has changed. + */ + function addHook( + event: "artifactsUpdated", + callback: (e: EventArtifactsUpdated) => void + ): void; + + /** + * register a callback for an event + * called when we start refreshing map data + */ + function addHook( + event: "mapDataRefreshStart", + callback: (e: EventMapDataRefreshStart) => void + ): void; + + /** + * register a callback for an event + * called just as we start to render data. has callback to inject cached entities into the map render + */ + function addHook( + event: "mapDataEntityInject", + callback: (e: EventMapDataEntityInject) => void + ): void; + + /** + * register a callback for an event + * called when we complete the map data load + */ + function addHook( + event: "mapDataRefreshEnd", + callback: (e: EventMapDataRefreshEnd) => void + ): void; + + /** + * register a callback for an event + * called when a portal has been received and is about to be added to its layer group. + * Note that this does NOT mean it is already visible or will be, shortly after. + * If a portal is added to a hidden layer it may never be shown at all. + */ + function addHook( + event: "portalAdded", + callback: (e: EventPortalAdded) => void + ): void; + + /** + * register a callback for an event + * called when a link is about to be added to the map + */ + function addHook( + event: "linkAdded", + callback: (e: EventLinkAdded) => void + ): void; + + /** + * register a callback for an event + * called when a field is about to be added to the map + */ + function addHook( + event: "fieldAdded", + callback: (e: EventFieldAdded) => void + ): void; + + /** + * register a callback for an event + * called when a portal has been removed + */ + function addHook( + event: "portalRemoved", + callback: (e: EventPortalRemoved) => void + ): void; + + /** + * register a callback for an event + * called when a link has been removed + */ + function addHook( + event: "linkRemoved", + callback: (e: EventLinkRemoved) => void + ): void; + + /** + * register a callback for an event + * called when a field has been removed + */ + function addHook( + event: "fieldRemoved", + callback: (e: EventFieldRemoved) => void + ): void; + + /** + * register a callback for an event + * called after each map data request finished. + */ + function addHook( + event: "requestFinished", + callback: (e: EventRequestFinished) => void + ): void; + function addHook( + event: "nicknameClicked", + callback: (e: EventNicknameClicked) => boolean + ): void; + function addHook(event: "search", callback: (e: EventSearch) => void): void; + + /** + * register a callback for an event + * called after IITC and all plugins loaded + * NOTE: if iitc is already loaded this event never happens. Check the @see iitcLoaded flag + */ + function addHook(event: "iitcLoaded", callback: () => void): void; + + /** + * register a callback for an event + * alled when a request to load full portal detail completes. + */ + function addHook( + event: "portalDetailLoaded", + callback: (e: EventPortalDetailLoaded) => void + ): void; + + /** + * register a callback for an event + * called when the current pane has changed. On desktop, this only selects the current chat pane; on mobile, it + * also switches between map, info and other panes defined by plugins + */ + function addHook( + event: "paneChanged", + callback: (e: EventPaneChanged) => void + ): void; + + /** + * register a callback for an event + * (user defined hooks) + */ + function addHook(event: string, callback: HookCallback): void; + + /** remove a registered a callback */ + function removeHook(event: string, callback: HookCallback): void; + + /** trigger event */ + function runHooks(event: string, data: any): boolean; + + /** register a custom event */ + function pluginCreateHook(event: string): void; + + /** private hook table */ + var _hooks: { [event: string]: HookCallback[] }; + + type HookCallback = (data: any) => boolean | void; + + interface EventPortalSelected { + selectedPortalGuid: string; + unselectedPortalGuid: string; + } + interface EventPublicChatDataAvailable { + raw: any; + result: Intel.ChatLine[]; + processed: any; + } + interface EventFactionChatDataAvailable { + raw: any; + result: Intel.ChatLine[]; + processed: any; + } + interface EventPortalDetailsUpdated { + guid: string; + portal: IITC.Portal; + portalDetails: any /* class portalDetail */; + portalData: IITC.PortalData; + } + interface EventArtifactsUpdated { + old: any; + new: any; + } + interface EventMapDataRefreshStart { + bounds: L.LatLngBounds; + mapZoom: number; + dataZoom: number; + minPortalLevel: number; + tileBounds: L.LatLngBounds; + } + interface EventMapDataEntityInject { + callback: (ents: any) => void; + } // TODO: ents = portalDetailLoaded.ent + // tslint:disable-next-line:no-empty-interface + interface EventMapDataRefreshEnd {} + interface EventPortalAdded { + portal: IITC.Portal; + previousData: IITC.PortalData; + } + interface EventLinkAdded { + link: IITC.Link; + } + interface EventFieldAdded { + field: IITC.Field; + } + interface EventPortalRemoved { + portal: IITC.Portal; + data: IITC.PortalData; + } + interface EventLinkRemoved { + link: IITC.Link; + data: IITC.LinkData; + } + interface EventFieldRemoved { + field: IITC.Field; + data: IITC.FieldData; + } + interface EventRequestFinished { + success: boolean; + } + interface EventNicknameClicked { + event: MouseEvent; + nickname: string; + } + type EventSearch = any; /* class search.Query */ + type EventPaneChanged = string; + + type PortalDetailEnt = [ + /*guid*/ string, + /*dict.timestamp*/ number, + /*data.result*/ Intel.PortalDetails + ]; + type EventPortalDetailLoaded = + | { + guid: string; + success: true; + details: IITC.PortalDataDetail; + ent: PortalDetailEnt; + } + | { guid: string; success: false; details: never; ent: never }; +} diff --git a/src/types/iitc/core/idle.d.ts b/src/types/iitc/core/idle.d.ts new file mode 100755 index 000000000..c24a4932b --- /dev/null +++ b/src/types/iitc/core/idle.d.ts @@ -0,0 +1,20 @@ +export {}; + +declare global { + var idleTime: number; // in seconds + + /** default MAX_IDLE_TIME */ + var _idleTimeLimit: number; + var IDLE_POLL_TIME: number; + + function idlePoll(): void; + function idleReset(): void; + function idleSet(): void; + function setupIdle(): void; + + /** + * add your function here if you want to be notified when the user + * resumes from being idle + */ + function addResumeFunction(fct: () => void): void; +} diff --git a/src/types/iitc/core/iitctypes.d.ts b/src/types/iitc/core/iitctypes.d.ts new file mode 100755 index 000000000..1e8bdc2e3 --- /dev/null +++ b/src/types/iitc/core/iitctypes.d.ts @@ -0,0 +1,148 @@ +import * as L from "leaflet"; +import "leafletExtension"; +import * as jQuery from "jquery"; + +export type PortalGUID = string; +export type LinkGUID = string; +export type FieldGUID = string; + +export namespace IITC { + /** Portal-Marker */ + class Portal extends L.CircleMarker { + options: PortalOptions; + } + + interface PortalOptions extends L.PathOptions { + guid: PortalGUID; + ent: any; + level: number; + team: number; + timestamp: number; + data: PortalDataDetail; + } + + interface PortalDataCore { + team: string; + latE6: number; + lngE6: number; + } + + interface PortalData extends PortalDataCore { + artifactBrief: { fragment: any; target: any } | null; + health: number; + image: string; // url + level: number; + mission: boolean; + mission50plus: boolean; + ornaments: string[]; + resCount: number; + timestamp: number; + title: string; + } + + interface PortalDataDetail extends PortalData { + artifactDetail: ArtifactDetail; + mods: [Mod | null, Mod | null, Mod | null, Mod | null]; + owner: string; + resonators: Resonator[]; + history: PortalHistory; + } + + interface PortalHistory { + _raw: number; + visited: boolean; + captured: boolean; + scoutControlled: boolean; + } + + interface Mod { + owner: string; + name: string; + rarity: ModRarity; + stats: { [k: string /*ModStats*/]: string }; + } + type ModStats = + | "REMOVAL_STICKNESS" /* all */ + /* Shield */ + | "MIGRATION" + /* Turret */ + | "ATTACK_FREQUENCY" + | "HIT_BONUS" + /* Forceamp */ + | "FORCE_AMPLIFIER" + /* ito- */ + | "XM_SPIN" + /* Multihack */ + | "BURNOUT_INSULATION" + /* Heat sink */ + | "HACK_SPEED" + /* Linkamp */ + | "LINK_RANGE_MULTIPLIER" + /* sbul */ + | "LINK_DEFENSE_BOOST" + | string; /* dummy for future stuff */ + type ModRarity = "COMMON" | "RARE" | "VERY_RARE"; + + type ModType = + | "RES_SHIELD" + | "MULTIHACK" + | "FORCE_AMP" + | "HEATSINK" + | "TURRET" + | "LINK_AMPLIFIER"; + + interface Resonator { + energy: number; + level: number; + owner: string; + } + + interface ArtifactDetail { + type: string; + displayName: string; + fragments: any[]; + } + + /** Link-Marker */ + class Link extends L.GeodesicPolyline { + options: LinkOptions; + } + + interface LinkOptions extends L.PathOptions { + team: number; + guid: string; + timestamp: number; + data: LinkData; + } + + interface LinkData { + dGuid: string; + dLatE6: number; + dLngE6: number; + oGuid: string; + oLatE6: number; + oLngE6: number; + team: string; + } + + /** Field-Polygon */ + class Field extends L.GeodesicPolygon { + options: FieldOptions; + } + + interface FieldOptions extends L.PathOptions { + team: number; + guid: string; + timestamp: number; + data: FieldData; + } + + interface FieldData { + team: string; + points: Array<{ + guid: string; + latE6: number; + lngE6: number; + }>; + } +} diff --git a/src/types/iitc/core/inteltypes.d.ts b/src/types/iitc/core/inteltypes.d.ts new file mode 100755 index 000000000..0619db71e --- /dev/null +++ b/src/types/iitc/core/inteltypes.d.ts @@ -0,0 +1,58 @@ +export namespace Intel { + // PLAYER + interface PlayerInfo { + nickname: string; + team: string; + ap: string; + available_invites: number; + energy: number; + level: number; + min_ap_for_current_level: string; + min_ap_for_next_level: string; + nickMatcher: RegExp; + verified_level: number; + xm_capacity: string; + } + + // ENTITY + type PortalDetails = []; + type FieldDetails = []; + type LinkDetails = []; + + // CHAT + interface ChatCallback { + result: ChatLine[]; + } + + type ChatLine = [/*guid*/ string, /*time*/ number, PlextContainer]; + + interface PlextContainer { + plext: { + plextType: "SYSTEM_BROADCAST" | "SYSTEM_NARROWCAST" | "PLAYER_GENERATED"; + markup: Array; + team: "RESISTANCE" | "ENLIGHTENED"; + text: string; + }; + } + + type MarkUpPlayer = ["PLAYER", MarkUpPlayerType]; + interface MarkUpPlayerType { + team: string; + plain: string; + } + + type MarkUpText = ["TEXT", MarkUpTextType]; + interface MarkUpTextType { + plain: string; + } + + type MarkUpPortal = ["PORTAL", MarkUpPortalType]; + interface MarkUpPortalType { + latE6: number; + lngE6: number; + team: string; + plain: string; + name: string; + address: string; + } +} diff --git a/src/types/iitc/core/location.d.ts b/src/types/iitc/core/location.d.ts new file mode 100755 index 000000000..14dc3088c --- /dev/null +++ b/src/types/iitc/core/location.d.ts @@ -0,0 +1,13 @@ +export {}; + +declare global { + /** retrieves current position from map and stores it cookies */ + function storeMapPosition(): void; + + /** + * either retrieves the last shown position from a cookie, from the + * URL or if neither is present, via Geolocation. If that fails, it + * returns a map that shows the whole world. + */ + function getPosition(): void; +} diff --git a/src/types/iitc/core/main.d.ts b/src/types/iitc/core/main.d.ts new file mode 100755 index 000000000..49a1db7da --- /dev/null +++ b/src/types/iitc/core/main.d.ts @@ -0,0 +1,87 @@ +import { FieldGUID, IITC, LinkGUID, PortalGUID } from "./iitctypes"; +import * as jQuery from "jquery"; +import { Intel } from "./inteltypes"; +import { MapDataRequest } from "./map_data_request"; + +declare global { + /** All iitc Pluigns */ + var plugin: any; + + /** iitc-Pluigns setup/initialize function */ + var bootPlugins: BootCallback[]; + type BootCallback = () => void; + + /** if true iitc main script was already loaded (plugin need to trigger setup on iths own) */ + var iitcLoaded: boolean; + + /** the Leaflet Map */ + var map: L.Map; + + /** google-api */ + var gapi: any; + + /** Layer visibilty control */ + var layerChooser: L.Control.Layers; + + /** Info about current player/agent */ + var PLAYER: Intel.PlayerInfo; + + /** Request handler */ + var mapDataRequest: MapDataRequest; + var DEFAULT_MAX_IDLE_TIME: number; + var DEFAULT_REFRESH: number; + + function startRefreshTimeout(): void; + + /** Load & show Portal Details Window */ + function renderPortalDetails(guid: PortalGUID | null): void; + + /** Make sure Portal is visible in Window */ + function zoomToAndShowPortal(guid: PortalGUID, position: L.LatLng): void; + + /** Create Portal-Marker */ + function createMarker( + position: L.LatLng, + options: IITC.PortalOptions + ): L.CircleMarker; + + // Map Stuff + function selectPortalByLatLng(lat: number, lng: number): void; + + /** add Layergroup to leaflets layer-chooser */ + function addLayerGroup( + name: string, + layer: L.LayerGroup, + defaultVisibile: boolean, + groupname?: string + ): void; + + /** remove a layer */ + function removeLayerGroup(layer: L.LayerGroup): void; + + /** get layer visiblity */ + function isLayerGroupDisplayed( + name: string, + defaultDisplay?: boolean + ): boolean; + + /** set layer visiblity */ + function updateDisplayedLayerGroup(name: string, display: boolean): void; + + /** escape Html string */ + function escapeHtmlSpecialChars(name: string): string; + + /** prepare marker for OverlappingMarkerSpiderfier */ + function registerMarkerForOMS(marker: L.Marker): void; + + /** convert team string to id */ + function teamStringToId(team: string): number; + + // Android + function useAndroidPanes(): boolean; + var currentPane: string; + function show(paneID: string): void; + + /** update status bar */ + function renderUpdateStatus(): void; +} diff --git a/src/types/iitc/core/map_data_calc_tools.d.ts b/src/types/iitc/core/map_data_calc_tools.d.ts new file mode 100755 index 000000000..30243d0ab --- /dev/null +++ b/src/types/iitc/core/map_data_calc_tools.d.ts @@ -0,0 +1,59 @@ +export {}; + +declare global { + var TILE_PARAMS: { + /** + * @default [200000,200000,200000,200000,200000,60000,60000,10000,5000,2500,2500,800,300,0,0]; + */ + ZOOM_TO_LINK_LENGTH: number[]; + + /** + * @default [8,8,8,8,7,7,7,6,6,5,4,4,3,2,2,1,1]; + */ + ZOOM_TO_LEVEL: number[]; + + /** + * @default [1,1,1,40,40,80,80,320,1000,2000,2000,4000,8000,16000,16000,32000]; + */ + TILES_PER_EDGE: number[]; + }; + + /** + * Ingress Intel splits up requests for map data (portals, links,fields) into tiles. To get data for the current viewport + * (i.e. what is currently visible) it first calculates which tiles intersect. + * For all those tiles, it then calculates the lat/lng bounds of that tile and a quadkey. + * Both the bounds and the quadkey are “somewhat” required to get complete data. + * + * Conversion functions courtesy of @link http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames + */ + function setupDataTileParams(): void; + + interface MapZoomTileParameters { + level: number; + tilesPerEdge: number; + minLinkLength: number; + hasPortals: boolean; + zoom: number; + } + + function getMapZoomTileParameters(zoom: number): MapZoomTileParameters; + + /** + * we can fetch data at a zoom level different to the map zoom. + * To improve the cacheing performance, we try and limit the number of zoom levels we retrieve data for + * to avoid impacting server load, we keep ourselves restricted to a zoom level with the sane number + * of tilesPerEdge and portal levels visible + */ + function getDataZoomForMapZoom(mapZoom: number): number; + + function lngToTile(lng: number, params: MapZoomTileParameters): number; + function latToTile(lat: number, params: MapZoomTileParameters): number; + function tileToLng(x: number, params: MapZoomTileParameters): number; + function tileToLat(y: number, params: MapZoomTileParameters): number; + + function pointToTileId( + params: MapZoomTileParameters, + x: number, + y: number + ): string; +} diff --git a/src/types/iitc/core/map_data_debug.d.ts b/src/types/iitc/core/map_data_debug.d.ts new file mode 100755 index 000000000..6dc788b0f --- /dev/null +++ b/src/types/iitc/core/map_data_debug.d.ts @@ -0,0 +1,36 @@ +/** useful bits to assist debugging map data tiles */ +export type DebugTileState = + | "ok" + | "error" + | "cache-fresh" + | "cache-stale" + | "requested" + | "retrying" + | "request-fail" + | "tile-fail" + | "tile-timeout" + | "render-queue"; + +declare global { + export class RenderDebugTiles { + CLEAR_CHECK_TIME: number; // = 0.1; + FADE_TIME: number; // = 1.0; + + private debugTileLayer: L.LayerGroup; + private debugTileToRectangle: {}; + private debugTileClearTimes: {}; + private timer?: number | undefined; + + reset(): void; + create(id: string, bounds: L.LatLngBounds): void; + setColour(id: string, borercol: string, fillcol: string): void; + setState(id: string, state: DebugTileState): void; + + /** + * @param waitTime in msec + */ + startTimer(waitTime: number): void; + + runClearPass(): void; + } +} diff --git a/src/types/iitc/core/map_data_render.d.ts b/src/types/iitc/core/map_data_render.d.ts new file mode 100755 index 000000000..302633d11 --- /dev/null +++ b/src/types/iitc/core/map_data_render.d.ts @@ -0,0 +1,66 @@ +import * as L from "leaflet"; +import { IITC } from "./iitctypes"; +import { Intel } from "./inteltypes"; + +/** class to handle rendering into leaflet the JSON data from the servers */ +export class Render { + portalMarkerScale?: number | undefined; + + private isRendering: boolean; + + /** object - represents the set of all deleted game entity GUIDs seen in a render pass */ + private deletedGuid: {}; + private seenPortalsGuid: {}; + private seenLinksGuid: {}; + private seenFieldsGuid: {}; + private bounds: L.LatLngBounds; + private level: number; + + /** start a render pass. called as we start to make the batch of data requests to the servers */ + startRenderPass(level: number, bounds: L.LatLngBounds): void; + + clearPortalsOutsideBounds(bounds: L.LatLngBounds): void; + clearFieldsOutsideBounds(bounds: L.LatLngBounds): void; + + /** process deleted entity list and entity data */ + processTileData(tiledata: any): void; + + processDeletedGameEntityGuids(deleted: {}): void; + processGameEntities(entities: {}): void; + + /** + * End a render pass. does any cleaning up required, postponed processing of data, etc. called when the render + * is considered complete + */ + endRenderPass(): void; + + bringPortalsToFront(): void; + deleteEntity(guid: string): void; + deletePortalEntity(guid: string): void; + deleteLinkEntity(guid: string): void; + deleteFieldEntity(guid: string): void; + + /** + * intel no longer returns portals at anything but the closest zoom + * stock intel creates 'placeholder' portals from the data in links/fields - IITC needs to do the same + * we only have the portal guid, lat/lng coords, and the faction - no other data + * having the guid, at least, allows the portal details to be loaded once it's selected. however, + * no highlighters, portal level numbers, portal names, useful counts of portals, etc are possible + */ + createPlaceholderPortalEntity( + guid: string, + latE6: number, + lngE6: number, + team: "E" | "R" | "N" + ): void; + + createPortalEntity(ent: Intel.PortalDetails): void; + createFieldEntity(ent: Intel.FieldDetails): void; + createLinkEntity(ent: Intel.LinkDetails): void; + + rescalePortalMarkers(): void; + + /** add the portal to the visible map layer */ + addPortalToMapLayer(portal: IITC.Portal): void; + removePortalFromMapLayer(portal: IITC.Portal): void; +} diff --git a/src/types/iitc/core/map_data_request.d.ts b/src/types/iitc/core/map_data_request.d.ts new file mode 100755 index 000000000..cf8111484 --- /dev/null +++ b/src/types/iitc/core/map_data_request.d.ts @@ -0,0 +1,159 @@ +import { DataCache } from "./data_cache"; +//import { RenderDebugTiles } from './map_data_debug'; +import { Render } from "./map_data_render"; + +export interface MapDataRequestStatus { + short: string; + long?: string | undefined; + progress?: number | undefined; +} + +/** + * class to request the map data tiles from the Ingress servers + * and then pass it on to the render class for display purposes + * Uses the map data cache class to reduce network requests + */ +export class MapDataRequest { + cache: DataCache; + render: Render; + debugTiles: RenderDebugTiles; + + activeRequestCount: number; + requestedTiles: {}; + renderQueue: []; + renderQueueTimer?: number | undefined; + renderQueuePaused: boolean; + idle: boolean; + + cachedTileCount: number; + requestedTileCount: number; + successTileCount: number; + failedTileCount: number; + staleTileCount: number; + + private status: MapDataRequestStatus; + + /** a 'set' to keep track of hard failures for tiles */ + tileErrorCount: {}; + + /** + * the 'set' of requested tile QKs + */ + queuedTiles: {}; + + /** store the parameters used for fetching the data. used to prevent unneeded refreshes after move/zoom */ + private fetchedDataParams: any; + + /** + * no more than this many requests in parallel. stock site seems to rely on browser limits (6, usually), sending + * many requests at once. + * using our own queue limit ensures that other requests (e.g. chat, portal details) don't get delayed + * @default 5 + */ + MAX_REQUESTS: number; + + /** + * this many tiles in one request + * @default 25 + */ + NUM_TILES_PER_REQUEST: number; + + /** + * number of times to retry a tile after an error (including "error: TIMEOUT" now - as stock intel does) + * TODO? different retry counters for TIMEOUT vs other errors..? + * @default 5 + */ + MAX_TILE_RETRIES: number; + + // refresh timers + MOVE_REFRESH: number; // = 3; //time, after a map move (pan/zoom) before starting the refresh processing + STARTUP_REFRESH: number; // = 3; //refresh time used on first load of IITC + IDLE_RESUME_REFRESH: number; // = 5; //refresh time used after resuming from idle + + /** + * after one of the above, there's an additional delay between preparing the refresh (clearing out of bounds, + * processing cache, etc) and actually sending the first network requests + * delay after preparing the data download before tile requests are sent + * @default 1 + */ + DOWNLOAD_DELAY: number; + + /** + * a short delay between one request finishing and the queue being run for the next request. + * @default 0 + */ + RUN_QUEUE_DELAY: number; + + /** + * delay before processing the queue after failed requests + * longer delay before doing anything after errors (other than TIMEOUT) + * @default 5 + */ + BAD_REQUEST_RUN_QUEUE_DELAY: number; + + /** + * delay before processing the queue after empty responses + * also long delay - empty responses are likely due to some server issues + * @default 5 + */ + EMPTY_RESPONSE_RUN_QUEUE_DELAY: number; + + /** + * delay before processing the queue after error==TIMEOUT requests. this is 'expected', so minimal extra delay over the regular RUN_QUEUE_DELAY + * @default 0 + */ + TIMEOUT_REQUEST_RUN_QUEUE_DELAY: number; + + /** + * render queue + * number of items to process in each render pass. there are pros and cons to smaller and larger values + * (however, if using leaflet canvas rendering, it makes sense to push as much as possible through every time) + */ + RENDER_BATCH_SIZE: number; + + /** + * delay before repeating the render loop. this gives a better chance for user interaction + * 0.1sec desktop, 0.2sec mobile + */ + RENDER_PAUSE: number; + + /** + * refresh time to use for close views z>12 when not idle and not moving + * @default 300 + */ + REFRESH_CLOSE: number; + + /** + * refresh time for far views z <= 12 + * @default 900 + */ + REFRESH_FAR: number; + + /** + * minimum refresh time is based on the time to complete a data fetch, times this value + * @default 2 + */ + FETCH_TO_REFRESH_FACTOR: number; + + start(): void; + mapMoveStart(): void; + mapMoveEnd(): void; + idleResume(): void; + clearTimeout(): void; + refreshOnTimeout(delayInSeconds: number): void; + setStatus(short: string, long?: string, progress?: number): void; + getStatus(): MapDataRequestStatus; + refresh(): void; + + delayProcessRequestQueue(delayInSeconds: number): void; + processRequestQueue(boolean): void; + sendTileRequest(tiles: string[]): void; + requeueTile(id: string, error: boolean): void; + private handleResponse(data: any, tiles: string[], success: boolean): void; + resetRenderQueue(): void; + pushRenderQueue(id: string, data: any, status: any): void; + + startQueueTimer(delayInSecond: number): void; + pauseRenderQueue(pause: boolean): void; + processRenderQueue(): void; +} diff --git a/src/types/iitc/core/ornaments.d.ts b/src/types/iitc/core/ornaments.d.ts new file mode 100755 index 000000000..afe1d9748 --- /dev/null +++ b/src/types/iitc/core/ornaments.d.ts @@ -0,0 +1,36 @@ +import { IITC } from "./iitctypes"; + +export {}; + +declare global { + /** + * Added as part of the Ingress #Helios in 2014, ornaments + * are additional image overlays for portals. + * + * currently there are 6 known types of ornaments: ap$x$suffix + * - cluster portals (without suffix) + * - volatile portals (_v) + * - meeting points (_start) + * - finish points (_end) + * + * Beacons and Frackers were introduced at the launch of the Ingress + * ingame store on November 1st, 2015 + * - Beacons (pe$TAG - $NAME) ie: 'peNIA - NIANTIC' + * - Frackers ('peFRACK') + * (there are 7 different colors for each of them) + */ + class Ornaments { + _portals: {}; + _layer: L.LayerGroup; + _beacons: L.LayerGroup; + _frackers: L.LayerGroup; + OVERLAY_SIZE: number; // 60, + OVERLAY_OPACITY: number; // 0.6, + + setup(): void; + addPortal(portal: IITC.Portal): void; + removePortal(portal: IITC.Portal): void; + } + + const ornaments: Ornaments; +} diff --git a/src/types/iitc/core/panes.d.ts b/src/types/iitc/core/panes.d.ts new file mode 100755 index 000000000..127b598fb --- /dev/null +++ b/src/types/iitc/core/panes.d.ts @@ -0,0 +1,8 @@ +export {}; + +declare global { + var currentPane: string; + + function show(id: string): void; + function hideall(): void; +} diff --git a/src/types/iitc/core/player_names.d.ts b/src/types/iitc/core/player_names.d.ts new file mode 100755 index 000000000..b2317402c --- /dev/null +++ b/src/types/iitc/core/player_names.d.ts @@ -0,0 +1,8 @@ +export {}; + +declare global { + /** + * test to see if a specific player GUID is a special system account (e.g. __JARVIS__, __ADA__) that shouldn't be listed as a player + */ + function isSystemPlayer(name: string): boolean; +} diff --git a/src/types/iitc/core/portal_data.d.ts b/src/types/iitc/core/portal_data.d.ts new file mode 100755 index 000000000..76857b6b7 --- /dev/null +++ b/src/types/iitc/core/portal_data.d.ts @@ -0,0 +1,61 @@ +import { FieldGUID, LinkGUID, PortalGUID } from "./iitctypes"; +export {}; + +declare global { + /** + * Get Links of portal + * search through the links data for all that link from or to a portal. returns an object with separate lists of in + * and out links. may or may not be as accurate as the portal details, depending on how much data the API returns + */ + function getPortalLinks(guid: PortalGUID): { + in: LinkGUID[]; + out: LinkGUID[]; + }; + function getPortalLinksCount(guid: PortalGUID): number; + + /** + * Get Fields of portal + * search through the fields for all that reference a portal + */ + function getPortalFields(guid: PortalGUID): FieldGUID[]; + function getPortalFields(guid: PortalGUID): number; + + /** + * find the lat/lon for a portal, using any and all available data + * (we have the list of portals, the cached portal details, plus links and fields as sources of portal locations) + */ + function findPortalLatLng(guid: PortalGUID): L.LatLng | undefined; + + /** find guid by position E6 */ + function findPortalGuidByPositionE6( + latE6: number, + lngE6: number + ): PortalGUID | null; + function pushPortalGuidPositionCache( + guid: PortalGUID, + latE6: number, + lngE6: number + ): void; + + /** + * get the AP gains from a portal, based only on the brief summary data from portals, links and fields + * not entirely accurate - but available for all portals on the screen + */ + function getPortalApGain(guid: PortalGUID): number | undefined; + + /** + * given counts of resonators, links and fields, calculate the available AP + * doesn't take account AP for resonator upgrades or AP for adding mods + */ + function portalApGainMaths( + resCount: number, + linkCount: number, + fieldCount: number + ): { + friendlyAp: number; + enemyAp: number; + destroyAp: number; + destroyResoAp: number; + captureAp: number; + }; +} diff --git a/src/types/iitc/core/portal_detail.d.ts b/src/types/iitc/core/portal_detail.d.ts new file mode 100755 index 000000000..af0710095 --- /dev/null +++ b/src/types/iitc/core/portal_detail.d.ts @@ -0,0 +1,23 @@ +import { IITC } from "./iitctypes"; + +export {}; + +declare global { + class PortalDetail { + setup(): void; + + /** Get portal detail from cache */ + get(guid: string): IITC.PortalDataDetail | undefined; + + /** Get portal detail from cache */ + isFresh(guid: string): boolean | undefined; + + /** + * Request Portal details from server + * NB: you shouldn't use it. + */ + request(guid: string): JQuery.Promise; + } + + var portalDetail: PortalDetail; +} diff --git a/src/types/iitc/core/portal_detail_display.d.ts b/src/types/iitc/core/portal_detail_display.d.ts new file mode 100755 index 000000000..c0170e59c --- /dev/null +++ b/src/types/iitc/core/portal_detail_display.d.ts @@ -0,0 +1,26 @@ +import { IITC, PortalGUID } from "./iitctypes"; + +export {}; + +declare global { + function resetScrollOnNewPortal(): void; + + function renderPortalDetails(guid: PortalGUID): void; + function getPortalMiscDetails( + guid: PortalGUID, + details?: IITC.PortalDataDetail + ): string; + + /** + * draws link-range and hack-range circles around the portal with the + * given details. Clear them if parameter 'd' is null. + */ + function setPortalIndicators(p: IITC.Portal): void; + + /** + * highlights portal with given GUID. Automatically clears highlights + * on old selection. Returns false if the selected portal changed. + * @returns true if it's still the same portal that just needs an update. + */ + function selectPortal(guid: PortalGUID): boolean; +} diff --git a/src/types/iitc/core/portal_detail_display_tools.d.ts b/src/types/iitc/core/portal_detail_display_tools.d.ts new file mode 100755 index 000000000..9ec72598a --- /dev/null +++ b/src/types/iitc/core/portal_detail_display_tools.d.ts @@ -0,0 +1,57 @@ +import { IITC } from "./iitctypes"; + +export {}; + +declare global { + /** + * returns displayable text+link about portal range + */ + function getRangeText(d: IITC.PortalDataDetail): string[]; + + /** + * given portal details, returns html code to display mod details. + */ + function getModDetails(d: IITC.PortalDataDetail): string; + + function getEnergyText(d: IITC.PortalDataDetail): string[]; + + /** + * octant=slot: 0=E, 1=NE, 2=N, 3=NW, 4=W, 5=SW, 6=S, SE=7 + * resos in the display should be ordered like this: + * N NE Since the view is displayed in rows, they + * NW E need to be ordered like this: N NE NW E W SE SW S + * W SE i.e. 2 1 3 0 4 7 5 6 + * SW S + * note: as of 2014-05-23 update, this is not true for portals with empty slots! + */ + function getResonatorDetails(d: IITC.PortalDataDetail): string; + + /** + * helper function that renders the HTML for a given resonator. Does + * not work with raw details-hash. Needs digested infos instead: + * slot: which slot this resonator occupies. Starts with 0 (east) and + * rotates clockwise. So, last one is 7 (southeast). + */ + function renderResonatorDetails( + slot: number, + level: number, + nrg: string, + nick: string + ): string[]; + + /** + * calculate AP gain from destroying portal and then capturing it by deploying resonators + */ + function getAttackApGainText( + d: IITC.PortalDataDetail, + fieldCount: number, + linkCount: number + ): string[]; + + function getHackDetailsText(d: IITC.PortalDataDetail): string[]; + + function getMitigationText( + d: IITC.PortalDataDetail, + linkCount: number + ): string[]; +} diff --git a/src/types/iitc/core/portal_highlighter.d.ts b/src/types/iitc/core/portal_highlighter.d.ts new file mode 100755 index 000000000..a9597f5e6 --- /dev/null +++ b/src/types/iitc/core/portal_highlighter.d.ts @@ -0,0 +1,29 @@ +import { IITC } from "./iitctypes"; + +export {}; + +declare global { + interface Hightligher { + hightlight: (portal: IITC.Portal) => void; + } + + /** an object mapping highlighter names to the object containing callback functions */ + var _highlighters: { [name: string]: Hightligher } | null; + + /** the name of the current highlighter */ + var _current_highlighter: string; + + /** + * = "No Highlights" + */ + var _no_highlighter: string; + + function addPortalHighlighter(name: string, data: Hightligher): void; + + // (re)creates the highlighter dropdown list + function updatePortalHighlighterControl(): void; + function changePortalHighlights(name: string): void; + + function highlightPortal(p: IITC.Portal): void; + function resetHighlightedPortals(): void; +} diff --git a/src/types/iitc/core/portal_info.d.ts b/src/types/iitc/core/portal_info.d.ts new file mode 100755 index 000000000..f0084749d --- /dev/null +++ b/src/types/iitc/core/portal_info.d.ts @@ -0,0 +1,93 @@ +import { IITC } from "./iitctypes"; + +export {}; + +declare global { + /** + * returns a float. Displayed portal level is always rounded down from that value. + */ + function getPortalLevel(d: IITC.PortalDataDetail): number; + + function getTotalPortalEnergy(d: IITC.PortalDataDetail): number; + + /** + * @deprecated use getTotalPortalEnergy (just renamed) + */ + function getPortalEnergy(d: IITC.PortalDataDetail): number; + + function getCurrentPortalEnergy(d: IITC.PortalDataDetail): number; + + /** + * formula by the great gals and guys at + * @link http://decodeingress.me/2012/11/18/ingress-portal-levels-and-link-range/ + */ + function getPortalRange(d: IITC.PortalDataDetail): number; + + /** additional range boost calculation */ + function getLinkAmpRangeBoost(d: IITC.PortalDataDetail): number; + + function getAttackApGain( + d: IITC.PortalDataDetail, + fieldCount: number, + linkCount: number + ): { + friendlyAp: number; + deployCount: number; + upgradeCount: number; + enemyAp: number; + destroyAp: number; + resoAp: number; + captureAp: number; + }; + + /** This function will return the potential level a player can upgrade it to */ + function potentialPortalLevel(d: IITC.PortalDataDetail): number; + + function fixPortalImageUrl(url: string): string; + + function getPortalModsByType( + d: IITC.PortalDataDetail, + type: IITC.ModType + ): IITC.Mod[]; + + function getPortalShieldMitigation(d: IITC.PortalDataDetail): number; + function getPortalLinkDefenseBoost(d: IITC.PortalDataDetail): number; + function getPortalLinksMitigation(linkCount: number): number; + function getPortalMitigationDetails( + d: IITC.PortalDataDetail, + linkCount: number + ): { + shields: number; + links: number; + linkDefenseBoost: number; + excess: number; + }; + function getMaxOutgoingLinks(d: IITC.PortalDataDetail): number; + + function getPortalHackDetails(d: IITC.PortalDataDetail): { + cooldown: number; + hacks: number; + burnout: number; + }; + + /** + * given a detailed portal structure, return summary portal data, as seen in the map tile data + */ + function getPortalSummaryData(d: IITC.PortalDataDetail): { + level: number; + title: string; + image: string; + resCount: number; + latE6: number; + health: number; + team: number; + lngE6: number; + type: "portal"; + }; + + function getPortalAttackValues(d: IITC.PortalDataDetail): { + hit_bonus: number; + force_amplifier: number; + attack_frequency: number; + }; +} diff --git a/src/types/iitc/core/portal_marker.d.ts b/src/types/iitc/core/portal_marker.d.ts new file mode 100755 index 000000000..bb9fc4f2c --- /dev/null +++ b/src/types/iitc/core/portal_marker.d.ts @@ -0,0 +1,16 @@ +import { IITC } from "./iitctypes"; + +export {}; + +declare global { + function portalMarkerScale(): number; + + /** + * create a new marker. 'data' contain the IITC-specific entity data to be stored in the object options + */ + function createMarker(latlng: L.LatLng, data: IITC.PortalData): IITC.Portal; + + function setMarkerStyle(marker: IITC.Portal, selected: boolean): void; + + function getMarkerStyleOptions(details: IITC.PortalOptions): L.PathOptions; +} diff --git a/src/types/iitc/core/redeeming.d.ts b/src/types/iitc/core/redeeming.d.ts new file mode 100755 index 000000000..e7dfadd1a --- /dev/null +++ b/src/types/iitc/core/redeeming.d.ts @@ -0,0 +1,25 @@ +export {}; + +declare global { + interface ResultData { + other: string[]; + xm: string; + ap: string; + inventory: any; + } + var REDEEM_SHORT_NAMES: { [key: string]: string }; + + /** These are HTTP status codes returned by the redemption API. */ + var REDEEM_STATUSES: { [key: number]: string }; + + function handleRedeemResponse( + data: ResultData, + textStatus: any, + jqXHR: JQuery.jqXHR + ): void; + + function formatPasscodeLong(data: ResultData): void; + function formatPasscodeShort(data: ResultData): void; + + function setupRedeem(): void; +} diff --git a/src/types/iitc/core/region_scoreboard.d.ts b/src/types/iitc/core/region_scoreboard.d.ts new file mode 100755 index 000000000..460ae644c --- /dev/null +++ b/src/types/iitc/core/region_scoreboard.d.ts @@ -0,0 +1,15 @@ +export {}; + +declare global { + class RegionScoreboard_ { + HistoryChart: HistoryChart_; + setup(): void; + shwoDialog(): void; + } + + class HistoryChart_ { + create(_regionScore: RegionScoreboard_, logscale: boolean): void; + } + + var RegionScoreboard: RegionScoreboard_; +} diff --git a/src/types/iitc/core/request_handling.d.ts b/src/types/iitc/core/request_handling.d.ts new file mode 100755 index 000000000..0654b6e25 --- /dev/null +++ b/src/types/iitc/core/request_handling.d.ts @@ -0,0 +1,37 @@ +export {}; + +declare global { + var activeRequests: JQuery.jqXHR[]; + + /** failed data requests calls */ + var failedRequestCount: number; + + var statusTotalMapTiles: number; + var statusCachedMapTiles: number; + var statusSuccessMapTiles: number; + var statusStaleMapTiles: number; + var statusErrorMapTiles: number; + + class Requests { + add(ajax: JQuery.jqXHR): void; + remove(ajax: JQuery.jqXHR): void; + abort(): void; + + /** + * sets the timer for the next auto refresh. Ensures only one timeout + * is queued. May be given 'override' in milliseconds if time should + * not be guessed automatically. Especially useful if a little delay + * is required, for example when zooming. + */ + startRefreshTimeout(override: number): void; + + /** + * add method here to be notified of auto-refreshes + */ + addRefreshFunction(fct: () => void): void; + + isLastRequest(ajax: JQuery.jqXHR): boolean; + } + + var requests: Requests; +} diff --git a/src/types/iitc/core/search.d.ts b/src/types/iitc/core/search.d.ts new file mode 100755 index 000000000..b2f55a1b1 --- /dev/null +++ b/src/types/iitc/core/search.d.ts @@ -0,0 +1,72 @@ +export {}; + +declare global { + /** + * you can implement your own result provider by listing to the search @see hook: + * addHook('search', function(query: SearchQuery) {}); + */ + class SearchQuery { + /** the term for which the user has searched */ + term: string; + + /** + * indicating if the user has pressed enter after searching. You should not search online or + * do heavy processing unless the user has confirmed the search term + */ + confirmed: boolean; + + /** called to add a result to the query */ + addResult(result: SearchResult): void; + + private init(): void; + private show(): void; + private hide(): void; + private resultLayer(result: SearchResult): L.LayerGroup; + private onResultSelected(result: SearchResult, event: any): void; + private removeSelectedResult(): void; + private onResultHoverStart(result: SearchResult, event: any): void; + private removeHoverResult(): void; + private onResultHoverEnd(result: SearchResult, event: any): void; + } + + type SearchResult = SearchResultPosition | SearchResultBounds; + interface SearchResultPosition extends SearchResultBase { + position: L.LatLngExpression; + } + + interface SearchResultBounds extends SearchResultBase { + bounds: L.LatLngBoundsExpression; + } + + interface SearchResultBase { + /** Will be interpreted as HTML, so make sure to escape properly. */ + title: string; + /** secondary information for this result.Will be interpreted as HTML, so make sure to escape properly. */ + description: JQuery | any[] | Element | Text | string; + /** a ILayer to be added to the map when the user selects this search result. Will be generated if not set. Set to `null` to prevent the result from being added to the map. */ + layer?: L.Layer | undefined; + /** a URL to a icon to display in the result list. Should be 12x12. */ + icon?: string | undefined; + /** + * a handler to be called when the result is selected. May return `true` to prevent the map from being repositioned. + * You may reposition the map yourself or do other work. + */ + onSelected?: + | ((result: SearchResult, event: UIEvent) => boolean | undefined) + | undefined; + /** + * a handler to be called when the result is removed from the map(because another result has been + * selected or the search was cancelled by the user). + */ + onRemove?: ((result: SearchResult) => void) | undefined; + } + + class Search { + lastSearch: SearchQuery | null; + + doSearch(term: string, confirmed: boolean): void; + setup(): void; + } + + var search: Search; +} diff --git a/src/types/iitc/core/send_request.d.ts b/src/types/iitc/core/send_request.d.ts new file mode 100755 index 000000000..770ad839e --- /dev/null +++ b/src/types/iitc/core/send_request.d.ts @@ -0,0 +1,28 @@ +export {}; + +declare global { + /** + * posts AJAX request to Ingress API. + * @param action last part of the actual URL, the rpc/dashboard. is added automatically + * @param data JSON data to post. method will be derived automatically from action, but may + * be overridden. Expects to be given Hash. Strings are not supported. + * @param successCallback method to call on success. See jQuery API docs for available arguments: http://api.jquery.com/jQuery.ajax/ + * @param errorCallback see above. Additionally it is logged if the request failed. + */ + function postAjax( + action: string, + data: any, + successCallback: ( + data: any, + textStatus: string, + jqXHR: JQuery.jqXHR + ) => void, + errorCallback: ( + jqXHR: JQuery.jqXHR, + textStatus: string, + errorThrown: string + ) => void + ): any; + + function outOfDateUserPrompt(): void; +} diff --git a/src/types/iitc/core/smartphone.d.ts b/src/types/iitc/core/smartphone.d.ts new file mode 100755 index 000000000..ec70241be --- /dev/null +++ b/src/types/iitc/core/smartphone.d.ts @@ -0,0 +1,24 @@ +import { PortalGUID } from "./iitctypes"; + +export {}; + +declare global { + /** + * this check is also used in main.js. Note it should not detect + * tablets because their display is large enough to use the desktop version. + * + * The stock intel site allows forcing mobile/full sites with a vp=m or vp=f + * parameter - let's support the same. (stock only allows this for some + * browsers - e.g. android phone/tablet. let's allow it for all, but + * no promises it'll work right) + */ + function isSmartphone(): boolean; + + function runOnSmartphonesBeforeBoot(): void; + function runOnSmartphonesAfterBoot(): void; + + function smartphoneInfo(data: { selectedPortalGuid: PortalGUID }): void; + + function setAndroidPermalink(): void; + function useAndroidPanes(): boolean; +} diff --git a/src/types/iitc/core/utils_file.d.ts b/src/types/iitc/core/utils_file.d.ts new file mode 100755 index 000000000..649d8a619 --- /dev/null +++ b/src/types/iitc/core/utils_file.d.ts @@ -0,0 +1,11 @@ +export {}; + +declare global { + function saveAs(data: any, filename: string, dataType: string): void; + + /** + * Save data to file with given filename, using IITCm file chooser, or generic browser routine. + * `dataType` can be set to filter IITCm file chooser filetypes. + */ + function saveFile(data: string, filename?: string, dataType?: string): void; +} diff --git a/src/types/iitc/core/utils_misc.d.ts b/src/types/iitc/core/utils_misc.d.ts new file mode 100755 index 000000000..dcd76bd97 --- /dev/null +++ b/src/types/iitc/core/utils_misc.d.ts @@ -0,0 +1,146 @@ +import * as L from "leaflet"; + +declare global { + /** + * Show about dialog + * + * Plugins metadata come from 2 sources: + * - buildName, pluginId, dateTimeVersion: inserted in plugin body by build script + * (only standard plugins) + * - script.name/version/description: from GM_info object, passed to wrapper + * `script` may be not available if userscript manager does not provede GM_info + * (atm: IITC-Mobile for iOS) + */ + function aboutIITC(): void; + + function layerGroupLength(layerGroup: L.LayerGroup): number; + + /** retrieves parameter from the URL?query=string. */ + function getURLParam(param: string): string; + + /** + * read cookie by name. + * https://stackoverflow.com/a/5639455/1684530 by cwolves + */ + function readCookie(name: string): string; + + function writeCookie(name: string, val: string): void; + + function eraseCookie(name: string): void; + + /** + * certain values were stored in cookies, but we're better off using localStorage instead - make it easy to convert + */ + function convertCookieToLocalStorage(name: string): void; + + /** + * add thousand separators to given number. + * https://stackoverflow.com/a/1990590/1684530 by Doug Neiner. + */ + function digits(d: number | string): string; + + function zeroPad(num: number, pad: number): string; + + function unixTimeToString( + time?: string | number | Date, + full?: boolean + ): string; + + /** + * convert time to string + * converts a javascript time to a precise date and time (optionally with millisecond precision) + * formatted in ISO-style YYYY-MM-DD hh:mm:ss.mmm - but using local timezone + */ + function unixTimeToDateTimeString( + ticks: number | string | Date, + millisecond?: boolean + ): string; + + /** convert time to string */ + function unixTimeToHHmm(time: number | string | Date): string; + + /** format time difference */ + function formatInterval(seconds: number, maxTerms?: number): string; + + function rangeLinkClick(): void; + function showPortalPosLinks(lat: number, lng: number, name?: string): void; + + function isTouchDevice(): boolean; + + function androidCopy(text: string): boolean; + + function getCurrentZoomTileParameters(): any; // return getMapZoomTileParameters() + + /** returns number of pixels left to scroll down before reaching the bottom. */ + function scrollBottom(element: string | JQuery): number; + + function zoomToAndShowPortal(guid: string, latlng: L.LatLng): void; + + function selectPortalByLatLng( + lat: number | L.LatLng | [number, number], + lng?: number + ): void; + + /** + * escape a javascript string, so quotes and backslashes are escaped with a backslash + * (for strings passed as parameters to html onclick="..." for example) + */ + function escapeJavascriptString(str: string): string; + + /** escape special characters, such as tags */ + function escapeHtmlSpecialChars(str: string): string; + + function prettyEnergy(nrg: number): string; + + function uniqueArray(arr: any[]): any[]; + + function genFourColumnTable(blocks: any[]): string; + + /** converts given text with newlines (\n) and tabs (\t) to a HTML table automatically. */ + function convertTextToTableMagic(text: string): string; + + /** + * Given 3 sets of points in an array[3]{lat, lng} returns the area of the triangle + * NOTE: not geodesic area! + */ + function calcTriArea(p: [L.LatLng, L.LatLng, L.LatLng]): number; + + /** Update layerGroups display status to window.overlayStatus and localStorage 'ingress.intelmap.layergroupdisplayed' */ + function updateDisplayedLayerGroup(name: string, display: boolean): void; + + /** + * Read layerGroup status from window.overlayStatus if it was added to map, + * read from cookie if it has not added to map yet. + * @return 'defaultDisplay' if both overlayStatus and cookie didn't have the record + */ + function isLayerGroupDisplayed( + name: string, + defaultDisplay: boolean + ): boolean; + + function addLayerGroup( + name: string, + layerGroup: L.LayerGroup, + defaultDisplay?: boolean + ): void; + + function removeLayerGroup(layerGroup: L.LayerGroup): void; + + function clampLatLng(latlng: L.LatLng): L.LatLng; + + function clampLatLngBounds(bounds: L.LatLngBounds): L.LatLngBounds; + + /** + * Makes the permalink for the portal with specified latlng, possibly including current map view. + * Portal latlng can be omitted to create mapview-only permalink. + * @param option: + * - includeMapView: Boolean = null + * Use to add zoom level and latlng of current map center. + * - fullURL: Boolean = null + * Use to make absolute fully qualified URL (default: relative link). + */ + function makePermalink(latlng: L.LatLng, options?: {}): string; + + // TODO: String.prototype.capitalize = (): string; + // TODO: String.prototype.startsWith = (string): boolean; +} diff --git a/src/types/iitc/index.d.ts b/src/types/iitc/index.d.ts new file mode 100755 index 000000000..abe0215de --- /dev/null +++ b/src/types/iitc/index.d.ts @@ -0,0 +1,58 @@ +// Type definitions for IITC (Ingress Intel Total Conversation) 0.30 +// Project: https://github.com/IITC-CE/ingress-intel-total-conversion +// Definitions by: McBen +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// Minimum TypeScript Version: 3.6 + +// generate docs: npx typedoc --mode file --includeDeclarations --excludeExternals core/ + +// dependencies FIXME: triggers error +// export * as L from "leaflet"; +import * as L from "leaflet"; +import "leafletExtentions"; + +import "spectrum"; + +// base +export * from "./core/main"; +export * from "./core/constants"; +export * from "./core/iitctypes"; +export * from "./core/inteltypes"; + +// direct file conversation +export * from "./core/android"; // from mobile +export * from "./core/artifact"; +export * from "./core/dialog"; +export * from "./core/hooks"; +export * from "./core/chat"; +export * from "./core/utils_misc"; +export * from "./core/data_cache"; +export * from "./core/map_data_request"; +export * from "./core/map_data_render"; +export * from "./core/map_data_debug"; +export * from "./core/player_names"; +export * from "./core/entity_info"; +export * from "./core/region_scoreboard"; +export * from "./core/map_data_calc_tools"; +export * from "./core/search"; +export * from "./core/game_status"; +export * from "./core/entity_decode"; +export * from "./core/portal_data"; +export * from "./core/portal_highlighter"; +export * from "./core/portal_detail"; +export * from "./core/portal_info"; +export * from "./core/send_request"; +export * from "./core/portal_marker"; +export * from "./core/portal_detail_display"; +export * from "./core/portal_detail_display_tools"; +export * from "./core/smartphone"; +export * from "./core/panes"; +export * from "./core/extract_niantic_parameters"; +export * from "./core/idle"; +export * from "./core/utils_file"; +export * from "./core/request_handling"; +export * from "./core/redeeming"; +export * from "./core/ornaments"; +export * from "./core/location"; +export * from "./core/boot"; +export * from "./core/constants"; diff --git a/src/types/iitc/package.json b/src/types/iitc/package.json new file mode 100755 index 000000000..259f31817 --- /dev/null +++ b/src/types/iitc/package.json @@ -0,0 +1,26 @@ +{ + "contributors": [ + { + "name": "McBen", + "url": "https://github.com/McBen" + } + ], + "dependencies": { + "@types/jquery": "*", + "@types/jqueryui": "*", + "@types/leaflet": "*", + "@types/spectrum": "*" + }, + "description": "TypeScript definitions for IITC (Ingress Intel Total Conversation)", + "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/iitc", + "license": "MIT", + "main": "", + "name": "iitc", + "repository": { + "type": "git", + "url": "git+https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/iitc" + }, + "types": "index.d.ts", + "version": "0.30.2" +} \ No newline at end of file diff --git a/src/types/leafletExtentions/index.d.ts b/src/types/leafletExtentions/index.d.ts new file mode 100755 index 000000000..d74861522 --- /dev/null +++ b/src/types/leafletExtentions/index.d.ts @@ -0,0 +1,39 @@ +import * as L from "leaflet"; + +declare module "leaflet" { + // geodesic + function geodesicPolyline( + latlngs: LatLng[], + options?: PolylineOptions + ): GeodesicPolyline; + function geodesicPolygon( + latlngs: LatLng[], + options?: PolylineOptions + ): GeodesicPolygon; + + class GeodesicPolyline extends Polyline { + getLatLngs(): LatLng[]; + } + + // tslint:disable-next-line:no-empty-interface + class GeodesicPolygon extends GeodesicPolyline { } + + // tslint:disable-next-line:no-empty-interface + class GeodesicCircle extends Polyline { } + + // extends PolynineOption to any prop + interface PolylineOptions { + /* guid: string */ + [propName: string]: any; + } + + interface LeafletEvent { + /* opID: string */ + /* background: boolean */ + [propName: string]: any; + } + + interface Marker { + update(): this; + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..1dcd591e6 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "outDir": "./built", + "sourceMap": true, + "target": "ES6", + "moduleResolution": "node", + "importsNotUsedAsValues": "error", + "esModuleInterop": true, + "isolatedModules": true, + "strict": false, + "typeRoots": [ + "./src/types", + "node_modules/@types" + ], + "skipLibCheck": false, + "forceConsistentCasingInFileNames": true, + "downlevelIteration": true, + "allowJs": true, + "checkJs": true, + "allowUmdGlobalAccess": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules/*" + ] +} \ No newline at end of file From 001dba30c566c47fc774eb1ae360535c2a88cdc0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 21:20:02 +0100 Subject: [PATCH 068/275] add ts-loader --- package.json | 3 ++- tsconfig.json | 2 +- webpack.config.js | 10 ++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e41f0dd41..d213086c0 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "style-loader": "^2.0.0", "through2": "^4.0.2", "to-string-loader": "^1.1.6", + "ts-loader": "^9.2.6", "tslib": "^2.3.1", "typescript": "^4.4.4", "url-loader": "^4.1.1", @@ -56,4 +57,4 @@ "sortablejs": "^1.12.0" }, "typings": "src/code/index.d.ts" -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index 1dcd591e6..1c2aae52a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,7 @@ "forceConsistentCasingInFileNames": true, "downlevelIteration": true, "allowJs": true, - "checkJs": true, + "checkJs": false, "allowUmdGlobalAccess": true }, "include": [ diff --git a/webpack.config.js b/webpack.config.js index fa7a7cb9f..6f6493d4d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -139,9 +139,15 @@ const config = { }, resolve: { modules: ["node_modules"], + extensions: ['.ts', '.js'], }, module: { rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + }, { test: /\.(png|gif|svg)$/, use: "url-loader", @@ -169,11 +175,11 @@ module.exports = (env, argv) => { const pluginConfig = require("./plugin.config.json"); const meta = pluginConfig.headers.common; if (argv.mode === "development") { - if(env.scot) { + if (env.scot) { config.output.path = path.join(outputPath, "scot"); config.devtool = "eval-source-map"; Object.assign(meta, pluginConfig.headers.scot); - } else if(env.pr) { + } else if (env.pr) { config.output.path = path.join(outputPath, "dev"); config.devtool = "inline-source-map"; Object.assign(meta, pluginConfig.headers.pr); From 0ad3db22fc76087cd10338b09e47ee702450389d Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 21:20:30 +0100 Subject: [PATCH 069/275] zone.ts --- src/code/model/zone.d.ts | 21 --------------------- src/code/model/{zone.js => zone.ts} | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 25 deletions(-) delete mode 100644 src/code/model/zone.d.ts rename src/code/model/{zone.js => zone.ts} (81%) diff --git a/src/code/model/zone.d.ts b/src/code/model/zone.d.ts deleted file mode 100644 index 911650855..000000000 --- a/src/code/model/zone.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -export default class WasabeeZone { - id: number; - name: string; - color: string; - points: Array; - constructor(obj: any); - toJSON(): { - id: number; - name: string; - color: string; - points: zonePoint[]; - }; - contains(latlng: any): boolean; -} -declare class zonePoint { - position: number; - lat: number; - lng: number; - constructor(obj: any); -} -export {}; diff --git a/src/code/model/zone.js b/src/code/model/zone.ts similarity index 81% rename from src/code/model/zone.js rename to src/code/model/zone.ts index 9d5a9a5a8..18a52c6b9 100644 --- a/src/code/model/zone.js +++ b/src/code/model/zone.ts @@ -1,4 +1,9 @@ export default class WasabeeZone { + id: ZoneID; + name: string; + color: string; + points: zonePoint[]; + constructor(obj) { this.id = Number(obj.id); this.name = obj.name; @@ -14,7 +19,7 @@ export default class WasabeeZone { toJSON() { return { - id: Number(this.id), + id: +this.id, name: `${this.name}`, color: this.color, points: this.points, @@ -22,7 +27,7 @@ export default class WasabeeZone { } //ray casting algo - contains(latlng) { + contains(latlng: { lat: number; lng: number }) { this.points.sort((a, b) => { return a.position - b.position; }); @@ -51,9 +56,13 @@ export default class WasabeeZone { } class zonePoint { + position: number; + lat: number; + lng: number; + constructor(obj) { this.position = Number(obj.position); - this.lat = Number(obj.lat); - this.lng = Number(obj.lng); + this.lat = +obj.lat; + this.lng = +obj.lng; } } From 1b7d09b26bc48a7aa695e5b10ff2d9cb437aa963 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 21:53:47 +0100 Subject: [PATCH 070/275] blockers --- src/code/model/blocker.d.ts | 24 -------- src/code/model/{blocker.js => blocker.ts} | 74 ++++++++++++++--------- 2 files changed, 46 insertions(+), 52 deletions(-) delete mode 100644 src/code/model/blocker.d.ts rename src/code/model/{blocker.js => blocker.ts} (61%) diff --git a/src/code/model/blocker.d.ts b/src/code/model/blocker.d.ts deleted file mode 100644 index ec8ade609..000000000 --- a/src/code/model/blocker.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type WasabeeOp from "./operation"; -import type WasabeePortal from "./portal"; -export interface IBlockerPortal { - opID: OpID; - id: PortalID; - name: string; - lat: string; - lng: string; -} -export default class WasabeeBlocker { - opID: string; - from: string; - to: string; - fromPortal?: IBlockerPortal; - toPortal?: IBlockerPortal; - constructor(obj: any); - static addPortal(op: WasabeeOp, portal: WasabeePortal): Promise; - static updatePortal(op: WasabeeOp, portal: WasabeePortal): Promise; - static removeBlocker(op: WasabeeOp, portalId: string): Promise; - static removeBlockers(opID: string): Promise; - static addBlocker(op: WasabeeOp, fromPortal: WasabeePortal, toPortal: WasabeePortal): Promise; - static getPortals(op: WasabeeOp): Promise; - static getAll(op: WasabeeOp): Promise; -} diff --git a/src/code/model/blocker.js b/src/code/model/blocker.ts similarity index 61% rename from src/code/model/blocker.js rename to src/code/model/blocker.ts index 56d6163c4..b9ea9f82c 100644 --- a/src/code/model/blocker.js +++ b/src/code/model/blocker.ts @@ -1,15 +1,31 @@ import db from "../db"; +import type WasabeeOp from "./operation"; +import type WasabeePortal from "./portal"; + +export interface IBlockerPortal { + opID: OpID; + id: PortalID; + name: string; + lat: string; + lng: string; +} export default class WasabeeBlocker { + opID: OpID; + from: PortalID; + to: PortalID; + + fromPortal?: WasabeePortal; + toPortal?: WasabeePortal; + constructor(obj) { this.opID = obj.opID; this.from = obj.fromPortal.id; this.to = obj.toPortal.id; } - static async addPortal(op, portal) { - const store = await (await db).transaction("blockers_portals", "readwrite") - .store; + static async addPortal(op: WasabeeOp, portal: WasabeePortal) { + const store = (await db).transaction("blockers_portals", "readwrite").store; const ent = { opID: op.ID, id: portal.id, @@ -25,7 +41,7 @@ export default class WasabeeBlocker { } // return true if a blocker portal is updated - static async updatePortal(op, portal) { + static async updatePortal(op: WasabeeOp, portal: WasabeePortal) { const store = (await db).transaction("blockers_portals", "readwrite").store; if (portal.name === portal.id) return false; const p = await store.get([op.ID, portal.id]); @@ -48,41 +64,43 @@ export default class WasabeeBlocker { static async removeBlocker(op, portalId) { const store = (await db).transaction("blockers", "readwrite").store; - let cursor = await store + let cfrom = await store .index("from") .openKeyCursor(IDBKeyRange.only([op.ID, portalId])); - while (cursor) { - store.delete(cursor.primaryKey); - cursor = await cursor.continue(); + while (cfrom) { + store.delete(cfrom.primaryKey); + cfrom = await cfrom.continue(); } - cursor = await store + let cto = await store .index("to") .openKeyCursor(IDBKeyRange.only([op.ID, portalId])); - while (cursor) { - store.delete(cursor.primaryKey); - cursor = await cursor.continue(); + while (cto) { + store.delete(cto.primaryKey); + cto = await cto.continue(); } await (await db).delete("blockers_portals", [op.ID, portalId]); } - static async removeBlockers(opID) { - let store = (await db).transaction("blockers", "readwrite").store; - let cursor = await store - .index("opID") - .openKeyCursor(IDBKeyRange.only(opID)); - while (cursor) { - store.delete(cursor.primaryKey); - cursor = await cursor.continue(); + static async removeBlockers(opID: string) { + const sb = (await db).transaction("blockers", "readwrite").store; + let co = await sb.index("opID").openKeyCursor(IDBKeyRange.only(opID)); + while (co) { + sb.delete(co.primaryKey); + co = await co.continue(); } - store = (await db).transaction("blockers_portals", "readwrite").store; - cursor = await store.index("opID").openKeyCursor(IDBKeyRange.only(opID)); - while (cursor) { - store.delete(cursor.primaryKey); - cursor = await cursor.continue(); + const sp = (await db).transaction("blockers_portals", "readwrite").store; + let cp = await sp.index("opID").openKeyCursor(IDBKeyRange.only(opID)); + while (cp) { + sp.delete(cp.primaryKey); + cp = await cp.continue(); } } - static async addBlocker(op, fromPortal, toPortal) { + static async addBlocker( + op: WasabeeOp, + fromPortal: WasabeePortal, + toPortal: WasabeePortal + ) { const blocker = new WasabeeBlocker({ opID: op.ID, fromPortal: fromPortal, @@ -94,14 +112,14 @@ export default class WasabeeBlocker { await WasabeeBlocker.addPortal(op, toPortal); } - static async getPortals(op) { + static async getPortals(op: WasabeeOp) { const portals = await ( await db ).getAllFromIndex("blockers_portals", "opID", op.ID); return portals; } - static async getAll(op) { + static async getAll(op: WasabeeOp) { const blockers = await ( await db ).getAllFromIndex("blockers", "opID", op.ID); From 6c9b05795b3afac6c3fdcec3606d0d8b9f0f1821 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 21:54:05 +0100 Subject: [PATCH 071/275] evented.ts --- src/code/model/evented.d.ts | 12 ------------ src/code/model/{evented.js => evented.ts} | 13 ++++++++++--- 2 files changed, 10 insertions(+), 15 deletions(-) delete mode 100644 src/code/model/evented.d.ts rename src/code/model/{evented.js => evented.ts} (79%) diff --git a/src/code/model/evented.d.ts b/src/code/model/evented.d.ts deleted file mode 100644 index 889d79964..000000000 --- a/src/code/model/evented.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default class Evented { - _events: { - [propName: string]: Array<{ - fct: (data: unknown) => void; - context: unknown; - }>; - }; - constructor(); - on(event: string, func: (data: unknown) => void, context?: unknown): this; - off(event: string, func: (data: unknown) => void, context?: unknown): this; - fire(event: string, data?: unknown): this; -} diff --git a/src/code/model/evented.js b/src/code/model/evented.ts similarity index 79% rename from src/code/model/evented.js rename to src/code/model/evented.ts index aac98c209..1a7075687 100644 --- a/src/code/model/evented.js +++ b/src/code/model/evented.ts @@ -9,17 +9,24 @@ function doNothing() {} export default class Evented { + _events: { + [event: string]: { + fct: (data: unknown) => void; + context: unknown; + }[]; + }; + constructor() { this._events = {}; } - on(event, func, context) { + on(event: string, func: (data: unknown) => void, context?: unknown) { if (!(event in this._events)) this._events[event] = []; this._events[event].push({ fct: func, context: context }); return this; } - off(event, func, context) { + off(event: string, func: (data: unknown) => void, context?: unknown) { const listeners = this._events[event].slice(); if (listeners) { for (const listener of listeners) { @@ -32,7 +39,7 @@ export default class Evented { return this; } - fire(event, data) { + fire(event: string, data?: unknown) { const listeners = this._events[event].slice(); if (listeners) { for (const listener of listeners) { From 8c33bca9b2ed865742f551fcc0608d848a825837 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 21:54:28 +0100 Subject: [PATCH 072/275] portal.ts --- src/code/model/portal.d.ts | 24 ------------------------ src/code/model/{portal.js => portal.ts} | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 25 deletions(-) delete mode 100644 src/code/model/portal.d.ts rename src/code/model/{portal.js => portal.ts} (85%) diff --git a/src/code/model/portal.d.ts b/src/code/model/portal.d.ts deleted file mode 100644 index 349ecff92..000000000 --- a/src/code/model/portal.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as L from "leaflet"; -export default class WasabeePortal { - id: string; - name: string; - lat: string; - lng: string; - comment: string; - hardness: string; - _latLng: L.LatLng; - constructor(obj: any); - toJSON(): { - id: string; - name: string; - lat: string; - lng: string; - comment: string; - hardness: string; - }; - get latLng(): L.LatLng; - static fake(lat: string | number, lng: string | number, id?: string, name?: string): WasabeePortal; - get faked(): boolean; - get loading(): boolean; - get pureFaked(): boolean; -} diff --git a/src/code/model/portal.js b/src/code/model/portal.ts similarity index 85% rename from src/code/model/portal.js rename to src/code/model/portal.ts index 9b90c712a..4e61c73c2 100644 --- a/src/code/model/portal.js +++ b/src/code/model/portal.ts @@ -1,6 +1,16 @@ +import type { LatLng } from "leaflet"; import { generateId } from "../auxiliar"; export default class WasabeePortal { + id: PortalID; + name: string; + lat: string; + lng: string; + comment: string; + hardness: string; + + _latLng: LatLng; + constructor(obj) { if (typeof obj == "string") { try { @@ -44,7 +54,12 @@ export default class WasabeePortal { return this._latLng; } - static fake(lat, lng, id, name) { + static fake( + lat: number | string, + lng: number | string, + id?: string, + name?: string + ) { console.assert(lat && lng, "WasabeePortal.fake called w/o lat/lng"); if (!id) id = generateId(); From 272c32c097a37967385bdcdf81a2392be70b41ce Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 17:17:43 -0600 Subject: [PATCH 073/275] Change donate link https://www.patreon.com/wasabee --- src/code/dialogs/about.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/dialogs/about.js b/src/code/dialogs/about.js index 2f0d6bdb7..aa9223491 100644 --- a/src/code/dialogs/about.js +++ b/src/code/dialogs/about.js @@ -31,7 +31,7 @@ const AboutDialog = WDialog.extend({ const tips = L.DomUtil.create("div", null, html); tips.innerHTML = - "

Show your love

Tip Jar@paypal"; + "

Show your love

Patreon"; const about = L.DomUtil.create("div", null, html); about.innerHTML = "

About Wasabee-IITC

" + From 5c50a5178b01a69a3cca0a6ef559e9573ed3b9ac Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:16:51 -0600 Subject: [PATCH 074/275] Add Patreon Changed the PayPal link to the new Patreon link. --- src/code/dialogs/about.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/dialogs/about.js b/src/code/dialogs/about.js index 2f0d6bdb7..aa9223491 100644 --- a/src/code/dialogs/about.js +++ b/src/code/dialogs/about.js @@ -31,7 +31,7 @@ const AboutDialog = WDialog.extend({ const tips = L.DomUtil.create("div", null, html); tips.innerHTML = - "

Show your love

Tip Jar@paypal"; + "

Show your love

Patreon"; const about = L.DomUtil.create("div", null, html); about.innerHTML = "

About Wasabee-IITC

" + From 5c39a24d25cf0ad0caa80348f93296f647595bcf Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:20:03 -0600 Subject: [PATCH 075/275] Add Danish language --- src/code/translations/danish.json | 391 ++++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 src/code/translations/danish.json diff --git a/src/code/translations/danish.json b/src/code/translations/danish.json new file mode 100644 index 000000000..a59f0bccc --- /dev/null +++ b/src/code/translations/danish.json @@ -0,0 +1,391 @@ +{ + "ABOUT_WASABEE": "Om Wasabee", + "acknowledged": "Anerkendt", + "ADD LINK TITLE": "Tilføj Links", + "ADD MARKER TITLE": "Tilføj Markøre", + "ADD_AGENT": "Tilføj Agent: ", + "ADD_BL": "Tilføj baglinie: ", + "ADD_BUTTON_LINKS": "Tilføj alle links med det samme.", + "ADD_LINKS": "Tilføj Links", + "ADD_MARKER": "+ Markør", + "ADD_NEW_OP": "Tilføj Ny Op", + "ADD_SUCC_INSTR": "Agent tilføjet", + "ADD_ZONE": "Tilføj Zone", + "ADD": "Tilføj", + "ADD1": "Tilføj første link", + "ADD2": "Tilføj andet link", + "AGENT_STATS": "Agent Stats", + "AGENT": "Agent", + "AGES": " (for længe siden)", + "ALREADY_HAS_MARKER": "Denne portal har allerede en markør, vælg en anden Portal.", + "AMAZ_TEAM_NAME": "Fantastisk holdnavn.", + "ANCHOR ASSIGNMENT": " Alle udgående links", + "ANCHOR_GMAP": "Google Map", + "ANCHOR_PORTAL": "Anker Portal ", + "ANCHOR_PORTAL2": "Anker Portal 2", + "ANCHOR_PORTAL3": "Anker Portal 3", + "ANCHOR1": "Anker 1 ", + "ANCHOR2": "Anker 2 ", + "ANCHOR3": "Anker 3 ", + "ANCHORS_AS_BOOKMARKS": "Ankere som bookmarks", + "API_KEY": " api key: ", + "ASS_TO": "Tildelt", + "ASSIGN LINK PROMPT": "Tilføj link fra: {portalName}", + "ASSIGN MARKER PROMPT": "Tildel markør fra: {portalName}", + "ASSIGN OUTBOUND PROMPT": "Tildel alle udgående links fra: {portalName}", + "ASSIGN OUTBOUND": "Tildel udgående links", + "ASSIGN": "Tildel", + "ASSIGNED_ONLY_SHORT": "KT", + "ASSIGNED_ONLY": "Kun tildelt", + "assigned": "Tildelt", + "AUTH ANDROID": "På Android, prøv 'hurtigt' først. Hvis det mislykkes, prøv hovedlogin med 'vælg_konto'.", + "AUTH INCOMPAT": "Du har aktiveret et plugin i TamperMonkey, der er inkompatibelt med Wasabee", + "AUTH IOS": "På iOS skal du bruge "Log ind". Hvis det mislykkes, skal du bruge 'Webview-login' og derefter bruge 'Verify Webview'-knappen for at fuldføre processen.", + "AUTH REQUIRED": "Godkendelse påkrævet", + "AUTH TOKEN REJECTED": "Afsendelse af godkendelsestoken til serveren blev afvist: {error}", + "AUTH_SELECT_ACCOUNT": "Vælg konto", + "AUTO_DRAWS": "Auto-tegne", + "AUTODRAWS": "Wasabee Indstillinger for automatisk tegning", + "AUTOLOAD_RATE": "Rate for anmodning om portaldetaljer (ms)", + "AUTOLOAD": "Indlæs automatisk manglende portaloplysninger", + "AUTOMARK STOP": "Auto-markering stoppede på grund af, at portaler ikke blev indlæst", + "AUTOMARK": "Auto-mærke", + "BAT_TOAD": "Battle Toads/manglende oversættelse", + "BLOCKER LIST TITLE": "Vis alle blokkere", + "BLOCKER TITLE": "Blokere", + "CANCEL": "Annuller", + "CAPSULE": "Kapsel", + "CapturePortalMarker": "erobre", + "CHANGE SERVER PROMPT": "Ny Wasabee Server", + "CHANGE SERVER": "Skift Server", + "CHANGE_WAS_SERVER": "Skift Wasabee Server", + "CHECKLIST BUTTON TITLE": "Operation Tjekliste", + "CHECKLIST BUTTON": "Tjekliste", + "CLEAR LINKS": "Ryd links", + "CLEAR MARKERS": "Ryd markører", + "CLEAR_EVERYTHING": "Ryd portaler/links/markører for aktuel OP", + "CLEAROPS BUTTON TITLE": "Ryd Data", + "CLEAROPS BUTTON": "Ryd Data", + "CLEAROPS PROMPT": "Ryd alle lokale OPS. Ops vil blive gendannet ved næste download.", + "CLOSE": "Luk", + "COMMENT": "Kommentar", + "COMPLETED BY": "Færdiggjort af {agentName}", + "completed": "Færdiggjort", + "CON_DEL": "Bekræft sletning: {opName}", + "COUNT": "Optælling", + "CREATE_NEW_TEAM": "Opret nyt team", + "CreateLinkAlert": "Link", + "CUR_USER_INFO": "Aktuelle brugeroplysninger", + "D_SHOW_LIST": "Input defensive nøgler", + "DEFAULT OP NAME": "Ny Op: {date}", + "DELETE ANCHOR PROMPT": "Ønsker du at slette dette anker og alle tilhørende links: ", + "DELETE ANCHOR TITLE": "Slet anker", + "DELETE MARKER PROMPT": "Vil du slette denne markør: ", + "DELETE MARKER TITLE": "Slet markør", + "DELETE_ANCHOR": "Slet", + "DELETE_LINK": "Slet", + "DELETE_OP": "Slet {opName}", + "DESCRIP_PLACEHOLD": "Beskrivelse (valgfri)", + "DestroyPortalAlert": "Ødelæg/Skyd", + "DRAW TOOLS FORMAT": "Draw Tools Format", + "DUPE_OP": "Duplikere Operation", + "END_PORT": "Slut Portal ", + "ExcludeMarker": "Udelad fra Auto-Tegn/Marker", + "EXPORT OP TITLE": "Eksporter aktuel Op", + "EXPORT OP": "Eksporter Op", + "EXPORT": "Eksporter: ", + "FAKED": "forfalsket: [{portalId}]", + "FANFIELD": "Tegn", + "FANFIELD2": "Tegne Fan Field", + "FarmPortalMarker": "Farm", + "FROM_1-2": "fra basislinie 1-2", + "FROM_1-3": "fra basislinie 1-3", + "FROM_2-3": "fra basislinie 2-3", + "FROM_DEPTH": "fra center", + "FROM_PORT": "Fra Portal", + "GET DT": "Få eksisterende DrawTools-tegning", + "GetKeyPortalMarker": "Hent nøgler", + "GotoPortalMarker": "Gå Til", + "H-GEN_INST": "Sæt portaler til det ydre lag. Vælg antal opdelinger. Klik på tegn", + "HF_DEEP_SEARCH": "Omfattende søgning", + "HF_DRAW_BUTTON": "Tegn", + "HF_REDRAW_BUTTON": "Gentegn", + "HG": "Homogent felt", + "HOURS": " ({hours} timer siden)", + "HOW_TO_VIDS": "

Sådan gør du videoer:

", + "IMP_COMP": "Import fuldført. Fundet", + "IMP_NOPE": "Import mislykkedes.", + "IMP_WAS_OP": "Importer Wasabee Operation", + "IMPORT_OP_SUCCESS": "Importeret Operation: {opName} lykkedes.", + "IMPORT_OP_TITLE": "Import Op: {date}", + "IMPORT_OP": "Importer Operation", + "IMPOSSIBLE": "Umulig", + "INGNAME_GID": "Ingress navn eller GoogleID", + "INPUT_DT_KEY_COUNT": "Input antal defensiv nøgler", + "INPUT_SQUAD_NAME": "Indtast et holdnavn", + "INVALID REQUEST": "Ugyldig forespørgsel", + "IOS NEED FAKE UA": "Du skal indstille en 'Custom UserAgent for Webviews' i IITC-Mobile-indstillingerne, ellers mislykkes login", + "KEY_LIST2": "Nøgleliste til Operationen: {opName}", + "KEYS": "Nøgler", + "KNOWN_BLOCK": "Kendte blokkere: {opName}", + "LA DESC": "Afhængigt af antallet og typen af ​​anvendte Link Amps, kan et lavere kildeportal level være tilstrækkeligt.", + "LA": "L8+ nogle LA", + "LANG": "Sprog", + "LEAVE": "Forlad", + "LetDecayPortalAlert": "Lad forfalde", + "LINK ASSIGNMENT": "Link opgave", + "LINK STATE PROMPT": "Link tilstand", + "LINK STATE": "Indstil linkstatus", + "LINKS BUTTON TITLE": "Links", + "LINKS": "Links", + "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", + "LOAD PORTALS": "Load Portaler", + "LOADING": "[loader]", + "LOADING1": "Loader: [{portalGuid}]", + "LOC_PROC": "Beliggenhed behandlet", + "LOCATION SUB": "Lokation registreret", + "LOCFRMSER": " (lokal og fra server)", + "LOG IN": "Log In", + "LOG_OUT": "Log Ud", + "MADRID_SET_1": "Vælg regionen for basislinket Anker 2 til Anker 3", + "MADRID_SET_2": "Vælg regionen for basislinket Anker 3 til Anker 1", + "MADRID_SET_3": "Vælg regionen for basislinket Anker 1 til Anker 2", + "MADRID_TITLE": "Madrid Protocol", + "MADRID_WAS_TAKEN": "Madrid Protocol", + "MADRID": "Tegn", + "MANAGE_TEAM": "Administrer {teamName}", + "MANAGE": "Administrer", + "MARKER ASSIGNMENT": "Markør Opgave", + "MARKER LIST TITLE": "Markør Liste", + "MARKER LIST": "Markører", + "MARKER STATE PROMPT": "Markør Status", + "MARKER STATE": "Indstil markørtilstand", + "MARKER_LIST": "Markør Liste: {opName}", + "MARKERS BUTTON TITLE": "Markører", + "MAX_SPLITS": "Max Delinger", + "MAX": "Fan Field", + "MeetAgentPortalMarker": "Mød Agent", + "MERGE ON UPDATE": "Flet ved opdatering", + "MERGE_CHANGES_LOCAL": "Lokale ændringer", + "MERGE_CHANGES_MERGE": "Flet resultat", + "MERGE_CHANGES_REMOTE": "Fjernændringer", + "MERGE_LOCAL": "Behold lokale", + "MERGE_MESSAGE": "Det ser ud til, at {opName} har lokale ændringer. Vil du flette dine ændringer med server-OP'en, bruge serverversionen eller beholde den lokale version?", + "MERGE_REBASE": "Flet", + "MERGE_REPLACE": "Brug server", + "MERGE_TITLE": "Flet lokal&fjern OP", + "MIN_SRC_PORT_LVL": "Minimums level påkrævet på kildeportalen", + "MINUTES": " ({minutes} minutter siden)", + "MM": "Multimax", + "MULTI_M_TITLE": "Tegn Max Lag", + "MULTI_M": "Tegn", + "MUST_NOT_BE_EMPTY": "Må ikke være tom", + "MY_CAP_ID": "Mit kapsel ID", + "MY_COUNT": "Mit Antal", + "NAME_REQ": "Navn påkrævet", + "NAME": "Navn: ", + "NEW_OP": "Ny operation", + "NEW_TEAM_NAME": "Nyt holdnavn", + "NEW_TEAM": "Nyt hold", + "NEW_WAS_SERVER": "Ny Wasabee Server", + "NEWOP BUTTON TITLE": "Opret en ny operation", + "NEWOP BUTTON": "Ny Op", + "NO_DT_ITEMS": "Ingen DrawTools tegnede elementer fundet", + "NO_LABEL": "Ingen etiket sat", + "NO_STOCK_INTEL": "Wasabee understøtter ikke stock intel tegninger", + "NO_TITLE": "Ingen titel angivet", + "NOT LOGGED IN SHORT": "Ikke logget ind", + "NOT LOGGED IN": "Ikke logget ind: {error}", + "NOT_SET": "ikke indstillet", + "NTNAME": "Navn", + "OK": "OK", + "ON_HAND": "Har Allerede", + "ONION_WAS_TAKEN": "Onion", + "ONION": "Draw", + "ONLY_DT_IMP": " (kun for DrawTools-import)", + "OP DELETED": "Operationen fjernet fra serveren: {opID}", + "OP PERM DENIED": "Tilladelse nægtet til operationen: {opID}", + "OP_BUTTON": "Operation", + "OP_CHECKLIST": "Operation Checklist: {opName}", + "OP_NAME_UNSET": "Operationsnavn blev deaktiveret", + "OP_PERMS": "Op Tilladelser", + "OP_SETTINGS_BUTTON": "Op ⚙", + "OP_SETTINGS_TITLE": "Op Indstillinger", + "OPEN_REQUEST": "[åbn anmodning]", + "OPER_COLOR": "Operation Farve: ", + "OPER_NAME": "Operation Navn: ", + "OPERATIONS": "Operationer", + "OPS BUTTON TITLE": "Operations Liste", + "OPS BUTTON": "Vælg OP", + "ORDER": "Sorter", + "OtherPortalAlert": "Andet", + "PASTE_INSTRUCT": "Indsæt en Wasabee draw-eksport her.\n\nWasabee kan ikke importere stock intel-formatet.\n\nDer er eksperimentel understøttelse af import af IITC DrawTools-formatet.\n\nFør du importerer DrawTools-formatet, skal du forhåndsvise områderne og sørge for, at alle portalerne indlæses så IITC har dem cachelagret. Alle portaler, der ikke er pre-cached, vil blive forfalsket.\n\nDu bliver nødt til at bruge 'swap'-funktionen til at flytte ankre fra de falske portaler til de rigtige portaler (de bør være på den korrekte placering, bare ikke forbundet med portal.\n\nCachede portaler er muligvis ikke korrekt navngivet.", + "pending": "Afventer", + "PERMS": "{opName} tilladelser", + "PLEASE_SELECT_PORTAL": "Vælg venligst en portal", + "PORT_FAKE": " portaler. Forfalsket ", + "PORTAL KEY LIST": "Nøgleliste for portal {portalName}", + "PORTAL_COUNT": "{count} portaler", + "PORTAL": "Portal", + "QD BUTTON CHANGE COLOR": "Klik for at ændre farve på næste link", + "QD BUTTON END": "Klik for at stoppe med at tegne felter", + "QD BUTTON TOGGLE MODE": "Klik for at ændre tegnetilstand", + "QD CHANGE COLOR": "Skift farve", + "QD END": "Slut", + "QD TITLE": "Hurtig tegn lag", + "QD TOGGLE MODE": "Skift tilstand", + "QDBASE": "Base Link", + "QDCONT": "Klik på en baglinieportal for at tegne et felt.", + "QDNEXT": "Klik på den anden ankerportal.", + "QDSTART": "Klik på den første ankerportal.", + "READ_SHORT": "L", + "READ": "Læs", + "RechargePortalAlert": "Recharge", + "REFERENCE_TIME": "Referencetid: ", + "REM_LOC_CP": "Fjern lokal kopi af {opName}", + "REMOVE_TEAM_CONFIRM_LABEL": "Vil du permanent fjerne {team Name} fra Wasabi-serveren?", + "REMOVE_TEAM_CONFIRM_TITLE": "Fjern hold {teamName}", + "REMOVE_TEAM": "Fjern hold: ", + "REMOVE": "Fjern", + "RENAME_TEAM": "Omdøb hold: ", + "RENAME": "Omdøb", + "REQUIRED": "Påkrævet", + "RESET": "Nulstil", + "REVERSE": "Endevend", + "ROCKS_COM": "enl.rocks community: ", + "ROLE": "Rolle", + "SAVELINKS TITLE": "Gem Links", + "SAVELINKS_DRAW": "Gem Links", + "SAVELINKS": "Gem Links", + "SECONDS": " ({seconds} sekunder siden)", + "SEL_SB_ANCHOR": "Vælg ankerportal.", + "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", + "SEL_SL_ANCHOR": "Vælg den portal, du vil gemme links til. Klik på knappen Gem links og se på tjeklisten.", + "SEL_SRC_ANC2": "Vælg både Kilde og Anker 2", + "SEL_SRC_PORT": "Vælg en kildeportal", + "SELECT PORTAL": "Vælg venligst en portal først", + "SELECT_FAN_PORTALS": "Vælg en ankerportal, en startportal og en slutportal, og fokuser over markområdet.", + "SELECT_FAN_PORTALS2": "Vent på, at alle portaler er indlæst, og klik derefter på tegn.", + "SELECT_INSTRUCTIONS": "Vælg to ankerportaler, og zoom derefter over rygsøjlen.", + "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", + "SELF SWAP": "Kan ikke bytte en portal med sig selv! Vælg en anden portal.", + "SEND ANALYTICS": "Send anonyme analysedata", + "SEND LOCATION": "Send placering", + "SEND TARGET AGENT": "Vælg modtager agent", + "SEND TARGET CONFIRM": "Vil du sende {portalName}-målet til {agent}?", + "SEND TARGET": "Send mål", + "SEND_LOC": "Send placering", + "SET_3_PORT": "Indstil venligst de tre portaler først!", + "SET_COMMENT": "Indstil kommentar", + "SET_LCOMMENT": "Indstil linkkommentar", + "SET_LINK_COMMENT": "Indstil kommentar til link: ", + "SET_LINKS_ZONES": "Indstil links til zoner ", + "SET_MARKER_COMMENT": "Sæt kommentar til markør på: ", + "SET_MARKER_TYPE_TITLE": "Skift markørtype", + "SET_MARKERS_ZONES": "Indstil markører til zoner", + "SET_MCOMMENT": "Indstil markørkommentar: {portalName}", + "SET_NEW_OP": "Indstil venligst det nye operationsnavn", + "SET_PCOMMENT": "Indstil portalkommentar: {portalName}", + "SET_PORT_COMMENT": "Indstil kommentar til portal: ", + "SET_PORTAL_COMMENT": "Indstil portalkommentar", + "SET": "set", + "SETTINGS": "Wasabee Indstillinger", + "SKINS_AVAILABLE": "Der er {count} tilgængelige skins.", + "SKINS_BUTTON": "Konfigurer skins", + "SKINS_DESCRIPTION": "Tilgængelige skin packs er placeret i højre kolonner. Flyt skins, du ønsker at bruge, til venstre kolonne.", + "SKINS_MANAGE_TITLE": "Administrer skins", + "SKIP_CONFIRM_ALWAYS": "Spørg aldrig (brug med forsigtighed)", + "SKIP_CONFIRM_ENTITY": "Spørg kun for hold/op", + "SKIP_CONFIRM_NEVER": "Spørg altid", + "SKIP_CONFIRM": "Spring bekræftelse over", + "SOURCE_PORT": "Kildeportal ", + "SQUAD": "hold", + "STARBURST TITLE": "Starburst", + "STARBURST_DRAW": "Tegn", + "STARBURST": "Starburst", + "START_PORT": "Start Portal ", + "STATE": "Status", + "SUPPORT_INSTRUCT": "For at få support, tilmeld dig Wasabee bruger Telegram kanal", + "SWAP PROMPT": "Vil du bytte: ", + "SWAP TITLE": "Byt portaler", + "SWAP WITH": " med ", + "SWAP": "Byt", + "SYNC DONE": "Download Complete
Click HERE for hints, tips, and documentation.", + "SYNC": "Download tilgængelige operationer", + "TARGET SENT": "Mål sendt", + "TEAM STATE": "Del placering", + "TEAM_CREATED": "Hold {teamName} oprettet", + "TEAM_NAME": "Hold navn", + "TEAM": "Hold", + "TEAMS BUTTON TITLE": "Liste over Wasabee-holdene", + "TEAMS BUTTON": "Hold", + "TO_PORT": "Til Portal", + "TRAWL SKIP TILES": "Trawl Skip fliser", + "TRAWL TITLE": "Trawl baner", + "TRAWL WARNING": "Dette vil indlæse flisedataene under alle tegnede links. Dette er en langsom proces.", + "TRAWL_AUTOMARK": "Automærke blokere efter trawl", + "TRAWL_BULK_LOAD_WARNING": "Denne metode indlæser flisedataene så hurtigt som muligt. Brug på eget ansvar.", + "TRAWL_BULK_LOAD": "Masseindlæsning af flisedata", + "TRAWL_CLEAR_MARKERS": "Ryd virus/ødelæggelsesmarkører før trawl", + "TRAWL_REMAINING": "{count} fliser tilbage", + "TRAWL": "Trawl efter blokere", + "TRAWLING": "Når du trawler banerne efter blokeringer, luk denne dialog for at stoppe", + "TYPE": "Type", + "UNASSIGNED": "Ikke tildelt", + "UNKNOWN": "Ukendt", + "UPDATE HOVER NOT CHANGED": "{opName} ikke ændret lokalt", + "UPDATE HOVER": "OPDATER {opName} på serveren", + "UPDATE_CONFLICT_DESC": "OP er blevet ændret på serveren siden sidste synkronisering. Ønsker du at erstatte serverversionen med den nuværende?", + "UPDATE_CONFLICT_TITLE": "Konflikt opdaget med server", + "UPDATE_COUNT": "Opdater optælling", + "UPDATED": "Opdateret", + "UpgradePortalAlert": "Upgrader", + "UPLOAD BUTTON HOVER": "UPLOAD {opName} (ikke på serveren i øjeblikket)", + "UPLOAD PERM DENIED": "Tilladelse til at uploade nægtet", + "UPLOADED": "Uploadet", + "USE PANES ON MOBILE": "Brug rammer (skal genindlæses)", + "USE_SWAP_INSTRUCT": ". Brug venligst swap-funktionen til at flytte falske portaler til de rigtige portaler på samme sted. Zoom ind på 'Loading'-portalerne i tjeklisten kan tvinge dem til at indlæse.", + "USE_VALID_NAME": "Brug venligst et gyldigt operationsnavn", + "UseVirusPortalAlert": "Brug Virus", + "VRLA DESC": "Afhængigt af antallet og typen af anvendte linkforstærkere kan et lavere kildeportal level være tilstrækkeligt.", + "VRLA": "L8+nogle VRLA", + "WASABEE BUTTON TITLE": "Wasabee: den er grøn og får smølfer til at græde.", + "WASABEE_D_LIST": "Input antal forsvarsnøgler", + "WD BUTTON TITLE": "Log forsvarsnøgler", + "WD BUTTON": "W-D Nøgler", + "WEBVIEW VERIFY": "Bekræft webvisning", + "WEBVIEW": "Webview Log på (iOS)", + "WRITE_SHORT": "S", + "WRITE": "Skrive", + "WSERVER": "Server: {url}", + "YESNO_DEL": "Er du sikker på, at du vil slette {opName}?", + "ZONE_DRAW": "Klik for at indstille zonegrænserne", + "ZONE": "Zone", + "smallScreen": { + "ADD_LINKS": "+ Links", + "ADD_MARKER": "+ Markør", + "BLOCKER TITLE": "Blokere", + "CHECKLIST BUTTON": "Kontrollere", + "CLEAROPS BUTTON": "Klar", + "EXPORT OP": "Eksporter", + "FAN_FIELD3": "Fan", + "FANFIELD": "Tegn", + "FANFIELD2": "Tegn Fan Field", + "KEYS": "Nøgler", + "LOG IN": "Log Ind", + "LOG_OUT": "Log Ud", + "MARKER LIST": "Markørere", + "MARKERS BUTTON TITLE": "Markørere", + "MAX": "Fan", + "MM": "Multi", + "MULTI_M_TITLE": "Tegn Max Lag", + "MULTI_M": "Tegn", + "NEWOP BUTTON": "Ny Op", + "OPS BUTTON": "Vælg OP", + "QD END": "Stop", + "STARBURST_DRAW": "Tegn", + "STARBURST": "Star", + "TEAMS BUTTON": "Hold", + "WD BUTTON": "W-D Nøgler" + } +} From f54dc8c6baf4db00f565c7d7380c41c72aa58441 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:22:23 -0600 Subject: [PATCH 076/275] Add Danish and Russian languages From 70416ae412864e3fb3cfe239e012c4c8a8976f13 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:23:00 -0600 Subject: [PATCH 077/275] Remove 39 unused keys --- src/code/translations/english.json | 38 ------------------------------ 1 file changed, 38 deletions(-) diff --git a/src/code/translations/english.json b/src/code/translations/english.json index 2dbfa9f53..d81ac5896 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -1,5 +1,4 @@ { - "ABOUT WASABEE-IITC": "About Wasabee-IITC", "ABOUT_WASABEE": "About Wasabee", "acknowledged": "Acknowledged", "ADD LINK TITLE": "Add Links", @@ -39,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Assigned Only", "assigned": "Assigned", - "ASSIGNED": "Assigned", "AUTH ANDROID": "On Android, try 'quick' first. If that fails, try the main login with 'select_account'.", "AUTH INCOMPAT": "You have activated a plugin in TamperMonkey that is incompatable with Wasabee", "AUTH IOS": "On iOS, use the main 'Log In' option. If that fails, use 'Webview Login' then use the 'Verify Webview' button to complete the process.", @@ -75,9 +73,7 @@ "COMMENT": "Comment", "COMPLETED BY": "Completed by {agentName}", "completed": "Completed", - "COMPLETED": "Completed", "CON_DEL": "Confirm Delete: {opName}", - "CONFIRM_DELETE": "Do you really want to delete this link: ", "COUNT": "Count", "CREATE_NEW_TEAM": "Create New Team", "CreateLinkAlert": "Link", @@ -88,19 +84,12 @@ "DELETE ANCHOR TITLE": "Delete Anchor", "DELETE MARKER PROMPT": "Do you want to delete this marker: ", "DELETE MARKER TITLE": "Delete Marker", - "DELETE PERM DENIED": "Permission to delete denied.", "DELETE_ANCHOR": "Delete", "DELETE_LINK": "Delete", - "DELETE_MARKER": "Delete", "DELETE_OP": "Delete {opName}", - "DELETED": "Successfully deleted.", "DESCRIP_PLACEHOLD": "Description (optional)", "DestroyPortalAlert": "Destroy", - "DISABLE_SYNC": "The IITC Sync plugin is not compatible with Wasabee. Please disable Sync.", - "DISABLED": "This feature is not ready for users", - "DONE": "Done", "DRAW TOOLS FORMAT": "Draw Tools Format", - "DT_FORMAT": "Draw Tools Format", "DUPE_OP": "Duplicate Operation", "END_PORT": "End Portal ", "ExcludeMarker": "Exclude from Auto-Draw/Mark", @@ -108,8 +97,6 @@ "EXPORT OP": "Export Op", "EXPORT": "Export: ", "FAKED": "Faked: [{portalId}]", - "FAN_FIELD3": "Fan Field", - "FANFIELD TITLE": "Fanfield", "FANFIELD": "Draw", "FANFIELD2": "Draw Fan Field", "FarmPortalMarker": "Farm", @@ -124,19 +111,16 @@ "FROM_DEPTH": "from the depth", "FROM_PORT": "From Portal", "GET DT": "Get existing DrawTools draw", - "GET_DT_DRAW": "Import draw from IITC Draw Tools", "GetKeyPortalMarker": "Get Keys", "GotoPortalMarker": "Go To", "H-GEN_INST": "Set portals for the outside layer. Choose number of splits. Click draw", "HF_DEEP_SEARCH": "Exhaustive search", "HF_DRAW_BUTTON": "Draw", - "HF_DRAW_DEEP_BUTTON": "Draw with deep recursion", "HF_REDRAW_BUTTON": "Redraw", "HG": "Homogeneous Field", "HOURS": " ({hours} hours ago)", "HOW_TO_VIDS": "

How-To Videos:

", "IMP_COMP": "Import Complete. Found ", - "IMP_DT_OP": "Imported Drawtools Op: ", "IMP_NOPE": "Import Failed: {error}", "IMP_WAS_OP": "Import Wasabee Operation", "IMPORT_OP_SUCCESS": "Imported Operation: {opName} successfuly.", @@ -166,10 +150,8 @@ "LOADING": "[loading]", "LOADING1": "Loading: [{portalGuid}]", "LOC_PROC": "location processed", - "LOC_UPDATE": "Location Update", "LOCATION SUB": "Location registered", "LOCFRMSER": " (locally and from server)", - "LOG IN QUICK": "Log In (quick; for Android)", "LOG IN": "Log In", "LOG_OUT": "Log Out", "MADRID_SET_1": "Select the region for baselink Anchor 2 to Anchor 3", @@ -209,8 +191,6 @@ "MM_SPINE": "Spine", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Draw", - "MULTIMAX": "Multimax!", - "MULTIMAX2": "Multimax", "MUST_NOT_BE_EMPTY": "Must Not Be Empty", "MY_CAP_ID": "My Capsule ID", "MY_COUNT": "My Count", @@ -222,16 +202,12 @@ "NEW_WAS_SERVER": "New Wasabee Server", "NEWOP BUTTON TITLE": "Create a new Operation", "NEWOP BUTTON": "New Op", - "NO_DATA": "No data", "NO_DT_ITEMS": "No DrawTools drawn items detected", "NO_LABEL": "No label set", - "NO_PORT_SEL": "No Portal Selected.", "NO_STOCK_INTEL": "Wasabee doesn't support stock intel draw imports", "NO_TITLE": "No title set", - "NO": "No", "NOT LOGGED IN SHORT": "Not Logged in", "NOT LOGGED IN": "Not Logged in: {error}", - "NOT_LOADED": "Not fully loaded, try again.", "NOT_SET": "not set", "NTNAME": "Name", "OK": "OK", @@ -257,11 +233,7 @@ "OtherPortalAlert": "Other", "PASTE_INSTRUCT": "Paste a Wasabee draw export here.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", "pending": "Pending", - "PENDING": "Pending", "PERMS": "{opName} permissions", - "PICK_DEST_FIRST": "Please select a destination portal first!", - "PICK_TAR_FIRST": "Please select a target portal first!", - "PICK_TARGETDEST_Portals": "Please select target and destination portals first!", "PLEASE_SELECT_PORTAL": "Please select a portal", "PORT_FAKE": " portals. Faked ", "PORTAL KEY LIST": "Key list for portal {portalName}", @@ -275,9 +247,7 @@ "QD TITLE": "Quick Draw Layers", "QD TOGGLE MODE": "Change mode", "QDBASE": "Base Link", - "QDCANCEL": "Cancel Drawing Fields", "QDCONT": "Click a spine portal to draw a field.", - "QDEND": "Click again on the same portal to finish drawing.", "QDNEXT": "Click the second anchor portal.", "QDSTART": "Click the first anchor portal.", "READ_SHORT": "RO", @@ -300,10 +270,8 @@ "SAVELINKS_DRAW": "Save Links", "SAVELINKS": "Save Links", "SECONDS": " ({seconds} seconds ago)", - "SEL_PORT_FIRST": "Please select anchor portals first!", "SEL_SB_ANCHOR": "Select the anchor.", "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", - "SEL_SB_ANCHOR3": "Please be patient, it can take a bit.", "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", "SEL_SRC_ANC2": "Select both Source and Anchor 2", "SEL_SRC_PORT": "Select a source portal", @@ -311,7 +279,6 @@ "SELECT_FAN_PORTALS": "Select an anchor portal, a start portal, and an end portal, then position the view over the field area.", "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", "SELECT_INSTRUCTIONS": "Select two anchor portals, then zoom over the spine area.", - "SELECT_MADRID_INSTRUCTIONS": "Select three anchor portals, zoom in on the area near the selected anchor, wait until the portals are loaded (portals must be on screen to be considered) then select the 'define spine region' button for the corresponding base links.", "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", "SELF SWAP": "Cannot swap a portal with itself! Select a different portal.", "SEND ANALYTICS": "Send Anonymous Analytics", @@ -357,16 +324,13 @@ "SWAP": "Swap", "SYNC DONE": "Download Complete
Click HERE for hints, tips, and documentation.", "SYNC": "Download Available Operations", - "TARDEST_DIFF": "Target and destination portals must be different.", "TARGET SENT": "Target sent", - "TEAM PERM DENIED": "Permission denied to team: {error}", "TEAM STATE": "Share Location", "TEAM_CREATED": "Team {teamName} created", "TEAM_NAME": "Team Name", "TEAM": "Team", "TEAMS BUTTON TITLE": "List Wasabee Teams", "TEAMS BUTTON": "Teams", - "TITLE": "title", "TO_PORT": "To Portal", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", @@ -390,7 +354,6 @@ "UPDATED": "Successfully updated", "UpgradePortalAlert": "Upgrade", "UPLOAD BUTTON HOVER": "UPLOAD {opName} (not currently on server)", - "UPLOAD PERM DENIED": "Permission to upload denied", "UPLOADED": "Successfully uploaded", "USE PANES ON MOBILE": "Use panes (need reload)", "USE_SWAP_INSTRUCT": ". Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", @@ -407,7 +370,6 @@ "WRITE_SHORT": "RW", "WRITE": "write", "WSERVER": "Server: {url}", - "YES": "Yes", "YESNO_DEL": "Are you sure you want to delete {opName}?", "ZONE_DRAW": "Click to set the zone boundaries", "ZONE": "Zone", From a2b2413a4b07cfedb64f866cb937538d4663e784 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:23:57 -0600 Subject: [PATCH 078/275] Remove 39 unused keys --- src/code/translations/filipino.json | 39 ----------------------------- 1 file changed, 39 deletions(-) diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index 789b5763c..3c71f260f 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -1,5 +1,4 @@ { - "ABOUT WASABEE-IITC": "Tungkol sa Wasabee-IITC", "ABOUT_WASABEE": "Tungkol sa Wasabee", "acknowledged": "Natanggap", "ADD LINK TITLE": "Magdagdag ng Links", @@ -39,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Assigned Only", "assigned": "Naitalaga", - "ASSIGNED": "Naitalaga", "AUTH ANDROID": "Sa Android, subukan muna ang 'quick'. Kung hindi gumana, subukan ang main login gamit ang 'select_account'.", "AUTH INCOMPAT": "May ginagamit kang plugin sa TamperMonkey na hindi angkop sa Wasabee", "AUTH IOS": "Sa iOS, subukan muna ang 'Log In'. Kung hindi gumana, gawin ang 'Webview Log in', mag-log in, tapos gamitin ang 'Verify Webview' button para makumpleto ang proseso.", @@ -67,7 +65,6 @@ "CLEAR LINKS": "Clear Links", "CLEAR MARKERS": "Clear Markers", "CLEAR_EVERYTHING": "Burahin Portals/Links/Markers", - "CLEAR": "Burahin ang Pinili", "CLEAROPS BUTTON TITLE": "Burahin lahat ng locally stored na operasyon", "CLEAROPS BUTTON": "Burahin Local Ops", "CLEAROPS PROMPT": "Nais mo bang tangalin ang lahat ng opersyon sa local storage? Ang mga Ops na nakalagay sa server ay mababawi sa susunod na sync.", @@ -75,9 +72,7 @@ "COMMENT": "Komentaryo", "COMPLETED BY": "Nakumpleto ni {agentName}", "completed": "Naikumpleto", - "COMPLETED": "Naikumpleto", "CON_DEL": "Kumpirmahin ang Pagtangal: {opName}", - "CONFIRM_DELETE": "Gusto mo bang tangalin ang link: ", "COUNT": "Bilang", "CREATE_NEW_TEAM": "Magbuo ng bagong Pangkat", "CreateLinkAlert": "Link", @@ -88,19 +83,12 @@ "DELETE ANCHOR TITLE": "Tanggalin ang Anchor", "DELETE MARKER PROMPT": "Gusto mo bang tangalin ang marker na ito: ", "DELETE MARKER TITLE": "Tanggalin ang Marker", - "DELETE PERM DENIED": "Walang pahintulot para mag tangal", "DELETE_ANCHOR": "Tangalin", "DELETE_LINK": "Tangalin", - "DELETE_MARKER": "Tangalin", "DELETE_OP": "Tangalin {opName}", - "DELETED": "Matagumpay na naitangal", "DESCRIP_PLACEHOLD": "Description (opsyonal)", "DestroyPortalAlert": "Sirain", - "DISABLE_SYNC": "Ang Wasabee at stock sync plugin ay hindi compatible. Paki disable sync para gamitin ang Wasabee", - "DISABLED": "Hindi pa handa ang feature na ito", - "DONE": "Tapos", "DRAW TOOLS FORMAT": "Draw Tools Format", - "DT_FORMAT": "Draw Tools Format", "DUPE_OP": "Kopyahin ang Operasyon", "END_PORT": "End Portal ", "ExcludeMarker": "Ibukod sa Auto-Draw/Pag-marka", @@ -108,8 +96,6 @@ "EXPORT OP": "I-Export ang Op", "EXPORT": "Export: ", "FAKED": "Faked: [{portalId}]", - "FAN_FIELD3": "Fan Field", - "FANFIELD TITLE": "Fanfield", "FANFIELD": "Guhit", "FANFIELD2": "Iguhit ang Fanfield", "FarmPortalMarker": "Farm", @@ -124,19 +110,16 @@ "FROM_DEPTH": "from the depth", "FROM_PORT": "Mula sa Portal", "GET DT": "Get existing DrawTools draw", - "GET_DT_DRAW": "Kunin ang current DrawTools draw", "GetKeyPortalMarker": "Kunin ang Keys", "GotoPortalMarker": "Pumunta", "H-GEN_INST": "Set portals for the outside layer. Choose number of splits. Click draw", "HF_DEEP_SEARCH": "Exhaustive search", "HF_DRAW_BUTTON": "Draw", - "HF_DRAW_DEEP_BUTTON": "Draw with deep recursion", "HF_REDRAW_BUTTON": "Redraw", "HG": "Homogeneous Field", "HOURS": " ({hours} oras nakalipas)", "HOW_TO_VIDS": "

How-To Videos:

", "IMP_COMP": "Natapos ang Pag Import. ", - "IMP_DT_OP": "Na-Import na Drawtools Op: ", "IMP_NOPE": "Pag-I-Import Hindi Matagumpay: {error}", "IMP_WAS_OP": "I-Import ang Wasabee operasyon", "IMPORT_OP_SUCCESS": "Na-Import na Operasyon: {opName} Matagumpay.", @@ -166,10 +149,8 @@ "LOADING": "[loading]", "LOADING1": "Loading: [{portalGuid}]", "LOC_PROC": "Lokasyon nai-proseso", - "LOC_UPDATE": "Pag-update ng Lokasyon", "LOCATION SUB": "Nairehistro ang lokasyon", "LOCFRMSER": " (locally at sa server)", - "LOG IN QUICK": "Log In (quick; for Android)", "LOG IN": "Mag Log In", "LOG_OUT": "Log Out", "MADRID_SET_1": "Select the region for baselink Anchor 2 to Anchor 3", @@ -209,8 +190,6 @@ "MM_SPINE": "Spine", "MULTI_M_TITLE": "Gumuhit ng Max Layers", "MULTI_M": "Multimax", - "MULTIMAX": "Multimax!", - "MULTIMAX2": "Multimax", "MUST_NOT_BE_EMPTY": "Hindi maari na walang laman", "MY_CAP_ID": "Aking Capsule ID", "MY_COUNT": "Aking Bilang", @@ -222,16 +201,12 @@ "NEW_WAS_SERVER": "Bagong Waasbee Server", "NEWOP BUTTON TITLE": "Bumuo ng bagong Operasyon", "NEWOP BUTTON": "Bagong Op", - "NO_DATA": "Walang Data", "NO_DT_ITEMS": "Walang DrawTools drawn items na nakita", "NO_LABEL": "Walang tatak", - "NO_PORT_SEL": "Walang napili na Portal.", "NO_STOCK_INTEL": "Hindi suportado ng Wasabee ang stock intel draw imports", "NO_TITLE": "Walang Pamagat", - "NO": "Hindi", "NOT LOGGED IN SHORT": "Hindi naka-Logged in", "NOT LOGGED IN": "Hindi naka-Logged in {error}", - "NOT_LOADED": "Hindi nai-load, ulitin muli.", "NOT_SET": "hindi naitalaga", "NTNAME": "Pangalan", "OK": "OK", @@ -257,11 +232,7 @@ "OtherPortalAlert": "Iba", "PASTE_INSTRUCT": "I-Paste ang Wasabee draw export dito.\n\nHindi ma-import ng Wasabee ang stock intel format.\n\nMerong experimental na suporta para sa pag-import ng IITC DrawTools format.\n\nBago i-import ang DrawTools format, tignan ang mga areas at siguraduhing lahat ng portals naka-load para naka-cached ito sa IITC. Ang mga portals na hindi pre-cached ay that are not pre-cached ay ipapalit ng 'fake' portal.\n\nKailangan mong gamitin ang 'Ipagpalit' feature para ipatlit ang mga anchor mula sa fake portal sa tamang portal. (ang portal ay dapat nasa tamang lokasyon.\n\nAng mga pangalan ng naka-Cached na portals ay hindi maaring nakapangalan ng tama.)", "pending": "Nakabinbin", - "PENDING": "Nakabinbin", "PERMS": "{opName} permisyo", - "PICK_DEST_FIRST": "Pumili muna ng destinasyon na portal!", - "PICK_TAR_FIRST": "Pumili muna ng simulang portal!", - "PICK_TARGETDEST_Portals": "Pumili muna ng simula and destinasyon na portals!", "PLEASE_SELECT_PORTAL": "Pumili ng portal", "PORT_FAKE": " portals ang nakita. Faked ", "PORTAL KEY LIST": "Listahan ng Key para sa Portal {portalName}", @@ -275,9 +246,7 @@ "QD TITLE": "Mabilisang Pagukit ng Layers", "QD TOGGLE MODE": "Change mode", "QDBASE": "Base Link", - "QDCANCEL": "Kanselahin Pagukit ng Fields", "QDCONT": "I-Click ang mga spine portal para I-drawing ang field.", - "QDEND": "I-Click muli ang kaparehong portal para tapusin ang pagukit.", "QDNEXT": "I-Click ang pangalawang anchor portal.", "QDSTART": "I-Click ang unang anchor portal.", "READ_SHORT": "RO", @@ -300,10 +269,8 @@ "SAVELINKS_DRAW": "Save Links", "SAVELINKS": "Save Links", "SECONDS": " ({seconds} segundong nakalipas)", - "SEL_PORT_FIRST": "Pumili muna ng anchor portals!", "SEL_SB_ANCHOR": "Pillin ang anchor, I-zoom sa area para dagdagan sa starburst", "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", - "SEL_SB_ANCHOR3": "Please be patient, it can take a bit.", "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", "SEL_SRC_ANC2": "Piliin ang Panimula at Anchor 2", "SEL_SRC_PORT": "Pumili ng panimulang portal", @@ -311,7 +278,6 @@ "SELECT_FAN_PORTALS": "Pumili ng mga anchor portals, (isang panimulang portal at panghuling portal) tapos i-zoom in sa lugar na i-fan field, hintayin na mag load ang mga portals (dapat nasa screen ang mga portals) at pindutin ang Fanfield button.", "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", "SELECT_INSTRUCTIONS": "Pumili ng dalawang anchor portals, tapos i-zoom in sa lugar para sa spine, hintayin mag-load ang mga portals (dapat nasa screen ang mga portals para gumana) tapos pindutin ang Multimax button.", - "SELECT_MADRID_INSTRUCTIONS": "Select three anchor portals, zoom in on the area near the selected anchor, wait until the portals are loaded (portals must be on screen to be considered) then select the 'define spine region' button for the corresponding base links.", "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", "SELF SWAP": "Hindi maaari ipagpalit ang portal sa sarili! Pumili ng ibang portal.", "SEND ANALYTICS": "Send Anonymous Analytics", @@ -357,16 +323,13 @@ "SWAP": "Ipagpalit", "SYNC DONE": "Matagumpay na i-Download
Mag-click DITO para sa mga pahiwatig, tip, at dokumentasyon.", "SYNC": "I-Download ang Matatamo na mga Operasyon", - "TARDEST_DIFF": "Dapat magkaiba ang simula at destinasyon na portals.", "TARGET SENT": "Naipadala ang Target", - "TEAM PERM DENIED": "Walang pahintulot sa pangkat {error}", "TEAM STATE": "Share Location", "TEAM_CREATED": "Pangkat {teamName} nabuo", "TEAM_NAME": "Pangalan ng Pangkat", "TEAM": "Pangkat", "TEAMS BUTTON TITLE": "I-Lista mga Wasabee Pangkat", "TEAMS BUTTON": "Pangkat", - "TITLE": "Pamagat", "TO_PORT": "Papunta sa Portal", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", @@ -390,7 +353,6 @@ "UPDATED": "Matagumpay na i-update", "UpgradePortalAlert": "Upgrade", "UPLOAD BUTTON HOVER": "UPLOAD {opName} (kasalukuyang wala sa server)", - "UPLOAD PERM DENIED": "Walang pahintulot para sa pag-upload", "UPLOADED": "Matagumpay na i-upload", "USE PANES ON MOBILE": "Use panes (need reload)", "USE_SWAP_INSTRUCT": ". Gamitin ang 'Ipagpalit' na feature para ipalit ang 'faked' portals sa totoong portals. Ang pag zoom sa 'Loading' portals sa listahan ay posibleng ma-'force load' ito.", @@ -407,7 +369,6 @@ "WRITE_SHORT": "RW", "WRITE": "isulat", "WSERVER": "Server: {url}", - "YES": "Oo", "YESNO_DEL": "Sigurado ka na gusto mo burahin ang {opName}?", "ZONE_DRAW": "Click to set the zone boundaries", "ZONE": "Zoned", From f10ea5b2e13678832bd5069ae8e69bbdfcf29b1b Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:25:24 -0600 Subject: [PATCH 079/275] Remove 39 unused keys --- src/code/translations/french.json | 39 ------------------------------- 1 file changed, 39 deletions(-) diff --git a/src/code/translations/french.json b/src/code/translations/french.json index c8effcc06..4d751943e 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -1,5 +1,4 @@ { - "ABOUT WASABEE-IITC": "À propos de Wasabee-IITC", "ABOUT_WASABEE": "Au sujet de Wasabee", "acknowledged": "Noté", "ADD LINK TITLE": "Ajouter des liens", @@ -39,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Seulement les affectations", "assigned": "Assigné", - "ASSIGNED": "Assigné", "AUTH ANDROID": "On Android, try 'quick' first. If that fails, try the main login with 'select_account'.", "AUTH INCOMPAT": "You have activated a plugin in TamperMonkey that is incompatable with Wasabee", "AUTH IOS": "On iOS, use the main 'Log In' option. If that fails, use 'Webview Login' then use the 'Verify Webview' button to complete the process.", @@ -67,7 +65,6 @@ "CLEAR LINKS": "Supprimer les liens", "CLEAR MARKERS": "Supprimer les marqueurs", "CLEAR_EVERYTHING": "Supprimer Portails/Links et Marquers", - "CLEAR": "Effacer", "CLEAROPS BUTTON TITLE": "Supprimer TOUTES les données Wasabee", "CLEAROPS BUTTON": "Supprimer les données Wasabee", "CLEAROPS PROMPT": "Toutes les opérations et données relatives à Wasabee seront supprimées de cet appareil. Seules les données présentes sur le/les serveurs seront récupérées à la prochaine synchronisation.", @@ -75,9 +72,7 @@ "COMMENT": "Commentaire", "COMPLETED BY": "Fait par {agentName}", "completed": "Completée", - "COMPLETED": "Completée", "CON_DEL": "Confirmer la suppression : {opName}", - "CONFIRM_DELETE": "Voulez-vous vraiment supprimer ce lien :", "COUNT": "Nombre", "CREATE_NEW_TEAM": "Créer une équipe", "CreateLinkAlert": "Lien", @@ -88,19 +83,12 @@ "DELETE ANCHOR TITLE": "Supprimer une ancre", "DELETE MARKER PROMPT": "Voulez vous supprimer le marqueur :", "DELETE MARKER TITLE": "Supprimer un marqueur", - "DELETE PERM DENIED": "Suppression interdite", "DELETE_ANCHOR": "Supprimer", "DELETE_LINK": "Supprimer", - "DELETE_MARKER": "Supprimer", "DELETE_OP": "Supprimer {opName}", - "DELETED": "Suppression faite.", "DESCRIP_PLACEHOLD": "Description (optionnelle)", "DestroyPortalAlert": "Casse", - "DISABLE_SYNC": "Le plugin \"Sync\" n'est pas compatible avec Wassabe. Désactiver le pour continuer", - "DISABLED": "Cette fonction n'est pas encore disponible", - "DONE": "Fait", "DRAW TOOLS FORMAT": "Format DrawTools", - "DT_FORMAT": "Format DrawTools", "DUPE_OP": "Dupliquer l'opération", "END_PORT": "Portail de fin", "ExcludeMarker": "Exclure d'Auto-Draw/Mark", @@ -108,8 +96,6 @@ "EXPORT OP": "Exporter", "EXPORT": "Exporter : ", "FAKED": "Faux [{portalId}]", - "FAN_FIELD3": "Fan Field", - "FANFIELD TITLE": "Fanfield", "FANFIELD": "Draw", "FANFIELD2": "Draw Fan Field", "FarmPortalMarker": "Farm", @@ -124,19 +110,16 @@ "FROM_DEPTH": "depuis l'intérieur vers l'extérieur", "FROM_PORT": "Depuis le Portail", "GET DT": "Récupérer le dessin actuel", - "GET_DT_DRAW": "Importer une dessin de DrawTools", "GetKeyPortalMarker": "Clés", "GotoPortalMarker": "Aller à", "H-GEN_INST": "Choisissez les 3 portails du field englobant, le nombre de couches et cliquez sur Draw.", "HF_DEEP_SEARCH": "Recherche exhaustive", "HF_DRAW_BUTTON": "Draw", - "HF_DRAW_DEEP_BUTTON": "Draw with deep recursion", "HF_REDRAW_BUTTON": "Re-Draw", "HG": "Field homogène", "HOURS": "(il y a {hours} heures)", "HOW_TO_VIDS": "

Tuto:

", "IMP_COMP": "Importation reussi. ", - "IMP_DT_OP": "Op Drawtools: ", "IMP_NOPE": "Echec de l'importation: {error}", "IMP_WAS_OP": "Importer les opérations Wasabee", "IMPORT_OP_SUCCESS": "Importer l'opération : {opName} Reussi.", @@ -166,10 +149,8 @@ "LOADING": "[chargement]", "LOADING1": "Chargement: {portalGuid}", "LOC_PROC": "Emplacement traité", - "LOC_UPDATE": "Emplacement mis à jour", "LOCATION SUB": "Location registered", "LOCFRMSER": "(Localement et sur le serveur)", - "LOG IN QUICK": "Log In (quick; for Android)", "LOG IN": "Connexion", "LOG_OUT": "Déconnexion", "MADRID_SET_1": "Définir la zone pour le multifield de base 2-3", @@ -209,8 +190,6 @@ "MM_SPINE": "Spine", "MULTI_M_TITLE": "Dessiner le maximum de couches", "MULTI_M": "Draw", - "MULTIMAX": "Multimax!", - "MULTIMAX2": "Multimax", "MUST_NOT_BE_EMPTY": "Ne dois pas être vide", "MY_CAP_ID": "ID de ma capsule", "MY_COUNT": "Mon nombre de clés", @@ -222,16 +201,12 @@ "NEW_WAS_SERVER": "Nouveau serveur Wasabee", "NEWOP BUTTON TITLE": "Créer une opération", "NEWOP BUTTON": "+ Op", - "NO_DATA": "Pas de données", "NO_DT_ITEMS": "Pas de Draw détecté", "NO_LABEL": "Pas de nom donné", - "NO_PORT_SEL": "Aucun portail sélectionné", "NO_STOCK_INTEL": "Wasabee ne supporte pas les draws de l'intel stock.", "NO_TITLE": "Titre non défini", - "NO": "Non", "NOT LOGGED IN SHORT": "Déconnecté", "NOT LOGGED IN": "Déconnecté : {error}", - "NOT_LOADED": "N'a pas chargé entierement, essayer à nouveau", "NOT_SET": "non défini", "NTNAME": "Nom", "OK": "OK", @@ -257,11 +232,7 @@ "OtherPortalAlert": "Autre", "PASTE_INSTRUCT": "Paste a Wasabee draw export here.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", "pending": "En attente", - "PENDING": "En attente", "PERMS": "Permissions de {opName}", - "PICK_DEST_FIRST": "Vous devez d'abord sélectionner un portail de destination!", - "PICK_TAR_FIRST": "Vous devez d'abord sélectionner un portail cible!", - "PICK_TARGETDEST_Portals": "Please select target and destination portals first!", "PLEASE_SELECT_PORTAL": "Selectionner un portail", "PORT_FAKE": "portails trouvés. ", "PORTAL KEY LIST": "Clés du portail {portalName}", @@ -275,9 +246,7 @@ "QD TITLE": "Quick Draw", "QD TOGGLE MODE": "Changer de mode", "QDBASE": "Base", - "QDCANCEL": "Annuler le draw du field", "QDCONT": "Cliquez sur un portail pour faire un field", - "QDEND": "Click again on the same portal to finish drawing.", "QDNEXT": "Cliquez sur la seconde ancre", "QDSTART": "Cliquez sur la première ancre", "READ_SHORT": "RO", @@ -300,10 +269,8 @@ "SAVELINKS_DRAW": "Copier les liens", "SAVELINKS": "Copie de liens intel", "SECONDS": "(il y a {seconds} secondes)", - "SEL_PORT_FIRST": "Selectionnez d'abord les ancres !", "SEL_SB_ANCHOR": "Sélectionner l'ancre.", "SEL_SB_ANCHOR2": "Dézoomer en laissant charger les portails de la zone puis cliquer sur Draw.", - "SEL_SB_ANCHOR3": "Patience, cela peut prendre du temps", "SEL_SL_ANCHOR": "Sélectionner le portail dont vous voulez copier les liens vers l'opération courante.", "SEL_SRC_ANC2": "Selectionnez le portail source ET la seconde ancre", "SEL_SRC_PORT": "Selectionnez le portail source.", @@ -311,7 +278,6 @@ "SELECT_FAN_PORTALS": "Selectionner une ancre, le premier portail et le dernier portail du Fanfield. Le reste sera calculé à partir des portails visibles.", "SELECT_FAN_PORTALS2": "Attendez le chargement des portails et cliquer sur Draw.", "SELECT_INSTRUCTIONS": "Selectionner deux ancres, puis zoomer sur la zone contenant l'alignement.", - "SELECT_MADRID_INSTRUCTIONS": "Selectionner les trois zones contenant les alignements ainsi que le premier portail chacun des deux premiers alignements.", "SELECT_ONION_PORTALS": "Les couches sont construites de la plus petite à la plus grande, avec au plus trois fields par portail en commençant par le portal défini, puis en utilisant les portails visibles.", "SELF SWAP": "Le portail selectionné est le même. Selectionnez un autre portail.", "SEND ANALYTICS": "Envoyer des statistiques anonymes", @@ -357,16 +323,13 @@ "SWAP": "Déplacer", "SYNC DONE": "Téléchargement terminé
Cliquez ICI pour obtenir des conseils, des astuces et de la documentation.", "SYNC": "Telecharger les opérations disponibles", - "TARDEST_DIFF": "La source et la cible doivent etre differentes.", "TARGET SENT": "Cible transmise", - "TEAM PERM DENIED": "Permission refusée pour l'équipe : {error}", "TEAM STATE": "Partage de position", "TEAM_CREATED": "Équipe {teamName} créée", "TEAM_NAME": "Nom d'équipe", "TEAM": "Équipe", "TEAMS BUTTON TITLE": "Liste des équipes", "TEAMS BUTTON": "Équipes", - "TITLE": "titre", "TO_PORT": "Vers le portail", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Fouille des bloquants", @@ -383,7 +346,6 @@ "UNKNOWN": "Inconnu", "UPDATE HOVER NOT CHANGED": "{opName} n'a pas changé localement", "UPDATE HOVER": "Mettre à jour {opName} sur le serveur", - "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "L'opération a été modifié sur le serveur depuis la dernière synchronisation. Voulez-vous écraser la version du serveur par la votre ?", "UPDATE_CONFLICT_TITLE": "Conflit avec le serveur", "UPDATE_COUNT": "Nombre mis un jour", @@ -407,7 +369,6 @@ "WRITE_SHORT": "RW", "WRITE": "modifier", "WSERVER": "Serveur: {url}", - "YES": "Oui", "YESNO_DEL": "Voulez vous vraiment supprimer {opName} ?", "ZONE_DRAW": "Click to set the zone boundaries", "ZONE": "Zone", From f3055a0c6c8ce3aa7c203d6151ea20664060ded1 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:26:06 -0600 Subject: [PATCH 080/275] Remove 39 unused keys --- src/code/translations/german.json | 39 ------------------------------- 1 file changed, 39 deletions(-) diff --git a/src/code/translations/german.json b/src/code/translations/german.json index 2cf6eae59..7a926631c 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -1,5 +1,4 @@ { - "ABOUT WASABEE-IITC": "Über Wasabee-IITC", "ABOUT_WASABEE": "Über Wasabee", "acknowledged": "Acknowledged", "ADD LINK TITLE": "Dialog - Links hinzufügen", @@ -39,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Assigned Only", "assigned": "Zugewiesen", - "ASSIGNED": "Zugewiesen", "AUTH ANDROID": "Mit Android versuche 'quick' zuerst. Wenn das fehlschlägt, versuche es mit 'select_account' ", "AUTH INCOMPAT": "Du hast ein Plugin aktiviert welches inkompatibel zu Wasabee ist.", "AUTH IOS": "Mit IOS nutze 'Log in'. Wenn das fehlschlägt nutze 'Webview Log in'; Danach nutze den 'Verify Webview' Knopf um den Prozess abzuschließen", @@ -67,7 +65,6 @@ "CLEAR LINKS": "Clear Links", "CLEAR MARKERS": "Clear Markers", "CLEAR_EVERYTHING": "Clear Portals/Links/Markers for current OP", - "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Lösche alle Wasabee Daten", "CLEAROPS BUTTON": "Lösche Wasabee Daten", "CLEAROPS PROMPT": "Das wird alle Wasabee Daten Löschen. Bei dem nächsten Sync wird alles wiederhergestellt.", @@ -75,9 +72,7 @@ "COMMENT": "Kommentar", "COMPLETED BY": "Abgeschlossen von {agentName}", "completed": "Abgeschlossen", - "COMPLETED": "Abgeschlossen", "CON_DEL": "Bestätige Löschen: {opName}", - "CONFIRM_DELETE": "Do you really want to delete this link: ", "COUNT": "Anzahl", "CREATE_NEW_TEAM": "Erstelle neues Team", "CreateLinkAlert": "Link", @@ -88,19 +83,12 @@ "DELETE ANCHOR TITLE": "Anker löschen", "DELETE MARKER PROMPT": "Möchtest du die Markierung löschen? : ", "DELETE MARKER TITLE": "Markierung löschen", - "DELETE PERM DENIED": "Keine Berechtigung zum löschen", "DELETE_ANCHOR": "Löschen", "DELETE_LINK": "Delete", - "DELETE_MARKER": "Delete", "DELETE_OP": "Delete {opName}", - "DELETED": "Erfolgreich gelöscht.", "DESCRIP_PLACEHOLD": "Beschreibung (optional)", "DestroyPortalAlert": "Destroy", - "DISABLE_SYNC": "Das Standard Synchronisations Plugin ist nicht mit Wasabee kompatibel - Bitte deaktiveren", - "DISABLED": "Diese Eigenschaft steht den Nutzern nicht zu verfügung", - "DONE": "Fertig", "DRAW TOOLS FORMAT": "Draw Tools Format", - "DT_FORMAT": "Draw Tools Format", "DUPE_OP": "Duplicate Operation", "END_PORT": "Endportal", "ExcludeMarker": "Exclude from Auto-Draw/Mark", @@ -108,8 +96,6 @@ "EXPORT OP": "Exportiere Op", "EXPORT": "Exportieren: ", "FAKED": "Faked: [{portalId}]", - "FAN_FIELD3": "Fan Field", - "FANFIELD TITLE": "Fächerfeld", "FANFIELD": "Fächerfeld!", "FANFIELD2": "Fächerfeld", "FarmPortalMarker": "Farm", @@ -124,19 +110,16 @@ "FROM_DEPTH": "from the depth", "FROM_PORT": "Von Portal", "GET DT": "Get existing DrawTools draw", - "GET_DT_DRAW": "Erhalte aktuelle DrawTools Zeichnung", "GetKeyPortalMarker": "Get Keys", "GotoPortalMarker": "Go To", "H-GEN_INST": "Set portals for the outside layer. Choose number of splits. Click draw", "HF_DEEP_SEARCH": "Exhaustive search", "HF_DRAW_BUTTON": "Draw", - "HF_DRAW_DEEP_BUTTON": "Draw with deep recursion", "HF_REDRAW_BUTTON": "Redraw", "HG": "Homogeneous Field", "HOURS": "vor ({hours} Stunden)", "HOW_TO_VIDS": "

Erklärungsvideos:

", "IMP_COMP": "Import Komplett. Gefunden ", - "IMP_DT_OP": "Importierte Drawtools Op: ", "IMP_NOPE": "Import Fehlgeschlagen: {error}", "IMP_WAS_OP": "Importiere Wasabee Operation", "IMPORT_OP_SUCCESS": "Importierte Operation: {opName}. Erfolgreich.", @@ -166,10 +149,8 @@ "LOADING": "[laden]", "LOADING1": "Lade: [{portalGuid}]", "LOC_PROC": "Standort verarbeitet", - "LOC_UPDATE": "Standort aktualisieren", "LOCATION SUB": "Standort registriert", "LOCFRMSER": " (locally and from server)", - "LOG IN QUICK": "Einloggen (quick; für Android)", "LOG IN": "Einloggen", "LOG_OUT": "Log Out", "MADRID_SET_1": "Select the region for baselink Anchor 2 to Anchor 3", @@ -209,8 +190,6 @@ "MM_SPINE": "Spine", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Maximale Feldanzahl", - "MULTIMAX": "Maximale Feldanzahl!", - "MULTIMAX2": "Multimax", "MUST_NOT_BE_EMPTY": "Darf nicht leer sein.", "MY_CAP_ID": "Kapsel ID", "MY_COUNT": "Meine Anzahl", @@ -222,16 +201,12 @@ "NEW_WAS_SERVER": "Neuer Wasabee Server", "NEWOP BUTTON TITLE": "Neue Operation erstellen", "NEWOP BUTTON": "Neue Op", - "NO_DATA": "Keine Daten", "NO_DT_ITEMS": "Keine DrawTools Daten erkannt", "NO_LABEL": "No label set", - "NO_PORT_SEL": "Keine Portale ausgewählt.", "NO_STOCK_INTEL": "Wasabee unterstützt keine Standard Intel imports", "NO_TITLE": "No title set", - "NO": "Nein", "NOT LOGGED IN SHORT": "Nicht eingeloggt.", "NOT LOGGED IN": "Nicht eingeloggt: {error}", - "NOT_LOADED": "Nicht vollständig geladen - bitte erneut probieren.", "NOT_SET": "nicht gesetzt", "NTNAME": "Name", "OK": "OK", @@ -257,11 +232,7 @@ "OtherPortalAlert": "Other", "PASTE_INSTRUCT": "Füge einen Wasabee Drawtools export hier ein.\n\nWasabee kann nicht mit dem Standard intel format umgehen.\n\nEs gibt einen Experimentellen Import vom IITC-DrawTools format.\n\n Vor dem Importieren bitte sicherstellen das alles geladen ist und die IITC es zwischengespeichert hat. Jedes nicht zwischengespeicherte Portal wird verfälscht. \n\nDu musst die 'Wechsel' Funktion verwenden um die verfälschten Portale zu korrigieren. (Sie sollten bereits an der richtigen Position sein - aber dem falschen Portal zugeordnet).", "pending": "Ausstehend", - "PENDING": "Ausstehend", "PERMS": "{opName} permissions", - "PICK_DEST_FIRST": "Bitte wähle zuerst ein Zielportal!", - "PICK_TAR_FIRST": "Bitte wähle zuerst ein Startportal!", - "PICK_TARGETDEST_Portals": "Bitte wähle zuerst Startportal und Endportal!", "PLEASE_SELECT_PORTAL": "Bitte wähle ein Portal", "PORT_FAKE": " Portale. Verfälscht ", "PORTAL KEY LIST": "Key list for portal {portalName}", @@ -275,9 +246,7 @@ "QD TITLE": "Schnelle Layer Zeichnung", "QD TOGGLE MODE": "Change mode", "QDBASE": "Basis Link", - "QDCANCEL": "Zeichnen von Feld abbrechen", "QDCONT": "Klicke auf ein Portal der Kette.", - "QDEND": "Erneut auf das Portal klicken, um die Zeichnung zu beenden.", "QDNEXT": "Klicke auf das zweite Ankerportal.", "QDSTART": "Klicke auf das erste Ankerportal.", "READ_SHORT": "RO", @@ -300,10 +269,8 @@ "SAVELINKS_DRAW": "Save Links", "SAVELINKS": "Save Links", "SECONDS": "vor ({seconds} Sekunden)", - "SEL_PORT_FIRST": "Bitte wähle zuerst die Ankerportale aus!", "SEL_SB_ANCHOR": "Wähle einen Anker, Zomme in das Areal und füge es zum Starburst hinzu.", "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", - "SEL_SB_ANCHOR3": "Please be patient, it can take a bit.", "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", "SEL_SRC_ANC2": "Lege Quelle und Anker 2 fest", "SEL_SRC_PORT": "Wähle ein Quellportal", @@ -311,7 +278,6 @@ "SELECT_FAN_PORTALS": "Wähle ein Ankerportal, wähle ein Startportal und ein Endportal, danach zoome in die Gegend des Fächers. Warte bis alle Portale geladen sind. Drücke anschließend den 'Fächerfeld' Knopf.", "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", "SELECT_INSTRUCTIONS": "Wähle zwei Ankerportale. Zoome in die Gegend der Portalkette - warte bis die Portale geladen sind und drücke den 'Maximale Feldanzahl' Knopf.", - "SELECT_MADRID_INSTRUCTIONS": "Select three anchor portals, zoom in on the area near the selected anchor, wait until the portals are loaded (portals must be on screen to be considered) then select the 'define spine region' button for the corresponding base links.", "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", "SELF SWAP": "Du kannst das Portal nicht mit sich selbst tauschen - Wähle ein anderes.", "SEND ANALYTICS": "Send Anonymous Analytics", @@ -357,16 +323,13 @@ "SWAP": "Wechseln", "SYNC DONE": "Download abgeschlossen
Klicken Sie HIER für Hinweise, Tipps und Dokumentation.", "SYNC": "Download verfügbarer Operationen", - "TARDEST_DIFF": "Start und Ziel müssen sich unterscheiden.", "TARGET SENT": "Ziel gesendet", - "TEAM PERM DENIED": "Keine Berechtigung für Team: {error}", "TEAM STATE": "Share Location", "TEAM_CREATED": "Team {teamName} erstellt.", "TEAM_NAME": "Team Name", "TEAM": "Team", "TEAMS BUTTON TITLE": "Auflistung Wasabee Teams", "TEAMS BUTTON": "Teams", - "TITLE": "title", "TO_PORT": "zu Portal", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", @@ -383,7 +346,6 @@ "UNKNOWN": "Unbekannt", "UPDATE HOVER NOT CHANGED": "{opName} lokal nicht verändert", "UPDATE HOVER": "UPDATE {opName} auf dem Server", - "UPDATE PERM DENIED": "Keine Berechtigung zum aktualisieren", "UPDATE_CONFLICT_DESC": "The OP has been modified on server since last sync. Do you want to replace the server version by the current one?", "UPDATE_CONFLICT_TITLE": "Conflict detected with server", "UPDATE_COUNT": "Aktualisiere Anzahl", @@ -407,7 +369,6 @@ "WRITE_SHORT": "RW", "WRITE": "schreiben", "WSERVER": "Server: {url}", - "YES": "Ja", "YESNO_DEL": "Bist du dir sicher das du {opName} löschen willst?", "ZONE_DRAW": "Click to set the zone boundaries", "ZONE": "Zoniert", From beb75d55d8a95b07ed9a1a2f05391499ce6cd7f7 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:27:02 -0600 Subject: [PATCH 081/275] Remove 39 unused keys --- src/code/translations/italian.json | 39 ------------------------------ 1 file changed, 39 deletions(-) diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index 01dafd9f8..d4f418842 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -1,5 +1,4 @@ { - "ABOUT WASABEE-IITC": "Info su Wasabee-IITC", "ABOUT_WASABEE": "Info su Wasabee", "acknowledged": "Ricevuto", "ADD LINK TITLE": "Aggiunta Link", @@ -39,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Solo Assegnati", "assigned": "Assegnato", - "ASSIGNED": "Assegnato", "AUTH ANDROID": "Su Android, prova prima il login 'rapido'. Se fallisce, prova ad accedere con 'select_account'.", "AUTH INCOMPAT": "Hai attivato un plugin in TamperMonkey incompatibile con Wasabee", "AUTH IOS": "Su iOS, usa 'Log In'. Se fallisce, prova 'Webview Log in'; poi premi 'Verify Webview' per completare il processo.", @@ -67,7 +65,6 @@ "CLEAR LINKS": "Elimina Link", "CLEAR MARKERS": "Elimina Marker", "CLEAR_EVERYTHING": "Elimina tutti i Portali/Link/Marker", - "CLEAR": "Deseleziona", "CLEAROPS BUTTON TITLE": "Elimina TUTTI i dati di Wasabee", "CLEAROPS BUTTON": "Elimina i dati di Wasabee", "CLEAROPS PROMPT": "Questo eliminerà tutte le OP e i dati relativi a Wasabee. Saranno ripristinati alla prossima sincronizzazione.", @@ -75,9 +72,7 @@ "COMMENT": "Commento", "COMPLETED BY": "Completato da {agentName}", "completed": "Completato", - "COMPLETED": "Completato", "CON_DEL": "Conferma eliminazione: {opName}", - "CONFIRM_DELETE": "Vuoi davvero eliminare questo link: ", "COUNT": "Conteggio", "CREATE_NEW_TEAM": "Crea Nuovo Team", "CreateLinkAlert": "Linkare", @@ -88,19 +83,12 @@ "DELETE ANCHOR TITLE": "Elimina Ancora", "DELETE MARKER PROMPT": "Vuoi eliminare questo Marker: ", "DELETE MARKER TITLE": "Elimina Marker", - "DELETE PERM DENIED": "Permesso di eliminare negato.", "DELETE_ANCHOR": "Elimina", "DELETE_LINK": "Elimina", - "DELETE_MARKER": "Elimina", "DELETE_OP": "Eliminare {opName}", - "DELETED": "Eliminato con successo.", "DESCRIP_PLACEHOLD": "Descrizione (facoltativo)", "DestroyPortalAlert": "Distruggere", - "DISABLE_SYNC": "Il plugin Sync stock non è compatibile con Wasabee. Per favore disabilita Sync.", - "DISABLED": "Questa funzione non è pronta per gli utenti", - "DONE": "Fatto", "DRAW TOOLS FORMAT": "Formato Draw Tools", - "DT_FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplica Operazione", "END_PORT": "Portale di fine ", "ExcludeMarker": "Escludi da Auto-Draw/Mark", @@ -108,8 +96,6 @@ "EXPORT OP": "Esporta Op", "EXPORT": "Esporta: ", "FAKED": "Simulato: [{portalId}]", - "FAN_FIELD3": "Fan Field", - "FANFIELD TITLE": "Fanfield", "FANFIELD": "Fanfield!", "FANFIELD2": "Fanfield", "FarmPortalMarker": "Farmare", @@ -124,19 +110,16 @@ "FROM_DEPTH": "dalla profondità", "FROM_PORT": "Portale di origine", "GET DT": "Usa disegno DrawTools esistente", - "GET_DT_DRAW": "Importa disegno DrawTools", "GetKeyPortalMarker": "Ottienere Chiavi", "GotoPortalMarker": "Andare A", "H-GEN_INST": "Seleziona Portali per lo strato esterno. Scegli il numero di split. Clicca Disegna", "HF_DEEP_SEARCH": "Ricerca esaustiva", "HF_DRAW_BUTTON": "Disegna", - "HF_DRAW_DEEP_BUTTON": "Disegna con ricorsione profonda", "HF_REDRAW_BUTTON": "Ridisegna", "HG": "Field Omogeneo", "HOURS": " ({hours} ore fa)", "HOW_TO_VIDS": "

Video tutorial:

", "IMP_COMP": "Importazione Completata. Trovato ", - "IMP_DT_OP": "Importata Operazione Drawtools: ", "IMP_NOPE": "Importazione Fallita: {error}", "IMP_WAS_OP": "Importa Operazione Wasabee", "IMPORT_OP_SUCCESS": "Importata Operazione: {opName} con successo.", @@ -166,10 +149,8 @@ "LOADING": "[caricamento]", "LOADING1": "Caricamento: [{portalGuid}]", "LOC_PROC": "posizione processata", - "LOC_UPDATE": "Aggiornamento posizione", "LOCATION SUB": "Posizione registrata", "LOCFRMSER": " (locale e dal server)", - "LOG IN QUICK": "Accedi (rapido; per Android)", "LOG IN": "Accedi", "LOG_OUT": "Logout", "MADRID_SET_1": "Seleziona l'area per la base da Ancora 2 a Ancora 3", @@ -209,8 +190,6 @@ "MM_SPINE": "Spine", "MULTI_M_TITLE": "Disegna più strati possibile", "MULTI_M": "Disegna", - "MULTIMAX": "Multimax!", - "MULTIMAX2": "Multimax", "MUST_NOT_BE_EMPTY": "Non può essere vuoto", "MY_CAP_ID": "ID Capsula", "MY_COUNT": "Conteggio", @@ -222,16 +201,12 @@ "NEW_WAS_SERVER": "Nuovo Server Wasabee", "NEWOP BUTTON TITLE": "Crea una nuova Operazione", "NEWOP BUTTON": "Nuova Op", - "NO_DATA": "Dati mancanti", "NO_DT_ITEMS": "Disegni DrawTools non rilevati", "NO_LABEL": "Etichetta non impostata", - "NO_PORT_SEL": "Portale non selezionato.", "NO_STOCK_INTEL": "Wasabee non supporta importazioni di disegni dalla intel stock", "NO_TITLE": "Titolo non impostato", - "NO": "No", "NOT LOGGED IN SHORT": "Non loggato", "NOT LOGGED IN": "Non loggato: {error}", - "NOT_LOADED": "Caricamento incompleto, riprova.", "NOT_SET": "non impostato", "NTNAME": "Nome", "OK": "OK", @@ -257,11 +232,7 @@ "OtherPortalAlert": "Altro", "PASTE_INSTRUCT": "Incolla un disegno esportato da Wasabee qui.\n\nWasabee non può importare il formato intel stock.\n\nL'importazione di disegni in formato IITC DrawTools è supportata in modo sperimentale.\n\nPrima di importare in formato DrawTools, controlla l'area e fai in modo che tutti i portali carichino, così da essere nella cache di IITC. Ogni Portale non nella cache sarà 'finto'.\n\nDovrete usare la funzione 'swap' per spostare le ancore dai portali 'finti' a quelli veri (dovrebbero essere al posto giusto, solo non associate al Portale).\n\nI Portali nella cache potrebbero non avere il giusto nome.", "pending": "In corso", - "PENDING": "In corso", "PERMS": "{opName} permessi", - "PICK_DEST_FIRST": "Seleziona prima un Portale di destinazione!", - "PICK_TAR_FIRST": "Seleziona prima un portale target!", - "PICK_TARGETDEST_Portals": "Seleziona prima i Portali target e destinazione!", "PLEASE_SELECT_PORTAL": "Seleziona un portale", "PORT_FAKE": " portali. Simulati ", "PORTAL KEY LIST": "Lista Chiavi per Portale: {portalName}", @@ -275,9 +246,7 @@ "QD TITLE": "Disegno Rapido Strati", "QD TOGGLE MODE": "Change mode", "QDBASE": "Link Base", - "QDCANCEL": "Annulla disegno Field", "QDCONT": "Clicca su un portale del filotto per disegnare un field.", - "QDEND": "Clicca di nuovo sullo stesso portale per terminare il disegno.", "QDNEXT": "Clicca il secondo Portale Ancora.", "QDSTART": "Clicca il primo Portale Ancora.", "READ_SHORT": "RO", @@ -300,10 +269,8 @@ "SAVELINKS_DRAW": "Salva Link", "SAVELINKS": "Salva Link", "SECONDS": " ({seconds} secondi fa)", - "SEL_PORT_FIRST": "Seleziona un portale prima!", "SEL_SB_ANCHOR": "Imposta l'ancora.", "SEL_SB_ANCHOR2": "Zooma indietro. Assicurati che tutti i Portali siano caricati, poi clicca Disegna.", - "SEL_SB_ANCHOR3": "Sii paziente. Ci vorrà un po'.", "SEL_SL_ANCHOR": "Seleziona il portale di cui salvare il link. Clicca il pulsante Salva Link e guarda la checklist.", "SEL_SRC_ANC2": "Seleziona Origine e Ancora 2", "SEL_SRC_PORT": "Seleziona un Portale di Origine", @@ -311,7 +278,6 @@ "SELECT_FAN_PORTALS": "Seleziona un'ancora, un Portale di inizio e uno di fine, poi zooma su un'area per il fanfield.", "SELECT_FAN_PORTALS2": "Aspetta che i Portali siano caricati, poi clicca Disegna.", "SELECT_INSTRUCTIONS": "Seleziona due ancore, poi zooma sul filotto", - "SELECT_MADRID_INSTRUCTIONS": "Seleziona tre Portali Ancora, zoomma sull'area vicino all'ancora selezionata, aspetta finchè i portali siano caricati (devono essere sullo schermo per essere considerati) poi seleziona il pulsante 'imposta area filotto' per il link base corrispondente.", "SELECT_ONION_PORTALS": "Strati creati da dentro a fuori. Zooma sul centro e seleziona il portale di inizio, poi zooma indietro sull'area.", "SELF SWAP": "Non si può scambiare un portale con se stesso! Seleziona un altro portale.", "SEND ANALYTICS": "Invia dati di utilizzo anonimi", @@ -357,16 +323,13 @@ "SWAP": "Scambia", "SYNC DONE": "Download Completato
Fare clic QUI per suggerimenti, suggerimenti e documentazione.", "SYNC": "Scarica Operazioni disponibili", - "TARDEST_DIFF": "I Portali Target e Destinazione devono essere diversi.", "TARGET SENT": "Target inviato", - "TEAM PERM DENIED": "Accesso negato al team: {error}", "TEAM STATE": "Condividi Posizione", "TEAM_CREATED": "Team {teamName} creato", "TEAM_NAME": "Nome Team", "TEAM": "Team", "TEAMS BUTTON TITLE": "Lista Team Wasabee", "TEAMS BUTTON": "Team", - "TITLE": "titolo", "TO_PORT": "Al Portale", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Controllo corridoi", @@ -390,7 +353,6 @@ "UPDATED": "Aggiornato con successo", "UpgradePortalAlert": "Upgradare", "UPLOAD BUTTON HOVER": "CARICA {opName} (al momento non sul server)", - "UPLOAD PERM DENIED": "Accesso negato all'upload", "UPLOADED": "Caricato con successo", "USE PANES ON MOBILE": "Use panes (need reload)", "USE_SWAP_INSTRUCT": ". Usare la funzione Scambio per spostare i Portali finti sui Portali veri nella stessa posizione. Zoomare sui Portali 'in caricamento' nella checklist potrebbe forzarli al caricamento.", @@ -407,7 +369,6 @@ "WRITE_SHORT": "RW", "WRITE": "scrittura", "WSERVER": "Server: {url}", - "YES": "Sì", "YESNO_DEL": "Sei sicuro di voler eliminare {opName}?", "ZONE_DRAW": "Click to set the zone boundaries", "ZONE": "Area", From 212ea5db6a5505b96a5fc419b448bfb66bdc2bb8 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:27:48 -0600 Subject: [PATCH 082/275] Remove 39 unused keys --- src/code/translations/portuguese.json | 39 --------------------------- 1 file changed, 39 deletions(-) diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index 67b0bcf1b..3168c5d3f 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -1,5 +1,4 @@ { - "ABOUT WASABEE-IITC": "Sobre Wasabee-IITC", "ABOUT_WASABEE": "Sobre Wasabee", "acknowledged": "Reconhecido", "ADD LINK TITLE": "Adicionar Links Dialogo", @@ -39,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "A", "ASSIGNED_ONLY": "Só Atribuir", "assigned": "Atribuído", - "ASSIGNED": "Atribuido", "AUTH ANDROID": "No Android, tentar primeiro 'rápido'. Se isso falhar, tentar o login principal com 'select_account'..", "AUTH INCOMPAT": "Você ativou um plugin no TamperMonkey que é incompatível com o Wasabee", "AUTH IOS": "No iOS, use o 'Login' principal. se isso falhar, faça 'Webview Log in', faça o login; em seguida, use o botão 'Verificar Webview' para concluir o processo.", @@ -67,7 +65,6 @@ "CLEAR LINKS": "Limpar Links", "CLEAR MARKERS": "Limpar Markers", "CLEAR_EVERYTHING": "limpar Portais/Links/Marcadores", - "CLEAR": "Limpar selecção", "CLEAROPS BUTTON TITLE": "limpar TODOS os dados Wasabee", "CLEAROPS BUTTON": "Limpar dados Wasabee", "CLEAROPS PROMPT": "Isto limpará todas as OPS e dados relacionados a Wasabee. Tudo será restaurado apartir do servidor na próxima sincronização.", @@ -75,9 +72,7 @@ "COMMENT": "Comentario", "COMPLETED BY": "Completo por ${value}", "completed": "Completo", - "COMPLETED": "Completo", "CON_DEL": "Confirmar Apagar: ${value}", - "CONFIRM_DELETE": "Desejas realmente excluir este link: ", "COUNT": "Contar", "CREATE_NEW_TEAM": "Criar Nova Equipa", "CreateLinkAlert": "Link", @@ -88,19 +83,12 @@ "DELETE ANCHOR TITLE": "Apagar Âncora", "DELETE MARKER PROMPT": "Desejas apagar esta âncora: ", "DELETE MARKER TITLE": "Apagar Marcador", - "DELETE PERM DENIED": "Permissão para excluir negada.", "DELETE_ANCHOR": "Apagar", "DELETE_LINK": "Apagar", - "DELETE_MARKER": "Apagar", "DELETE_OP": "Apagar ${value}", - "DELETED": "Excluído com sucesso.", "DESCRIP_PLACEHOLD": "Descrição (opcional)", "DestroyPortalAlert": "Destroir", - "DISABLE_SYNC": "O plugin de sincronização de stoque não é compatível com Wassabe. Desativa a sincronização.", - "DISABLED": "Este recurso não está pronto para os usuários", - "DONE": "Feito", "DRAW TOOLS FORMAT": "Formato Draw Tools", - "DT_FORMAT": "Formato das Ferramentas de Desenho", "DUPE_OP": "Duplicar Operação", "END_PORT": "Portal final ", "ExcludeMarker": "Excluir de Auto-Desenhar / Marcar", @@ -108,8 +96,6 @@ "EXPORT OP": "Exportar Op", "EXPORT": "Exportar: ", "FAKED": "Falsificado: [${value}]", - "FAN_FIELD3": "Fan Field", - "FANFIELD TITLE": "Fanfield", "FANFIELD": "Desenhar", "FANFIELD2": "Desenhar Fan Field", "FarmPortalMarker": "Farmar", @@ -124,19 +110,16 @@ "FROM_DEPTH": "da profundidade", "FROM_PORT": "A Partir do Portal", "GET DT": "Obtenha o desenho existente do DrawTools", - "GET_DT_DRAW": "Importar Dezenho DrawTools", "GetKeyPortalMarker": "Retirar Chaves", "GotoPortalMarker": "Ir para", "H-GEN_INST": "Define portais para a camada externa. Escolhe o número de divisões. Clica para desenhar", "HF_DEEP_SEARCH": "Pesquisa exaustiva", "HF_DRAW_BUTTON": "Desenhar", - "HF_DRAW_DEEP_BUTTON": "Desenhar com recursão profunda", "HF_REDRAW_BUTTON": "Redesenhar", "HG": "Campo Homogêneo", "HOURS": " (${value} horas atrás)", "HOW_TO_VIDS": "

Vídeos de instruções:

", "IMP_COMP": "Importação concluída. Encontrada ", - "IMP_DT_OP": "Importar OP Drawtools: ", "IMP_NOPE": "A Importação Falhou: {error}", "IMP_WAS_OP": "Importar Operação Wasabee", "IMPORT_OP_SUCCESS": "OP Importada: ${value} successfuly.", @@ -166,10 +149,8 @@ "LOADING": "[a carregar]", "LOADING1": "a carregar: [${value}]", "LOC_PROC": "localização processada", - "LOC_UPDATE": "Atualização de localização", "LOCATION SUB": "Localização registrada", "LOCFRMSER": " (localmente e do servidor)", - "LOG IN QUICK": "Log In (Rápido; para Android)", "LOG IN": "Log In", "LOG_OUT": "Log Out", "MADRID_SET_1": "Selecione a região para a ligação de base Âncora 2 à Âncora 3", @@ -209,8 +190,6 @@ "MM_SPINE": "Spine", "MULTI_M_TITLE": "Desenhar camadas máximas", "MULTI_M": "Desenhar", - "MULTIMAX": "Multimax!", - "MULTIMAX2": "Multimax", "MUST_NOT_BE_EMPTY": "Não deve estar vazio", "MY_CAP_ID": "Minha Capsula ID", "MY_COUNT": "Minha Conta", @@ -222,16 +201,12 @@ "NEW_WAS_SERVER": "Novo servidor Waasbee", "NEWOP BUTTON TITLE": "Criar uma nova operação", "NEWOP BUTTON": "Nova Op", - "NO_DATA": "sem dados", "NO_DT_ITEMS": "Nenhum item desenhado do DrawTools foi detectado", "NO_LABEL": "Nenhum rótulo definido", - "NO_PORT_SEL": "Nenhum portal selecionado.", "NO_STOCK_INTEL": "Wasabee não suporta importações de desenho de inteligência de stoque", "NO_TITLE": "Nenhum título definido", - "NO": "Não", "NOT LOGGED IN SHORT": "Não logado", "NOT LOGGED IN": "Não logado: ${value}", - "NOT_LOADED": "Não totalmente carregado, tente novamente.", "NOT_SET": "não configurado", "NTNAME": "Nome", "OK": "OK", @@ -257,11 +232,7 @@ "OtherPortalAlert": "Otros", "PASTE_INSTRUCT": "Cola uma exportação de desenho Wasabee aqui.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", "pending": "Pendente", - "PENDING": "Pendente", "PERMS": "${value} permissões", - "PICK_DEST_FIRST": "Seleciona um portal de destino primeiro!", - "PICK_TAR_FIRST": "Seleciona um portal de destino primeiro!", - "PICK_TARGETDEST_Portals": "Seleciona primeiro os portais de destino e destino!", "PLEASE_SELECT_PORTAL": "Seleciona um portal", "PORT_FAKE": " portais. Falsificado ", "PORTAL KEY LIST": "Lista de chaves para portal ${value}", @@ -275,9 +246,7 @@ "QD TITLE": "Camadas de desenho rápido", "QD TOGGLE MODE": "Change mode", "QDBASE": "Link Base", - "QDCANCEL": "Cancelar campos de desenho", "QDCONT": "Clica num portal espinha para desenhar um campo.", - "QDEND": "Clica novamente no mesmo portal para finalizar o desenho.", "QDNEXT": "Clica no segundo portal de âncora.", "QDSTART": "Clica no primeiro portal de âncora.", "READ_SHORT": "Ler Abreviado", @@ -300,10 +269,8 @@ "SAVELINKS_DRAW": "Save Links", "SAVELINKS": "Save Links", "SECONDS": " (${value} segundos atrás)", - "SEL_PORT_FIRST": "Selecione primeiro os portais âncora!", "SEL_SB_ANCHOR": "Seleciona a âncora.", "SEL_SB_ANCHOR2": "Reduzir o zoom. Verifica se todos os portais foram carregados e clica em desenhar.", - "SEL_SB_ANCHOR3": "Por favor, sê paciente, pode demorar um pouco.", "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", "SEL_SRC_ANC2": "Selecionar a fonte e a âncora 2", "SEL_SRC_PORT": "Selecionar um portal de origem", @@ -311,7 +278,6 @@ "SELECT_FAN_PORTALS": "Selecionar um portal de âncora, um portal inicial e um portal final e, em seguida, posiciona a visualização sobre a área do campo.", "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", "SELECT_INSTRUCTIONS": "Select two anchor portals, then zoom over the spine area.", - "SELECT_MADRID_INSTRUCTIONS": "Selecionar três portais de âncora, amplia a área próxima à âncora selecionada, espera até que os portais sejam carregados (os portais devem aparecer na tela para serem considerados) e selecioner o botão 'definir região da coluna' para os links de base correspondentes.", "SELECT_ONION_PORTALS": "As camadas são construídas de dentro para fora. Aumenta o zoom para o centro e seleciona o portal inicial, em seguida, diminui o zoom para a área.", "SELF SWAP": "Não é possível trocar um portal contigo mesmo! Seleciona um portal diferente.", "SEND ANALYTICS": "Enviar análises anônimas", @@ -357,16 +323,13 @@ "SWAP": "Troca", "SYNC DONE": "Download Completo", "SYNC": "Download operações disponíveis", - "TARDEST_DIFF": "Os portais de destino e destino devem ser diferentes.", "TARGET SENT": "Alvo Enviado", - "TEAM PERM DENIED": "Permissão negada à equipa: ${value}", "TEAM STATE": "Partilhar localização", "TEAM_CREATED": "Equipa ${value} created", "TEAM_NAME": "Nome Equipa", "TEAM": "Equipa", "TEAMS BUTTON TITLE": "Listar equipas Wasabee", "TEAMS BUTTON": "Equipas", - "TITLE": "titulo", "TO_PORT": "Para o Portal", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", @@ -383,7 +346,6 @@ "UNKNOWN": "Desconhecido", "UPDATE HOVER NOT CHANGED": "${value} não mudou localmente", "UPDATE HOVER": "UPDATE ${value} no servidor", - "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "A OP foi modificada no servidor desde a última sincronização. Queres substituir a versão do servidor pela atual?", "UPDATE_CONFLICT_TITLE": "Conflito detectado com o servidor", "UPDATE_COUNT": "Contagem de atualização", @@ -407,7 +369,6 @@ "WRITE_SHORT": "RW", "WRITE": "escrita", "WSERVER": "Servidor: ${value}", - "YES": "Sim", "YESNO_DEL": "Tem certeza de que deseja excluir ${value}?", "ZONE_DRAW": "Click to set the zone boundaries", "ZONE": "Zone", From a3c568f443472970354a0f7258285588ddc2fe75 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:28:32 -0600 Subject: [PATCH 083/275] Add russian language file --- src/code/translations/russian.json | 391 +++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 src/code/translations/russian.json diff --git a/src/code/translations/russian.json b/src/code/translations/russian.json new file mode 100644 index 000000000..08d4f9cd0 --- /dev/null +++ b/src/code/translations/russian.json @@ -0,0 +1,391 @@ +{ + "ABOUT_WASABEE": "О Wasabee", + "acknowledged": "цель получена", + "ADD LINK TITLE": "Добавление линков", + "ADD MARKER TITLE": "Добавление маркеров", + "ADD_AGENT": "Добавить агента: ", + "ADD_BL": "Добавить перемычки: ", + "ADD_BUTTON_LINKS": "Добавить все линки сразу.", + "ADD_LINKS": "Добавить линки", + "ADD_MARKER": "+ маркер", + "ADD_NEW_OP": "Добавить новую ОПРЦ", + "ADD_SUCC_INSTR": "Агент добавлен", + "ADD_ZONE": "Добавить зону", + "ADD": "Добавить", + "ADD1": "Добавить первый линк", + "ADD2": "Добавить второй линк", + "AGENT_STATS": "Данные агента", + "AGENT": "Агент", + "AGES": " (давно)", + "ALREADY_HAS_MARKER": "У этого портала уже есть маркер. Выбери другой портал.", + "AMAZ_TEAM_NAME": "Отличное название.", + "ANCHOR ASSIGNMENT": " все исходящие линки", + "ANCHOR_GMAP": "Google Map", + "ANCHOR_PORTAL": "Опорный портал ", + "ANCHOR_PORTAL2": "Опорный портал 2", + "ANCHOR_PORTAL3": "Опорный портал 3", + "ANCHOR1": "Опорник 1 ", + "ANCHOR2": "Опорник 2 ", + "ANCHOR3": "Опорник 3 ", + "ANCHORS_AS_BOOKMARKS": "Опорники в закладки", + "API_KEY": " ключ api: ", + "ASS_TO": "Назначено агенту", + "ASSIGN LINK PROMPT": "Назначить линк с портала: {portalName}", + "ASSIGN MARKER PROMPT": "Назначить маркер с {portalName}", + "ASSIGN OUTBOUND PROMPT": "Назначить все исходящие линки с {portalName}", + "ASSIGN OUTBOUND": "Назначить исходящие линки", + "ASSIGN": "Назначить", + "ASSIGNED_ONLY_SHORT": "AO", + "ASSIGNED_ONLY": "Только назначенные", + "assigned": "Назначено", + "AUTH ANDROID": "На Android, попробуй сначала 'быстрый логин'. Если не получится, попробуй обычный логин через 'выбери аккаунт'.", + "AUTH INCOMPAT": "Ты активировал в TamperMonkey плагин, который несовместим с Wasabee", + "AUTH IOS": "На iOS, используй основную опцию 'Логин'. Если не получится, используй 'Логин Webview', а затем кнопку 'Подтвердить Webview' для завершения процесса.", + "AUTH REQUIRED": "Необходима аутентификация", + "AUTH TOKEN REJECTED": "Отправка аутентификационного токена на сервер отклонена: {error}", + "AUTH_SELECT_ACCOUNT": "Выбери аккаунт", + "AUTO_DRAWS": "Авто-рисовка", + "AUTODRAWS": "Опции авто-рисовки Wasabee", + "AUTOLOAD_RATE": "Скорость запроса данных портала (ms)", + "AUTOLOAD": "Автоматически загружать недостающие данные портала", + "AUTOMARK STOP": "Авто-маркировка остановлена, т.к. порталы не были загружены", + "AUTOMARK": "Авто-маркировка", + "BAT_TOAD": "Боевые жабы", + "BLOCKER LIST TITLE": "Показать все кроссы", + "BLOCKER TITLE": "кроссы", + "CANCEL": "Отменить", + "CAPSULE": "Капсула", + "CapturePortalMarker": "Захватить", + "CHANGE SERVER PROMPT": "Новый сервер Wasabee", + "CHANGE SERVER": "Сменить сервер", + "CHANGE_WAS_SERVER": "Сменить сервер Wasabee", + "CHECKLIST BUTTON TITLE": "Чек-лист операции", + "CHECKLIST BUTTON": "Чек-лист", + "CLEAR LINKS": "Удалить линки", + "CLEAR MARKERS": "Удалить маркеры", + "CLEAR_EVERYTHING": "Удалить порталы/линки/маркеры для текущей ОПРЦ", + "CLEAROPS BUTTON TITLE": "Удалить данные", + "CLEAROPS BUTTON": "Удалить данные", + "CLEAROPS PROMPT": "Удалить все локальные ОПРЦ. ОПРЦ будут восстановлены при следующей загрузке.", + "CLOSE": "Закрыть", + "COMMENT": "Комментарий", + "COMPLETED BY": "Выполнено агентом {agentName}", + "completed": "Выполнено", + "CON_DEL": "Подтверди удаление: {opName}", + "COUNT": "Количество", + "CREATE_NEW_TEAM": "Создать новую команду", + "CreateLinkAlert": "Линк", + "CUR_USER_INFO": "Информация о пользователе", + "D_SHOW_LIST": "Ввести ключи на руках", + "DEFAULT OP NAME": "Новая ОПРЦ: {date}", + "DELETE ANCHOR PROMPT": "Хочешь удалить этот портал и все связанные линки: ", + "DELETE ANCHOR TITLE": "Удалить портал", + "DELETE MARKER PROMPT": "Хочешь удалить этот маркер: ", + "DELETE MARKER TITLE": "Удалить маркер", + "DELETE_ANCHOR": "Удалить", + "DELETE_LINK": "Удалить", + "DELETE_OP": "Удалить {opName}", + "DESCRIP_PLACEHOLD": "Описание (опционально)", + "DestroyPortalAlert": "Снести", + "DRAW TOOLS FORMAT": "Формат ДТ", + "DUPE_OP": "Дублировать операцию", + "END_PORT": "Конечный портал ", + "ExcludeMarker": "Исключить из авто-рисовки/маркировки", + "EXPORT OP TITLE": "Экспортировать текущую ОПРЦ", + "EXPORT OP": "Экспортировать ОПРЦ", + "EXPORT": "Экспортировать: ", + "FAKED": "Неподгружен: [{portalId}]", + "FANFIELD": "Нарисовать", + "FANFIELD2": "Нарисовать Fan Field", + "FarmPortalMarker": "Отфармить", + "FROM_1-2": "от опорного линка 1-2", + "FROM_1-3": "от опорного линка 1-3", + "FROM_2-3": "от опорного линка 2-3", + "FROM_DEPTH": "из глубины", + "FROM_PORT": "С портала", + "GET DT": "Получить существующее ДТ", + "GetKeyPortalMarker": "Получить ключи", + "GotoPortalMarker": "Перейти к", + "H-GEN_INST": "Выбери порталы для внешнего слоя. Выбери порядок гомогенности. Нажми 'рисовать'.", + "HF_DEEP_SEARCH": "Инсчерпывающий поиск", + "HF_DRAW_BUTTON": "Рисовать", + "HF_REDRAW_BUTTON": "Перерисовать", + "HG": "Гомогенное поле", + "HOURS": " ({hours} часов назад)", + "HOW_TO_VIDS": "

Обучающие видео:

", + "IMP_COMP": "Импорт завершён. Найдено ", + "IMP_NOPE": "Ошибка импорта.", + "IMP_WAS_OP": "Импортировать ОПРЦ Wasabee", + "IMPORT_OP_SUCCESS": "ОПРЦ: {opName} импортирована успешно.", + "IMPORT_OP_TITLE": "Импортировать ОПРЦ: {date}", + "IMPORT_OP": "Импортировать операцию", + "IMPOSSIBLE": "Невозможно", + "INGNAME_GID": "Ник Ingress или GoogleID", + "INPUT_DT_KEY_COUNT": "Введи количество ключей на руках", + "INPUT_SQUAD_NAME": "Введи имя отряда", + "INVALID REQUEST": "Неверный запрос", + "IOS NEED FAKE UA": "Нужно установить 'Custom UserAgent for Webviews' в настройках IITC-Mobile, чтобы вход удался", + "KEY_LIST2": "Список ключей для операции: {opName}", + "KEYS": "Ключи", + "KNOWN_BLOCK": "Известные кроссы: {opName}", + "LA DESC": "В зависимости от количества и типа использованных ламп для линковки может быть достаточно более низкого уровня портала.", + "LA": "П8 с несколькими LA", + "LANG": "Язык", + "LEAVE": "Выйти", + "LetDecayPortalAlert": "Просадить", + "LINK ASSIGNMENT": " Назначение линка", + "LINK STATE PROMPT": "Статус линка", + "LINK STATE": "Установить статус линка", + "LINKS BUTTON TITLE": "Линки", + "LINKS": "Линки", + "LINKS2": "{portalName} : Линки ({outgoing}↑/{incoming}↓)", + "LOAD PORTALS": "Загрузить порталы", + "LOADING": "[загрузка]", + "LOADING1": "Загрузка: [{portalGuid}]", + "LOC_PROC": "Местоположение обработано", + "LOCATION SUB": "Местоположение зарегистрировано", + "LOCFRMSER": " (локально и с сервера)", + "LOG IN": "Логин", + "LOG_OUT": "Выход", + "MADRID_SET_1": "Выбери область для опорного линка сопорника 2 на опорник 3", + "MADRID_SET_2": "Выбери область для опорного линка сопорника 3 на опорник 1", + "MADRID_SET_3": "Выбери область для опорного линка сопорника 1 на опорник 2", + "MADRID_TITLE": "Мадридский протокол", + "MADRID_WAS_TAKEN": "Мадридский протокол", + "MADRID": "Нарисовать", + "MANAGE_TEAM": "Редактировать {teamName}", + "MANAGE": "Редактировать", + "MARKER ASSIGNMENT": " Назначение маркера", + "MARKER LIST TITLE": "Список маркеров", + "MARKER LIST": "Маркеры", + "MARKER STATE PROMPT": "Статус маркера", + "MARKER STATE": " Установить статус маркера", + "MARKER_LIST": "Список маркеров: {opName}", + "MARKERS BUTTON TITLE": "Маркеры", + "MAX_SPLITS": "Максимальный уровень", + "MAX": "Fan Field", + "MeetAgentPortalMarker": "Встретить агента", + "MERGE ON UPDATE": "Объединить при обновлении", + "MERGE_CHANGES_LOCAL": "Изменения на устройстве", + "MERGE_CHANGES_MERGE": "Объединить результат", + "MERGE_CHANGES_REMOTE": "Изменения на сервере", + "MERGE_LOCAL": "Сохранить версию с устройства", + "MERGE_MESSAGE": "Похоже, что в ОПРЦ{opName} внесены изменения на устройстве. Хочешь объединить изменения с ОПРЦ на сервере, использовать версию с сервера или сохранить версию с устройства?", + "MERGE_REBASE": "Объединить", + "MERGE_REPLACE": "Использовать версию с сервера", + "MERGE_TITLE": "Объединение версий ОПРЦ на устройстве и на сервере", + "MIN_SRC_PORT_LVL": "Минимальный требуемый уровень портала для линковки", + "MINUTES": " ({minutes} минут назад)", + "MM": "Multimax", + "MULTI_M_TITLE": "Нарисовать максимальное количество слоёв", + "MULTI_M": "Нарисовать", + "MUST_NOT_BE_EMPTY": "Не должно быть пустым", + "MY_CAP_ID": "ID моей капсулы", + "MY_COUNT": "Моё количество", + "NAME_REQ": "Требуется имя", + "NAME": "Название: ", + "NEW_OP": "Новая операция", + "NEW_TEAM_NAME": "Новое имя команды", + "NEW_TEAM": "Новая команда", + "NEW_WAS_SERVER": "Новый сервер Wasabee", + "NEWOP BUTTON TITLE": "Создать новую операцию", + "NEWOP BUTTON": "Новая ОПРЦ", + "NO_DT_ITEMS": "Не обнаружено элементов ДТ", + "NO_LABEL": "Метка не установлена", + "NO_STOCK_INTEL": "Wasabee не поддерживает импорт из Intel", + "NO_TITLE": "Название не установлено", + "NOT LOGGED IN SHORT": "Не залогинен", + "NOT LOGGED IN": "Не залогинен: {error}", + "NOT_SET": "не установлено", + "NTNAME": "Название", + "OK": "OK", + "ON_HAND": "На руках", + "ONION_WAS_TAKEN": "Onion", + "ONION": "Нарисовать", + "ONLY_DT_IMP": " (только для импорта ДТ)", + "OP DELETED": "Операция удалена с сервера: {opID}", + "OP PERM DENIED": "Отказано в доступе к операции: {opID}", + "OP_BUTTON": "Операция", + "OP_CHECKLIST": "Чек-лист операции: {opName}", + "OP_NAME_UNSET": "Название операции не задано", + "OP_PERMS": "Разрешения ОПРЦ", + "OP_SETTINGS_BUTTON": "ОПРЦ ⚙", + "OP_SETTINGS_TITLE": "Настройки операции", + "OPEN_REQUEST": "[открытый запрос]", + "OPER_COLOR": "Цвет операции: ", + "OPER_NAME": "Название операции: ", + "OPERATIONS": "Операции", + "OPS BUTTON TITLE": "Список операций", + "OPS BUTTON": "Выбери ОПРЦ", + "ORDER": "Порядок", + "OtherPortalAlert": "Другое", + "PASTE_INSTRUCT": "Вставь экспортируемые данные Wasabee здесь.\n\nWasabee не может импортировать данные в формате интела.\n\nЕсть эксперементальная поддержка ДТ формата IITC.\n\nПрежде чем импортировать ДТ в формате IITC, просмотрите область ДТ и убедитесь, что все порталы загружены и кэшированы в IITC. Любой неподгруженный портал будет неподгружен.\n\nНужно будет использовать функцию 'замена', чтобы переместить порталы со неподгруженных на настоящие (местоположение порталов будет корректным, однако неподгруженные порталы не будут связаны с реальными).\n\nКэшированные порталы могут некорректно называться.", + "pending": "Ожидается", + "PERMS": "Разрешения {opName}", + "PLEASE_SELECT_PORTAL": "Выбери портал", + "PORT_FAKE": " порталов. Неподгружены ", + "PORTAL KEY LIST": "Список ключей для портала {portalName}", + "PORTAL_COUNT": "{count} порталов", + "PORTAL": "Портал", + "QD BUTTON CHANGE COLOR": "Кликни, чтобы изменить цвет следующего линка", + "QD BUTTON END": "Кликни, чтобы остановить прорисовку полей", + "QD BUTTON TOGGLE MODE": "Кликни, чтобы поменять режим рисовки", + "QD CHANGE COLOR": "Изменить цвет", + "QD END": "Стоп", + "QD TITLE": "Слои быстрой рисовки", + "QD TOGGLE MODE": "Изменить режим", + "QDBASE": "Опорный линк", + "QDCONT": "Кликни портал в грядке, чтобы нарисовать поле.", + "QDNEXT": "Кликни на второй опорный портал.", + "QDSTART": "Кликни на первый опорный портал.", + "READ_SHORT": "RO", + "READ": "только чтение", + "RechargePortalAlert": "Зарядить", + "REFERENCE_TIME": "Reference time: ", + "REM_LOC_CP": "Удалить локальную копию {opName}", + "REMOVE_TEAM_CONFIRM_LABEL": "Хочешь навсегда удалить {teamName} с сервера Wasabee?", + "REMOVE_TEAM_CONFIRM_TITLE": "Удаление команды {teamName}", + "REMOVE_TEAM": "Удалить команду: ", + "REMOVE": "Удалить", + "RENAME_TEAM": "Переименовать команду: ", + "RENAME": "Переименовать", + "REQUIRED": "Требуется", + "RESET": "Сброс", + "REVERSE": "Обратить", + "ROCKS_COM": "Сообщество enl.rocks: ", + "ROLE": "Роль", + "SAVELINKS TITLE": "Сохранить линки", + "SAVELINKS_DRAW": "Сохранить линки", + "SAVELINKS": "Сохранить линки", + "SECONDS": " ({seconds} секунд назад)", + "SEL_SB_ANCHOR": "Выбери опорник.", + "SEL_SB_ANCHOR2": "Уменьши масштаб. Убедись, что порталы полностью загрузились, затем кликни рисовку.", + "SEL_SL_ANCHOR": "Выбери портал, линки которого нужно сохранить. Кликни на кнопку сохранения линков и посмотри в чек-лист.", + "SEL_SRC_ANC2": "Выбери оба портала: начальный и опорник 2", + "SEL_SRC_PORT": "Выбери начальный портал", + "SELECT PORTAL": "Сначала выбери портал", + "SELECT_FAN_PORTALS": "Выбери опорный портал, стартовый портал и конечный портал, а затем позиционируйте карту над областью полей.", + "SELECT_FAN_PORTALS2": "Подожди, пока все порталы загрузятся, затем кликни рисовку.", + "SELECT_INSTRUCTIONS": "Выбери два опорных портала, затем увеличь область грядки.", + "SELECT_ONION_PORTALS": "Слои строятся изнутри наружу. Приблизь масштаб в центр и выбери начальный портал, затем отдали масштаб на всю область.", + "SELF SWAP": "Нельзя заменить портал на тот же самый! Выбери другой портал.", + "SEND ANALYTICS": "Отправить аналитику анонимно", + "SEND LOCATION": "Отправить местоположение", + "SEND TARGET AGENT": "Выбрать получателя цели", + "SEND TARGET CONFIRM": "Хочешь отправить цель {portalName} агенту {agent}?", + "SEND TARGET": "Отправить цель", + "SEND_LOC": "Отправить местоположение", + "SET_3_PORT": "Сначала задай три портала!", + "SET_COMMENT": "Задать комментарий", + "SET_LCOMMENT": "Задать комментарий к линку", + "SET_LINK_COMMENT": "Задать комментарий для линка: ", + "SET_LINKS_ZONES": "Задать линкам зоны ", + "SET_MARKER_COMMENT": "Задать комментарий для маркера на: ", + "SET_MARKER_TYPE_TITLE": "Изменить тип маркера", + "SET_MARKERS_ZONES": "Задать маркеры в зоны", + "SET_MCOMMENT": "Задать комментария маркеру: {portalName}", + "SET_NEW_OP": "Задай имя для новой операции", + "SET_PCOMMENT": "Задать комментарий порталу: {portalName}", + "SET_PORT_COMMENT": "Задать комментарий порталу: ", + "SET_PORTAL_COMMENT": "Задать комментарий порталу", + "SET": "задать", + "SETTINGS": "Настройки Wasabee", + "SKINS_AVAILABLE": "Есть {count} доступных скинов.", + "SKINS_BUTTON": "Настроить скины", + "SKINS_DESCRIPTION": "Пакеты доступных скинов размещены в правой колонке. Перемести в левую колонку те, которые хочешь использовать.", + "SKINS_MANAGE_TITLE": "Управление скинами", + "SKIP_CONFIRM_ALWAYS": "Никогда не спрашивать (используй осторожно)", + "SKIP_CONFIRM_ENTITY": "Спрашивать только для команд/ОПРЦ", + "SKIP_CONFIRM_NEVER": "Всегда спрашивать", + "SKIP_CONFIRM": "Подтверждение пропуска", + "SOURCE_PORT": "Начальный портал ", + "SQUAD": "Отряд", + "STARBURST TITLE": "Звезда", + "STARBURST_DRAW": "Рисовка", + "STARBURST": "Звезда", + "START_PORT": "Стартовый портал ", + "STATE": "Статус", + "SUPPORT_INSTRUCT": "Для поддержки, присоединяйся к The Wasabee User Telegram Channel", + "SWAP PROMPT": "Хочешь заменить: ", + "SWAP TITLE": "Замена порталов", + "SWAP WITH": " на ", + "SWAP": "Замена", + "SYNC DONE": "Загрузка завершена
Кликни ЗДЕСЬ для подсказок, советов и документации.", + "SYNC": "Загрузить доступные операции", + "TARGET SENT": "Цель отправлена", + "TEAM STATE": "Делиться местоположением", + "TEAM_CREATED": "Команда {teamName} создана", + "TEAM_NAME": "Название команды", + "TEAM": "Команда", + "TEAMS BUTTON TITLE": "Список команд Wasabee", + "TEAMS BUTTON": "Команды", + "TO_PORT": "На портал", + "TRAWL SKIP TILES": "Шаг тайлов для выверки", + "TRAWL TITLE": "Выверка трасс", + "TRAWL WARNING": "Этот метод загрузит данные тайлов под всеми нарисованными линками. Это медленный процесс.", + "TRAWL_AUTOMARK": "Автоматически маркировать кроссы после выверки", + "TRAWL_BULK_LOAD_WARNING": "Этот метод загрузит данные тайлов так быстро, как это возможно. Используй его на свой страх и риск.", + "TRAWL_BULK_LOAD": "Массово загрузить данные тайлов", + "TRAWL_CLEAR_MARKERS": "Очистить маркеры вирусов и сноса перед выверкой", + "TRAWL_REMAINING": "{count} тайлов осталось", + "TRAWL": "Выверка для поиска кроссов", + "TRAWLING": "Выверка трасс для поиска кроссов, закрой этот диалог, чтобы остановить процесс", + "TYPE": "Тип", + "UNASSIGNED": "Не назначен", + "UNKNOWN": "Неизвестен", + "UPDATE HOVER NOT CHANGED": "{opName} не изменилась локально", + "UPDATE HOVER": "ОБНОВИТЬ {opName} на сервере", + "UPDATE PERM DENIED": "У тебя недостаточно прав для обновления", + "UPDATE_CONFLICT_DESC": "ОПРЦ изменилась на сервере с момента последней синхронизации. Хочешь заменить версию на сервере текущей?", + "UPDATE_CONFLICT_TITLE": "Обнаружен конфликт с сервером", + "UPDATE_COUNT": "Количество обновлений", + "UPDATED": "Успешно обновлено", + "UpgradePortalAlert": "Апнуть", + "UPLOAD BUTTON HOVER": "ЗАГРУЗИТЬ {opName} на сервер (пока что её там нет)", + "UPLOADED": "Успешно загружено на сервер", + "USE PANES ON MOBILE": "Использовать панели (нужна перезагрузка)", + "USE_SWAP_INSTRUCT": ". Используй функцию замены, чтобы заменить неподгруженные порталы на настоящие на тех же местах. Увеличение масштаба на порталах чек-листа с меткой 'загрузка' может заставить их загрузиться.", + "USE_VALID_NAME": "Используй действительное название операции", + "UseVirusPortalAlert": "Использовать вирус", + "VRLA DESC": "В зависимости от количества и типа использованных ламп может быть достаточно более низкого уровня портала для линковки.", + "VRLA": "П8 с несколькими VRLA", + "WASABEE BUTTON TITLE": "Wasabee: зелёный и заставляет смурфов плакать.", + "WASABEE_D_LIST": "Ввод количества ключей на руках", + "WD BUTTON TITLE": "Список ключей на руках", + "WD BUTTON": "Ключи на руках", + "WEBVIEW VERIFY": "Подтвердить Webview", + "WEBVIEW": "Логин Webview (iOS)", + "WRITE_SHORT": "RW", + "WRITE": "чтение и запись", + "WSERVER": "Сервер: {url}", + "YESNO_DEL": "Уверен, что хочешь удалить {opName}?", + "ZONE_DRAW": "Кликни, чтобы задать границы зоны", + "ZONE": "Зона", + "smallScreen": { + "ADD_LINKS": "+ Линки", + "ADD_MARKER": "+ Маркер", + "BLOCKER TITLE": "кроссы", + "CHECKLIST BUTTON": "Чек-лист", + "CLEAROPS BUTTON": "Очистить", + "EXPORT OP": "Экспортировать", + "FAN_FIELD3": "Fan", + "FANFIELD": "Рисовка", + "FANFIELD2": "Нарисовать Fan Field", + "KEYS": "Ключи", + "LOG IN": "Логин", + "LOG_OUT": "Выход", + "MARKER LIST": "Маркеры", + "MARKERS BUTTON TITLE": "Маркеры", + "MAX": "Fan", + "MM": "Multi", + "MULTI_M_TITLE": "Рисовать максимальное количество слоёв", + "MULTI_M": "Рисовать", + "NEWOP BUTTON": "Новая ОПРЦ", + "OPS BUTTON": "Выбрать ОПРЦ", + "QD END": "Конец", + "STARBURST_DRAW": "Рисовать", + "STARBURST": "Звезда", + "TEAMS BUTTON": "Команды", + "WD BUTTON": "Ключи на руках" + } +} From 804b9e7e149d3da0eaf7ff5b4034cc9c7f589211 Mon Sep 17 00:00:00 2001 From: TheMitch2 <62919690+TheMitch2@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:29:00 -0600 Subject: [PATCH 084/275] Remove 39 unused keys --- src/code/translations/spanish.json | 39 ------------------------------ 1 file changed, 39 deletions(-) diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index c204d713a..0c80f0a60 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -1,5 +1,4 @@ { - "ABOUT WASABEE-IITC": "Sobre Wasabee-IITC", "ABOUT_WASABEE": "Sobre Wasabee", "acknowledged": "Acknowledged", "ADD LINK TITLE": "Texto de Agregar Links", @@ -39,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Assigned Only", "assigned": "Asignado", - "ASSIGNED": "Asignado", "AUTH ANDROID": "On En Android, prueba 'rápido' primero. Si eso falla, intenta el inicio de sesión principal con 'select_account'.", "AUTH INCOMPAT": "Has activado un plugin en TamperMonkey que es incompatible con Wasabee", "AUTH IOS": "En iOS, usa el 'Iniciar Sesión' principal. Si eso falla intenta usar 'Inicio de Sesión Vista Web'; luego usa el botón 'Verificar Vista Web' para completar el proceso.", @@ -67,7 +65,6 @@ "CLEAR LINKS": "Clear Links", "CLEAR MARKERS": "Clear Markers", "CLEAR_EVERYTHING": "Borrar Portales/Links/Marcadores", - "CLEAR": "Borrar selección", "CLEAROPS BUTTON TITLE": "Borrar TODOS los Datos de Wasabee", "CLEAROPS BUTTON": "Borrar Datos de Wasabee", "CLEAROPS PROMPT": "Esta opción borrará todas las OPS y datos relacionados a Wasabee. Todo será restaurado desde el servidor en la próxima sincronización.", @@ -75,9 +72,7 @@ "COMMENT": "Comentario", "COMPLETED BY": "Completado por {agentName}", "completed": "Completo", - "COMPLETED": "Completo", "CON_DEL": "Confirmar Borrado {opName}", - "CONFIRM_DELETE": "Estás seguro de querer borrar este link", "COUNT": "Contar", "CREATE_NEW_TEAM": "Crear Nuevo Equipo", "CreateLinkAlert": "Linkear", @@ -88,19 +83,12 @@ "DELETE ANCHOR TITLE": "Borrar Ancla", "DELETE MARKER PROMPT": "Quisieras borrar este marcador", "DELETE MARKER TITLE": "Borrar Marcador", - "DELETE PERM DENIED": "Permiso para borrar denegado", "DELETE_ANCHOR": "Borrar", "DELETE_LINK": "Borrar", - "DELETE_MARKER": "Borrar", "DELETE_OP": "Borrar {opName}", - "DELETED": "Borrado exitosamente", "DESCRIP_PLACEHOLD": "Descripción (opcional)", "DestroyPortalAlert": "Destruir", - "DISABLE_SYNC": "El plugin estándar de Sincronización no es compatible con Wassabe. Por favor, deshabilitar Sync.", - "DISABLED": "Esta opción no está lista para los usuarios", - "DONE": "Hecho", "DRAW TOOLS FORMAT": "Draw Tools Format", - "DT_FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplicar Operación", "END_PORT": "Portal de Fin", "ExcludeMarker": "Excluir del Dibujo/Marcado Automático", @@ -108,8 +96,6 @@ "EXPORT OP": "Exportar Op", "EXPORT": "Exportar", "FAKED": "Faked: [{portalId}]", - "FAN_FIELD3": "Fan Field", - "FANFIELD TITLE": "Fanfield", "FANFIELD": "¡Dibujar!", "FANFIELD2": "Fanfield", "FarmPortalMarker": "Farmear", @@ -124,19 +110,16 @@ "FROM_DEPTH": "from the depth", "FROM_PORT": "Desde el Portal", "GET DT": "Get existing DrawTools draw", - "GET_DT_DRAW": "Obtener dibujo existente de DrawTools", "GetKeyPortalMarker": "Obtener Keys", "GotoPortalMarker": "Ir A", "H-GEN_INST": "Set portals for the outside layer. Choose number of splits. Click draw", "HF_DEEP_SEARCH": "Exhaustive search", "HF_DRAW_BUTTON": "Draw", - "HF_DRAW_DEEP_BUTTON": "Draw with deep recursion", "HF_REDRAW_BUTTON": "Redraw", "HG": "Homogeneous Field", "HOURS": "(Hace {hours} horas)", "HOW_TO_VIDS": "

Videos de Cómo Se Hace:

", "IMP_COMP": "Importación Completa. Se encontró", - "IMP_DT_OP": "Op en Drawtools Importada", "IMP_NOPE": "Importación Falló: {error}", "IMP_WAS_OP": "Importar Operación Wasabee", "IMPORT_OP_SUCCESS": "Operación {opName} Importada Exitosamente.", @@ -166,10 +149,8 @@ "LOADING": "[cargando]", "LOADING1": "Cargando: [{portalGuid}]", "LOC_PROC": "ubicación procesada", - "LOC_UPDATE": "Actualización de Ubicación", "LOCATION SUB": "Ubicación registrada", "LOCFRMSER": "(localmente y del servidor)", - "LOG IN QUICK": "Iniciar Sesión (rápido; para Android)", "LOG IN": "Iniciar Sesión", "LOG_OUT": "Cerrar sesión", "MADRID_SET_1": "Select the region for baselink Anchor 2 to Anchor 3", @@ -209,8 +190,6 @@ "MM_SPINE": "Spine", "MULTI_M_TITLE": "Draw Max Layers", "MULTI_M": "Multimax", - "MULTIMAX": "¡Multimax!", - "MULTIMAX2": "Multimax", "MUST_NOT_BE_EMPTY": "No Debe Quedar Vacío", "MY_CAP_ID": "ID de Mi Cápsula", "MY_COUNT": "Mi Conteo", @@ -222,16 +201,12 @@ "NEW_WAS_SERVER": "Nuevo Servidor de Wasabee", "NEWOP BUTTON TITLE": "Crear una nueva Operación", "NEWOP BUTTON": "Nueva Op", - "NO_DATA": "Sin data", "NO_DT_ITEMS": "No se detectó elementos dibujados con DrawTools", "NO_LABEL": "Sin etiqueta definida", - "NO_PORT_SEL": "Ningún Portal Portal Seleccionado.", "NO_STOCK_INTEL": "Wasabee no soporta la importación de dibujos trazados en intel regular", "NO_TITLE": "Sin título definido", - "NO": "No", "NOT LOGGED IN SHORT": "Sesión No Iniciada", "NOT LOGGED IN": "Sesión No Iniciada: {error}", - "NOT_LOADED": "No está cargado completamente, intentar de nuevo.", "NOT_SET": "no definido", "NTNAME": "Nombre", "OK": "OK", @@ -257,11 +232,7 @@ "OtherPortalAlert": "Otro", "PASTE_INSTRUCT": "Pega un dibujo exportado de Wasabee aquí.\n\nWasabee no puede importar del formato normal de intel.\n\nHay soporte experimental para importar del formato DrawTools de IITC.\n\nAntes de importar del formato DrawTools, revise las áreas y asegúrese que todos los portales carguen para que estén en la caché de IITC. Cualquier portal que no haya estado pre-cargado será falsificado. Tendrás que usar la opción 'intercambiar' para mover las anclas de los portales falsos a los portales reales (estarán en la ubicación correcta, pero no asociados con el portal.\n\nPortales en la caché puede que no estén nombrados correctamente.", "pending": "Pendiente", - "PENDING": "Pendiente", "PERMS": "{opName} permisos", - "PICK_DEST_FIRST": "¡Por favor, primero elige un portal de destino!", - "PICK_TAR_FIRST": "¡Por favor, primero elige un portal objetivo!", - "PICK_TARGETDEST_Portals": "¡Por favor, primero selecciona portales de origen y de destino!", "PLEASE_SELECT_PORTAL": "Por favor, seleccionar un portal", "PORT_FAKE": "portales. Falsificados", "PORTAL KEY LIST": "Lista de Llaves del Portal {portalName}", @@ -271,11 +242,9 @@ "QD BUTTON END": "Dar click para detener dibujo de campos", "QD BUTTON TOGGLE MODE": "Click to change draw mode", "QD CHANGE COLOR": "Change color", - "QD END": "Fin", "QD TITLE": "Dibujar Capas Rápido", "QD TOGGLE MODE": "Change mode", "QDBASE": "Link Base", - "QDCANCEL": "Cancelar Dibujar Campos", "QDCONT": "Dar click a un portal anidado para dibujar el campo.", "QDEND": "Dar click nuevamente al mismo portal para finalizar el dibujo.", "QDNEXT": "Dar click al segundo portal ancla.", @@ -300,10 +269,8 @@ "SAVELINKS_DRAW": "Save Links", "SAVELINKS": "Save Links", "SECONDS": "(Hace {seconds} segundos)", - "SEL_PORT_FIRST": "¡Por favor, primero seleccionar portal ancla!", "SEL_SB_ANCHOR": "Selecciona el área del ancla para hacer acercamiento para añadir a la supernova.", "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", - "SEL_SB_ANCHOR3": "Please be patient, it can take a bit.", "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", "SEL_SRC_ANC2": "Selecciona tanto la Fuente como el Ancla 2", "SEL_SRC_PORT": "Selecciona un portal fuente", @@ -311,7 +278,6 @@ "SELECT_FAN_PORTALS": "Selecciona un portal ancla, un portal de inicio y un portal de fin, luego haz un acercamiento en el área para el fan field. Espera hasta que los portales hayan cargado (los portales deben estar en la pantalla para ser considerados) y presiona el botón Fanfield.", "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", "SELECT_INSTRUCTIONS": "Selecciona dos portales ancla, luego luego haz un acercamiento en el área para los nodos de las capas. Espera hasta que los portales hayan cargado (los portales deben estar en la pantalla para ser considerados) y presiona el botón Multimax.", - "SELECT_MADRID_INSTRUCTIONS": "Select three anchor portals, zoom in on the area near the selected anchor, wait until the portals are loaded (portals must be on screen to be considered) then select the 'define spine region' button for the corresponding base links.", "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", "SELF SWAP": "¡No se puede intercambiar un portal consigo mismo! Selecciona un portal diferente.", "SEND ANALYTICS": "Send Anonymous Analytics", @@ -357,16 +323,13 @@ "SWAP": "Intercambiar", "SYNC DONE": "Descarga Completa
Haga clic AQUÍ para obtener sugerencias, consejos y documentación.", "SYNC": "Descargar Operaciones Disponibles", - "TARDEST_DIFF": "Los portales objetivo y de destino deben ser diferentes.", "TARGET SENT": "Objetivo enviado", - "TEAM PERM DENIED": "Permiso denegeado al equipo: {error}", "TEAM STATE": "Share Location", "TEAM_CREATED": "Equipo {teamName} creado", "TEAM_NAME": "Nombre de Equipo", "TEAM": "Equipo", "TEAMS BUTTON TITLE": "Listar Equipos Wasabee", "TEAMS BUTTON": "Equipos", - "TITLE": "título", "TO_PORT": "Hacia el Portal", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", @@ -390,7 +353,6 @@ "UPDATED": "Actualizado exitosamente", "UpgradePortalAlert": "Actualizar", "UPLOAD BUTTON HOVER": "CARGAR {opName} (no se encuentra actualmente en el servidor)", - "UPLOAD PERM DENIED": "Permiso para cargar denegado", "UPLOADED": "Cargado exitosamente", "USE PANES ON MOBILE": "Use panes (need reload)", "USE_SWAP_INSTRUCT": "Por favor, usa la opción de intercambiar portales para mover los portales falsificados hacia los portales reales en la misma ubicación. Hacer un acercamiento en los portales que están 'Cargando' en la lista de verificación puede forzarlos a cargar.", @@ -407,7 +369,6 @@ "WRITE_SHORT": "RW", "WRITE": "escribir", "WSERVER": "Servidor {url}", - "YES": "Sí", "YESNO_DEL": "Estás seguro de querer borrar {opName}", "ZONE_DRAW": "Click to set the zone boundaries", "ZONE": "Zona", From 52dc9cd0471922f3802536918be303f33744c9dc Mon Sep 17 00:00:00 2001 From: TheMitch2 Date: Thu, 2 Dec 2021 17:06:59 -0600 Subject: [PATCH 085/275] Update english.json --- src/code/translations/english.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code/translations/english.json b/src/code/translations/english.json index d81ac5896..c886c43d5 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -317,7 +317,7 @@ "STARBURST": "Starburst", "START_PORT": "Start Portal ", "STATE": "State", - "SUPPORT_INSTRUCT": "For support, please join the The Wasabee User Telegram Channel", + "SUPPORT_INSTRUCT": "For support, please join the Wasabee User Telegram Channel", "SWAP PROMPT": "Do you want to swap: ", "SWAP TITLE": "Swap Portals", "SWAP WITH": " with ", @@ -400,4 +400,4 @@ "TEAMS BUTTON": "Teams", "WD BUTTON": "W-D Keys" } -} +} \ No newline at end of file From b1b9af114d0009a4ddb73d3744eb6df297402e0a Mon Sep 17 00:00:00 2001 From: TheMitch2 Date: Thu, 2 Dec 2021 17:26:20 -0600 Subject: [PATCH 086/275] Update english.json --- src/code/translations/english.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/code/translations/english.json b/src/code/translations/english.json index c886c43d5..b367c0fbb 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -91,7 +91,7 @@ "DestroyPortalAlert": "Destroy", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplicate Operation", - "END_PORT": "End Portal ", + "END_PORT": "End Portal", "ExcludeMarker": "Exclude from Auto-Draw/Mark", "EXPORT OP TITLE": "Export current Op", "EXPORT OP": "Export Op", @@ -119,7 +119,7 @@ "HF_REDRAW_BUTTON": "Redraw", "HG": "Homogeneous Field", "HOURS": " ({hours} hours ago)", - "HOW_TO_VIDS": "

How-To Videos:

", + "HOW_TO_VIDS": "

How-To Videos:

", "IMP_COMP": "Import Complete. Found ", "IMP_NOPE": "Import Failed: {error}", "IMP_WAS_OP": "Import Wasabee Operation", @@ -177,7 +177,7 @@ "MERGE_CHANGES_MERGE": "Merge result", "MERGE_CHANGES_REMOTE": "Remote changes", "MERGE_LOCAL": "Keep local", - "MERGE_MESSAGE": "It seems that {opName} has local changes. Do you want to merge your modifications with the server OP, use the server version or keep the local version?", + "MERGE_MESSAGE": "It seems that {opName} has local changes. Do you want to merge your modifications with the server, use the server version, or keep the local version?", "MERGE_REBASE": "Merge", "MERGE_REPLACE": "Use server", "MERGE_TITLE": "Merge local&remote OP", @@ -315,7 +315,7 @@ "STARBURST TITLE": "Starburst", "STARBURST_DRAW": "Draw", "STARBURST": "Starburst", - "START_PORT": "Start Portal ", + "START_PORT": "Start Portal", "STATE": "State", "SUPPORT_INSTRUCT": "For support, please join the Wasabee User Telegram Channel", "SWAP PROMPT": "Do you want to swap: ", @@ -348,7 +348,7 @@ "UPDATE HOVER NOT CHANGED": "{opName} not changed locally", "UPDATE HOVER": "UPDATE {opName} on the server", "UPDATE PERM DENIED": "You do not have permission to update", - "UPDATE_CONFLICT_DESC": "The OP has been modified on server since last sync. Do you want to replace the server version by the current one?", + "UPDATE_CONFLICT_DESC": "The OP has been modified on the server since last sync. Do you want to replace the server version with the current one?", "UPDATE_CONFLICT_TITLE": "Conflict detected with server", "UPDATE_COUNT": "Update Count", "UPDATED": "Successfully updated", @@ -361,7 +361,7 @@ "UseVirusPortalAlert": "Use Virus", "VRLA DESC": "Depending on the number and type of Link Amps used, a lower source portal level might suffice.", "VRLA": "L8+some VRLA", - "WASABEE BUTTON TITLE": "Wasabee: it is green and makes smurfs cry.", + "WASABEE BUTTON TITLE": "Wasabee: It is green and makes smurfs cry.", "WASABEE_D_LIST": "Input Defensive Key Count", "WD BUTTON TITLE": "Log Defensive Keys", "WD BUTTON": "W-D Keys", From 1e8a1e0258701f5d1d425fcf4fae04fe2ec44eb3 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 22:22:29 +0100 Subject: [PATCH 087/275] task.ts --- src/code/dialogs/autodraws/multimaxDialog.js | 4 +- src/code/dialogs/checklist.js | 10 +- src/code/index.d.ts | 7 +- src/code/model/link.d.ts | 38 ------ src/code/model/link.js | 119 ----------------- src/code/model/link.ts | 88 +++++++++++++ src/code/model/marker.d.ts | 47 ------- src/code/model/marker.js | 127 ------------------- src/code/model/marker.ts | 88 +++++++++++++ src/code/model/operation.js | 10 +- src/code/model/task.ts | 89 +++++++++++++ src/code/ui/link.js | 6 +- 12 files changed, 283 insertions(+), 350 deletions(-) delete mode 100644 src/code/model/link.d.ts delete mode 100644 src/code/model/link.js create mode 100644 src/code/model/link.ts delete mode 100644 src/code/model/marker.d.ts delete mode 100644 src/code/model/marker.js create mode 100644 src/code/model/marker.ts create mode 100644 src/code/model/task.ts diff --git a/src/code/dialogs/autodraws/multimaxDialog.js b/src/code/dialogs/autodraws/multimaxDialog.js index 55c60795e..0b1d51933 100644 --- a/src/code/dialogs/autodraws/multimaxDialog.js +++ b/src/code/dialogs/autodraws/multimaxDialog.js @@ -130,10 +130,10 @@ const MultimaxDialog = AutoDraw.extend({ // skip base if (l.toPortalId === pOne.id && l.fromPortalId === pTwo.id) continue; if (l.fromPortalId === pOne.id && l.toPortalId === pTwo.id) continue; - if (l.opOrder > order) l.opOrder += diff; + if (l.order > order) l.order += diff; } for (const m of this._operation.markers) { - if (m.opOrder > order) m.opOrder += diff; + if (m.order > order) m.order += diff; } } diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 63e5c6cc3..507694a87 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -104,7 +104,7 @@ const OperationChecklistDialog = WDialog.extend({ const columns = [ { name: this._smallScreen ? "#" : wX("ORDER"), - value: (thing) => thing.opOrder, + value: (thing) => thing.order, // sort: (a, b) => a - b, format: (cell, value, thing) => { const oif = L.DomUtil.create("input"); @@ -114,9 +114,9 @@ const OperationChecklistDialog = WDialog.extend({ L.DomEvent.on(oif, "change", (ev) => { L.DomEvent.stop(ev); if (thing instanceof WasabeeLink) { - operation.setLinkOrder(thing.ID, oif.value); + operation.setLinkOrder(thing.ID, +oif.value); } else { - operation.setMarkerOrder(thing.ID, oif.value); + operation.setMarkerOrder(thing.ID, +oif.value); } }); cell.appendChild(oif); @@ -302,7 +302,7 @@ const OperationChecklistDialog = WDialog.extend({ countFields: function (operation, doAlert) { const links = Array.from(operation.links); - links.sort((a, b) => a.opOrder - b.opOrder); + links.sort((a, b) => a.order - b.order); let fieldCount = 0; let emptyCount = 0; @@ -327,7 +327,7 @@ const OperationChecklistDialog = WDialog.extend({ b.add(link.fromPortalId); // ignore link with order 0 - if (link.opOrder > 0) { + if (link.order > 0) { // the link closes at least one field const p1 = operation.getPortal(link.fromPortalId); const p2 = operation.getPortal(link.toPortalId); diff --git a/src/code/index.d.ts b/src/code/index.d.ts index d0439ddfc..48d8c0a8c 100644 --- a/src/code/index.d.ts +++ b/src/code/index.d.ts @@ -1,13 +1,12 @@ -/// - export {}; declare global { type OpID = string; type PortalID = string; type TeamID = string; - type LinkID = string; - type MarkerID = string; + type TaskID = string; + type LinkID = TaskID; + type MarkerID = TaskID; type GoogleID = string; type ZoneID = number; } diff --git a/src/code/model/link.d.ts b/src/code/model/link.d.ts deleted file mode 100644 index 430485bf2..000000000 --- a/src/code/model/link.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type WasabeeOp from "./operation"; -export default class WasabeeLink { - ID: string; - fromPortalId: string; - toPortalId: string; - description?: string; - assignedTo?: string; - throwOrderPos: number; - color: string; - completed: boolean; - zone: number; - constructor(obj: any); - assign(gid: any): void; - toJSON(): { - ID: string; - fromPortalId: string; - toPortalId: string; - description: string; - assignedTo: string; - throwOrderPos: number; - color: string; - completed: boolean; - zone: number; - }; - get comment(): string; - set comment(c: string); - get opOrder(): number; - set opOrder(o: number); - setOrder(o: number | string): void; - get state(): "pending" | "completed" | "assigned"; - set state(s: string); - get portalId(): string; - getLatLngs(operation: WasabeeOp): any[]; - get latLngs(): any[]; - setColor(color: string, operation: WasabeeOp): void; - getColor(operation: WasabeeOp): string; - length(operation: WasabeeOp): number; -} diff --git a/src/code/model/link.js b/src/code/model/link.js deleted file mode 100644 index aa2011988..000000000 --- a/src/code/model/link.js +++ /dev/null @@ -1,119 +0,0 @@ -import { generateId } from "../auxiliar"; -import { getSelectedOperation } from "../selectedOp"; - -export default class WasabeeLink { - constructor(obj) { - this.ID = obj.ID ? obj.ID : generateId(); - this.fromPortalId = obj.fromPortalId; - this.toPortalId = obj.toPortalId; - this.description = obj.description; - this.assignedTo = obj.assignedTo ? obj.assignedTo : null; - this.throwOrderPos = obj.throwOrderPos ? Number(obj.throwOrderPos) : 0; - this.color = obj.color ? obj.color : "main"; - this.completed = obj.completed ? !!obj.completed : false; - this.zone = obj.zone ? Number(obj.zone) : 1; - } - - assign(gid) { - this.assignedTo = gid ? gid : null; - } - - // build object to serialize - toJSON() { - return { - ID: this.ID, - fromPortalId: this.fromPortalId, - toPortalId: this.toPortalId, - description: this.description, - assignedTo: this.assignedTo, - throwOrderPos: Number(this.throwOrderPos), - color: this.color, - completed: !!this.completed, // !! forces a boolean value - zone: Number(this.zone), - }; - } - - // for interface consistency, the other types use comment - // we can't rename them here w/o making the corresponding changes on the server - get comment() { - return this.description; - } - - set comment(c) { - this.description = c; - } - - // for interface consistency, other types use order - get opOrder() { - return this.throwOrderPos; - } - - set opOrder(o) { - this.throwOrderPos = Number.parseInt(o, 10); - } - - // make the interface match (kinda) what markers do - // 'pending','assigned','acknowledged','completed' - // THESE ARE INTERNAL VALUES AND SHOULD NOT BE wX'd!!! - get state() { - if (this.completed) return "completed"; - if (this.assignedTo) return "assigned"; - return "pending"; - } - - set state(s) { - if (s == "completed") { - this.completed = true; - } else { - this.completed = false; - } - } - - // kludge to make the interface work - get portalId() { - return this.fromPortalId; - } - - getLatLngs(operation) { - if (!operation) operation = getSelectedOperation(); - - const returnArray = Array(); - - const fromPortal = operation.getPortal(this.fromPortalId); - if (!fromPortal || !fromPortal.lat) { - console.log("unable to get source portal"); - return null; - } - returnArray.push(fromPortal.latLng); - - const toPortal = operation.getPortal(this.toPortalId); - if (!toPortal || !toPortal.lat) { - console.log("unable to get destination portal"); - return null; - } - returnArray.push(toPortal.latLng); - - return returnArray; - } - - get latLngs() { - return this.getLatLngs(getSelectedOperation()); - } - - setColor(color, operation) { - this.color = color; - if (this.color == operation.color) this.color = "main"; - operation.update(); - } - - getColor(operation) { - let color = this.color; - if (color == "main") color = operation.color; - return color; - } - - length(operation) { - const latlngs = this.getLatLngs(operation); - return L.latLng(latlngs[0]).distanceTo(latlngs[1]); - } -} diff --git a/src/code/model/link.ts b/src/code/model/link.ts new file mode 100644 index 000000000..ee01efa82 --- /dev/null +++ b/src/code/model/link.ts @@ -0,0 +1,88 @@ +import { getSelectedOperation } from "../selectedOp"; +import type WasabeeOp from "./operation"; + +import Task from "./task"; + +function fromServer(obj: any) { + // convert link task + obj.order = +obj.throwOrderPos || 0; + obj.state = "pending"; + obj.completedID = obj.completed ? obj.assignedTo : null; + if (obj.completedID) obj.state = "completed"; + else if (obj.assignedTo) obj.state = "assigned"; + if (obj.description) obj.comment = obj.description; + return obj; +} + +export default class WasabeeLink extends Task { + fromPortalId: PortalID; + toPortalId: PortalID; + color: string; + + constructor(obj: any) { + if (obj.throwOrderPos !== undefined) { + obj = fromServer(obj); + } + super(obj); + this.fromPortalId = obj.fromPortalId; + this.toPortalId = obj.toPortalId; + this.color = obj.color ? obj.color : "main"; + } + + // build object to serialize + toJSON() { + return { + ID: this.ID, + throwOrderPos: this.order, + zone: this.zone, + assignedTo: this.assignedTo, + completed: !!this.completedID, // !! forces a boolean value + fromPortalId: this.fromPortalId, + toPortalId: this.toPortalId, + color: this.color, + description: this.comment, + }; + } + + // kludge to make the interface work + get portalId() { + return this.fromPortalId; + } + + getLatLngs(operation: WasabeeOp) { + operation = operation || getSelectedOperation(); + const returnArray = Array(); + + const fromPortal = operation.getPortal(this.fromPortalId); + if (!fromPortal || !fromPortal.lat) { + console.log("unable to get source portal"); + return null; + } + returnArray.push(fromPortal.latLng); + + const toPortal = operation.getPortal(this.toPortalId); + if (!toPortal || !toPortal.lat) { + console.log("unable to get destination portal"); + return null; + } + returnArray.push(toPortal.latLng); + + return returnArray; + } + + setColor(color: string, operation: WasabeeOp) { + this.color = color; + if (this.color == operation.color) this.color = "main"; + } + + getColor(operation: WasabeeOp) { + let color = this.color; + if (color == "main") color = operation.color; + return color; + } + + length(operation: WasabeeOp) { + const latlngs = this.getLatLngs(operation); + return L.latLng(latlngs[0]).distanceTo(latlngs[1]); + } +} diff --git a/src/code/model/marker.d.ts b/src/code/model/marker.d.ts deleted file mode 100644 index f688b712a..000000000 --- a/src/code/model/marker.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -export default class WasabeeMarker { - ID: string; - portalId: string; - type: string; - comment?: string; - order: number; - completedID: boolean; - assignedTo: string; - zone: number; - _state: "pending" | "assigned" | "acknowledged" | "completed"; - static get markerTypes(): Set; - static get constants(): { - MARKER_TYPE_CAPTURE: string; - MARKER_TYPE_DECAY: string; - MARKER_TYPE_EXCLUDE: string; - MARKER_TYPE_DESTROY: string; - MARKER_TYPE_FARM: string; - MARKER_TYPE_GOTO: string; - MARKER_TYPE_KEY: string; - MARKER_TYPE_LINK: string; - MARKER_TYPE_MEETAGENT: string; - MARKER_TYPE_OTHER: string; - MARKER_TYPE_RECHARGE: string; - MARKER_TYPE_UPGRADE: string; - MARKER_TYPE_VIRUS: string; - }; - constructor(obj: any); - toJSON(): { - ID: string; - portalId: string; - type: string; - comment: string; - state: "pending" | "completed" | "assigned" | "acknowledged"; - completedID: boolean; - assignedTo: string; - order: number; - zone: number; - }; - get opOrder(): number; - set opOrder(o: number); - setOrder(o: number | string): void; - assign(gid: any): void; - set state(state: "pending" | "completed" | "assigned" | "acknowledged"); - get state(): "pending" | "completed" | "assigned" | "acknowledged"; - isDestructMarker(): boolean; - static isDestructMarkerType(type: any): boolean; -} diff --git a/src/code/model/marker.js b/src/code/model/marker.js deleted file mode 100644 index ae7e18dea..000000000 --- a/src/code/model/marker.js +++ /dev/null @@ -1,127 +0,0 @@ -import { generateId } from "../auxiliar"; - -const markers = { - MARKER_TYPE_CAPTURE: "CapturePortalMarker", - MARKER_TYPE_DECAY: "LetDecayPortalAlert", - MARKER_TYPE_EXCLUDE: "ExcludeMarker", - MARKER_TYPE_DESTROY: "DestroyPortalAlert", - MARKER_TYPE_FARM: "FarmPortalMarker", - MARKER_TYPE_GOTO: "GotoPortalMarker", - MARKER_TYPE_KEY: "GetKeyPortalMarker", - MARKER_TYPE_LINK: "CreateLinkAlert", - MARKER_TYPE_MEETAGENT: "MeetAgentPortalMarker", - MARKER_TYPE_OTHER: "OtherPortalAlert", - MARKER_TYPE_RECHARGE: "RechargePortalAlert", - MARKER_TYPE_UPGRADE: "UpgradePortalAlert", - MARKER_TYPE_VIRUS: "UseVirusPortalAlert", -}; - -const destructMarkerTypes = [ - markers.MARKER_TYPE_DECAY, - markers.MARKER_TYPE_DESTROY, - markers.MARKER_TYPE_VIRUS, -]; - -const markerTypes = new Set(Object.values(markers)); - -const STATE_UNASSIGNED = "pending"; -const STATE_ASSIGNED = "assigned"; -const STATE_ACKNOWLEDGED = "acknowledged"; -const STATE_COMPLETED = "completed"; - -export default class WasabeeMarker { - // static properties is not supported by eslint yet - static get markerTypes() { - return markerTypes; - } - - static get constants() { - return markers; - } - - constructor(obj) { - this.ID = obj.ID ? obj.ID : generateId(); - this.portalId = obj.portalId; - this.type = obj.type; - this.comment = obj.comment; - this.completedID = obj.completedID ? obj.completedID : null; - this.order = obj.order ? Number(obj.order) : 0; - this.zone = obj.zone ? Number(obj.zone) : 1; - - this.assign(obj.assignedTo); // WAS this.assignedTo = obj.assignedTo ? obj.assignedTo : null; - // if ._state then it came from indexeddb, otherwise from server/localStorage - if (obj._state) { - this.state = obj._state; - } else this.state = obj.state ? obj.state : null; - } - - // not called when pushing to indexeddb, but used when sending to server - toJSON() { - return { - ID: this.ID, - portalId: this.portalId, - type: this.type, - comment: this.comment, - state: this._state, // no need to validate here - completedID: this.completedID, - assignedTo: this.assignedTo, - order: Number(this.order), - zone: Number(this.zone), - }; - } - - get opOrder() { - return this.order; - } - - set opOrder(o) { - this.order = Number.parseInt(o, 10); - } - - assign(gid) { - if (!gid || gid == "") { - this._state = STATE_UNASSIGNED; - this.assignedTo = null; - return; - } - - this.assignedTo = gid; - this._state = STATE_ASSIGNED; - return; - } - - set state(state) { - switch (state) { - case STATE_UNASSIGNED: - this.assignedTo = null; - this._state = STATE_UNASSIGNED; - break; - case STATE_ASSIGNED: // fall-through - case STATE_ACKNOWLEDGED: - if (!this.assignedTo || this.assignedTo == "") { - this._state = STATE_UNASSIGNED; - break; - } - this._state = state; - break; - case STATE_COMPLETED: - this._state = STATE_COMPLETED; - break; - default: - this._state = STATE_UNASSIGNED; - break; - } - } - - get state() { - return this._state; - } - - isDestructMarker() { - return destructMarkerTypes.includes(this.type); - } - - static isDestructMarkerType(type) { - return destructMarkerTypes.includes(type); - } -} diff --git a/src/code/model/marker.ts b/src/code/model/marker.ts new file mode 100644 index 000000000..2c1a6a230 --- /dev/null +++ b/src/code/model/marker.ts @@ -0,0 +1,88 @@ +import Task from "./task"; + +const markers = { + MARKER_TYPE_CAPTURE: "CapturePortalMarker", + MARKER_TYPE_DECAY: "LetDecayPortalAlert", + MARKER_TYPE_EXCLUDE: "ExcludeMarker", + MARKER_TYPE_DESTROY: "DestroyPortalAlert", + MARKER_TYPE_FARM: "FarmPortalMarker", + MARKER_TYPE_GOTO: "GotoPortalMarker", + MARKER_TYPE_KEY: "GetKeyPortalMarker", + MARKER_TYPE_LINK: "CreateLinkAlert", + MARKER_TYPE_MEETAGENT: "MeetAgentPortalMarker", + MARKER_TYPE_OTHER: "OtherPortalAlert", + MARKER_TYPE_RECHARGE: "RechargePortalAlert", + MARKER_TYPE_UPGRADE: "UpgradePortalAlert", + MARKER_TYPE_VIRUS: "UseVirusPortalAlert", +}; + +const destructMarkerTypes = [ + markers.MARKER_TYPE_DECAY, + markers.MARKER_TYPE_DESTROY, + markers.MARKER_TYPE_VIRUS, +]; + +const markerTypes = new Set(Object.values(markers)); + +const iconTypes = { + CapturePortalMarker: "capture", + LetDecayPortalAlert: "decay", + ExcludeMarker: "exclude", + DestroyPortalAlert: "destroy", + FarmPortalMarker: "farm", + GotoPortalMarker: "goto", + GetKeyPortalMarker: "key", + CreateLinkAlert: "link", + MeetAgentPortalMarker: "meetagent", + OtherPortalAlert: "other", + RechargePortalAlert: "recharge", + UpgradePortalAlert: "upgrade", + UseVirusPortalAlert: "virus", +}; + +export default class WasabeeMarker extends Task { + portalId: PortalID; + type: string; + + // static properties is not supported by eslint yet + static get markerTypes() { + return markerTypes; + } + + static get constants() { + return markers; + } + + constructor(obj: any) { + super(obj); + this.portalId = obj.portalId; + this.type = obj.type; + } + + toJSON(): any { + return { + ID: this.ID, + zone: Number(this.zone), + order: Number(this.order), + completedID: this.completedID, + assignedTo: this.assignedTo, + state: this._state, + + portalId: this.portalId, + type: this.type, + comment: this.comment, + }; + } + + get friendlyType() { + return iconTypes[this.type]; + } + + isDestructMarker() { + return destructMarkerTypes.includes(this.type); + } + + static isDestructMarkerType(type) { + return destructMarkerTypes.includes(type); + } +} diff --git a/src/code/model/operation.js b/src/code/model/operation.js index 75af4ece0..3a6b31007 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.js @@ -415,7 +415,7 @@ export default class WasabeeOp extends Evented { setLinkOrder(linkID, order) { for (const v of this.links) { if (v.ID == linkID) { - v.opOrder = Number(order); + v.setOrder(order); } } this.update(true); @@ -424,7 +424,7 @@ export default class WasabeeOp extends Evented { setMarkerOrder(markerID, order) { for (const v of this.markers) { if (v.ID == markerID) { - v.opOrder = Number(order); + v.setOrder(order); } } this.update(true); @@ -660,7 +660,7 @@ export default class WasabeeOp extends Evented { this ); if (options.description) link.description = options.description; - if (options.order) link.opOrder = options.order; + if (options.order) link.setOrder(options.order); if (options.color) link.color = options.color; if (!existingLink) { @@ -1007,10 +1007,10 @@ export default class WasabeeOp extends Evented { get nextOrder() { let o = 0; for (const l of this.links) { - o = Math.max(o, l.opOrder); + o = Math.max(o, l.order); } for (const m of this.markers) { - o = Math.max(o, m.opOrder); + o = Math.max(o, m.order); } return ++o; } diff --git a/src/code/model/task.ts b/src/code/model/task.ts new file mode 100644 index 000000000..67c6eb6c5 --- /dev/null +++ b/src/code/model/task.ts @@ -0,0 +1,89 @@ +import { generateId } from "../auxiliar"; + +export default class Task { + ID: TaskID; + order: number; + zone: ZoneID; + assignedTo?: GoogleID; + completedID?: GoogleID; + comment?: string; + + _state: "pending" | "assigned" | "acknowledged" | "completed"; + + constructor(obj: any) { + this.ID = obj.ID || generateId(); + this.zone = +obj.zone || 1; + this.order = +obj.order || 0; + this.assignedTo = obj.assignedTo ? obj.assignedTo : null; + this.completedID = obj.completedID ? obj.completedID : null; + this.comment = obj.comment ? obj.comment : ""; + this.state = obj._state || obj.state; + } + + toServer() { + return this.toJSON(); + } + + toJSON(): any { + return { + ID: this.ID, + zone: Number(this.zone), + order: Number(this.order), + completedID: this.completedID, + assignedTo: this.assignedTo, + state: this._state, + }; + } + + get state() { + return this._state; + } + + set state(state) { + switch (state) { + case "assigned": // fall-through + case "acknowledged": + if (!this.assignedTo || this.assignedTo == "") { + this._state = "pending"; + break; + } + this._state = state; + break; + case "completed": + this.complete(); + break; + case "pending": + default: + this.assignedTo = null; + this._state = "pending"; + break; + } + } + + setOrder(o: number | string) { + this.order = +o || 0; + } + + assign(gid?: GoogleID) { + if (gid !== this.assignedTo) this._state = gid ? "pending" : "assigned"; + this.assignedTo = gid ? gid : null; + } + + complete(gid?: GoogleID) { + if (!this.completedID || gid) + this.completedID = gid ? gid : this.assignedTo; + this._state = "completed"; + } + + get completed() { + return this._state == "completed"; + } + + set completed(v) { + if (v) this.complete(); + else { + delete this.completedID; + this.state = "assigned"; + } + } +} diff --git a/src/code/ui/link.js b/src/code/ui/link.js index 0411d6c81..d132f6384 100644 --- a/src/code/ui/link.js +++ b/src/code/ui/link.js @@ -110,9 +110,9 @@ const WLLink = L.GeodesicPolyline.extend({ L.DomUtil.create("div", null, div).appendChild( displayFormat(link, operation) ); - if (link.description) - L.DomUtil.create("div", "enl", div).textContent = link.description; - L.DomUtil.create("div", "enl", div).textContent = "# " + link.throwOrderPos; + if (link.comment) + L.DomUtil.create("div", "enl", div).textContent = link.comment; + L.DomUtil.create("div", "enl", div).textContent = "# " + link.order; const buttonset = L.DomUtil.create("div", "buttonset", div); if (operation.canWrite()) { const del = L.DomUtil.create("button", null, buttonset); From 4e6e038fe544231192ae5cecc9a81f19c385a78a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 22:24:30 +0100 Subject: [PATCH 088/275] db.ts --- src/code/db.d.ts | 58 ------------------------------------- src/code/{db.js => db.ts} | 60 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 59 deletions(-) delete mode 100644 src/code/db.d.ts rename src/code/{db.js => db.ts} (64%) diff --git a/src/code/db.d.ts b/src/code/db.d.ts deleted file mode 100644 index a0c64d7ef..000000000 --- a/src/code/db.d.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { DBSchema } from "idb"; -import type WasabeeAgent from "./model/agent"; -import type { IBlockerPortal } from "./model/blocker"; -import type WasabeeBlocker from "./model/blocker"; -import type { ILocalOp } from "./model/operation"; -import type WasabeeTeam from "./model/team"; -import type { WDKey } from "./wd"; -interface WasabeeDB extends DBSchema { - agents: { - key: GoogleID; - value: WasabeeAgent; - indexes: { - date: string; - fetched: string; - }; - }; - teams: { - key: TeamID; - value: WasabeeTeam; - indexes: { - fetched: string; - }; - }; - defensivekeys: { - key: [GoogleID, PortalID]; - value: WDKey; - indexes: { - PortalID: string; - Count: number; - }; - }; - operations: { - key: OpID; - value: ILocalOp; - indexes: { - fetched: string; - server: string; - }; - }; - blockers: { - key: [OpID, PortalID, PortalID]; - value: WasabeeBlocker; - indexes: { - opID: OpID; - from: PortalID; - to: PortalID; - }; - }; - blockers_portals: { - key: [OpID, PortalID]; - value: IBlockerPortal; - indexes: { - opID: OpID; - }; - }; -} -declare const db: Promise>; -export default db; diff --git a/src/code/db.js b/src/code/db.ts similarity index 64% rename from src/code/db.js rename to src/code/db.ts index 2b2f7feff..741477c2c 100644 --- a/src/code/db.js +++ b/src/code/db.ts @@ -1,9 +1,67 @@ import { openDB } from "idb"; +import type { DBSchema } from "idb"; +import type WasabeeAgent from "./model/agent"; +import type { IBlockerPortal } from "./model/blocker"; +import type WasabeeBlocker from "./model/blocker"; +import type { ILocalOp } from "./model/operation"; +import type WasabeeTeam from "./model/team"; +import type { WDKey } from "./wd"; + const version = 3; +interface WasabeeDB extends DBSchema { + agents: { + key: GoogleID; + value: WasabeeAgent; + indexes: { + date: string; + fetched: string; + }; + }; + teams: { + key: TeamID; + value: WasabeeTeam; + indexes: { + fetched: string; + }; + }; + defensivekeys: { + key: [GoogleID, PortalID]; + value: WDKey; + indexes: { + PortalID: string; + Count: number; + }; + }; + operations: { + key: OpID; + value: ILocalOp; + indexes: { + fetched: string; + server: string; + }; + }; + blockers: { + key: [OpID, PortalID, PortalID]; + value: WasabeeBlocker; + indexes: { + opID: OpID; + from: PortalID; + to: PortalID; + }; + }; + blockers_portals: { + key: [OpID, PortalID]; + value: IBlockerPortal; + indexes: { + opID: OpID; + }; + }; +} + // XXX audit these to make sure all the various indexes are used -const db = openDB("wasabee", version, { +const db = openDB("wasabee", version, { upgrade(db, oldVersion, newVersion, tx) { if (oldVersion < 1) { const agents = db.createObjectStore("agents", { keyPath: "id" }); From 8b5519e7c16bfb24d6df4a658055b419209c7547 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 22:27:46 +0100 Subject: [PATCH 089/275] wX.ts --- src/code/wX.d.ts | 3 --- src/code/{wX.js => wX.ts} | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 src/code/wX.d.ts rename src/code/{wX.js => wX.ts} (95%) diff --git a/src/code/wX.d.ts b/src/code/wX.d.ts deleted file mode 100644 index 49bf52ccf..000000000 --- a/src/code/wX.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare function wX(key: string, data?: object): any; -export declare function getLanguage(): any; -export default wX; diff --git a/src/code/wX.js b/src/code/wX.ts similarity index 95% rename from src/code/wX.js rename to src/code/wX.ts index 4cf9e0b58..a784dedb2 100644 --- a/src/code/wX.js +++ b/src/code/wX.ts @@ -1,13 +1,12 @@ import statics from "./static"; -// aliases to make review easier let strings = statics.strings; const defaultLang = statics.constants.DEFAULT_LANGUAGE; const localStoreKey = statics.constants.LANGUAGE_KEY; const templateRe = /\{ *([\w_ -]+) *\}/g; -export function wX(key, data) { +export function wX(key: string, data?: object) { const lang = getLanguage(); // if the skin system is initialized, switch to it @@ -62,4 +61,4 @@ export function getLanguage() { return lang; } -export default wX; +export default wX; \ No newline at end of file From 8e8e75b6c8dd6defd6d2383a96a010fcaf4953b4 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 22:31:12 +0100 Subject: [PATCH 090/275] crosslink.ts --- src/code/crosslinks.d.ts | 22 ------------------ src/code/{crosslinks.js => crosslinks.ts} | 28 ++++++++++++++++------- 2 files changed, 20 insertions(+), 30 deletions(-) delete mode 100644 src/code/crosslinks.d.ts rename src/code/{crosslinks.js => crosslinks.ts} (93%) diff --git a/src/code/crosslinks.d.ts b/src/code/crosslinks.d.ts deleted file mode 100644 index 859fa8b9d..000000000 --- a/src/code/crosslinks.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as L from "leaflet"; -interface LLC extends L.LatLng { - _cartesian?: [number, number, number]; -} -export declare function greatCircleArcIntersectByLatLngs(a0: LLC, a1: LLC, b0: LLC, b1: LLC): boolean; -export declare function greatCircleArcIntersect(existing: any, drawn: any): boolean; -export declare function checkAllLinks(): void; -export declare function initCrossLinks(): void; -export declare class GeodesicLine { - lat1: number; - lat2: number; - lng1: number; - lng2: number; - sinLat1CosLat2: number; - sinLat2CosLat1: number; - cosLat1CosLat2SinDLng: number; - constructor(start: L.LatLng, end: L.LatLng); - isMeridian(): boolean; - latAtLng(lng: any): number; - bearing(): number; -} -export {}; diff --git a/src/code/crosslinks.js b/src/code/crosslinks.ts similarity index 93% rename from src/code/crosslinks.js rename to src/code/crosslinks.ts index 7c978b5c8..d8e0e6bba 100644 --- a/src/code/crosslinks.js +++ b/src/code/crosslinks.ts @@ -8,14 +8,14 @@ import PortalUI from "./ui/portal"; // from iitc rework : https://github.com/IITC-CE/ingress-intel-total-conversion/pull/333 const d2r = Math.PI / 180; -function toCartesian(lat, lng) { +function toCartesian(lat: number, lng: number): [number, number, number] { lat *= d2r; lng *= d2r; var o = Math.cos(lat); return [o * Math.cos(lng), o * Math.sin(lng), Math.sin(lat)]; } -function cross(t, n) { +function cross(t: [number, number, number], n: [number, number, number]): [number, number, number] { return [ t[1] * n[2] - t[2] * n[1], t[2] * n[0] - t[0] * n[2], @@ -23,17 +23,21 @@ function cross(t, n) { ]; } -function dot(t, n) { +function dot(t: [number, number, number], n: [number, number, number]) { return t[0] * n[0] + t[1] * n[1] + t[2] * n[2]; } -function equals(a, b) { +function equals(a: L.LatLng, b: L.LatLng) { return a.lat === b.lat && a.lng === b.lng; } // take L.LatLng // note: cache cos/sin calls in the object, in order to be efficient, try using same LatLng objects across calls, like using latLng from WasabeePortal attached to an op -export function greatCircleArcIntersectByLatLngs(a0, a1, b0, b1) { +interface LLC extends L.LatLng { + _cartesian?: [number, number, number], +} + +export function greatCircleArcIntersectByLatLngs(a0: LLC, a1: LLC, b0: LLC, b1: LLC) { // 0) quick checks // zero length line if (equals(a0, a1)) return false; @@ -295,7 +299,15 @@ export function initCrossLinks() { } export class GeodesicLine { - constructor(start, end) { + lat1: number; + lat2: number; + lng1: number; + lng2: number; + sinLat1CosLat2: number; + sinLat2CosLat1: number; + cosLat1CosLat2SinDLng: number; + + constructor(start: L.LatLng, end: L.LatLng) { let d2r = Math.PI / 180.0; // let r2d = 180.0 / Math.PI; //eslint-disable-line // maths based on http://williams.best.vwh.net/avform.htm#Int @@ -335,7 +347,7 @@ export class GeodesicLine { lat = Math.atan( (this.sinLat1CosLat2 * Math.sin(lng - this.lng2) - this.sinLat2CosLat1 * Math.sin(lng - this.lng1)) / - this.cosLat1CosLat2SinDLng + this.cosLat1CosLat2SinDLng ); } return (lat * 180) / Math.PI; // return value in degrees @@ -349,4 +361,4 @@ export class GeodesicLine { const x = this.sinLat2CosLat1 - this.sinLat1CosLat2 * Math.cos(dLng); return Math.atan2(y, x); } -} +} \ No newline at end of file From 460af0d858d61f729ca4938ad584057f5bec96a2 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 22:48:01 +0100 Subject: [PATCH 091/275] team.ts --- src/code/mapDrawing.js | 2 -- src/code/model/team.d.ts | 15 --------------- src/code/model/{team.js => team.ts} | 18 +++++++++++++++--- 3 files changed, 15 insertions(+), 20 deletions(-) delete mode 100644 src/code/model/team.d.ts rename src/code/model/{team.js => team.ts} (85%) diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index f307a93d9..631993405 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -153,8 +153,6 @@ export async function drawSingleTeam(teamID, layerMap, alreadyDone) { const team = await WasabeeTeam.get(teamID, 15); // hold time is 15 seconds here, probably too aggressive now that firebase works well // common case: team was enabled here, but was since disabled in another client and the pull returned an error if (team == null) return done; - // we don't need to draw if pulled from cache - if (team.cached === true) return done; const agents = team.getAgents(); for (const agent of agents) { diff --git a/src/code/model/team.d.ts b/src/code/model/team.d.ts deleted file mode 100644 index e7c6fcd33..000000000 --- a/src/code/model/team.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import WasabeeAgent from "./agent"; -export default class WasabeeTeam { - fetched: number; - id: string; - name: string; - rc: string; - rk: string; - jlt: string; - agents: Array; - _a: Array; - constructor(data: any); - getAgents(): WasabeeAgent[]; - _updateCache(): Promise; - static get(teamID: any, maxAgeSeconds?: number): Promise; -} diff --git a/src/code/model/team.js b/src/code/model/team.ts similarity index 85% rename from src/code/model/team.js rename to src/code/model/team.ts index 7a0c7747b..c4523b807 100644 --- a/src/code/model/team.js +++ b/src/code/model/team.ts @@ -4,6 +4,16 @@ import { teamPromise } from "../server"; import db from "../db"; export default class WasabeeTeam { + fetched: number; + id: string; + name: string; + rc: string; + rk: string; + jlt: string; + agents: Array; + + _a: Array; + constructor(data) { if (typeof data == "string") { try { @@ -52,8 +62,10 @@ export default class WasabeeTeam { static async get(teamID, maxAgeSeconds = 60) { const cached = await (await db).get("teams", teamID); if (cached) { - if (cached.fetched + maxAgeSeconds * 1000 > Date.now()) - return new WasabeeTeam(cached); + const t = new WasabeeTeam(cached); + if (t.fetched > Date.now() - 1000 * maxAgeSeconds) { + return t; + } } if (!WasabeeMe.isLoggedIn()) return null; @@ -66,4 +78,4 @@ export default class WasabeeTeam { } return null; } -} +} \ No newline at end of file From 8eea3082de646f8daee6c7152601b3984da093e6 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 22:53:58 +0100 Subject: [PATCH 092/275] agent.ts --- src/code/model/agent.d.ts | 29 --------------------------- src/code/model/{agent.js => agent.ts} | 27 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 31 deletions(-) delete mode 100644 src/code/model/agent.d.ts rename src/code/model/{agent.js => agent.ts} (91%) diff --git a/src/code/model/agent.d.ts b/src/code/model/agent.d.ts deleted file mode 100644 index 40b3b92d8..000000000 --- a/src/code/model/agent.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as L from "leaflet"; -export default class WasabeeAgent { - id: string; - name: string; - vname: string; - rocksname: string; - intelname: string; - intelfaction: string; - level: number; - enlid: string; - pic: string; - Vverified: boolean; - blacklisted: boolean; - rocks: boolean; - lat: number; - lng: number; - date: string; - ShareWD?: boolean; - LoadWD?: boolean; - squad?: string; - state?: boolean; - fetched: number; - cached?: boolean; - constructor(obj: any); - getTeamName(teamID?: number): Promise; - _updateCache(): Promise; - get latLng(): L.LatLng; - static get(gid: string, maxAgeSeconds?: number): Promise; -} diff --git a/src/code/model/agent.js b/src/code/model/agent.ts similarity index 91% rename from src/code/model/agent.js rename to src/code/model/agent.ts index 92b63beda..b717240bf 100644 --- a/src/code/model/agent.js +++ b/src/code/model/agent.ts @@ -3,7 +3,31 @@ import WasabeeMe from "./me"; import WasabeeTeam from "./team"; import db from "../db"; + export default class WasabeeAgent { + id: string; + name: string; + vname: string; + rocksname: string; + intelname: string; + intelfaction: string; + level: number; + enlid: string; + pic: string; + Vverified: boolean; + blacklisted: boolean; + rocks: boolean; + lat: number; + lng: number; + date: string; + + ShareWD?: boolean; + LoadWD?: boolean; + squad?: string; + state?: boolean; + + fetched: number; + constructor(obj) { if (typeof obj == "string") { try { @@ -135,11 +159,10 @@ export default class WasabeeAgent { } // hold agent data up to 24 hours by default -- don't bother the server if all we need to do is resolve GID -> name - static async get(gid, maxAgeSeconds = 86400) { + static async get(gid: string, maxAgeSeconds = 86400) { const cached = await (await db).get("agents", gid); if (cached && cached.fetched > Date.now() - 1000 * maxAgeSeconds) { const a = new WasabeeAgent(cached); - a.cached = true; // console.debug("returning from cache", a); return a; } From c35c6cd6145d71672d4ea4d4d18a69be062c486b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 22:57:00 +0100 Subject: [PATCH 093/275] me.ts --- src/code/model/me.d.ts | 48 --------------------------------- src/code/model/{me.js => me.ts} | 38 +++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 49 deletions(-) delete mode 100644 src/code/model/me.d.ts rename src/code/model/{me.js => me.ts} (85%) diff --git a/src/code/model/me.d.ts b/src/code/model/me.d.ts deleted file mode 100644 index 443c8c926..000000000 --- a/src/code/model/me.d.ts +++ /dev/null @@ -1,48 +0,0 @@ -export interface MeTeam { - ID: string; - Name: string; - RocksComm: string; - RocksKey: string; - JoinLinkToken: string; - ShareWD: "On" | "Off"; - LoadWD: "On" | "Off"; - State: "On" | "Off"; - Owner: string; - VTeam: string; - VTeamRole: string; -} -interface MeOp { - ID: string; -} -export default class WasabeeMe { - GoogleID: string; - name: string; - vname: string; - rocksname: string; - intelname: string; - level: number; - Teams: Array; - Ops: Array; - fetched: number; - Vverified: boolean; - blacklisted: boolean; - enlid: string; - pic: string; - intelfaction: string; - querytoken: string; - _teamMap: Map; - constructor(data: any); - static maxCacheAge(): number; - toJSON(): this; - store(): void; - remove(): void; - static localGet(): WasabeeMe; - static isLoggedIn(): boolean; - static cacheGet(): WasabeeMe; - static waitGet(force?: boolean): Promise; - static purge(): Promise; - teamJoined(teamID: any): boolean; - teamEnabled(teamID: any): boolean; - makeTeamMap(): void; -} -export {}; diff --git a/src/code/model/me.js b/src/code/model/me.ts similarity index 85% rename from src/code/model/me.js rename to src/code/model/me.ts index 15d028bd8..00fdc2d9d 100644 --- a/src/code/model/me.js +++ b/src/code/model/me.ts @@ -3,7 +3,43 @@ import db from "../db"; import { constants } from "../static"; +export interface MeTeam { + ID: string, + Name: string, + RocksComm: string, + RocksKey: string, + JoinLinkToken: string, + ShareWD: "On" | "Off", + LoadWD: "On" | "Off", + State: "On" | "Off", + Owner: string, + VTeam: string, + VTeamRole: string, +} + +interface MeOp { + ID: string, +} + export default class WasabeeMe { + GoogleID: string; + name: string; + vname: string; + rocksname: string; + intelname: string; + level: number; + Teams: Array; + Ops: Array; + fetched: number; + Vverified: boolean; + blacklisted: boolean; + enlid: string; + pic: string; + intelfaction: string; + querytoken: string; + + _teamMap: Map; + constructor(data) { if (typeof data == "string") { try { @@ -100,7 +136,7 @@ export default class WasabeeMe { } // use waitGet with "force == true" if you want a fresh value now - static async waitGet(force) { + static async waitGet(force?: boolean) { let me = WasabeeMe.localGet(); if ( From 2dac6375811423f3a69b31388c3aa2e8d1b06e72 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 10 Nov 2021 23:16:42 +0100 Subject: [PATCH 094/275] operation.ts --- src/code/model/operation.d.ts | 202 ------------- src/code/model/{operation.js => operation.ts} | 279 ++++++++++++------ 2 files changed, 182 insertions(+), 299 deletions(-) delete mode 100644 src/code/model/operation.d.ts rename src/code/model/{operation.js => operation.ts} (87%) diff --git a/src/code/model/operation.d.ts b/src/code/model/operation.d.ts deleted file mode 100644 index ddde21a5b..000000000 --- a/src/code/model/operation.d.ts +++ /dev/null @@ -1,202 +0,0 @@ -import * as L from "leaflet"; -import WasabeeLink from "./link"; -import WasabeePortal from "./portal"; -import WasabeeMarker from "./marker"; -import WasabeeZone from "./zone"; -import Evented from "./evented"; -export declare type KeyOnHand = { - portalId: PortalID; - gid: GoogleID; - capsule: string; - onhand: number; -}; -export declare type OpPermItem = { - role: "read" | "write" | "assignonly"; - teamid: string; - zone: number; -}; -interface IOperation { - ID: OpID; - name: string; - creator: string | GoogleID; - opportals: WasabeePortal[]; - anchors: string[]; - links: WasabeeLink[]; - markers: WasabeeMarker[]; - color: string; - comment: string; - zones: WasabeeZone[]; - referencetime: string; -} -export interface IServerOp extends IOperation { - creator: GoogleID; - teamlist: OpPermItem[]; - keysonhand: KeyOnHand[]; - lasteditid: string; - fetched: string; - modified: string; -} -export interface ILocalOp extends IOperation { - teamlist: OpPermItem[]; - keysonhand: KeyOnHand[]; - lasteditid: string; - fetched: string; - fetchedOp: string; - server: string; - localchanged: boolean; - remoteChanged: boolean; - background: boolean; - stored: number; -} -export default class WasabeeOp extends Evented implements IOperation { - ID: string; - name: string; - creator: string; - anchors: string[]; - links: WasabeeLink[]; - markers: WasabeeMarker[]; - color: string; - comment: string; - zones: WasabeeZone[]; - referencetime: string; - teamlist: OpPermItem[]; - keysonhand: KeyOnHand[]; - lasteditid: string; - fetched: string; - fetchedOp: string; - localchanged: boolean; - remoteChanged: boolean; - server: string; - blockers: WasabeeLink[]; - background: boolean; - stored: number; - _idToOpportals: Map; - _coordsToOpportals: Map; - _dirtyCoordsTable: boolean; - _batchmode: boolean; - constructor(obj: any); - static load(opID: any): Promise; - static delete(opID: any): Promise; - static migrate(opID: any): Promise; - store(): Promise; - toJSON(): IOperation; - toExport(): string; - get opportals(): WasabeePortal[]; - buildCoordsLookupTable(): void; - getColor(): string; - containsPortal(portal: any): boolean; - getPortalByLatLng(lat: any, lng: any): WasabeePortal; - containsLinkFromTo(fromPortalId: any, toPortalId: any): boolean; - containsLink(link: any): boolean; - containsMarker(portal: any, markerType: any): boolean; - containsMarkerByID(portalID: any, markerType: any): boolean; - getPortalMarkers(portal: any): Map; - getLinkByPortalIDs(portalId1: any, portalId2: any): WasabeeLink; - getLink(portal1: any, portal2: any): WasabeeLink; - getLinkListFromPortal(portal: any): WasabeeLink[]; - getPortal(portalID: any): WasabeePortal; - getMarker(markerID: any): WasabeeMarker; - removeAnchor(portalId: any): void; - removeMarker(marker: any): void; - setMarkerComment(marker: any, comment: any): void; - setMarkerState(markerID: any, state: any): void; - setLinkComment(link: any, comment: any): void; - setLinkState(linkID: any, state: any): void; - setLinkColor(linkID: any, color: any): void; - setLinkOrder(linkID: any, order: any): void; - setMarkerOrder(markerID: any, order: any): void; - setPortalComment(portal: any, comment: any): void; - setPortalHardness(portal: any, hardness: any): void; - removeLink(startPortal: any, endPortal: any): void; - reverseLink(startPortalID: any, endPortalID: any): void; - cleanAll(): void; - cleanAnchorList(): void; - cleanPortalList(): void; - addPortal(portal: any): void; - _addPortal(portal: any): boolean; - updatePortal(portal: any): boolean; - _updatePortal(portal: any): boolean; - addLink(fromPortal: WasabeePortal, toPortal: WasabeePortal, options?: { - description?: string; - order?: number; - color?: string; - replace?: boolean; - }): WasabeeLink; - containsAnchor(portalId: string): boolean; - addAnchor(portal: WasabeePortal): void; - get fakedPortals(): WasabeePortal[]; - _swapPortal(originalPortal: WasabeePortal, newPortal: WasabeePortal): void; - swapPortal(originalPortal: WasabeePortal, newPortal: WasabeePortal): void; - addMarker(markerType: string, portal: WasabeePortal, options: any): boolean; - assignMarker(id: any, gid: any): void; - assignLink(id: any, gid: any): void; - clearAllItems(): void; - clearAllLinks(): void; - clearAllMarkers(): void; - update(updateLocalchanged?: boolean): void; - updateBlockers(): void; - startBatchMode(): void; - endBatchMode(): void; - convertLinksToObjs(links: any): any[]; - convertMarkersToObjs(markers: any): any[]; - convertPortalsToObjs(portals: any): any[]; - convertZonesToObjs(zones: any): any[]; - get mbr(): L.LatLngBounds; - canWriteServer(): boolean; - canWrite(): boolean; - getPermission(): "write" | "read" | "assignonly"; - isOnCurrentServer(): boolean; - isServerOp(): boolean; - isOwnedOp(): boolean; - get nextOrder(): number; - keyOnHand(portalId: any, gid: any, onhand: any, capsule: any): void; - KeysOnHandForPortal(portalId: any): number; - KeysRequiredForPortal(portalId: any): number; - zoneName(zoneID: any): any; - setZone(thing: any, zoneID: any): void; - removeZone(zoneID: any): void; - removeZonePoints(zoneID: any): void; - renameZone(zoneID: any, name: any): void; - addZone(): number; - addZonePoint(zoneID: number, latlng: L.LatLng): void; - changes(origin?: WasabeeOp): { - addition: any[]; - edition: any[]; - deletion: any[]; - name: any; - color: any; - comment: any; - }; - checkChanges(): boolean; - mergeZones(op: any): number; - applyChanges(changes: any, op: any): { - compatibility: { - ok: boolean; - rewrite: { - link: number; - marker: number; - }; - }; - addition: { - link: number; - marker: number; - zone: number; - ignored: number; - }; - deletion: { - link: number; - marker: number; - }; - edition: { - portal: number; - link: number; - marker: number; - assignment: number; - duplicate: number; - singlePortalLink: number; - removed: number; - }; - }; - determineZone(latlng: any): number; -} -export { }; diff --git a/src/code/model/operation.js b/src/code/model/operation.ts similarity index 87% rename from src/code/model/operation.js rename to src/code/model/operation.ts index 3a6b31007..e11d6d3bb 100644 --- a/src/code/model/operation.js +++ b/src/code/model/operation.ts @@ -11,8 +11,88 @@ import db from "../db"; // 0.20->0.21 blocker migration import WasabeeBlocker from "./blocker"; +import type Task from "./task"; +import type { LatLngExpression } from "leaflet"; + +export type KeyOnHand = { + portalId: string; + gid: string; + capsule: string; + onhand: number; +}; + +export type OpPermItem = { + role: "read" | "write" | "assignonly"; + teamid: string; + zone: number; +}; + +interface IOperation { + ID: OpID; + name: string; + creator: string | GoogleID; + opportals: WasabeePortal[]; + anchors: string[]; + links: WasabeeLink[]; + markers: WasabeeMarker[]; + color: string; + comment: string; + zones: WasabeeZone[]; + referencetime: string; +} + +export interface IServerOp extends IOperation { + creator: GoogleID; + teamlist: OpPermItem[]; + keysonhand: KeyOnHand[]; + lasteditid: string; + fetched: string; + modified: string; +} + +export interface ILocalOp extends IOperation { + teamlist: OpPermItem[]; + keysonhand: KeyOnHand[]; + lasteditid: string; + fetched: string; + fetchedOp: string; + server: string; + localchanged: boolean; + remoteChanged: boolean; + background: boolean; + stored: number; +} + +export default class WasabeeOp extends Evented implements IOperation { + ID: string; + name: string; + creator: string; + anchors: Array; + links: Array; + markers: Array; + color: string; + comment: string; + teamlist: Array; + fetched: string; + stored: number; + localchanged: boolean; + blockers: Array; + keysonhand: Array; + zones: Array; + + referencetime: string; + lasteditid: string; + remoteChanged: boolean; + server: string; + fetchedOp: string; + background: boolean; + + _idToOpportals: Map; + _coordsToOpportals: Map; + + _dirtyCoordsTable: boolean = false; + _batchmode: boolean = false; -export default class WasabeeOp extends Evented { constructor(obj) { super(); if (typeof obj == "string") { @@ -74,7 +154,7 @@ export default class WasabeeOp extends Evented { this.cleanPortalList(); } - static async load(opID) { + static async load(opID: OpID) { try { const raw = await (await db).get("operations", opID); if (raw == null) @@ -89,12 +169,12 @@ export default class WasabeeOp extends Evented { return null; } - static async delete(opID) { + static async delete(opID: OpID) { delete localStorage[opID]; // leave for now await (await db).delete("operations", opID); } - static async migrate(opID) { + static async migrate(opID: OpID) { // skip ones already completed const have = await (await db).get("operations", opID); if (have != null) { @@ -155,7 +235,7 @@ export default class WasabeeOp extends Evented { } // build object to serialize, shallow copy, local-only values excluded - toJSON() { + toJSON(): any { return { ID: this.ID, name: this.name, @@ -248,19 +328,19 @@ export default class WasabeeOp extends Evented { } } - containsPortal(portal) { + containsPortal(portal: WasabeePortal) { return this._idToOpportals.has(portal.id); } // assume lat and lng are strings from .toFixed(6) - getPortalByLatLng(lat, lng) { + getPortalByLatLng(lat: string, lng: string) { if (this._dirtyCoordsTable) { this.buildCoordsLookupTable(); } return this._coordsToOpportals.get(lat + "/" + lng); } - containsLinkFromTo(fromPortalId, toPortalId) { + containsLinkFromTo(fromPortalId: PortalID, toPortalId: PortalID) { if (this.links.length == 0) return false; for (const l of this.links) { @@ -274,15 +354,15 @@ export default class WasabeeOp extends Evented { return false; } - containsLink(link) { + containsLink(link: WasabeeLink) { return this.containsLinkFromTo(link.fromPortalId, link.toPortalId); } - containsMarker(portal, markerType) { + containsMarker(portal: WasabeePortal, markerType: string) { return this.containsMarkerByID(portal.id, markerType); } - containsMarkerByID(portalID, markerType) { + containsMarkerByID(portalID: PortalID, markerType: string) { if (this.markers.length == 0) return false; for (const m of this.markers) { if (m.portalId == portalID && m.type == markerType) { @@ -292,8 +372,8 @@ export default class WasabeeOp extends Evented { return false; } - getPortalMarkers(portal) { - const markers = new Map(); + getPortalMarkers(portal: WasabeePortal) { + const markers = new Map(); if (!portal) return markers; for (const m of this.markers) { if (m.portalId == portal.id) { @@ -303,7 +383,7 @@ export default class WasabeeOp extends Evented { return markers; } - getLinkByPortalIDs(portalId1, portalId2) { + getLinkByPortalIDs(portalId1: PortalID, portalId2: PortalID) { for (const l of this.links) { if ( (l.fromPortalId == portalId1 && l.toPortalId == portalId2) || @@ -315,11 +395,11 @@ export default class WasabeeOp extends Evented { return null; } - getLink(portal1, portal2) { + getLink(portal1: WasabeePortal, portal2: WasabeePortal) { return this.getLinkByPortalIDs(portal1.id, portal2.id); } - getLinkListFromPortal(portal) { + getLinkListFromPortal(portal: WasabeePortal) { const links = this.links.filter(function (listLink) { return ( listLink.fromPortalId == portal.id || listLink.toPortalId == portal.id @@ -328,11 +408,11 @@ export default class WasabeeOp extends Evented { return links; } - getPortal(portalID) { + getPortal(portalID: PortalID) { return this._idToOpportals.get(portalID); } - getMarker(markerID) { + getMarker(markerID: MarkerID) { for (const m of this.markers) { if (m.ID == markerID) { return m; @@ -341,7 +421,7 @@ export default class WasabeeOp extends Evented { return null; } - removeAnchor(portalId) { + removeAnchor(portalId: PortalID) { this.anchors = this.anchors.filter(function (anchor) { return anchor !== portalId; }); @@ -357,7 +437,7 @@ export default class WasabeeOp extends Evented { this.updateBlockers(); } - removeMarker(marker) { + removeMarker(marker: WasabeeMarker) { this.markers = this.markers.filter(function (listMarker) { return listMarker.ID !== marker.ID; }); @@ -366,7 +446,7 @@ export default class WasabeeOp extends Evented { this.updateBlockers(); } - setMarkerComment(marker, comment) { + setMarkerComment(marker: WasabeeMarker, comment: string) { for (const v of this.markers) { if (v.ID == marker.ID) { v.comment = comment; @@ -375,7 +455,7 @@ export default class WasabeeOp extends Evented { this.update(true); } - setMarkerState(markerID, state) { + setMarkerState(markerID: MarkerID, state: Task["state"]) { for (const v of this.markers) { if (v.ID == markerID) { // validation happens in the marker class @@ -385,16 +465,16 @@ export default class WasabeeOp extends Evented { this.update(true); } - setLinkComment(link, comment) { + setLinkComment(link: WasabeeLink, comment: string) { for (const v of this.links) { if (v.ID == link.ID) { - v.description = comment; + v.comment = comment; } } this.update(true); } - setLinkState(linkID, state) { + setLinkState(linkID: LinkID, state: Task["state"]) { for (const v of this.links) { if (v.ID == linkID) { v.state = state; @@ -403,7 +483,7 @@ export default class WasabeeOp extends Evented { this.update(true); } - setLinkColor(linkID, color) { + setLinkColor(linkID: LinkID, color: string) { for (const v of this.links) { if (v.ID == linkID) { v.color = color; @@ -412,7 +492,7 @@ export default class WasabeeOp extends Evented { this.update(true); } - setLinkOrder(linkID, order) { + setLinkOrder(linkID: LinkID, order: string | number) { for (const v of this.links) { if (v.ID == linkID) { v.setOrder(order); @@ -421,7 +501,7 @@ export default class WasabeeOp extends Evented { this.update(true); } - setMarkerOrder(markerID, order) { + setMarkerOrder(markerID: MarkerID, order: string | number) { for (const v of this.markers) { if (v.ID == markerID) { v.setOrder(order); @@ -430,7 +510,7 @@ export default class WasabeeOp extends Evented { this.update(true); } - setPortalComment(portal, comment) { + setPortalComment(portal: WasabeePortal, comment: string) { const p = this.getPortal(portal.id); if (p) { p.comment = comment; @@ -438,7 +518,7 @@ export default class WasabeeOp extends Evented { } } - setPortalHardness(portal, hardness) { + setPortalHardness(portal: WasabeePortal, hardness: string) { const p = this.getPortal(portal.id); if (p) { p.hardness = hardness; @@ -447,7 +527,7 @@ export default class WasabeeOp extends Evented { } //Passed in are the start, end, and portal the link is being removed from(so the other portal can be removed if no more links exist to it) - removeLink(startPortal, endPortal) { + removeLink(startPortal: PortalID, endPortal: PortalID) { const newLinks = []; for (const l of this.links) { if (!(l.fromPortalId == startPortal && l.toPortalId == endPortal)) { @@ -461,7 +541,7 @@ export default class WasabeeOp extends Evented { this.updateBlockers(); } - reverseLink(startPortalID, endPortalID) { + reverseLink(startPortalID: PortalID, endPortalID: PortalID) { const newLinks = []; for (const l of this.links) { if (l.fromPortalId == startPortalID && l.toPortalId == endPortalID) { @@ -480,11 +560,7 @@ export default class WasabeeOp extends Evented { this.cleanCaches(); } - cleanCaches() { - for (const l of this.links) { - delete l._crosslinksGL; - } - } + cleanCaches() {} cleanAnchorList() { const newAnchorList = []; @@ -499,7 +575,7 @@ export default class WasabeeOp extends Evented { //This removes opportals with no links and removes duplicates cleanPortalList() { - const newPortals = new Map(); + const newPortals = new Map(); for (const l of this.links) { newPortals.set(l.fromPortalId, this._idToOpportals.get(l.fromPortalId)); newPortals.set(l.toPortalId, this._idToOpportals.get(l.toPortalId)); @@ -512,7 +588,7 @@ export default class WasabeeOp extends Evented { } // sanitize OP if it get corrupt by my code elsewhere... - const missingPortal = new Set(); + const missingPortal = new Set(); let corrupt = this.links.length + this.markers.length; for (const [id, v] of newPortals) { if (v === undefined) { @@ -537,13 +613,13 @@ export default class WasabeeOp extends Evented { this.buildCoordsLookupTable(); } - addPortal(portal) { + addPortal(portal: WasabeePortal) { if (!this.updatePortal(portal) && this._addPortal(portal)) { this.update(false); // adding a portal may just be due to a blocker } } - _addPortal(portal) { + _addPortal(portal: WasabeePortal) { if (!this.containsPortal(portal)) { const key = portal.lat + "/" + portal.lng; if (this._coordsToOpportals.has(key)) { @@ -566,7 +642,7 @@ export default class WasabeeOp extends Evented { return false; } - updatePortal(portal) { + updatePortal(portal: WasabeePortal) { if (this._updatePortal(portal)) { this.update(true); return true; @@ -576,7 +652,7 @@ export default class WasabeeOp extends Evented { // update portal silently if one with mathching ID or with matching position // return true if this update a portal data - _updatePortal(portal) { + _updatePortal(portal: WasabeePortal) { const old = this.getPortal(portal.id); if (old) { if (!portal.faked) { @@ -635,7 +711,16 @@ export default class WasabeeOp extends Evented { } // options: {description,order,color,replace} - addLink(fromPortal, toPortal, options = {}) { + addLink( + fromPortal: WasabeePortal, + toPortal: WasabeePortal, + options: { + description?: string; + order?: number; + color?: string; + replace?: boolean; + } = {} + ) { console.assert(fromPortal && toPortal, "missing portal for link"); if (fromPortal.id === toPortal.id) { console.debug( @@ -652,14 +737,11 @@ export default class WasabeeOp extends Evented { const link = existingLink && options.replace ? existingLink - : new WasabeeLink( - { - fromPortalId: fromPortal.id, - toPortalId: toPortal.id, - }, - this - ); - if (options.description) link.description = options.description; + : new WasabeeLink({ + fromPortalId: fromPortal.id, + toPortalId: toPortal.id, + }); + if (options.description) link.comment = options.description; if (options.order) link.setOrder(options.order); if (options.color) link.color = options.color; @@ -679,7 +761,7 @@ export default class WasabeeOp extends Evented { return link; } - containsAnchor(portalId) { + containsAnchor(portalId: string) { if (this.anchors.length == 0) return false; for (const a of this.anchors) { if (a == portalId) { @@ -689,7 +771,7 @@ export default class WasabeeOp extends Evented { return false; } - addAnchor(portal) { + addAnchor(portal: WasabeePortal) { // doing this ourselves saves a trip to update(); this._addPortal(portal); if (!this.containsAnchor(portal.id)) { @@ -703,7 +785,7 @@ export default class WasabeeOp extends Evented { } // silently swap two anchors - _swapPortal(originalPortal, newPortal) { + _swapPortal(originalPortal: WasabeePortal, newPortal: WasabeePortal) { this.anchors = this.anchors.filter(function (listAnchor) { return listAnchor !== originalPortal.id; }); @@ -711,11 +793,6 @@ export default class WasabeeOp extends Evented { const linksToRemove = []; for (const l of this.links) { - // purge any crosslink check cache - if (l._crosslinksGL) { - delete l._crosslinksGL; - } - if (l.fromPortalId == originalPortal.id) { if (l.toPortalId === newPortal.id) { console.debug( @@ -752,14 +829,14 @@ export default class WasabeeOp extends Evented { ); } - swapPortal(originalPortal, newPortal) { + swapPortal(originalPortal: WasabeePortal, newPortal: WasabeePortal) { this._addPortal(newPortal); this._swapPortal(originalPortal, newPortal); this.update(true); this.updateBlockers(); } - addMarker(markerType, portal, options) { + addMarker(markerType: string, portal: WasabeePortal, options) { if (!portal) return false; if (this.containsMarker(portal, markerType)) return false; // save a trip to update() @@ -781,7 +858,7 @@ export default class WasabeeOp extends Evented { return true; } - assignMarker(id, gid) { + assignMarker(id: MarkerID, gid: GoogleID) { for (const v of this.markers) { if (v.ID == id) { v.assign(gid); @@ -790,7 +867,7 @@ export default class WasabeeOp extends Evented { } } - assignLink(id, gid) { + assignLink(id: LinkID, gid: GoogleID) { for (const v of this.links) { if (v.ID == id) { v.assign(gid); @@ -800,9 +877,9 @@ export default class WasabeeOp extends Evented { } clearAllItems() { - this.anchors = Array(); - this.links = Array(); - this.markers = Array(); + this.anchors = []; + this.links = []; + this.markers = []; this._idToOpportals.clear(); this._coordsToOpportals.clear(); @@ -810,14 +887,14 @@ export default class WasabeeOp extends Evented { } clearAllLinks() { - this.links = Array(); + this.links = []; this.cleanAnchorList(); this.cleanPortalList(); this.update(true); } clearAllMarkers() { - this.markers = Array(); + this.markers = []; this.cleanPortalList(); this.update(true); } @@ -850,16 +927,16 @@ export default class WasabeeOp extends Evented { this.updateBlockers(); } - convertLinksToObjs(links) { + convertLinksToObjs(links: any[]) { const tmpLinks = new Array(); if (!links || links.length == 0) return tmpLinks; for (const l of links) { - tmpLinks.push(new WasabeeLink(l, this)); + tmpLinks.push(new WasabeeLink(l)); } return tmpLinks; } - convertMarkersToObjs(markers) { + convertMarkersToObjs(markers: any[]) { const tmpMarkers = new Array(); if (!markers || markers.length == 0) return tmpMarkers; if (markers) { @@ -870,7 +947,7 @@ export default class WasabeeOp extends Evented { return tmpMarkers; } - convertPortalsToObjs(portals) { + convertPortalsToObjs(portals: any[]) { const tmpPortals = Array(); if (!portals || portals.length == 0) return tmpPortals; for (const p of portals) { @@ -884,7 +961,7 @@ export default class WasabeeOp extends Evented { return tmpPortals; } - convertZonesToObjs(zones) { + convertZonesToObjs(zones: any[]) { if (!zones || zones.length == 0) { // if not set, use the defaults return [ @@ -1018,7 +1095,12 @@ export default class WasabeeOp extends Evented { // this is only for local display if FireBase doesn't trigger a refresh // KOH always takes place on the server because non-write-access // agents need to make changes & sync - keyOnHand(portalId, gid, onhand, capsule) { + keyOnHand( + portalId: PortalID, + gid: GoogleID, + onhand: number, + capsule: string + ) { if (typeof onhand == "string") { onhand = Number.parseInt(onhand, 10); } @@ -1037,7 +1119,7 @@ export default class WasabeeOp extends Evented { } } - const k = { + const k: KeyOnHand = { portalId: portalId, gid: gid, onhand: onhand, @@ -1047,27 +1129,20 @@ export default class WasabeeOp extends Evented { this.update(false); } - KeysOnHandForPortal(portalId) { + KeysOnHandForPortal(portalId: PortalID) { let i = 0; for (const k of this.keysonhand) if (k.portalId == portalId) i += k.onhand; return i; } - KeysRequiredForPortal(portalId) { + KeysRequiredForPortal(portalId: PortalID) { let i = 0; for (const l of this.links) if (l.toPortalId == portalId) i++; return i; } - getZone(zoneID) { - for (const z of this.zones) { - if (z.id == zoneID) return z; - } - return null; - } - - zoneName(zoneID) { - if (zoneID == "0") + zoneName(zoneID: ZoneID) { + if (zoneID == 0) // All zone return "All"; for (const z of this.zones) { @@ -1076,13 +1151,20 @@ export default class WasabeeOp extends Evented { return zoneID; } + getZone(zoneID: ZoneID) { + for (const z of this.zones) { + if (z.id == zoneID) return z; + } + return null; + } + // a wrapper to set WasabeePortal or WasabeeLink zone and update - setZone(thing, zoneID) { + setZone(thing: Task, zoneID: ZoneID) { thing.zone = Number(zoneID); this.update(true); } - removeZone(zoneID) { + removeZone(zoneID: ZoneID) { if (zoneID == 1) { console.log("cannot remove zone 1"); return; @@ -1099,7 +1181,7 @@ export default class WasabeeOp extends Evented { this.update(true); } - removeZonePoints(zoneID) { + removeZonePoints(zoneID: ZoneID) { for (const z of this.zones) { if (z.id == zoneID) { z.points = []; @@ -1108,7 +1190,7 @@ export default class WasabeeOp extends Evented { this.update(true); } - renameZone(zoneID, name) { + renameZone(zoneID: ZoneID, name: string) { for (const z of this.zones) { if (z.id == zoneID) { z.name = name; @@ -1119,7 +1201,7 @@ export default class WasabeeOp extends Evented { } addZone() { - const ids = new Set(); + const ids = new Set(); for (const z of this.zones) { ids.add(z.id); } @@ -1129,7 +1211,7 @@ export default class WasabeeOp extends Evented { return newid; } - addZonePoint(zoneID, latlng) { + addZonePoint(zoneID: number, latlng: L.LatLng) { for (const z of this.zones) { if (z.id == zoneID) { z.points.push({ @@ -1143,11 +1225,14 @@ export default class WasabeeOp extends Evented { this.update(true); } - changes(origin) { + changes(origin?: WasabeeOp) { const changes = { addition: new Array(), edition: new Array(), deletion: new Array(), + name: null, + color: null, + comment: null, }; // empty op if old OP (or local OP) const oldOp = new WasabeeOp(origin ? origin : this.fetchedOp || {}); @@ -1246,7 +1331,7 @@ export default class WasabeeOp extends Evented { return this.localchanged; } - mergeZones(op) { + mergeZones(op: WasabeeOp) { const ids = new Set(); let count = 0; for (const z of this.zones) { @@ -1262,7 +1347,7 @@ export default class WasabeeOp extends Evented { } // assume that `this` is a server OP (teams/keys are correct) - applyChanges(changes, op) { + applyChanges(changes, op: WasabeeOp) { const summary = { compatibility: { ok: true, @@ -1461,7 +1546,7 @@ export default class WasabeeOp extends Evented { return summary; } - determineZone(latlng) { + determineZone(latlng: { lat: number; lng: number }) { // sort first, lowest ID wins if a marker is in 2 overlapping zones this.zones.sort((a, b) => { return a.id - b.id; From 7c8a8408861506d1330a8281befd80e5960da7d1 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 11 Nov 2021 10:10:26 +0100 Subject: [PATCH 095/275] fix some types --- src/code/global.d.ts | 14 ++++++++++++++ src/code/model/index.d.ts | 10 ---------- src/code/ui/zone.js | 2 +- src/types/leafletExtentions/index.d.ts | 22 ++++++++++++++++++++++ 4 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 src/code/global.d.ts delete mode 100644 src/code/model/index.d.ts diff --git a/src/code/global.d.ts b/src/code/global.d.ts new file mode 100644 index 000000000..1bc7a680a --- /dev/null +++ b/src/code/global.d.ts @@ -0,0 +1,14 @@ +declare module "*.css" { + const content: string; + export default content; +} + +declare module "*.json" { + const content: any; + export default content; +} + +declare module "*.svg" { + const content: string; + export default content; +} diff --git a/src/code/model/index.d.ts b/src/code/model/index.d.ts deleted file mode 100644 index a1fa7fb2a..000000000 --- a/src/code/model/index.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// diff --git a/src/code/ui/zone.js b/src/code/ui/zone.js index 7184d5faa..a74c60d7e 100644 --- a/src/code/ui/zone.js +++ b/src/code/ui/zone.js @@ -12,7 +12,7 @@ const WLZone = L.LayerGroup.extend({ let layer; if (zone.points.length == 1) layer = L.marker(zone.points[0], { - icon: L.divIcon.coloredSvg(zone.color), + icon: new L.DivIcon.ColoredSvg(zone.color), }); else if (zone.points.length == 2) layer = L.polyline(zone.points, { color: zone.color }); diff --git a/src/types/leafletExtentions/index.d.ts b/src/types/leafletExtentions/index.d.ts index d74861522..272eb58f3 100755 --- a/src/types/leafletExtentions/index.d.ts +++ b/src/types/leafletExtentions/index.d.ts @@ -21,6 +21,22 @@ declare module "leaflet" { // tslint:disable-next-line:no-empty-interface class GeodesicCircle extends Polyline { } + interface Polyline { + initialize: typeof L.Polyline.prototype.constructor; + } + interface Marker { + initialize: typeof L.Marker.prototype.constructor; + } + interface LayerGroup { + initialize: typeof L.LayerGroup.prototype.constructor; + } + interface Layer { + _popup: Popup; + } + interface Popup { + _wrapper: HTMLDivElement; + } + // extends PolynineOption to any prop interface PolylineOptions { /* guid: string */ @@ -36,4 +52,10 @@ declare module "leaflet" { interface Marker { update(): this; } + + namespace DivIcon { + class ColoredSvg extends DivIcon { + constructor(color: string, options?: MarkerOptions); + } + } } From 2fe05bfadda4984798ba4f8a2c5c69bbb288a154 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 11 Nov 2021 11:43:39 +0100 Subject: [PATCH 096/275] server: promise returns object --- src/code/dialogs/mergeDialog.js | 4 +- src/code/model/agent.ts | 11 ++- src/code/model/me.ts | 10 +-- src/code/model/operation.ts | 26 +++--- src/code/model/team.ts | 8 +- src/code/server.d.ts | 135 +++++++++++++++++++------------- src/code/server.js | 32 ++------ src/code/ui/agent.js | 32 +------- src/code/wd.js | 3 +- 9 files changed, 118 insertions(+), 143 deletions(-) diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index 8633859ca..3f027807d 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -61,9 +61,7 @@ const MergeDialog = WDialog.extend({ const origin = new WasabeeOp( // while merge should only occurs with server ops, it appears users succeed to merge // with local ops. This is a failsafe for those edge-cases - this.options.opOwn.fetchedOp - ? this.options.opOwn.fetchedOp - : this.options.opOwn.toExport() + this.options.opOwn.getFetchedOp() || this.options.opOwn.toExport() ); const changes = this.options.opOwn.changes(origin); const summary = this._opRebase.applyChanges(changes, this.options.opOwn); diff --git a/src/code/model/agent.ts b/src/code/model/agent.ts index b717240bf..dadf032fd 100644 --- a/src/code/model/agent.ts +++ b/src/code/model/agent.ts @@ -30,12 +30,11 @@ export default class WasabeeAgent { constructor(obj) { if (typeof obj == "string") { - try { - obj = JSON.parse(obj); - } catch (e) { - console.error(e); - obj = {}; - } + console.trace('agent waits for an object'); + obj = { + id: "00000", + name: 'invalid agent', + }; } // console.debug("passed to constructor", obj); diff --git a/src/code/model/me.ts b/src/code/model/me.ts index 00fdc2d9d..eedf2cb73 100644 --- a/src/code/model/me.ts +++ b/src/code/model/me.ts @@ -42,12 +42,8 @@ export default class WasabeeMe { constructor(data) { if (typeof data == "string") { - try { - data = JSON.parse(data); - } catch (e) { - console.error(e); - return null; - } + console.trace('me waits for an object'); + return null; } this.GoogleID = data.GoogleID; this.name = data.name; @@ -100,7 +96,7 @@ export default class WasabeeMe { static localGet() { const lsme = localStorage[constants.AGENT_INFO_KEY]; if (typeof lsme == "string") { - return new WasabeeMe(lsme); // do not store + return new WasabeeMe(JSON.parse(lsme)); // do not store } return null; } diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index e11d6d3bb..9b0353f44 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -12,7 +12,6 @@ import db from "../db"; // 0.20->0.21 blocker migration import WasabeeBlocker from "./blocker"; import type Task from "./task"; -import type { LatLngExpression } from "leaflet"; export type KeyOnHand = { portalId: string; @@ -96,12 +95,8 @@ export default class WasabeeOp extends Evented implements IOperation { constructor(obj) { super(); if (typeof obj == "string") { - try { - obj = JSON.parse(obj); - } catch (e) { - console.error("corrupted operation", e); - return null; - } + console.trace("op waits for an object"); + return null; } this.ID = obj.ID ? obj.ID : generateId(); @@ -254,12 +249,21 @@ export default class WasabeeOp extends Evented implements IOperation { // JSON with everything optional removed -- inception grade logic here toExport() { // round-trip through JSON.stringify to ensure a deep copy - const o = new WasabeeOp(JSON.stringify(this)); - // drop +0.21 - o.cleanPortalList(); // remove portals which are only relevant to blockers + const o = new WasabeeOp(JSON.parse(JSON.stringify(this))); return JSON.stringify(o); } + getFetchedOp() { + if (!this.fetchedOp) return null; + try { + const json = JSON.parse(this.fetchedOp); + return new WasabeeOp(json); + } catch (e) { + console.error("corrupted fetched op", e); + return null; + } + } + // read only (for inspection) get opportals() { return Array.from(this._idToOpportals.values()); @@ -1235,7 +1239,7 @@ export default class WasabeeOp extends Evented implements IOperation { comment: null, }; // empty op if old OP (or local OP) - const oldOp = new WasabeeOp(origin ? origin : this.fetchedOp || {}); + const oldOp = new WasabeeOp(origin ? origin : this.getFetchedOp() || {}); const oldLinks = new Map(oldOp.links.map((l) => [l.ID, l])); const oldMarkers = new Map(oldOp.markers.map((m) => [m.ID, m])); diff --git a/src/code/model/team.ts b/src/code/model/team.ts index c4523b807..78583bfd3 100644 --- a/src/code/model/team.ts +++ b/src/code/model/team.ts @@ -16,12 +16,8 @@ export default class WasabeeTeam { constructor(data) { if (typeof data == "string") { - try { - data = JSON.parse(data); - } catch (e) { - console.error(e); - return; - } + console.trace("team waits for an object"); + return; } let fromServer = false; diff --git a/src/code/server.d.ts b/src/code/server.d.ts index ad7e1ea57..f01f78cd3 100644 --- a/src/code/server.d.ts +++ b/src/code/server.d.ts @@ -3,66 +3,93 @@ import WasabeeMarker from "./model/marker"; import type WasabeeLink from "./model/link"; import type WasabeePortal from "./model/portal"; import type { WDKey } from "./wd"; -interface IServerUpdate { - updateID?: string; +import WasabeeMe from "./model/me"; +import WasabeeTeam from "./model/team"; +import WasabeeAgent from "./model/agent"; + +interface IServerStatus { + status: string; } -export default function (): any; -export declare function uploadOpPromise(): Promise; -export declare function updateOpPromise(operation: WasabeeOp): Promise; -export declare function deleteOpPromise(opID: OpID): Promise; -export declare function statOpPromise(opID: OpID): Promise; -export declare function teamPromise(teamid: TeamID): Promise; +interface IServerUpdate extends IServerStatus { + updateID: string; +} + +export default function (): string; +export declare function GetWasabeeServer(): string; +export declare function SetWasabeeServer(server: string): void; +export declare function GetUpdateList(): any; + +declare function genericGet(url: string, formData: FormData | string, contentType?: string): Promise; +declare function genericPost(url: string, formData: FormData | string, contentType?: string): Promise; +declare function genericPut(url: string, formData: FormData | string, contentType?: string): Promise; +declare function genericDelete(url: string, formData: FormData | string, contentType?: string): Promise; + +// query data +export declare function mePromise(): Promise; export declare function opPromise(opID: OpID): Promise; -export declare function mePromise(): Promise; -export declare function agentPromise(GID: GoogleID): Promise; -export declare function assignMarkerPromise(opID: OpID, markerID: MarkerID, agentID: GoogleID): Promise; -export declare function assignLinkPromise(opID: OpID, linkID: LinkID, agentID: GoogleID): Promise; -export declare function targetPromise(agentID: GoogleID, portal: WasabeePortal, type?: string): Promise; -export declare function routePromise(agentID: GoogleID, portal: WasabeePortal): Promise; -export declare function SendAccessTokenAsync(accessToken: string): Promise; -export declare function SetTeamState(teamID: TeamID, state: "On" | "Off"): Promise; -export declare function SetTeamShareWD(teamID: TeamID, state: "On" | "Off"): Promise; -export declare function SetTeamLoadWD(teamID: TeamID, state: "On" | "Off"): Promise; -export declare function SetMarkerState(opID: OpID, markerID: MarkerID, state: string): Promise; -export declare function SetLinkState(opID: OpID, linkID: LinkID, state: string): Promise; -export declare function opKeyPromise(opID: OpID, portalID: PortalID, onhand: number, capsule: string): Promise; -export declare function dKeyPromise(json: string): Promise; -export declare function dKeyBulkPromise(json: string): Promise; +export declare function teamPromise(teamid: TeamID): Promise; +export declare function agentPromise(GID: GoogleID): Promise; export declare function dKeylistPromise(): Promise<{ DefensiveKeys: WDKey[]; }>; -export declare function locationPromise(lat: number, lng: number): Promise; -export declare function logoutPromise(): Promise; -export declare function addPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; -export declare function delPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; -export declare function leaveTeamPromise(teamID: TeamID): Promise; -export declare function removeAgentFromTeamPromise(agentID: GoogleID, teamID: TeamID): Promise; -export declare function setAgentTeamSquadPromise(agentID: GoogleID, teamID: TeamID, squad: string): Promise; -export declare function addAgentToTeamPromise(agentID: GoogleID, teamID: TeamID): Promise; -export declare function renameTeamPromise(teamID: TeamID, name: string): Promise; -export declare function rocksPromise(teamID: TeamID, community: string, apikey: string): Promise; -export declare function newTeamPromise(name: string): Promise; -export declare function deleteTeamPromise(teamID: TeamID): Promise; -export declare function oneTimeToken(token: string): Promise; -export declare function GetWasabeeServer(): any; -export declare function GetUpdateList(): any; -export declare function SetWasabeeServer(server: string): void; -export declare function sendTokenToWasabee(token: string): Promise; -export declare function getCustomTokenFromServer(): Promise; export declare function loadConfig(): Promise; -export declare function changeTeamOwnerPromise(teamID: TeamID, newOwner: GoogleID): Promise; export declare function createJoinLinkPromise(teamID: TeamID): Promise<{ Key: string; }>; -export declare function deleteJoinLinkPromise(teamID: TeamID): Promise; -export declare function setAssignmentStatus(op: WasabeeOp, object: WasabeeLink | WasabeeMarker, completed: boolean): Promise; -export declare function sendAnnounce(teamID: TeamID, message: string): Promise; -export declare function pullRocks(teamID: TeamID): Promise; -export declare function reverseLinkDirection(opID: OpID, linkID: LinkID): Promise; -export declare function setOpInfo(opID: OpID, info: any): Promise; -export declare function setMarkerComment(opID: OpID, markerID: MarkerID, comment: string): Promise; -export declare function setLinkComment(opID: OpID, linkID: LinkID, desc: string): Promise; -export declare function setLinkZone(opID: OpID, linkID: LinkID, zone: ZoneID): Promise; -export declare function setMarkerZone(opID: OpID, markerID: MarkerID, zone: ZoneID): Promise; -export declare function setIntelID(name: string, faction: string, querytoken: string): Promise; -export { }; + +// query action +export declare function targetPromise(agentID: GoogleID, portal: WasabeePortal, type?: string): Promise; +export declare function sendAnnounce(teamID: TeamID, message: string): Promise; +export declare function pullRocks(teamID: TeamID): Promise; + +// special case +export declare function uploadOpPromise(): Promise; +export declare function updateOpPromise(operation: WasabeeOp): Promise; + +// login/out +export declare function SendAccessTokenAsync(accessToken: string): Promise; +export declare function logoutPromise(): Promise; +export declare function oneTimeToken(token: string): Promise; +export declare function sendTokenToWasabee(token: string): Promise; +export declare function getCustomTokenFromServer(): Promise; +// me +export declare function leaveTeamPromise(teamID: TeamID): Promise; +export declare function dKeyPromise(json: string): Promise; +export declare function dKeyBulkPromise(json: string): Promise; +export declare function locationPromise(lat: number, lng: number): Promise; +export declare function setIntelID(name: string, faction: string, querytoken: string): Promise; +export declare function SetTeamState(teamID: TeamID, state: "On" | "Off"): Promise; +export declare function SetTeamShareWD(teamID: TeamID, state: "On" | "Off"): Promise; +export declare function SetTeamLoadWD(teamID: TeamID, state: "On" | "Off"): Promise; + +// update data +// team +export declare function newTeamPromise(name: string): Promise; +export declare function renameTeamPromise(teamID: TeamID, name: string): Promise; +export declare function deleteTeamPromise(teamID: TeamID): Promise; +export declare function changeTeamOwnerPromise(teamID: TeamID, newOwner: GoogleID): Promise; +export declare function addAgentToTeamPromise(agentID: GoogleID, teamID: TeamID): Promise; +export declare function removeAgentFromTeamPromise(agentID: GoogleID, teamID: TeamID): Promise; +export declare function rocksPromise(teamID: TeamID, community: string, apikey: string): Promise; +export declare function setAgentTeamSquadPromise(agentID: GoogleID, teamID: TeamID, squad: string): Promise; +export declare function deleteJoinLinkPromise(teamID: TeamID): Promise; + + +// op +export declare function addPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; +export declare function deleteOpPromise(opID: OpID): Promise; +export declare function delPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; +export declare function setOpInfo(opID: OpID, info: any): Promise; +// op task +export declare function assignMarkerPromise(opID: OpID, markerID: MarkerID, agentID: GoogleID): Promise; +export declare function assignLinkPromise(opID: OpID, linkID: LinkID, agentID: GoogleID): Promise; +export declare function SetMarkerState(opID: OpID, markerID: MarkerID, state: string): Promise; +export declare function SetLinkState(opID: OpID, linkID: LinkID, state: string): Promise; +export declare function setAssignmentStatus(op: WasabeeOp, object: WasabeeLink | WasabeeMarker, completed: boolean): Promise; +export declare function reverseLinkDirection(opID: OpID, linkID: LinkID): Promise; +export declare function setMarkerComment(opID: OpID, markerID: MarkerID, comment: string): Promise; +export declare function setLinkComment(opID: OpID, linkID: LinkID, desc: string): Promise; +export declare function setLinkZone(opID: OpID, linkID: LinkID, zone: ZoneID): Promise; +export declare function setMarkerZone(opID: OpID, markerID: MarkerID, zone: ZoneID): Promise; +// op keys +export declare function opKeyPromise(opID: OpID, portalID: PortalID, onhand: number, capsule: string): Promise; diff --git a/src/code/server.js b/src/code/server.js index 0a7d32e9b..67dc62551 100644 --- a/src/code/server.js +++ b/src/code/server.js @@ -105,11 +105,6 @@ export function deleteOpPromise(opID) { return genericDelete(`/api/v1/draw/${opID}`, new FormData()); } -// returns a promise to op stat from the server -export function statOpPromise(opID) { - return genericGet(`/api/v1/draw/${opID}/stat`); -} - // returns a promise to a WasabeeTeam -- used only by WasabeeTeam.get // use WasabeeTeam.get export function teamPromise(teamid) { @@ -227,16 +222,6 @@ export function targetPromise(agentID, portal, type = "ad hoc") { ); } -// work in progress -- server support not finished -export function routePromise(agentID, portal) { - const ll = portal.lat + "," + portal.lng; - const fd = new FormData(); - fd.append("id", agentID); - fd.append("portal", portal.name); - fd.append("ll", ll); - return genericPost(`/api/v1/agent/${agentID}/route`, fd); -} - // returns a promise to /me if the access token is valid export function SendAccessTokenAsync(accessToken) { return genericPost( @@ -421,11 +406,10 @@ async function genericPut(url, formData, contentType) { switch (response.status) { case 200: try { - const text = await response.text(); - const obj = JSON.parse(text); + const obj = await response.json(); if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); // returns a promise to the content - return Promise.resolve(text); + return Promise.resolve(obj); } catch (e) { console.error(e); return Promise.reject(e); @@ -476,11 +460,10 @@ async function genericPost(url, formData, contentType) { switch (response.status) { case 200: try { - const text = await response.text(); - const obj = JSON.parse(text); + const obj = await response.json(); if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); // returns a promise to the content - return Promise.resolve(text); + return Promise.resolve(obj); } catch (e) { console.error(e); return Promise.reject(e); @@ -531,11 +514,10 @@ async function genericDelete(url, formData, contentType) { switch (response.status) { case 200: try { - const text = await response.text(); - const obj = JSON.parse(text); + const obj = await response.json(); if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); // returns a promise to the content - return Promise.resolve(text); + return Promise.resolve(obj); } catch (e) { console.error(e); return Promise.reject(e); @@ -582,11 +564,13 @@ async function genericGet(url) { case 200: try { const text = await response.text(); + // isn't always json ? no, see /firebase paths (jwt) if ( response.headers.get("Content-Type").includes("application/json") ) { const obj = JSON.parse(text); if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); + return Promise.resolve(obj); } // returns a promise to the content return Promise.resolve(text); diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index bfbad6584..a9491e0e2 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -1,7 +1,7 @@ import PortalUI from "./portal"; import ConfirmDialog from "../dialogs/confirmDialog"; import AgentDialog from "../dialogs/agentDialog"; -import { targetPromise, routePromise } from "../server"; +import { targetPromise } from "../server"; import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; @@ -50,7 +50,7 @@ function timeSinceformat(agent) { if (Number.isNaN(date)) return `(${agent.date} UTC)`; // FireFox Date.parse no good if (date == 0) return ""; - const seconds = Math.floor((new Date() - date) / 1000); + const seconds = Math.floor((Date.now() - date) / 1000); if (seconds < 0) return ""; let interval = Math.floor(seconds / 31536000 / 2592000 / 86400); @@ -220,34 +220,6 @@ const WLAgent = L.Marker.extend({ d.enable(); }); - // this needs wX - const requestRoute = L.DomUtil.create("button", null, content); - requestRoute.textContent = "Send Route to Target"; - requestRoute.style.display = "none"; // hide this until the server-side is ready - L.DomEvent.on(requestRoute, "click", (ev) => { - L.DomEvent.stop(ev); - const selectedPortal = PortalUI.getSelected(); - if (!selectedPortal) { - alert(wX("SELECT PORTAL")); - return; - } - - const d = new ConfirmDialog({ - title: "Send Route to Target", - label: "Do you really want to request the route to be sent?", - type: "agent", - callback: async () => { - try { - await routePromise(agent.id, selectedPortal); - alert("Route Sent"); - } catch (e) { - console.error(e); - } - }, - }); - d.enable(); - }); - const op = getSelectedOperation(); const assignments = L.DomUtil.create("ul", "assignments", content); for (const m of op.markers) { diff --git a/src/code/wd.js b/src/code/wd.js index c4b9b5498..0024c1882 100644 --- a/src/code/wd.js +++ b/src/code/wd.js @@ -63,8 +63,7 @@ export async function drawWasabeeDkeys() { if (WasabeeMe.isLoggedIn()) { try { - const data = await dKeylistPromise(); - const list = JSON.parse(data); + const list = await dKeylistPromise(); if (!list || !list.DefensiveKeys || list.DefensiveKeys.length == 0) return; window.plugin.wasabee.idb.clear("defensivekeys"); From e0f3bd268cbe33a9f5b932cbbcdf69cb7a09fa5b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 11 Nov 2021 17:20:52 +0100 Subject: [PATCH 097/275] server: factor api call + standardize errors --- src/code/dialogs/defensiveKeysDialog.js | 4 +- src/code/dialogs/keysList.js | 8 +- src/code/dialogs/teamListDialog.js | 9 +- src/code/error.ts | 46 ++ src/code/model/me.ts | 17 +- src/code/server.d.ts | 75 +- src/code/server.js | 990 ++++++++++-------------- src/code/translations/english.json | 4 + src/code/translations/filipino.json | 4 + src/code/translations/french.json | 4 + src/code/translations/german.json | 4 + src/code/translations/italian.json | 6 +- src/code/translations/portuguese.json | 4 + src/code/translations/spanish.json | 4 + src/code/uiCommands.js | 6 +- 15 files changed, 567 insertions(+), 618 deletions(-) create mode 100644 src/code/error.ts diff --git a/src/code/dialogs/defensiveKeysDialog.js b/src/code/dialogs/defensiveKeysDialog.js index 246fcd0f1..bd2680e3d 100644 --- a/src/code/dialogs/defensiveKeysDialog.js +++ b/src/code/dialogs/defensiveKeysDialog.js @@ -12,9 +12,9 @@ const DefensiveKeysDialog = WDialog.extend({ TYPE: "defensiveKeysDialog", }, - addHooks: async function () { + addHooks: function () { WDialog.prototype.addHooks.call(this); - this._me = await WasabeeMe.waitGet(); + this._me = WasabeeMe.localGet(); this._pch = (portal) => { this._portalClickedHook(portal); }; diff --git a/src/code/dialogs/keysList.js b/src/code/dialogs/keysList.js index 1445192e2..9a5f28f3b 100644 --- a/src/code/dialogs/keysList.js +++ b/src/code/dialogs/keysList.js @@ -18,13 +18,13 @@ const KeysList = WDialog.extend({ usePane: true, }, - addHooks: async function () { + addHooks: function () { WDialog.prototype.addHooks.call(this); const operation = getSelectedOperation(); this._opID = operation.ID; window.map.on("wasabee:op:select wasabee:op:change", this.update, this); if (WasabeeMe.isLoggedIn()) { - this._me = await WasabeeMe.waitGet(); + this._me = WasabeeMe.localGet(); } else { this._me = null; } @@ -53,12 +53,12 @@ const KeysList = WDialog.extend({ }); }, - update: async function () { + update: function () { const operation = getSelectedOperation(); if (operation.ID != this._opID) console.log("operation changed"); // update me if needed - if (WasabeeMe.isLoggedIn()) this._me = await WasabeeMe.waitGet(); + if (WasabeeMe.isLoggedIn()) this._me = WasabeeMe.localGet(); else this._me = null; this.setTitle(wX("KEY_LIST2", { opName: operation.name })); diff --git a/src/code/dialogs/teamListDialog.js b/src/code/dialogs/teamListDialog.js index 15aadd2a9..e43e5a3eb 100644 --- a/src/code/dialogs/teamListDialog.js +++ b/src/code/dialogs/teamListDialog.js @@ -9,7 +9,6 @@ import { SetTeamLoadWD, } from "../server"; import PromptDialog from "./promptDialog"; -import AuthDialog from "./authDialog"; import TeamMembershipList from "./teamMembershipList"; import ConfirmDialog from "./confirmDialog"; import ManageTeamDialog from "./manageTeamDialog"; @@ -22,7 +21,7 @@ const TeamListDialog = WDialog.extend({ addHooks: async function () { WDialog.prototype.addHooks.call(this); - this._me = await WasabeeMe.waitGet(true); // no cache + this._me = await WasabeeMe.waitGet(true, true); // no cache unless server error window.map.on("wasabee:teams", this.update, this); window.map.on("wasabee:logout", this.closeDialog, this); this._displayDialog(); @@ -34,9 +33,9 @@ const TeamListDialog = WDialog.extend({ window.map.off("wasabee:logout", this.closeDialog, this); }, - update: async function () { + update: function () { if (!this._enabled) return; - this._me = await WasabeeMe.waitGet(); // cache is fine -- this can probably be removed + this._me = WasabeeMe.localGet(); this.setContent(this._buildContent()); }, @@ -156,8 +155,6 @@ const TeamListDialog = WDialog.extend({ _displayDialog: function () { if (!this._me) { this.disable(); - const ad = new AuthDialog(); - ad.enable(); return; } diff --git a/src/code/error.ts b/src/code/error.ts new file mode 100644 index 000000000..548eb9c15 --- /dev/null +++ b/src/code/error.ts @@ -0,0 +1,46 @@ +import wX from "./wX"; + +interface IServerError { + code: number; + text: string; + error?: string; +} + +// no stacktrace error +export class ServerError implements IServerError { + code: number; + text: string; + error?: string; + + constructor(obj: IServerError) { + this.code = obj.code; + this.text = obj.text; + this.error = obj.error; + } + + toString() { + switch (this.code) { + case 401: + if (this.error) + return wX("NOT LOGGED IN", this); + return wX("NOT LOGGED IN SHORT"); + case 403: + if (this.error) + return wX("PERM DENIED", this); + return wX("PERM DENIED SHORT"); + case 410: + if (this.error) + return wX("NO LONGER AVAILABLE", this); + return wX("NO LONGER AVAILABLE SHORT"); + case 412: + // for internal use only + if (this.error) + return 'Mismatch version: ' + this.error; + return 'Mismatch version'; + default: + if (this.error) + return this.text + ': ' + this.error; + return this.text; + } + } +} diff --git a/src/code/model/me.ts b/src/code/model/me.ts index eedf2cb73..67dadfcf5 100644 --- a/src/code/model/me.ts +++ b/src/code/model/me.ts @@ -42,7 +42,7 @@ export default class WasabeeMe { constructor(data) { if (typeof data == "string") { - console.trace('me waits for an object'); + console.trace("me waits for an object"); return null; } this.GoogleID = data.GoogleID; @@ -132,9 +132,9 @@ export default class WasabeeMe { } // use waitGet with "force == true" if you want a fresh value now - static async waitGet(force?: boolean) { - let me = WasabeeMe.localGet(); - + // may throw if force == true + static async waitGet(force?: boolean, noFail?: boolean) { + const me = WasabeeMe.localGet(); if ( me === null || me.fetched == undefined || @@ -145,15 +145,12 @@ export default class WasabeeMe { const response = await mePromise(); const newme = new WasabeeMe(response); newme.store(); - me = newme; } catch (e) { - WasabeeMe.purge(); - console.error(e); - // alert(e.toString()); - me = null; + if (force && !noFail) throw e; } } - return me; + // use updated (or null) me object + return WasabeeMe.localGet(); } static async purge() { diff --git a/src/code/server.d.ts b/src/code/server.d.ts index f01f78cd3..42577bfbb 100644 --- a/src/code/server.d.ts +++ b/src/code/server.d.ts @@ -19,51 +19,55 @@ export declare function GetWasabeeServer(): string; export declare function SetWasabeeServer(server: string): void; export declare function GetUpdateList(): any; -declare function genericGet(url: string, formData: FormData | string, contentType?: string): Promise; -declare function genericPost(url: string, formData: FormData | string, contentType?: string): Promise; -declare function genericPut(url: string, formData: FormData | string, contentType?: string): Promise; -declare function genericDelete(url: string, formData: FormData | string, contentType?: string): Promise; +declare function genericGet(url: string, formData: FormData | string, contentType?: string): Promise; +declare function genericPost(url: string, formData: FormData | string, contentType?: string): Promise; +declare function genericPut(url: string, formData: FormData | string, contentType?: string): Promise; +declare function genericDelete(url: string, formData: FormData | string, contentType?: string): Promise; -// query data -export declare function mePromise(): Promise; -export declare function opPromise(opID: OpID): Promise; -export declare function teamPromise(teamid: TeamID): Promise; -export declare function agentPromise(GID: GoogleID): Promise; -export declare function dKeylistPromise(): Promise<{ - DefensiveKeys: WDKey[]; -}>; +// server config export declare function loadConfig(): Promise; -export declare function createJoinLinkPromise(teamID: TeamID): Promise<{ - Key: string; -}>; - -// query action -export declare function targetPromise(agentID: GoogleID, portal: WasabeePortal, type?: string): Promise; -export declare function sendAnnounce(teamID: TeamID, message: string): Promise; -export declare function pullRocks(teamID: TeamID): Promise; - -// special case -export declare function uploadOpPromise(): Promise; -export declare function updateOpPromise(operation: WasabeeOp): Promise; // login/out export declare function SendAccessTokenAsync(accessToken: string): Promise; export declare function logoutPromise(): Promise; export declare function oneTimeToken(token: string): Promise; +// firebase export declare function sendTokenToWasabee(token: string): Promise; export declare function getCustomTokenFromServer(): Promise; -// me + +/* me & d */ +// query +export declare function mePromise(): Promise; +export declare function dKeylistPromise(): Promise<{ + DefensiveKeys: WDKey[]; +}>; +// update data export declare function leaveTeamPromise(teamID: TeamID): Promise; -export declare function dKeyPromise(json: string): Promise; -export declare function dKeyBulkPromise(json: string): Promise; export declare function locationPromise(lat: number, lng: number): Promise; export declare function setIntelID(name: string, faction: string, querytoken: string): Promise; export declare function SetTeamState(teamID: TeamID, state: "On" | "Off"): Promise; export declare function SetTeamShareWD(teamID: TeamID, state: "On" | "Off"): Promise; export declare function SetTeamLoadWD(teamID: TeamID, state: "On" | "Off"): Promise; +export declare function dKeyPromise(json: string): Promise; +export declare function dKeyBulkPromise(json: string): Promise; +/* agent */ +// query +export declare function agentPromise(GID: GoogleID): Promise; +// action +export declare function targetPromise(agentID: GoogleID, portal: WasabeePortal, type?: string): Promise; + + +/* team */ +// query +export declare function teamPromise(teamid: TeamID): Promise; +export declare function createJoinLinkPromise(teamID: TeamID): Promise<{ + Key: string; +}>; +// action +export declare function sendAnnounce(teamID: TeamID, message: string): Promise; +export declare function pullRocks(teamID: TeamID): Promise; // update data -// team export declare function newTeamPromise(name: string): Promise; export declare function renameTeamPromise(teamID: TeamID, name: string): Promise; export declare function deleteTeamPromise(teamID: TeamID): Promise; @@ -74,13 +78,18 @@ export declare function rocksPromise(teamID: TeamID, community: string, apikey: export declare function setAgentTeamSquadPromise(agentID: GoogleID, teamID: TeamID, squad: string): Promise; export declare function deleteJoinLinkPromise(teamID: TeamID): Promise; - -// op -export declare function addPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; +/* op */ +// query +export declare function opPromise(opID: OpID): Promise; +// special +export declare function uploadOpPromise(): Promise; +export declare function updateOpPromise(operation: WasabeeOp): Promise; +// update data export declare function deleteOpPromise(opID: OpID): Promise; +export declare function addPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; export declare function delPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; export declare function setOpInfo(opID: OpID, info: any): Promise; -// op task +// update task export declare function assignMarkerPromise(opID: OpID, markerID: MarkerID, agentID: GoogleID): Promise; export declare function assignLinkPromise(opID: OpID, linkID: LinkID, agentID: GoogleID): Promise; export declare function SetMarkerState(opID: OpID, markerID: MarkerID, state: string): Promise; @@ -91,5 +100,5 @@ export declare function setMarkerComment(opID: OpID, markerID: MarkerID, comment export declare function setLinkComment(opID: OpID, linkID: LinkID, desc: string): Promise; export declare function setLinkZone(opID: OpID, linkID: LinkID, zone: ZoneID): Promise; export declare function setMarkerZone(opID: OpID, markerID: MarkerID, zone: ZoneID): Promise; -// op keys +// update keys export declare function opKeyPromise(opID: OpID, portalID: PortalID, onhand: number, capsule: string): Promise; diff --git a/src/code/server.js b/src/code/server.js index 67dc62551..0666122e5 100644 --- a/src/code/server.js +++ b/src/code/server.js @@ -1,234 +1,108 @@ import WasabeeMe from "./model/me"; import WasabeeOp from "./model/operation"; import { getSelectedOperation, removeOperation } from "./selectedOp"; -import wX from "./wX"; import WasabeeMarker from "./model/marker"; +import { ServerError } from "./error"; export default function () { return GetWasabeeServer(); } -// uploads an op to the server -// refreshed op stored to localStorage; "me" upated to reflect new op in list -export async function uploadOpPromise() { - const operation = getSelectedOperation(); - const json = operation.toExport(); - - const response = await genericPost( - "/api/v1/draw", - json, - "application/json;charset=UTF-8" - ); - const newme = new WasabeeMe(response); - newme.store(); - const newop = await opPromise(operation.ID); - newop.localchanged = false; - await newop.store(); - return newop; +export function GetWasabeeServer() { + // Wasabee-IITC, use the configured server + if (window.plugin && window.plugin.wasabee) { + let server = + localStorage[window.plugin.wasabee.static.constants.SERVER_BASE_KEY]; + if (server == null) { + server = window.plugin.wasabee.static.constants.SERVER_BASE_DEFAULT; + localStorage[window.plugin.wasabee.static.constants.SERVER_BASE_KEY] = + server; + } + return server; + } + // Wasabee-WebUI doesn't need to specify the server + return ""; } -// sends a changed op to the server -export async function updateOpPromise(operation) { - const json = operation.toExport(); - - try { - const construct = { - method: "PUT", - mode: "cors", - cache: "default", - credentials: "include", - redirect: "manual", - referrerPolicy: "origin", - body: json, - headers: { "Content-Type": "application/json;charset=UTF-8" }, - }; - if (operation.lasteditid) - construct.headers["If-Match"] = operation.lasteditid; - - const response = await fetch( - GetWasabeeServer() + `/api/v1/draw/${operation.ID}`, - construct - ); - - switch (response.status) { - case 200: - try { - const text = await response.text(); - const obj = JSON.parse(text); - if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); - operation.lasteditid = obj.updateID; - operation.remoteChanged = false; - operation.fetched = new Date().toUTCString(); - return Promise.resolve(true); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - case 412: - // mismatch etag - try { - return Promise.resolve(false); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - case 401: - WasabeeMe.purge(); - try { - const err = await response.json(); - return Promise.reject(wX("NOT LOGGED IN", { error: err.error })); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - default: - try { - const err = await response.json(); - return Promise.reject(err.error); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - } - } catch (e) { - console.error(e); - return Promise.reject(e); +export function GetUpdateList() { + if (window.plugin && window.plugin.wasabee) { + return window.plugin.wasabee._updateList; } + return window.wasabeewebui._updateList; } -// removes an op from the server -export function deleteOpPromise(opID) { - return genericDelete(`/api/v1/draw/${opID}`, new FormData()); +export function SetWasabeeServer(server) { + server = server.trim(); + if (!server.startsWith("http")) server = "https://" + server; + if (server.endsWith("/")) server = server.slice(0, -1); + localStorage[window.plugin.wasabee.static.constants.SERVER_BASE_KEY] = server; } -// returns a promise to a WasabeeTeam -- used only by WasabeeTeam.get -// use WasabeeTeam.get -export function teamPromise(teamid) { - return genericGet(`/api/v1/team/${teamid}`); +/* +On fail, all promises reject an ServerError { code: number, text: string, error?: string } +If http code is 401: request Me.purge (fire wasabee:logout) +On success, it may returns: + - the requested data as string + - the requested object + - 304 (if modified) + - true/false (updateOp) +*/ + +export function loadConfig() { + return genericGet(`/static/wasabee-webui-config.json`); } -// returns a promise to fetch a WasabeeOp -// local change: If the server's copy is newer than the local copy, otherwise none -// not generic since 304 result processing and If-Modified-Since header -export async function opPromise(opID) { - let ims = "Sat, 29 Oct 1994 19:43:31 GMT"; // the dawn of time... - const localop = await WasabeeOp.load(opID); - if (localop != null && localop.fetched) ims = localop.fetched; +// returns a promise to /me if the access token is valid +export function SendAccessTokenAsync(accessToken) { + return genericPost( + "/aptok", + JSON.stringify({ accessToken: accessToken }), + "application/json;charset=UTF-8" + ); +} - try { - const server = GetWasabeeServer(); - const headers = {}; - // ops synced since 0.19: prefer lasteditid if available - if (localop && localop.lasteditid) - headers["If-None-Match"] = localop.lasteditid; - else headers["If-Modified-Since"] = ims; - const response = await fetch(server + `/api/v1/draw/${opID}`, { - method: "GET", - mode: "cors", - cache: "default", - credentials: "include", - redirect: "manual", - referrerPolicy: "origin", - headers: headers, - }); +// sets logout status on the server; return value is status code +export function logoutPromise() { + return genericGet("/api/v1/me/logout"); +} - let raw = null; - let newop = null; // I hate javascript - switch (response.status) { - case 200: - raw = await response.json(); - newop = new WasabeeOp(raw); - newop.localchanged = false; - newop.server = server; - newop.fetchedOp = JSON.stringify(raw); - return Promise.resolve(newop); - case 304: // If-None-Match or If-Modified-Since replied NotModified - console.warn("server copy is older/unmodified, keeping local copy"); - localop.server = server; - return Promise.resolve(localop); - case 401: - WasabeeMe.purge(); - raw = await response.json(); - return Promise.reject(wX("NOT LOGGED IN", { error: raw.error })); - case 403: - await removeOperation(opID); - raw = await response.json(); - return Promise.reject( - wX("OP PERM DENIED", { opID: opID }) + ": " + raw.error - ); - case 410: - await removeOperation(opID); - raw = await response.json(); - return Promise.reject( - wX("OP DELETED", { opID: opID }) + ": " + raw.error - ); - default: - try { - const err = await response.json(); - return Promise.reject(err.error); - } catch (e) { - console.error(e); - raw = await response.text(); - return Promise.reject(raw); - } - } - } catch (e) { - console.error(e); - return Promise.reject(e); - } +// local change: none // cache: none +export function oneTimeToken(token) { + const url = "/oneTimeToken"; + const fd = new FormData(); + fd.append("token", token); + return genericPost(url, fd); } +/**** me & d ****/ + // returns a promise to WasabeeMe -- should be called only by WasabeeMe.waitGet() // use WasabeeMe.cacheGet or WasabeeMe.waitGet for caching export function mePromise() { - return genericGet("/me?json=y"); -} - -// returns a promise to get the agent's JSON data from the server -- should be called only by WasabeeAgent.get() -export function agentPromise(GID) { - return genericGet(`/api/v1/agent/${GID}`); + return genericGet("/api/v1/me"); } -// local change: none // cache: none -export function assignMarkerPromise(opID, markerID, agentID) { - const fd = new FormData(); - fd.append("agent", agentID); - return genericPost(`/api/v1/draw/${opID}/marker/${markerID}/assign`, fd); +// returns a promise to a list of defensive keys for all enabled teams +export function dKeylistPromise() { + return genericGet("/api/v1/d"); } -// performs a link assignment on the server, sending notifications -export function assignLinkPromise(opID, linkID, agentID) { - const fd = new FormData(); - fd.append("agent", agentID); - return genericPost(`/api/v1/draw/${opID}/link/${linkID}/assign`, fd); +// removes the agent from the team; return value is status code +export function leaveTeamPromise(teamID) { + return genericDelete(`/api/v1/me/${teamID}`, new FormData()); } -// sends a target (portal) to the server to notify the agent -export function targetPromise(agentID, portal, type = "ad hoc") { - return genericPost( - `/api/v1/agent/${agentID}/target`, - JSON.stringify({ - Name: portal.name, - Lat: portal.lat, - Lng: portal.lng, - ID: portal.id, - Type: type, - }), - "application/json;charset=UTF-8" - ); +// updates an agent's location ; return value is status code +export function locationPromise(lat, lng) { + return genericGet(`/api/v1/me?lat=${lat}&lon=${lng}`); } -// returns a promise to /me if the access token is valid -export function SendAccessTokenAsync(accessToken) { - return genericPost( - "/aptok", - JSON.stringify({ accessToken: accessToken }), - "application/json;charset=UTF-8" - ); +export function setIntelID(name, faction, querytoken) { + const fd = new FormData(); + fd.append("name", name); + fd.append("faction", faction); + fd.append("qt", querytoken); + return genericPut(`/api/v1/me/intelid`, fd); } // changes agent's team state on the server; return value is status message @@ -244,52 +118,6 @@ export function SetTeamLoadWD(teamID, state) { return genericGet(`/api/v1/me/${teamID}/wdload?state=${state}`); } -// changes a markers status on the server, sending relevant notifications -export function SetMarkerState(opID, markerID, state) { - let action = "incomplete"; - switch (state) { - case "acknowledged": - action = "acknowledge"; - break; - case "pending": - action = "incomplete"; - break; - case "completed": - action = "complete"; - break; - default: - action = "incomplete"; - } - - return genericGet(`/api/v1/draw/${opID}/marker/${markerID}/${action}`); -} - -// changes a link's status on the server, sending relevant notifications -export function SetLinkState(opID, linkID, state) { - let action = "incomplete"; - switch (state) { - // no acknowledge for links -- use incomplete - case "pending": - action = "incomplete"; - break; - case "completed": - action = "complete"; - break; - default: - action = "incomplete"; - } - - return genericGet(`/api/v1/draw/${opID}/link/${linkID}/${action}`); -} - -// updates an agent's key count, return value is status code -export function opKeyPromise(opID, portalID, onhand, capsule) { - const fd = new FormData(); - fd.append("count", onhand); - fd.append("capsule", capsule); - return genericPost(`/api/v1/draw/${opID}/portal/${portalID}/keyonhand`, fd); -} - // updates an agent's single defensive key export function dKeyPromise(json) { return genericPost("/api/v1/d", json, "application/json;charset=UTF-8"); @@ -300,54 +128,65 @@ export function dKeyBulkPromise(json) { return genericPost("/api/v1/d/bulk", json, "application/json;charset=UTF-8"); } -// returns a promise to a list of defensive keys for all enabled teams -export function dKeylistPromise() { - return genericGet("/api/v1/d"); -} +/* agent */ -// updates an agent's location ; return value is status code -export function locationPromise(lat, lng) { - return genericGet(`/api/v1/me?lat=${lat}&lon=${lng}`); +// returns a promise to get the agent's JSON data from the server -- should be called only by WasabeeAgent.get() +export function agentPromise(GID) { + return genericGet(`/api/v1/agent/${GID}`); } -// sets logout status on the server; return value is status code -export function logoutPromise() { - return genericGet("/api/v1/me/logout"); +// sends a target (portal) to the server to notify the agent +export function targetPromise(agentID, portal, type = "ad hoc") { + return genericPost( + `/api/v1/agent/${agentID}/target`, + JSON.stringify({ + Name: portal.name, + Lat: portal.lat, + Lng: portal.lng, + ID: portal.id, + Type: type, + }), + "application/json;charset=UTF-8" + ); } -// adds a permission to an op; return value is status code -export function addPermPromise(opID, teamID, role, zone) { - const fd = new FormData(); - fd.append("team", teamID); - fd.append("role", role); - fd.append("zone", zone); - return genericPost(`/api/v1/draw/${opID}/perms`, fd); +/* team */ + +// returns a promise to a WasabeeTeam -- used only by WasabeeTeam.get +// use WasabeeTeam.get +export function teamPromise(teamid) { + return genericGet(`/api/v1/team/${teamid}`); } -// removes a permission from an op; return value is status code -export function delPermPromise(opID, teamID, role, zone) { +export function sendAnnounce(teamID, message) { const fd = new FormData(); - fd.append("team", teamID); - fd.append("role", role); - fd.append("zone", zone); - return genericDelete(`/api/v1/draw/${opID}/perms`, fd); + fd.append("m", message); + return genericPost(`/api/v1/team/${teamID}/announce`, fd); } -// removes the agent from the team; return value is status code -export function leaveTeamPromise(teamID) { - return genericDelete(`/api/v1/me/${teamID}`, new FormData()); +export function pullRocks(teamID) { + return genericGet(`/api/v1/team/${teamID}/rocks`); } -// removes another agent from an owned team ; return value is status code -export function removeAgentFromTeamPromise(agentID, teamID) { - return genericDelete(`/api/v1/team/${teamID}/${agentID}`, new FormData()); +// local change: none // cache: none +export function newTeamPromise(name) { + return genericGet(`/api/v1/team/new?name=${name}`); } // local change: none // cache: none -export function setAgentTeamSquadPromise(agentID, teamID, squad) { +export function renameTeamPromise(teamID, name) { const fd = new FormData(); - fd.append("squad", squad); - return genericPost(`/api/v1/team/${teamID}/${agentID}/squad`, fd); + fd.append("teamname", name); + return genericPut(`/api/v1/team/${teamID}/rename`, fd); +} + +// local change: none // cache: none +export function deleteTeamPromise(teamID) { + return genericDelete(`/api/v1/team/${teamID}`, new FormData()); +} + +export function changeTeamOwnerPromise(teamID, newOwner) { + return genericGet(`/api/v1/team/${teamID}/chown?to=${newOwner}`); } // local change: none // cache: none @@ -355,11 +194,9 @@ export function addAgentToTeamPromise(agentID, teamID) { return genericPost(`/api/v1/team/${teamID}/${agentID}`, new FormData()); } -// local change: none // cache: none -export function renameTeamPromise(teamID, name) { - const fd = new FormData(); - fd.append("teamname", name); - return genericPut(`/api/v1/team/${teamID}/rename`, fd); +// removes another agent from an owned team ; return value is status code +export function removeAgentFromTeamPromise(agentID, teamID) { + return genericDelete(`/api/v1/team/${teamID}/${agentID}`, new FormData()); } // local change: none // cache: none @@ -370,306 +207,214 @@ export function rocksPromise(teamID, community, apikey) { } // local change: none // cache: none -export function newTeamPromise(name) { - return genericGet(`/api/v1/team/new?name=${name}`); +export function setAgentTeamSquadPromise(agentID, teamID, squad) { + const fd = new FormData(); + fd.append("squad", squad); + return genericPost(`/api/v1/team/${teamID}/${agentID}/squad`, fd); } -// local change: none // cache: none -export function deleteTeamPromise(teamID) { - return genericDelete(`/api/v1/team/${teamID}`, new FormData()); +export function createJoinLinkPromise(teamID) { + return genericGet(`/api/v1/team/${teamID}/genJoinKey`); } -// local change: none // cache: none -export function oneTimeToken(token) { - const url = "/oneTimeToken"; - const fd = new FormData(); - fd.append("token", token); - return genericPost(url, fd); +export function deleteJoinLinkPromise(teamID) { + return genericGet(`/api/v1/team/${teamID}/delJoinKey`); } -async function genericPut(url, formData, contentType) { +// returns a promise to fetch a WasabeeOp +// local change: If the server's copy is newer than the local copy, otherwise none +// not generic since 304 result processing and If-Modified-Since header +export async function opPromise(opID) { + let ims = "Sat, 29 Oct 1994 19:43:31 GMT"; // the dawn of time... + const localop = await WasabeeOp.load(opID); + if (localop != null && localop.fetched) ims = localop.fetched; + try { - const construct = { - method: "PUT", - mode: "cors", - cache: "default", - credentials: "include", - redirect: "manual", - referrerPolicy: "origin", - body: formData, - }; - if (contentType != null) { - construct.headers = { "Content-Type": contentType }; - } - const response = await fetch(GetWasabeeServer() + url, construct); + const raw = await generic({ + url: `/api/v1/draw/${opID}`, + method: "GET", + headers: localop + ? { + "If-None-Match": localop.lasteditid, + "If-Modified-Since": localop.lasteditid ? null : ims, + } + : null, + }); - switch (response.status) { - case 200: - try { - const obj = await response.json(); - if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); - // returns a promise to the content - return Promise.resolve(obj); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - case 401: - WasabeeMe.purge(); - try { - const err = await response.json(); - return Promise.reject(wX("NOT LOGGED IN", { error: err.error })); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - default: - try { - const err = await response.json(); - return Promise.reject(err.error); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; + if (raw === 304) { + localop.server = GetWasabeeServer(); + return localop; } - } catch (e) { - console.error(e); - return Promise.reject(e); - } -} -async function genericPost(url, formData, contentType) { - try { - const construct = { - method: "POST", - mode: "cors", - cache: "default", - credentials: "include", - redirect: "manual", - referrerPolicy: "origin", - body: formData, - }; - if (contentType != null) { - construct.headers = { "Content-Type": contentType }; + const newop = new WasabeeOp(raw); + newop.localchanged = false; + newop.server = GetWasabeeServer(); + newop.fetchedOp = JSON.stringify(raw); + return newop; + } catch (e) { + if (!(e instanceof ServerError)) { + // unexpected error + console.error(e); + return Promise.reject( + new ServerError({ + code: -1, + text: `Unexpected error: ${e}`, + }) + ); } - const response = await fetch(GetWasabeeServer() + url, construct); - - switch (response.status) { - case 200: - try { - const obj = await response.json(); - if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); - // returns a promise to the content - return Promise.resolve(obj); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - case 401: - WasabeeMe.purge(); - try { - const err = await response.json(); - return Promise.reject(wX("NOT LOGGED IN", { error: err.error })); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; + switch (e.code) { + case 403: + // fallthrough + case 410: + await removeOperation(opID); + // fallthrough default: - try { - const err = await response.json(); - return Promise.reject(err.error); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; + return Promise.reject(e); } - } catch (e) { - console.error(e); - return Promise.reject(e); } } -async function genericDelete(url, formData, contentType) { - try { - const construct = { - method: "DELETE", - mode: "cors", - cache: "default", - credentials: "include", - redirect: "manual", - referrerPolicy: "origin", - body: formData, - }; - if (contentType != null) { - construct.headers = { "Content-Type": contentType }; - } - const response = await fetch(GetWasabeeServer() + url, construct); +// uploads an op to the server +// refreshed op stored to localStorage; "me" upated to reflect new op in list +export async function uploadOpPromise() { + const operation = getSelectedOperation(); + const json = operation.toExport(); - switch (response.status) { - case 200: - try { - const obj = await response.json(); - if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); - // returns a promise to the content - return Promise.resolve(obj); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - case 401: - WasabeeMe.purge(); - try { - const err = await response.json(); - return Promise.reject(wX("NOT LOGGED IN", { error: err.error })); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - default: - try { - const err = await response.json(); - return Promise.reject(err.error); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - } - } catch (e) { - console.error(e); - return Promise.reject(e); - } + const response = await genericPost( + "/api/v1/draw", + json, + "application/json;charset=UTF-8" + ); + const newme = new WasabeeMe(response); + newme.store(); + const newop = await opPromise(operation.ID); + newop.localchanged = false; + await newop.store(); + return newop; } -async function genericGet(url) { +// sends a changed op to the server +export async function updateOpPromise(operation) { + const json = operation.toExport(); + try { - const response = await fetch(GetWasabeeServer() + url, { - method: "GET", - mode: "cors", - cache: "default", - credentials: "include", - redirect: "manual", - referrerPolicy: "origin", + const update = await generic({ + url: `/api/v1/draw/${operation.ID}`, + method: "PUT", + body: json, + headers: { + "Content-Type": "application/json;charset=UTF-8", + "If-Match": operation.lasteditid || null, + }, }); - - switch (response.status) { - case 200: - try { - const text = await response.text(); - // isn't always json ? no, see /firebase paths (jwt) - if ( - response.headers.get("Content-Type").includes("application/json") - ) { - const obj = JSON.parse(text); - if (obj.updateID) GetUpdateList().set(obj.updateID, Date.now()); - return Promise.resolve(obj); - } - // returns a promise to the content - return Promise.resolve(text); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - case 401: - WasabeeMe.purge(); - try { - const err = await response.json(); - return Promise.reject(wX("NOT LOGGED IN", { error: err.error })); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; - case 403: - try { - const err = await response.json(); - return Promise.reject("forbidden: " + err.error); - } catch (e) { - console.error(e); - return Promise.reject(e); - } + operation.lasteditid = update.updateID; + operation.remoteChanged = false; + operation.fetched = new Date().toUTCString(); + operation.fetchedOp = JSON.stringify(operation); + return true; + } catch (e) { + if (!(e instanceof ServerError)) { + // unexpected error + console.error(e); + return Promise.reject( + new ServerError({ + code: -1, + text: `Unexpected error: ${e}`, + }) + ); + } + switch (e.code) { + case 412: + return false; // break; + case 410: + await removeOperation(operation.ID); + // fallthrough default: - console.log(response); - try { - const err = await response.json(); - return Promise.reject(err.error); - } catch (e) { - console.error(e); - return Promise.reject(e); - } - // break; + return Promise.reject(e); } - } catch (e) { - console.error(e); - return Promise.reject(e); } } -export function GetWasabeeServer() { - // Wasabee-IITC, use the configured server - if (window.plugin && window.plugin.wasabee) { - let server = - localStorage[window.plugin.wasabee.static.constants.SERVER_BASE_KEY]; - if (server == null) { - server = window.plugin.wasabee.static.constants.SERVER_BASE_DEFAULT; - localStorage[window.plugin.wasabee.static.constants.SERVER_BASE_KEY] = - server; - } - return server; - } - // Wasabee-WebUI doesn't need to specify the server - return ""; +// removes an op from the server +export function deleteOpPromise(opID) { + return genericDelete(`/api/v1/draw/${opID}`, new FormData()); } -export function GetUpdateList() { - if (window.plugin && window.plugin.wasabee) { - return window.plugin.wasabee._updateList; - } - return window.wasabeewebui._updateList; +export function setOpInfo(opID, info) { + const fd = new FormData(); + fd.append("info", info); + return genericPost(`/api/v1/draw/${opID}/info`, fd); } -export function SetWasabeeServer(server) { - server = server.trim(); - if (!server.startsWith("http")) server = "https://" + server; - if (server.endsWith("/")) server = server.slice(0, -1); - localStorage[window.plugin.wasabee.static.constants.SERVER_BASE_KEY] = server; +// adds a permission to an op; return value is status code +export function addPermPromise(opID, teamID, role, zone) { + const fd = new FormData(); + fd.append("team", teamID); + fd.append("role", role); + fd.append("zone", zone); + return genericPost(`/api/v1/draw/${opID}/perms`, fd); } -/* The following are for Wasabee-WebUI and not used in Wasabee-IITC */ - -// in the service-worker for IITC -export function sendTokenToWasabee(token) { - // no need for a form-data, just send the raw token - return genericPost(`/api/v1/me/firebase`, token); +// removes a permission from an op; return value is status code +export function delPermPromise(opID, teamID, role, zone) { + const fd = new FormData(); + fd.append("team", teamID); + fd.append("role", role); + fd.append("zone", zone); + return genericDelete(`/api/v1/draw/${opID}/perms`, fd); } -export function getCustomTokenFromServer() { - return genericGet(`/api/v1/me/firebase`); +// local change: none // cache: none +export function assignMarkerPromise(opID, markerID, agentID) { + const fd = new FormData(); + fd.append("agent", agentID); + return genericPost(`/api/v1/draw/${opID}/marker/${markerID}/assign`, fd); } -export function loadConfig() { - return genericGet(`/static/wasabee-webui-config.json`); +// performs a link assignment on the server, sending notifications +export function assignLinkPromise(opID, linkID, agentID) { + const fd = new FormData(); + fd.append("agent", agentID); + return genericPost(`/api/v1/draw/${opID}/link/${linkID}/assign`, fd); } -export function changeTeamOwnerPromise(teamID, newOwner) { - return genericGet(`/api/v1/team/${teamID}/chown?to=${newOwner}`); -} +// changes a markers status on the server, sending relevant notifications +export function SetMarkerState(opID, markerID, state) { + let action = "incomplete"; + switch (state) { + case "acknowledged": + action = "acknowledge"; + break; + case "pending": + action = "incomplete"; + break; + case "completed": + action = "complete"; + break; + default: + action = "incomplete"; + } -export function createJoinLinkPromise(teamID) { - return genericGet(`/api/v1/team/${teamID}/genJoinKey`); + return genericGet(`/api/v1/draw/${opID}/marker/${markerID}/${action}`); } -export function deleteJoinLinkPromise(teamID) { - return genericGet(`/api/v1/team/${teamID}/delJoinKey`); +// changes a link's status on the server, sending relevant notifications +export function SetLinkState(opID, linkID, state) { + let action = "incomplete"; + switch (state) { + // no acknowledge for links -- use incomplete + case "pending": + action = "incomplete"; + break; + case "completed": + action = "complete"; + break; + default: + action = "incomplete"; + } + + return genericGet(`/api/v1/draw/${opID}/link/${linkID}/${action}`); } export function setAssignmentStatus(op, object, completed) { @@ -681,26 +426,10 @@ export function setAssignmentStatus(op, object, completed) { return genericGet(`/api/v1/draw/${op.ID}/${type}/${object.ID}/${c}`); } -export function sendAnnounce(teamID, message) { - const fd = new FormData(); - fd.append("m", message); - return genericPost(`/api/v1/team/${teamID}/announce`, fd); -} - -export function pullRocks(teamID) { - return genericGet(`/api/v1/team/${teamID}/rocks`); -} - export function reverseLinkDirection(opID, linkID) { return genericGet(`/api/v1/draw/${opID}/link/${linkID}/swap`); } -export function setOpInfo(opID, info) { - const fd = new FormData(); - fd.append("info", info); - return genericPost(`/api/v1/draw/${opID}/info`, fd); -} - export function setMarkerComment(opID, markerID, comment) { const fd = new FormData(); fd.append("comment", comment); @@ -725,10 +454,151 @@ export function setMarkerZone(opID, markerID, zone) { return genericPost(`/api/v1/draw/${opID}/marker/${markerID}/zone`, fd); } -export function setIntelID(name, faction, querytoken) { +// updates an agent's key count, return value is status code +export function opKeyPromise(opID, portalID, onhand, capsule) { const fd = new FormData(); - fd.append("name", name); - fd.append("faction", faction); - fd.append("qt", querytoken); - return genericPut(`/api/v1/me/intelid`, fd); + fd.append("count", onhand); + fd.append("capsule", capsule); + return genericPost(`/api/v1/draw/${opID}/portal/${portalID}/keyonhand`, fd); +} + +/* The following are for Wasabee-WebUI and not used in Wasabee-IITC */ + +// in the service-worker for IITC +export function sendTokenToWasabee(token) { + // no need for a form-data, just send the raw token + return genericPost(`/api/v1/me/firebase`, token); +} + +export function getCustomTokenFromServer() { + return generic({ + url: `/api/v1/me/firebase`, + method: "GET", + raw: true, + }); +} + +/* generic method */ +/** + * Generic fetch method against wasabee server + * + * @param {Object} request + * @param {string} request.url + * @param {string} request.method + * @param {string | FormData} [request.body] + * @param {HeadersInit} [request.headers] + * @param {boolean} [request.raw] + * @param {boolean} [request.retried] + * @returns {Promise<304 | string | Object>} + */ +async function generic(request) { + /** @type RequestInit */ + const requestInit = { + method: request.method, + mode: "cors", + cache: "default", + credentials: "include", + redirect: "manual", + referrerPolicy: "origin", + }; + if (request.body) requestInit.body = request.body; + if (request.headers) requestInit.headers = request.headers; + + try { + const response = await fetch(GetWasabeeServer() + request.url, requestInit); + /** @type Object | string */ + const payload = await response.text(); + + let jsonPayload; + if (!request.raw) { + if (!payload && !request.retried && response.ok) { + // server shouldn't reply empty string + console.warn( + `server answers is empty on [${request.url}], retry once, just in case` + ); + return generic({ ...request, retried: true }); + } + try { + jsonPayload = JSON.parse(payload); + } catch { + if (response.ok) + return Promise.reject( + new ServerError({ + code: -1, + text: "unexpected server answer", + }) + ); + } + } + + switch (response.status) { + case 200: + if (!request.raw && jsonPayload.updateID) + GetUpdateList().set(jsonPayload.updateID, Date.now()); + return Promise.resolve(request.raw ? payload : jsonPayload); + // break; + case 304: // If-None-Match or If-Modified-Since replied NotModified + return Promise.resolve(304); + // break + case 401: + WasabeeMe.purge(); + // fallthrough; + case 403: // forbidden + // fallthrough + case 410: // Gone + // fallthrough + case 412: // mismatch etag + // fallthrough + default: + return Promise.reject( + new ServerError({ + code: response.status, + text: response.statusText, + error: jsonPayload ? jsonPayload.error : null, + }) + ); + } + } catch (e) { + console.error(e); + return Promise.reject( + new ServerError({ + code: -1, + text: "Network error", + }) + ); + } +} + +function genericGet(url) { + return generic({ + method: "GET", + url: url, + }); +} + +function genericPost(url, formData, contentType) { + return generic({ + url: url, + method: "POST", + body: formData, + headers: contentType ? { "Content-Type": contentType } : null, + }); +} + +function genericPut(url, formData, contentType) { + return generic({ + url: url, + method: "PUT", + body: formData, + headers: contentType ? { "Content-Type": contentType } : null, + }); +} + +function genericDelete(url, formData, contentType) { + return generic({ + url: url, + method: "DELETE", + body: formData, + headers: contentType ? { "Content-Type": contentType } : null, + }); } diff --git a/src/code/translations/english.json b/src/code/translations/english.json index 2dbfa9f53..7bbd973e3 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -229,6 +229,8 @@ "NO_STOCK_INTEL": "Wasabee doesn't support stock intel draw imports", "NO_TITLE": "No title set", "NO": "No", + "NO LONGER AVAILABLE": "Resource removed from server: {error}", + "NO LONGER AVAILABLE SHORT": "Resource removed from server", "NOT LOGGED IN SHORT": "Not Logged in", "NOT LOGGED IN": "Not Logged in: {error}", "NOT_LOADED": "Not fully loaded, try again.", @@ -258,6 +260,8 @@ "PASTE_INSTRUCT": "Paste a Wasabee draw export here.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", "pending": "Pending", "PENDING": "Pending", + "PERM DENIED": "Permission denied: {error}", + "PERM DENIED SHORT": "Permission denied", "PERMS": "{opName} permissions", "PICK_DEST_FIRST": "Please select a destination portal first!", "PICK_TAR_FIRST": "Please select a target portal first!", diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index 789b5763c..bae57b108 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -229,6 +229,8 @@ "NO_STOCK_INTEL": "Hindi suportado ng Wasabee ang stock intel draw imports", "NO_TITLE": "Walang Pamagat", "NO": "Hindi", + "NO LONGER AVAILABLE": "Resource removed from server: {error}", + "NO LONGER AVAILABLE SHORT": "Resource removed from server", "NOT LOGGED IN SHORT": "Hindi naka-Logged in", "NOT LOGGED IN": "Hindi naka-Logged in {error}", "NOT_LOADED": "Hindi nai-load, ulitin muli.", @@ -258,6 +260,8 @@ "PASTE_INSTRUCT": "I-Paste ang Wasabee draw export dito.\n\nHindi ma-import ng Wasabee ang stock intel format.\n\nMerong experimental na suporta para sa pag-import ng IITC DrawTools format.\n\nBago i-import ang DrawTools format, tignan ang mga areas at siguraduhing lahat ng portals naka-load para naka-cached ito sa IITC. Ang mga portals na hindi pre-cached ay that are not pre-cached ay ipapalit ng 'fake' portal.\n\nKailangan mong gamitin ang 'Ipagpalit' feature para ipatlit ang mga anchor mula sa fake portal sa tamang portal. (ang portal ay dapat nasa tamang lokasyon.\n\nAng mga pangalan ng naka-Cached na portals ay hindi maaring nakapangalan ng tama.)", "pending": "Nakabinbin", "PENDING": "Nakabinbin", + "PERM DENIED": "Walang pahintulot: {error}", + "PERM DENIED SHORT": "Walang pahintulot", "PERMS": "{opName} permisyo", "PICK_DEST_FIRST": "Pumili muna ng destinasyon na portal!", "PICK_TAR_FIRST": "Pumili muna ng simulang portal!", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index c8effcc06..80ea69727 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -229,6 +229,8 @@ "NO_STOCK_INTEL": "Wasabee ne supporte pas les draws de l'intel stock.", "NO_TITLE": "Titre non défini", "NO": "Non", + "NO LONGER AVAILABLE": "Ressource supprimée du serveur: {error}", + "NO LONGER AVAILABLE SHORT": "Ressource supprimée du serveur", "NOT LOGGED IN SHORT": "Déconnecté", "NOT LOGGED IN": "Déconnecté : {error}", "NOT_LOADED": "N'a pas chargé entierement, essayer à nouveau", @@ -258,6 +260,8 @@ "PASTE_INSTRUCT": "Paste a Wasabee draw export here.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", "pending": "En attente", "PENDING": "En attente", + "PERM DENIED": "Permission refusée: {error}", + "PERM DENIED SHORT": "Permission refusée", "PERMS": "Permissions de {opName}", "PICK_DEST_FIRST": "Vous devez d'abord sélectionner un portail de destination!", "PICK_TAR_FIRST": "Vous devez d'abord sélectionner un portail cible!", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index 2cf6eae59..c70118d5d 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -229,6 +229,8 @@ "NO_STOCK_INTEL": "Wasabee unterstützt keine Standard Intel imports", "NO_TITLE": "No title set", "NO": "Nein", + "NO LONGER AVAILABLE": "Ressource vom Server entfernt: {error}", + "NO LONGER AVAILABLE SHORT": "Ressource vom Server entfernt", "NOT LOGGED IN SHORT": "Nicht eingeloggt.", "NOT LOGGED IN": "Nicht eingeloggt: {error}", "NOT_LOADED": "Nicht vollständig geladen - bitte erneut probieren.", @@ -258,6 +260,8 @@ "PASTE_INSTRUCT": "Füge einen Wasabee Drawtools export hier ein.\n\nWasabee kann nicht mit dem Standard intel format umgehen.\n\nEs gibt einen Experimentellen Import vom IITC-DrawTools format.\n\n Vor dem Importieren bitte sicherstellen das alles geladen ist und die IITC es zwischengespeichert hat. Jedes nicht zwischengespeicherte Portal wird verfälscht. \n\nDu musst die 'Wechsel' Funktion verwenden um die verfälschten Portale zu korrigieren. (Sie sollten bereits an der richtigen Position sein - aber dem falschen Portal zugeordnet).", "pending": "Ausstehend", "PENDING": "Ausstehend", + "PERM DENIED": "Keine Berechtigung: {error}", + "PERM DENIED SHORT": "Keine Berechtigung", "PERMS": "{opName} permissions", "PICK_DEST_FIRST": "Bitte wähle zuerst ein Zielportal!", "PICK_TAR_FIRST": "Bitte wähle zuerst ein Startportal!", diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index 01dafd9f8..c3046e3b2 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -229,6 +229,8 @@ "NO_STOCK_INTEL": "Wasabee non supporta importazioni di disegni dalla intel stock", "NO_TITLE": "Titolo non impostato", "NO": "No", + "NO LONGER AVAILABLE": "Risorsa rimossa dal server: {error}", + "NO LONGER AVAILABLE SHORT": "Risorsa rimossa dal server", "NOT LOGGED IN SHORT": "Non loggato", "NOT LOGGED IN": "Non loggato: {error}", "NOT_LOADED": "Caricamento incompleto, riprova.", @@ -258,6 +260,8 @@ "PASTE_INSTRUCT": "Incolla un disegno esportato da Wasabee qui.\n\nWasabee non può importare il formato intel stock.\n\nL'importazione di disegni in formato IITC DrawTools è supportata in modo sperimentale.\n\nPrima di importare in formato DrawTools, controlla l'area e fai in modo che tutti i portali carichino, così da essere nella cache di IITC. Ogni Portale non nella cache sarà 'finto'.\n\nDovrete usare la funzione 'swap' per spostare le ancore dai portali 'finti' a quelli veri (dovrebbero essere al posto giusto, solo non associate al Portale).\n\nI Portali nella cache potrebbero non avere il giusto nome.", "pending": "In corso", "PENDING": "In corso", + "PERM DENIED": "Accesso negato: {error}", + "PERM DENIED SHORT": "Accesso negato", "PERMS": "{opName} permessi", "PICK_DEST_FIRST": "Seleziona prima un Portale di destinazione!", "PICK_TAR_FIRST": "Seleziona prima un portale target!", @@ -438,4 +442,4 @@ "TEAMS BUTTON": "Teams", "WD BUTTON": "W-D Keys" } -} +} \ No newline at end of file diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index 67b0bcf1b..06cdfe1d7 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -229,6 +229,8 @@ "NO_STOCK_INTEL": "Wasabee não suporta importações de desenho de inteligência de stoque", "NO_TITLE": "Nenhum título definido", "NO": "Não", + "NO LONGER AVAILABLE": "Recurso removido do servidor: {error}", + "NO LONGER AVAILABLE SHORT": "Recurso removido do servidor", "NOT LOGGED IN SHORT": "Não logado", "NOT LOGGED IN": "Não logado: ${value}", "NOT_LOADED": "Não totalmente carregado, tente novamente.", @@ -258,6 +260,8 @@ "PASTE_INSTRUCT": "Cola uma exportação de desenho Wasabee aqui.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", "pending": "Pendente", "PENDING": "Pendente", + "PERM DENIED": "Permissão negada: {error}", + "PERM DENIED SHORT": "Permissão negada", "PERMS": "${value} permissões", "PICK_DEST_FIRST": "Seleciona um portal de destino primeiro!", "PICK_TAR_FIRST": "Seleciona um portal de destino primeiro!", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index c204d713a..55df57032 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -229,6 +229,8 @@ "NO_STOCK_INTEL": "Wasabee no soporta la importación de dibujos trazados en intel regular", "NO_TITLE": "Sin título definido", "NO": "No", + "NO LONGER AVAILABLE": "Recurso eliminado del servidor: {error}", + "NO LONGER AVAILABLE SHORT": "Recurso eliminado del servidor", "NOT LOGGED IN SHORT": "Sesión No Iniciada", "NOT LOGGED IN": "Sesión No Iniciada: {error}", "NOT_LOADED": "No está cargado completamente, intentar de nuevo.", @@ -258,6 +260,8 @@ "PASTE_INSTRUCT": "Pega un dibujo exportado de Wasabee aquí.\n\nWasabee no puede importar del formato normal de intel.\n\nHay soporte experimental para importar del formato DrawTools de IITC.\n\nAntes de importar del formato DrawTools, revise las áreas y asegúrese que todos los portales carguen para que estén en la caché de IITC. Cualquier portal que no haya estado pre-cargado será falsificado. Tendrás que usar la opción 'intercambiar' para mover las anclas de los portales falsos a los portales reales (estarán en la ubicación correcta, pero no asociados con el portal.\n\nPortales en la caché puede que no estén nombrados correctamente.", "pending": "Pendiente", "PENDING": "Pendiente", + "PERM DENIED": "Permiso denegado: {error}", + "PERM DENIED SHORT": "Permiso denegado", "PERMS": "{opName} permisos", "PICK_DEST_FIRST": "¡Por favor, primero elige un portal de destino!", "PICK_TAR_FIRST": "¡Por favor, primero elige un portal objetivo!", diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index 83ed65075..08e415763 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -18,6 +18,7 @@ import { } from "./selectedOp"; import PortalUI from "./ui/portal"; +import { ServerError } from "./error"; export function addPortal(operation, portal) { if (!portal) { @@ -534,8 +535,9 @@ export async function fullSync() { alert(wX("SYNC DONE")); } catch (e) { console.error(e); - new AuthDialog().enable(); - alert("You are not logged in."); + if (e instanceof ServerError) alert(e.toString()); + if (WasabeeMe.isLoggedIn()) alert(wX("NOT_LOADED")); + else new AuthDialog().enable(); } } From 8a8680be0681c03c16914798331bfd313be1ec53 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 00:09:51 +0100 Subject: [PATCH 098/275] wasabee alert: add title --- src/code/buttons/uploadButton.js | 11 +++++----- src/code/buttons/wasabeeButton.js | 3 ++- src/code/dialogs/authDialog.js | 23 +++++++++++--------- src/code/dialogs/autodraws/fanfield.js | 7 ++++-- src/code/dialogs/autodraws/flipflop.js | 7 +++--- src/code/dialogs/autodraws/homogeneous.js | 11 +++++----- src/code/dialogs/autodraws/madrid.js | 7 +++--- src/code/dialogs/autodraws/multimaxDialog.js | 7 +++--- src/code/dialogs/autodraws/onionfield.js | 3 ++- src/code/dialogs/autodraws/saveLinks.js | 3 ++- src/code/dialogs/autodraws/starburst.js | 3 ++- src/code/dialogs/autodraws/tools.js | 3 ++- src/code/dialogs/checklist.js | 5 +++-- src/code/dialogs/defensiveKeysDialog.js | 5 +++-- src/code/dialogs/importDialog.js | 15 +++++++------ src/code/dialogs/linkDialog.js | 13 ++++++----- src/code/dialogs/manageTeamDialog.js | 23 ++++++++++---------- src/code/dialogs/markerAddDialog.js | 3 ++- src/code/dialogs/newopDialog.js | 3 ++- src/code/dialogs/opPerms.js | 9 ++++---- src/code/dialogs/opSettings.js | 7 +++--- src/code/dialogs/sendTargetDialog.js | 5 +++-- src/code/dialogs/teamListDialog.js | 13 ++++++----- src/code/dialogs/teamMembershipList.js | 3 ++- src/code/dialogs/trawl.js | 7 +++--- src/code/error.ts | 23 ++++++++++++++++++++ src/code/firebaseSupport.js | 3 ++- src/code/init.js | 7 +++--- src/code/model/operation.ts | 3 ++- src/code/selectedOp.js | 3 ++- src/code/toolbox.js | 3 ++- src/code/ui/agent.js | 5 +++-- src/code/uiCommands.js | 21 +++++++++++------- src/code/wX.ts | 2 +- 34 files changed, 166 insertions(+), 103 deletions(-) diff --git a/src/code/buttons/uploadButton.js b/src/code/buttons/uploadButton.js index c43469f87..cdb66be4c 100644 --- a/src/code/buttons/uploadButton.js +++ b/src/code/buttons/uploadButton.js @@ -10,6 +10,7 @@ import { getSelectedOperation, makeSelectedOperation } from "../selectedOp"; import ConfirmDialog from "../dialogs/confirmDialog"; import MergeDialog from "../dialogs/mergeDialog"; import wX from "../wX"; +import { displayError, displayInfo } from "../error"; const UploadButton = WButton.extend({ statics: { @@ -42,7 +43,7 @@ const UploadButton = WButton.extend({ const r = await uploadOpPromise(); // switch to the new version in local store -- uploadOpPromise stores it await makeSelectedOperation(r.ID); - alert(wX("UPLOADED")); + displayInfo(wX("UPLOADED")); this.update(); // this._invisible(); } catch (e) { @@ -50,11 +51,11 @@ const UploadButton = WButton.extend({ console.warn(e.toString() + ": trying as update"); try { await updateOpPromise(operation); - alert(wX("UPDATED")); + displayInfo(wX("UPDATED")); this.update(); } catch (e) { console.error(e); - alert(`Upload + Update Failed: ${e.toString()}`); + displayError(`Upload + Update Failed: ${e.toString()}`); } this.button.classList.remove("loading"); } @@ -134,7 +135,7 @@ const UploadButton = WButton.extend({ // reload if we use rebase if (operation != getSelectedOperation()) await makeSelectedOperation(operation.ID); - alert(wX("UPDATED")); + displayInfo(wX("UPDATED")); this.update(); } else { // need rebase or force @@ -159,7 +160,7 @@ const UploadButton = WButton.extend({ } } catch (e) { console.error(e); - alert(`Update Failed: ${e.toString()}`); + displayError(`Update Failed: ${e.toString()}`); } this.button.classList.remove("loading"); return; diff --git a/src/code/buttons/wasabeeButton.js b/src/code/buttons/wasabeeButton.js index 1178a8620..046da41fa 100644 --- a/src/code/buttons/wasabeeButton.js +++ b/src/code/buttons/wasabeeButton.js @@ -12,6 +12,7 @@ import { wX } from "../wX"; import { logoutPromise } from "../server"; import { postToFirebase } from "../firebaseSupport"; import { resetCaches } from "../uiCommands"; +import { displayError } from "../error"; const WasabeeButton = WButton.extend({ statics: { @@ -111,7 +112,7 @@ const WasabeeButton = WButton.extend({ await logoutPromise(); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } WasabeeMe.purge(); postToFirebase({ id: "wasabeeLogout" }); // trigger request firebase token on re-login diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index f6f481194..a7bc51e20 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -11,6 +11,7 @@ import { sendLocation, fullSync } from "../uiCommands"; import { wX } from "../wX"; import { postToFirebase } from "../firebaseSupport"; import WasabeeMe from "../model/me"; +import { displayError } from "../error"; const AuthDialog = WDialog.extend({ statics: { @@ -43,7 +44,7 @@ const AuthDialog = WDialog.extend({ _displayDialog: function () { const syncLoggedIn = window.gapi.auth2.getAuthInstance(); if (syncLoggedIn) { - alert(wX("AUTH INCOMPAT")); + displayError(wX("AUTH INCOMPAT")); return; } @@ -128,7 +129,7 @@ const AuthDialog = WDialog.extend({ postToFirebase({ id: "wasabeeLogin", method: "iOS" }); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } window.map.fire("wasabee:defensivekeys"); }); @@ -173,7 +174,7 @@ const AuthDialog = WDialog.extend({ postToFirebase({ id: "wasabeeLogin", method: "One Time Token" }); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } } window.map.fire("wasabee:defensivekeys"); @@ -212,7 +213,7 @@ const AuthDialog = WDialog.extend({ if (response.error) { postToFirebase({ id: "exception", error: response.error }); if (response.error === "idpiframe_initialization_failed") { - alert("You need enable cookies or allow [*.]google.com"); + displayError("You need enable cookies or allow [*.]google.com"); } if ( response.error == "user_logged_out" || @@ -223,7 +224,7 @@ const AuthDialog = WDialog.extend({ if (responseSelect.error) { postToFirebase({ id: "exception", error: response.error }); const err = `error from gapiAuth (immediate_failed): ${responseSelect.error}: ${responseSelect.error_subtype}`; - alert(err); + displayError(err); console.log(err); return; } @@ -235,7 +236,7 @@ const AuthDialog = WDialog.extend({ method: "gsapiAuth (immediate_failed)", }); } catch (e) { - alert(wX("AUTH TOKEN REJECTED", { error: e.toString() })); + displayError(wX("AUTH TOKEN REJECTED", { error: e.toString() })); console.error(e); this.closeDialog(); } @@ -245,7 +246,7 @@ const AuthDialog = WDialog.extend({ const err = `error from gapiAuth: ${response.error}: ${response.error_subtype}`; postToFirebase({ id: "exception", error: err }); console.log(err); - alert(err); + displayError(err); } return; } @@ -256,7 +257,7 @@ const AuthDialog = WDialog.extend({ } catch (e) { postToFirebase({ id: "exception", error: e.toString() }); console.error(e); - alert(e.toString()); + displayError(e); this.closeDialog(); } }); @@ -275,7 +276,7 @@ const AuthDialog = WDialog.extend({ if (response.error) { this.closeDialog(); const err = `error from gsapiAuthChoose: ${response.error}: ${response.error_subtype}`; - alert(err); + displayError(err); postToFirebase({ id: "exception", error: err }); return; } @@ -285,7 +286,9 @@ const AuthDialog = WDialog.extend({ postToFirebase({ id: "wasabeeLogin", method: "gsapiAuthChoose" }); } catch (e) { console.error(e); - alert(`send access token failed (gsapiAuthChoose): ${e.toString()}`); + displayError( + `send access token failed (gsapiAuthChoose): ${e.toString()}` + ); postToFirebase({ id: "exception", error: e.toString() }); } } diff --git a/src/code/dialogs/autodraws/fanfield.js b/src/code/dialogs/autodraws/fanfield.js index a50b42db4..bf439682a 100644 --- a/src/code/dialogs/autodraws/fanfield.js +++ b/src/code/dialogs/autodraws/fanfield.js @@ -5,6 +5,7 @@ import { greatCircleArcIntersect, GeodesicLine } from "../../crosslinks"; import WasabeeLink from "../../model/link"; import { clearAllLinks } from "../../uiCommands"; import wX from "../../wX"; +import { displayError, displayInfo } from "../../error"; export function angle(a, p) { if (a.id == p.id) throw Error("same portal"); @@ -138,7 +139,7 @@ const FanfieldDialog = AutoDraw.extend({ // fanfiled determines the portals between start/end and their angle (and order) fanfield: function () { if (!this._anchor || !this._start || !this._end) { - alert(wX("SET_3_PORT")); + displayError(wX("SET_3_PORT")); return; } @@ -209,7 +210,9 @@ const FanfieldDialog = AutoDraw.extend({ op.endBatchMode(); const ap = 313 * order + 1250 * fields; // too many parameters for wX(); - alert(`Fanfield found ${order} links and ${fields} fields for ${ap} AP`); + displayInfo( + `Fanfield found ${order} links and ${fields} fields for ${ap} AP` + ); }, }); diff --git a/src/code/dialogs/autodraws/flipflop.js b/src/code/dialogs/autodraws/flipflop.js index b2021c6f3..b6c9da176 100644 --- a/src/code/dialogs/autodraws/flipflop.js +++ b/src/code/dialogs/autodraws/flipflop.js @@ -8,6 +8,7 @@ import WasabeeMarker from "../../model/marker"; import { angle } from "./fanfield"; import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; +import { displayError, displayInfo } from "../../error"; function selectAngleInterval(anchor, portalsSorted, start, end) { const startAngle = angle(anchor, start); @@ -130,7 +131,7 @@ const FlipFlopDialog = AutoDraw.extend({ button.textContent = wX("FANFIELD"); L.DomEvent.on(button, "click", () => { const total = this.doFanGun(); - alert(`Flip flop: found ${total} links`); + displayInfo(`Flip flop: found ${total} links`); }); return container; @@ -262,7 +263,7 @@ const FlipFlopDialog = AutoDraw.extend({ doFanGun: function () { // Calculate the multimax if (!this._anchorOne) { - alert(wX("INVALID REQUEST")); + displayError(wX("INVALID REQUEST")); return 0; } @@ -326,7 +327,7 @@ const FlipFlopDialog = AutoDraw.extend({ best.steps = best.steps.slice(0, maxSteps); if (!best.two) { - alert(wX("INVALID REQUEST")); + displayError(wX("INVALID REQUEST")); return 0; } diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index c6113ba9e..30cfaf882 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -11,6 +11,7 @@ import { import wX from "../../wX"; import PortalUI from "../../ui/portal"; +import { displayError, displayWarning } from "../../error"; const HomogeneousDialog = AutoDraw.extend({ statics: { @@ -142,7 +143,7 @@ const HomogeneousDialog = AutoDraw.extend({ this._layerGroup.clearLayers(); if (!this._anchorOne || !this._anchorTwo || !this._anchorThree) { - alert("please select three anchors"); + displayError("please select three anchors"); return; } @@ -175,7 +176,7 @@ const HomogeneousDialog = AutoDraw.extend({ this._draw(); if (this._failed > 0) { - alert( + displayWarning( `Unable to find ${this._failed} splits, try less depth or a different region` ); } @@ -186,7 +187,7 @@ const HomogeneousDialog = AutoDraw.extend({ this._layerGroup.clearLayers(); if (!this._anchorOne || !this._anchorTwo || !this._anchorThree) { - alert("please select three anchors"); + displayError("please select three anchors"); return; } @@ -218,7 +219,7 @@ const HomogeneousDialog = AutoDraw.extend({ this._draw(); if (this._failed > 0) { - alert( + displayWarning( `Unable to find ${this._failed} splits, try less depth or a different region` ); } @@ -226,7 +227,7 @@ const HomogeneousDialog = AutoDraw.extend({ this._failed = 0; if (!this._anchorOne || !this._anchorTwo || !this._anchorThree) { - alert("please select three anchors"); + displayError("please select three anchors"); return; } }, diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index 0f1b2a82d..c3d45fa48 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -1,3 +1,4 @@ +import { displayError, displayInfo } from "../../error"; import { getSelectedOperation } from "../../selectedOp"; import { clearAllLinks } from "../../uiCommands"; import wX from "../../wX"; @@ -66,7 +67,7 @@ const MadridDialog = MultimaxDialog.extend({ const total = this._balancedcheck.checked ? this.doBalancedMadrid.call(this) : this.doMadrid.call(this); - alert(`Madrid found ${total} layers`); + displayInfo(`Madrid found ${total} layers`); // this.closeDialog(); }); @@ -104,7 +105,7 @@ const MadridDialog = MultimaxDialog.extend({ !this._portalSets.setTwo.portals.length || !this._portalSets.setThree.portals.length ) { - alert(wX("INVALID REQUEST")); + displayError(wX("INVALID REQUEST")); return 0; } @@ -220,7 +221,7 @@ const MadridDialog = MultimaxDialog.extend({ !this._portalSets.setTwo.portals.length || !this._portalSets.setThree.portals.length ) { - alert(wX("INVALID REQUEST")); + displayError(wX("INVALID REQUEST")); return 0; } this._operation.startBatchMode(); // bypass save and crosslinks checks diff --git a/src/code/dialogs/autodraws/multimaxDialog.js b/src/code/dialogs/autodraws/multimaxDialog.js index 0b1d51933..0c38539a0 100644 --- a/src/code/dialogs/autodraws/multimaxDialog.js +++ b/src/code/dialogs/autodraws/multimaxDialog.js @@ -4,6 +4,7 @@ import { getSelectedOperation } from "../../selectedOp"; import wX from "../../wX"; import { testPortal, clearAllLinks } from "../../uiCommands"; import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; +import { displayError, displayInfo } from "../../error"; // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX @@ -71,7 +72,7 @@ const MultimaxDialog = AutoDraw.extend({ button.textContent = wX("MULTI_M"); L.DomEvent.on(button, "click", () => { const total = this.doMultimax.call(this); - alert(`Multimax found ${total} layers`); + displayInfo(`Multimax found ${total} layers`); // this.closeDialog(); }); @@ -144,7 +145,7 @@ const MultimaxDialog = AutoDraw.extend({ }); if (!Array.isArray(sequence) || !sequence.length) { - // alert("No layers found"); + // displayInfo("No layers found"); return [0, order, null]; } @@ -177,7 +178,7 @@ const MultimaxDialog = AutoDraw.extend({ // Calculate the multimax if (!this._anchorOne || !this._anchorTwo || !portals.length) { - alert(wX("INVALID REQUEST")); + displayError(wX("INVALID REQUEST")); return 0; } diff --git a/src/code/dialogs/autodraws/onionfield.js b/src/code/dialogs/autodraws/onionfield.js index 42f739b71..3571adaf2 100644 --- a/src/code/dialogs/autodraws/onionfield.js +++ b/src/code/dialogs/autodraws/onionfield.js @@ -5,6 +5,7 @@ import { greatCircleArcIntersect } from "../../crosslinks"; import WasabeeLink from "../../model/link"; import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; +import { displayError } from "../../error"; const OnionfieldDialog = AutoDraw.extend({ statics: { @@ -65,7 +66,7 @@ const OnionfieldDialog = AutoDraw.extend({ // this._operation is OK here this._operation = getSelectedOperation(); if (!this._anchor) { - alert("no anchor selected"); + displayError("no anchor selected"); return; } this._colors = [ diff --git a/src/code/dialogs/autodraws/saveLinks.js b/src/code/dialogs/autodraws/saveLinks.js index bad5da83b..c1d9a0455 100644 --- a/src/code/dialogs/autodraws/saveLinks.js +++ b/src/code/dialogs/autodraws/saveLinks.js @@ -3,6 +3,7 @@ import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { clearAllLinks, getAllPortalsLinked } from "../../uiCommands"; import wX from "../../wX"; +import { displayError } from "../../error"; const SaveLinksDialog = AutoDraw.extend({ statics: { @@ -61,7 +62,7 @@ const SaveLinksDialog = AutoDraw.extend({ saveLinks: function () { if (!this._anchor) { - alert("Select an anchor portal"); + displayError("Select an anchor portal"); return; } diff --git a/src/code/dialogs/autodraws/starburst.js b/src/code/dialogs/autodraws/starburst.js index 503e7d0ab..29033fe80 100644 --- a/src/code/dialogs/autodraws/starburst.js +++ b/src/code/dialogs/autodraws/starburst.js @@ -3,6 +3,7 @@ import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; +import { displayError } from "../../error"; const StarburstDialog = AutoDraw.extend({ statics: { @@ -64,7 +65,7 @@ const StarburstDialog = AutoDraw.extend({ starburst: function () { if (!this._anchor) { - alert("Select an anchor portal"); + displayError("Select an anchor portal"); return; } diff --git a/src/code/dialogs/autodraws/tools.js b/src/code/dialogs/autodraws/tools.js index 2460798c2..ae6594a7c 100644 --- a/src/code/dialogs/autodraws/tools.js +++ b/src/code/dialogs/autodraws/tools.js @@ -5,6 +5,7 @@ import wX from "../../wX"; import { getAllPortalsOnScreen } from "../../uiCommands"; import PortalUI from "../../ui/portal"; +import { displayError } from "../../error"; // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX @@ -116,7 +117,7 @@ export const AutoDraw = WDialog.extend({ ); } else { display.textContent = wX("NOT_SET"); - alert(wX("PLEASE_SELECT_PORTAL")); + displayError(wX("PLEASE_SELECT_PORTAL")); } }); }, diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 507694a87..19a943dcf 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -19,6 +19,7 @@ import wX from "../wX"; import PortalUI from "../ui/portal"; import LinkUI from "../ui/link"; +import { displayInfo, displayWarning } from "../error"; const OperationChecklistDialog = WDialog.extend({ statics: { @@ -365,9 +366,9 @@ const OperationChecklistDialog = WDialog.extend({ li.textContent = c; li.appendChild(LinkUI.displayFormat(link, operation)); } - alert(container, true); + displayWarning(container, true); } else { - alert(`Found ${fieldCount} fields and no empty fields.`); + displayInfo(`Found ${fieldCount} fields and no empty fields.`); } } return { field: fieldCount, empty: emptyCount }; diff --git a/src/code/dialogs/defensiveKeysDialog.js b/src/code/dialogs/defensiveKeysDialog.js index bd2680e3d..0ad3fddee 100644 --- a/src/code/dialogs/defensiveKeysDialog.js +++ b/src/code/dialogs/defensiveKeysDialog.js @@ -6,6 +6,7 @@ import WasabeeDList from "./wasabeeDlist"; import { getAgentPortalWasabeeDkeys } from "../wd"; import PortalUI from "../ui/portal"; +import { displayError, displayInfo } from "../error"; const DefensiveKeysDialog = WDialog.extend({ statics: { @@ -112,11 +113,11 @@ const DefensiveKeysDialog = WDialog.extend({ const j = JSON.stringify(dk); console.log(j); await dKeyPromise(j); - alert("Registered with server"); + displayInfo("Registered with server"); window.map.fire("wasabee:defensivekeys"); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } }, }); diff --git a/src/code/dialogs/importDialog.js b/src/code/dialogs/importDialog.js index 3b3ee1bd9..5334467fb 100644 --- a/src/code/dialogs/importDialog.js +++ b/src/code/dialogs/importDialog.js @@ -6,6 +6,7 @@ import wX from "../wX"; import { makeSelectedOperation } from "../selectedOp"; import PromptDialog from "./promptDialog"; import { zoomToOperation } from "../uiCommands"; +import { displayError, displayInfo } from "../error"; const ImportDialog = WDialog.extend({ statics: { @@ -91,7 +92,7 @@ const ImportDialog = WDialog.extend({ const rq = await fetch(url, { mode: "cors" }); this._textarea.value = await rq.text(); } catch (e) { - alert("Unable to fetch data from the given url."); + displayError("Unable to fetch data from the given url."); return; } }, @@ -106,7 +107,7 @@ const ImportDialog = WDialog.extend({ new RegExp("^(https?://)?(www\\.)?intel.ingress.com/intel.*") ) ) { - alert(wX("NO_STOCK_INTEL")); + displayError(wX("NO_STOCK_INTEL")); return; } @@ -143,7 +144,7 @@ const ImportDialog = WDialog.extend({ const importedOp = new WasabeeOp(data); const localOp = await WasabeeOp.load(importedOp.ID); if (localOp) { - alert( + displayError( wX("IMP_NOPE", { error: "op already exists, either delete it or duplicate", }) @@ -152,11 +153,11 @@ const ImportDialog = WDialog.extend({ } else { await importedOp.store(); await makeSelectedOperation(importedOp.ID); - alert(wX("IMPORT_OP_SUCCESS", { opName: importedOp.name })); + displayInfo(wX("IMPORT_OP_SUCCESS", { opName: importedOp.name })); } } catch (e) { console.error("WasabeeTools: failed to import data", e); - alert(wX("IMP_NOPE", { error: "data invalid" })); + displayError(wX("IMP_NOPE", { error: "data invalid" })); } }, @@ -174,7 +175,7 @@ const ImportDialog = WDialog.extend({ data = JSON.parse(string); } catch (e) { console.error("Failed parseDrawTools", e); - alert(e.toString()); + displayError(e); return null; } @@ -224,7 +225,7 @@ const ImportDialog = WDialog.extend({ newop.addLink(prev, first); } } - alert( + displayInfo( wX("IMP_COMP") + found + wX("PORT_FAKE") + faked + wX("USE_SWAP_INSTRUCT") ); diff --git a/src/code/dialogs/linkDialog.js b/src/code/dialogs/linkDialog.js index 076d5113d..72e3b1710 100644 --- a/src/code/dialogs/linkDialog.js +++ b/src/code/dialogs/linkDialog.js @@ -4,6 +4,7 @@ import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; import PortalUI from "../ui/portal"; +import { displayError } from "../error"; const LinkDialog = WDialog.extend({ statics: { @@ -56,7 +57,7 @@ const LinkDialog = WDialog.extend({ PortalUI.displayFormat(this._source, this._smallScreen) ); } else { - alert(wX("PLEASE_SELECT_PORTAL")); + displayError(wX("PLEASE_SELECT_PORTAL")); } }); @@ -83,7 +84,7 @@ const LinkDialog = WDialog.extend({ PortalUI.displayFormat(this._anchor1, this._smallScreen) ); } else { - alert(wX("PLEASE_SELECT_PORTAL")); + displayError(wX("PLEASE_SELECT_PORTAL")); } }); const anchor1AddButton = L.DomUtil.create("button", "add", container); @@ -97,7 +98,7 @@ const LinkDialog = WDialog.extend({ order: operation.nextOrder, }); } else { - alert("Select both Source and Anchor 1"); + displayError("Select both Source and Anchor 1"); } }); @@ -124,7 +125,7 @@ const LinkDialog = WDialog.extend({ PortalUI.displayFormat(this._anchor2, this._smallScreen) ); } else { - alert(wX("PLEASE_SELECT_PORTAL")); + displayError(wX("PLEASE_SELECT_PORTAL")); } }); const anchor2AddButton = L.DomUtil.create("button", "add", container); @@ -138,7 +139,7 @@ const LinkDialog = WDialog.extend({ order: operation.nextOrder, }); } else { - alert(wX("SEL_SRC_ANC2")); + displayError(wX("SEL_SRC_ANC2")); } }); @@ -147,7 +148,7 @@ const LinkDialog = WDialog.extend({ button.textContent = wX("ADD_BUTTON_LINKS"); L.DomEvent.on(button, "click", (ev) => { L.DomEvent.stop(ev); - if (!this._source) alert(wX("SEL_SRC_PORT")); + if (!this._source) displayError(wX("SEL_SRC_PORT")); const operation = getSelectedOperation(); if (this._anchor1) { operation.addLink(this._source, this._anchor1, { diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index c26301122..189e386f3 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -18,6 +18,7 @@ import wX from "../wX"; import ConfirmDialog from "./confirmDialog"; import AgentUI from "../ui/agent"; +import { displayError, displayInfo } from "../error"; // The update method here is the best so far, bring all the others up to this one const ManageTeamDialog = WDialog.extend({ @@ -78,15 +79,15 @@ const ManageTeamDialog = WDialog.extend({ this.options.team.ID, squadDialog.inputField.value ); - alert( + displayInfo( `squad updated to ${squadDialog.inputField.value} for ${obj.name}` ); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } } else { - alert(wX("INPUT_SQUAD_NAME")); + displayInfo(wX("INPUT_SQUAD_NAME")); } this.update(); }, @@ -169,11 +170,11 @@ const ManageTeamDialog = WDialog.extend({ L.DomEvent.stop(ev); try { await addAgentToTeamPromise(addField.value, this.options.team.ID); - alert(wX("ADD_SUCC_INSTR")); + displayInfo(wX("ADD_SUCC_INSTR")); window.map.fire("wasabee:team:update"); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } }); @@ -188,12 +189,12 @@ const ManageTeamDialog = WDialog.extend({ L.DomEvent.stop(ev); try { await renameTeamPromise(this.options.team.ID, renameField.value); - alert(`renamed to ${renameField.value}`); + displayInfo(`renamed to ${renameField.value}`); this.options.team.Name = renameField.value; // for display window.map.fire("wasabee:team:update"); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } }); @@ -219,13 +220,13 @@ const ManageTeamDialog = WDialog.extend({ rockscommField.value, rocksapiField.value ); - alert("updated rocks info"); + displayInfo("updated rocks info"); this.options.team.RocksComm = rockscommField.value; // for display this.options.team.RocksKey = rocksapiField.value; // for display this.update(); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } }); @@ -274,12 +275,12 @@ const ManageTeamDialog = WDialog.extend({ callback: async () => { try { await deleteTeamPromise(this.options.team.ID); - alert(`${this.options.team.Name} removed`); + displayInfo(`${this.options.team.Name} removed`); this.closeDialog(); await WasabeeMe.waitGet(true); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } window.map.fire("wasabee:teams"); }, diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index 25dc3375b..247b82959 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -7,6 +7,7 @@ import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; import PortalUI from "../ui/portal"; +import { displayError } from "../error"; const MarkerAddDialog = WDialog.extend({ statics: { @@ -154,7 +155,7 @@ const MarkerAddDialog = WDialog.extend({ if (WasabeeMarker.isDestructMarkerType(selectedType)) WasabeeBlocker.removeBlocker(operation, PortalUI.getSelected().id); await this.update(); - } else alert(wX("ALREADY_HAS_MARKER")); + } else displayError(wX("ALREADY_HAS_MARKER")); localStorage[window.plugin.wasabee.static.constants.LAST_MARKER_KEY] = selectedType; }, diff --git a/src/code/dialogs/newopDialog.js b/src/code/dialogs/newopDialog.js index ea63c77aa..956dcc854 100644 --- a/src/code/dialogs/newopDialog.js +++ b/src/code/dialogs/newopDialog.js @@ -4,6 +4,7 @@ import ImportDialog from "./importDialog"; import PromptDialog from "./promptDialog"; import { makeSelectedOperation } from "../selectedOp"; import wX from "../wX"; +import { displayError } from "../error"; const NewopDialog = WDialog.extend({ statics: { @@ -45,7 +46,7 @@ const NewopDialog = WDialog.extend({ await newop.store(); await makeSelectedOperation(newop.ID); } else { - alert(wX("OP_NAME_UNSET")); + displayError(wX("OP_NAME_UNSET")); } }, placeholder: wX("MUST_NOT_BE_EMPTY"), diff --git a/src/code/dialogs/opPerms.js b/src/code/dialogs/opPerms.js index 83e5bb4e5..2e0427e6a 100644 --- a/src/code/dialogs/opPerms.js +++ b/src/code/dialogs/opPerms.js @@ -5,6 +5,7 @@ import WasabeeTeam from "../model/team"; import WasabeeMe from "../model/me"; import { addPermPromise, delPermPromise } from "../server"; import wX from "../wX"; +import { displayError } from "../error"; const OpPermList = WDialog.extend({ statics: { @@ -175,7 +176,7 @@ const OpPermList = WDialog.extend({ addPerm: async function (teamID, role, zone) { if (!WasabeeMe.isLoggedIn()) { - alert(wX("NOT LOGGED IN SHORT")); + displayError(wX("NOT LOGGED IN SHORT")); return; } const operation = getSelectedOperation(); @@ -196,13 +197,13 @@ const OpPermList = WDialog.extend({ window.map.fire("wasabee:op:change"); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } }, delPerm: async function (obj) { if (!WasabeeMe.isLoggedIn()) { - alert(wX("NOT LOGGED IN SHORT")); + displayError(wX("NOT LOGGED IN SHORT")); return; } const operation = getSelectedOperation(); @@ -220,7 +221,7 @@ const OpPermList = WDialog.extend({ window.map.fire("wasabee:op:change"); } catch (e) { console.error(e); - alert(e); + displayError(e); } }, }); diff --git a/src/code/dialogs/opSettings.js b/src/code/dialogs/opSettings.js index 7b3e2fe11..b65dfb5ec 100644 --- a/src/code/dialogs/opSettings.js +++ b/src/code/dialogs/opSettings.js @@ -16,6 +16,7 @@ import { addToColorList } from "../skin"; import WasabeeMe from "../model/me"; import { convertColorToHex } from "../auxiliar"; +import { displayError } from "../error"; const OpSettingDialog = WDialog.extend({ statics: { @@ -75,7 +76,7 @@ const OpSettingDialog = WDialog.extend({ L.DomEvent.on(input, "change", async (ev) => { L.DomEvent.stop(ev); if (!input.value || input.value == "") { - alert(wX("USE_VALID_NAME")); + displayError(wX("USE_VALID_NAME")); } else { const so = getSelectedOperation(); so.name = input.value; @@ -144,7 +145,7 @@ const OpSettingDialog = WDialog.extend({ window.map.fire("wasabee:op:change"); } catch (e) { console.log(e); - alert("Invalid date format"); + displayError("Invalid date format"); } }); } else { @@ -202,7 +203,7 @@ const OpSettingDialog = WDialog.extend({ console.log("delete from server successful"); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } } await removeOperation(so.ID); diff --git a/src/code/dialogs/sendTargetDialog.js b/src/code/dialogs/sendTargetDialog.js index 606555c07..65068f597 100644 --- a/src/code/dialogs/sendTargetDialog.js +++ b/src/code/dialogs/sendTargetDialog.js @@ -8,6 +8,7 @@ import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; import PortalUI from "../ui/portal"; +import { displayError, displayInfo } from "../error"; const SendTargetDialog = WDialog.extend({ statics: { @@ -130,10 +131,10 @@ const SendTargetDialog = WDialog.extend({ } targetPromise(this._value, this._portal, this._targettype) .then(() => { - alert(wX("TARGET SENT")); + displayInfo(wX("TARGET SENT")); this.closeDialog(); }) - .catch((e) => alert(e)); + .catch((e) => displayError(e)); }, }); diff --git a/src/code/dialogs/teamListDialog.js b/src/code/dialogs/teamListDialog.js index e43e5a3eb..12319bd73 100644 --- a/src/code/dialogs/teamListDialog.js +++ b/src/code/dialogs/teamListDialog.js @@ -13,6 +13,7 @@ import TeamMembershipList from "./teamMembershipList"; import ConfirmDialog from "./confirmDialog"; import ManageTeamDialog from "./manageTeamDialog"; import wX from "../wX"; +import { displayError, displayInfo } from "../error"; const TeamListDialog = WDialog.extend({ statics: { @@ -169,16 +170,16 @@ const TeamListDialog = WDialog.extend({ callback: async () => { const newname = p.inputField.value; if (!newname) { - alert(wX("NAME_REQ")); + displayError(wX("NAME_REQ")); return; } try { await newTeamPromise(newname); - alert(wX("TEAM_CREATED", { teamName: newname })); + displayInfo(wX("TEAM_CREATED", { teamName: newname })); this._me = await WasabeeMe.waitGet(true); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } window.map.fire("wasabee:teams"); }, @@ -206,7 +207,7 @@ const TeamListDialog = WDialog.extend({ this._me = await WasabeeMe.waitGet(true); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } return newState; }, @@ -219,7 +220,7 @@ const TeamListDialog = WDialog.extend({ await WasabeeMe.waitGet(true); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } return newState; }, @@ -232,7 +233,7 @@ const TeamListDialog = WDialog.extend({ await WasabeeMe.waitGet(true); } catch (e) { console.error(e); - alert(e.toString()); + displayError(e); } return newState; }, diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index 69aa80628..59c37a01a 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -4,6 +4,7 @@ import WasabeeTeam from "../model/team"; import wX from "../wX"; import AgentUI from "../ui/agent"; +import { displayError } from "../error"; const TeamMembershipList = WDialog.extend({ statics: { @@ -19,7 +20,7 @@ const TeamMembershipList = WDialog.extend({ window.map.on("wasabee:logout", this.closeDialog, this); this._displayDialog().catch((e) => { console.error(e); - alert(e.toString()); + displayError(e); }); }, diff --git a/src/code/dialogs/trawl.js b/src/code/dialogs/trawl.js index 187a3c0bc..cafe9ecc7 100644 --- a/src/code/dialogs/trawl.js +++ b/src/code/dialogs/trawl.js @@ -5,6 +5,7 @@ import { blockerAutomark } from "../uiCommands"; import VLatLon from "geodesy/latlon-ellipsoidal-vincenty"; import WasabeeMarker from "../model/marker"; import WasabeeBlocker from "../model/blocker"; +import { displayInfo } from "../error"; const TrawlerDialog = WDialog.extend({ statics: { @@ -187,7 +188,7 @@ const TrawlerDialog = WDialog.extend({ window.removeHook("mapDataRefreshEnd", this._mapRefreshHook); if (this.options.automark) blockerAutomark(getSelectedOperation()); this.closeDialog(); - alert("trawl done"); + displayInfo("trawl done"); }, }); @@ -364,7 +365,7 @@ const TrawlDialog = WDialog.extend({ // render the results mdr.pauseRenderQueue(false); - this.bulkAlert = alert( + this.bulkAlert = displayInfo( "please wait until status says 'done'; If the first didn't trigger a load, close this dialog and try again" ); }, @@ -373,7 +374,7 @@ const TrawlDialog = WDialog.extend({ if (this.automark.checked == true) blockerAutomark(getSelectedOperation()); window.mapDataRequest.debugTiles = this.oldDebugTiles; this.bulkAlert.dialog("close"); - alert("bulk data load done"); + displayInfo("bulk data load done"); window.removeHook("mapDataRefreshEnd", this._mapRefreshHook); }, }); diff --git a/src/code/error.ts b/src/code/error.ts index 548eb9c15..2a6ecc632 100644 --- a/src/code/error.ts +++ b/src/code/error.ts @@ -6,6 +6,29 @@ interface IServerError { error?: string; } +export function displayInfo(content: string | HTMLElement, isHTML?: boolean) { + return window.dialog({ + title: 'Wasabee info', + text: isHTML ? null : content.toString(), + html: isHTML ? content : null, + }) +} + +export function displayWarning(content: string | HTMLElement, isHTML?: boolean) { + return window.dialog({ + title: 'Wasabee warning', + text: isHTML ? null : content.toString(), + html: isHTML ? content : null, + }) +} + +export function displayError(err: { toString(): string }) { + return window.dialog({ + title: 'Wasabee error', + text: err.toString(), + }) +} + // no stacktrace error export class ServerError implements IServerError { code: number; diff --git a/src/code/firebaseSupport.js b/src/code/firebaseSupport.js index 0f683235e..6812ef0e7 100644 --- a/src/code/firebaseSupport.js +++ b/src/code/firebaseSupport.js @@ -17,6 +17,7 @@ import WasabeeOp from "./model/operation"; import WasabeePortal from "./model/portal"; import PortalUI from "./ui/portal"; +import { displayInfo } from "./error"; // TODO: use a dedicated message channel: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging @@ -110,7 +111,7 @@ export function initFirebase() { }; const portal = new WasabeePortal(raw); const f = PortalUI.displayFormat(portal); - alert(f.outerHTML + "
Sent by: " + target.Sender, true); + displayInfo(f.outerHTML + "
Sent by: " + target.Sender, true); } catch (e) { console.error(e); } diff --git a/src/code/init.js b/src/code/init.js index 59abef6b4..84a1c54c2 100644 --- a/src/code/init.js +++ b/src/code/init.js @@ -20,6 +20,7 @@ import WasabeeMe from "./model/me"; import WasabeeOp from "./model/operation"; import db from "./db"; import polyfill from "./polyfill"; +import { displayError } from "./error"; const Wasabee = window.plugin.wasabee; Wasabee.static = statics; @@ -36,7 +37,7 @@ window.plugin.wasabee.init = async () => { window.iitcBuildDate == undefined || window.iitcBuildDate < "2020-01-18-170317" ) { - alert( + displayError( "Wasabee won't work on this version of IITC; please update to 0.30.1 or newer from https://iitc.app. On desktop, do not use the IITC button, use the TamperMonkey/GreaseMonkey method." ); return; @@ -45,7 +46,7 @@ window.plugin.wasabee.init = async () => { try { Wasabee.idb = await db; } catch (e) { - alert("Wasabee: unable to access the storage: " + e.toString()); + displayError("Wasabee: unable to access the storage: " + e.toString()); plugin_info.error = e; //eslint-disable-line return; } @@ -227,7 +228,7 @@ window.plugin.wasabee.init = async () => { // and use webpack, rather than importing it ourself function initGoogleAPI() { if (typeof window.gapi !== "undefined") { - alert( + displayError( "Wasabee detected another GAPI instance; there may be authentication issues" ); window.gapi.load("auth2", () => { diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 9b0353f44..13bd28dbb 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -12,6 +12,7 @@ import db from "../db"; // 0.20->0.21 blocker migration import WasabeeBlocker from "./blocker"; import type Task from "./task"; +import { displayWarning } from "../error"; export type KeyOnHand = { portalId: string; @@ -607,7 +608,7 @@ export default class WasabeeOp extends Evented implements IOperation { if (missingPortal.size > 0) { // leave some trace console.trace("op corruption: missing portals"); - alert( + displayWarning( `Oops, something went wrong and OP ${this.name} got corrupted. Fix by removing ${missingPortal.size} missing portals and ${corrupt} links/markers. Please check your OP and report to the devs.` ); this.cleanAnchorList(); diff --git a/src/code/selectedOp.js b/src/code/selectedOp.js index e55873171..447eed460 100644 --- a/src/code/selectedOp.js +++ b/src/code/selectedOp.js @@ -2,6 +2,7 @@ import WasabeeOp from "./model/operation"; import WasabeeBlocker from "./model/blocker"; import wX from "./wX"; import { generateId } from "./auxiliar"; +import { displayError } from "./error"; function setRestoreOpID(opID) { localStorage[window.plugin.wasabee.static.constants.SELECTED_OP_KEY] = opID; @@ -80,7 +81,7 @@ export async function makeSelectedOperation(opID) { const op = await WasabeeOp.load(opID); if (op == null) { console.log("makeSelectedOperation called on invalid opID"); - alert("attempted to load invalid opID"); + displayError("attempted to load invalid opID"); return; } diff --git a/src/code/toolbox.js b/src/code/toolbox.js index a19ac9f82..4709763b5 100644 --- a/src/code/toolbox.js +++ b/src/code/toolbox.js @@ -3,6 +3,7 @@ import SettingsDialog from "./dialogs/settingsDialog"; import OnlineAgentList from "./dialogs/onlineAgentList"; import wX from "./wX"; import { locationPromise } from "./server"; +import { displayInfo } from "./error"; /* This function adds the Wasabee options to the IITC toolbox */ export function setupToolbox() { @@ -38,7 +39,7 @@ export function setupToolbox() { position.coords.latitude, position.coords.longitude ); - alert(wX("LOC_PROC")); + displayInfo(wX("LOC_PROC")); } catch (e) { console.error(e); } diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index a9491e0e2..8322836ba 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -6,6 +6,7 @@ import { getSelectedOperation } from "../selectedOp"; import wX from "../wX"; import WasabeeAgent from "../model/agent"; +import { displayInfo, displayWarning } from "../error"; function formatDisplay(agent) { const display = L.DomUtil.create("a", "wasabee-agent-label"); @@ -197,7 +198,7 @@ const WLAgent = L.Marker.extend({ L.DomEvent.stop(ev); const selectedPortal = PortalUI.getSelected(); if (!selectedPortal) { - alert(wX("SELECT PORTAL")); + displayWarning(wX("SELECT PORTAL")); return; } @@ -211,7 +212,7 @@ const WLAgent = L.Marker.extend({ callback: async () => { try { await targetPromise(agent.id, selectedPortal); - alert(wX("TARGET SENT")); + displayInfo(wX("TARGET SENT")); } catch (e) { console.error(e); } diff --git a/src/code/uiCommands.js b/src/code/uiCommands.js index 08e415763..288e438c2 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.js @@ -18,11 +18,16 @@ import { } from "./selectedOp"; import PortalUI from "./ui/portal"; -import { ServerError } from "./error"; +import { + displayError, + displayInfo, + displayWarning, + ServerError, +} from "./error"; export function addPortal(operation, portal) { if (!portal) { - alert(wX("SELECT PORTAL")); + displayError(wX("SELECT PORTAL")); return; } operation.addPortal(portal); @@ -31,11 +36,11 @@ export function addPortal(operation, portal) { export function swapPortal(operation, portal) { const selectedPortal = PortalUI.getSelected(); if (!selectedPortal) { - alert(wX("SELECT PORTAL")); + displayError(wX("SELECT PORTAL")); return; } if (portal.id === selectedPortal.id) { - alert(wX("SELF SWAP")); + displayError(wX("SELF SWAP")); return; } @@ -404,7 +409,7 @@ export async function blockerAutomark(operation, first = true) { let wportal = operation.getPortal(portalId); if (!wportal) wportal = PortalUI.get(portalId); if (!wportal) { - alert(wX("AUTOMARK STOP")); + displayInfo(wX("AUTOMARK STOP")); return; } // console.log(wportal); @@ -532,11 +537,11 @@ export async function fullSync() { window.map.fire("wasabee:fullsync"); window.map.fire("wasabee:teams"); // if any team dialogs are open - alert(wX("SYNC DONE")); + displayInfo(wX("SYNC DONE")); } catch (e) { console.error(e); - if (e instanceof ServerError) alert(e.toString()); - if (WasabeeMe.isLoggedIn()) alert(wX("NOT_LOADED")); + if (e instanceof ServerError) displayError(e); + if (WasabeeMe.isLoggedIn()) displayWarning(wX("NOT_LOADED")); else new AuthDialog().enable(); } } diff --git a/src/code/wX.ts b/src/code/wX.ts index a784dedb2..1aea8ac57 100644 --- a/src/code/wX.ts +++ b/src/code/wX.ts @@ -13,7 +13,7 @@ export function wX(key: string, data?: object) { if (window.plugin.wasabee.skin && window.plugin.wasabee.skin.strings) strings = window.plugin.wasabee.skin.strings; - let s = null; + let s: string = null; if (strings[lang] && strings[lang][key]) s = strings[lang][key]; if (!s && strings[defaultLang] && strings[defaultLang][key]) s = strings[defaultLang][key]; From 5704aa0bbaad100f095c433308df2e6bf246268b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 09:09:27 +0100 Subject: [PATCH 099/275] rename agent fields --- src/code/dialogs/manageTeamDialog.js | 4 +- src/code/dialogs/teamMembershipList.js | 6 +- src/code/model/agent.ts | 160 +++++++++++++++++-------- tsconfig.json | 3 +- 4 files changed, 115 insertions(+), 58 deletions(-) diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 189e386f3..5f3b0174f 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -55,13 +55,13 @@ const ManageTeamDialog = WDialog.extend({ }, { name: wX("TEAM STATE"), - value: (agent) => agent.state, + value: (agent) => agent.shareLocation, sort: (a, b) => a && !b, // , format: (cell, value) => (cell.textContent = value) }, { name: wX("SQUAD"), - value: (agent) => agent.squad, + value: (agent) => agent.comment, sort: (a, b) => a.localeCompare(b), format: (cell, value, obj) => { const button = L.DomUtil.create("a", null, cell); diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index 59c37a01a..8413946e6 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -61,13 +61,13 @@ const TeamMembershipList = WDialog.extend({ }, { name: wX("SQUAD"), - value: (agent) => agent.squad, + value: (agent) => agent.comment, sort: (a, b) => a.localeCompare(b), // , format: (cell, value) => (cell.textContent = value) }, { name: "Sharing Location", - value: (agent) => agent.state, + value: (agent) => agent.shareLocation, sort: (a, b) => a.localeCompare(b), format: (cell, value) => { if (value) cell.textContent = "✅"; @@ -75,7 +75,7 @@ const TeamMembershipList = WDialog.extend({ }, { name: "Sharing W-D Keys", - value: (agent) => agent.ShareWD, + value: (agent) => agent.shareWDKeys, sort: (a, b) => a.localeCompare(b), format: (cell, value) => { if (value) cell.textContent = "✅"; diff --git a/src/code/model/agent.ts b/src/code/model/agent.ts index dadf032fd..9fa2e5831 100644 --- a/src/code/model/agent.ts +++ b/src/code/model/agent.ts @@ -1,59 +1,129 @@ import { agentPromise } from "../server"; import WasabeeMe from "./me"; -import WasabeeTeam from "./team"; import db from "../db"; - -export default class WasabeeAgent { - id: string; +interface BaseAgent { + id: GoogleID; name: string; - vname: string; - rocksname: string; - intelname: string; - intelfaction: string; - level: number; - enlid: string; - pic: string; + intelname?: string; + intelfaction: "unset" | "ENLIGHTENED" | "RESISTANCE"; + pic?: string; + lat: number; + lng: number; + date: string; +} + +interface RockAgent extends BaseAgent { + rocksname?: string; + rocks: boolean; +} + +interface VAgent extends BaseAgent { + enlid?: string; + vname?: string; Vverified: boolean; + level: number; blacklisted: boolean; - rocks: boolean; +} + +interface ServerTeamAgent extends BaseAgent { + shareWD?: boolean; + loadWD?: boolean; + state?: boolean; + squad?: string; +} + +export interface ServerAgent + extends BaseAgent, + RockAgent, + VAgent, + ServerTeamAgent {} + +// local model +interface TeamAgent extends BaseAgent { + shareWDKeys?: boolean; + loadWDKeys?: boolean; + shareLocation?: boolean; + comment?: string; +} + +interface Agent extends BaseAgent, RockAgent, VAgent, TeamAgent { + fetched?: number; +} + +// convert agent in server model to client model +function serverAgentToAgent(agent: ServerAgent) { + return { + ...agent, + shareWDKeys: agent.shareWD, + loadWDKeys: agent.loadWD, + shareLocation: agent.state, + comment: agent.squad, + }; +} + +export default class WasabeeAgent implements Agent { + id: GoogleID; + name: string; + pic?: string; lat: number; lng: number; date: string; - ShareWD?: boolean; - LoadWD?: boolean; - squad?: string; - state?: boolean; + // intel + intelname?: string; + intelfaction: "unset" | "ENLIGHTENED" | "RESISTANCE"; + + // V + enlid?: string; + vname?: string; + Vverified: boolean; + level: number; + blacklisted: boolean; + + // rocks + rocksname?: string; + rocks: boolean; + + // per team data + shareWDKeys?: boolean; + loadWDKeys?: boolean; + shareLocation?: boolean; + comment?: string; fetched: number; - constructor(obj) { + constructor(obj: Agent) { if (typeof obj == "string") { - console.trace('agent waits for an object'); - obj = { - id: "00000", - name: 'invalid agent', - }; + console.trace("agent waits for an object"); + return null; } + // if ServerAgent + if ("shareWD" in obj || "squad" in obj) obj = serverAgentToAgent(obj); // console.debug("passed to constructor", obj); // things which are stable across all teams this.id = obj.id; this.name = obj.name; - this.vname = obj.vname; - this.rocksname = obj.rocksname; - this.intelname = obj.intelname !== "unset" ? obj.intelname : null; + this.intelname = obj.intelname !== "unset" ? obj.intelname : ""; this.intelfaction = obj.intelfaction; - this.level = obj.level ? Number(obj.level) : 0; - this.enlid = obj.enlid ? obj.enlid : null; this.pic = obj.pic ? obj.pic : null; - this.Vverified = !!obj.Vverified; - this.blacklisted = !!obj.blacklisted; - this.rocks = !!obj.rocks; this.lat = obj.lat ? obj.lat : 0; this.lng = obj.lng ? obj.lng : 0; this.date = obj.date ? obj.date : null; // last location sub, not fetched + // V + this.enlid = obj.enlid ? obj.enlid : null; + this.vname = obj.vname; + this.Vverified = !!obj.Vverified; + this.level = obj.level ? Number(obj.level) : 0; + this.blacklisted = !!obj.blacklisted; + // rocks + this.rocksname = obj.rocksname; + this.rocks = !!obj.rocks; + + if (this.Vverified) this.name = this.vname || this.name; + else if (this.rocks) this.name = this.rocksname || this.name; + else if (this.intelname) this.name = this.intelname + " [!]"; /* what did we decide to do with these? this.startlat = obj.startlat ? obj.startlat : 0; @@ -62,10 +132,10 @@ export default class WasabeeAgent { this.sharestart = obj.sharestart ? obj.sharestart : false; */ // vary per-team, don't set on direct pulls - if (obj.ShareWD) this.ShareWD = obj.ShareWD; - if (obj.LoadWD) this.LoadWD = obj.LoadWD; - if (obj.squad) this.squad = obj.squad; - if (obj.state) this.state = obj.state; + if (obj.shareWDKeys) this.shareWDKeys = obj.shareWDKeys; + if (obj.loadWDKeys) this.loadWDKeys = obj.loadWDKeys; + if (obj.shareLocation) this.shareLocation = obj.shareLocation; + if (obj.comment) this.comment = obj.comment; // this.distance = obj.distance ? Number(obj.distance) : 0; // don't use this // not sent by server, but preserve if from cache @@ -83,20 +153,6 @@ export default class WasabeeAgent { return this.name; } - // deprecated - async getTeamName(teamID = 0) { - if (teamID == 0) return this.name; - - const team = await WasabeeTeam.get(teamID); - if (team == null) return this.name; - // XXX is there a cute team.agents.filter() we can use here? - for (const a of team.agents) { - if (a.id == this.id) return a.name; - } - - return this.name; - } - async _updateCache() { // load anything currently cached const cached = await (await db).get("agents", this.id); @@ -140,10 +196,10 @@ export default class WasabeeAgent { // cansendto is never true from a team pull, but might be true from a direct pull // remove things which make no sense in the global cache - delete cached.ShareWD; - delete cached.LoadWD; - delete cached.squad; - delete cached.state; + delete cached.shareWDKeys; + delete cached.loadWDKeys; + delete cached.comment; + delete cached.shareLocation; try { await (await db).put("agents", cached); diff --git a/tsconfig.json b/tsconfig.json index 1c2aae52a..27ebd6618 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,8 @@ "downlevelIteration": true, "allowJs": true, "checkJs": false, - "allowUmdGlobalAccess": true + "allowUmdGlobalAccess": true, + "noUnusedLocals": true }, "include": [ "src/**/*" From 8a7e3337fad7ca08263c3a4ba909f54630750ce1 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 09:17:19 +0100 Subject: [PATCH 100/275] team.ts to use agent.ts --- src/code/dialogs/assignDialog.js | 3 +- src/code/dialogs/manageTeamDialog.js | 2 +- src/code/dialogs/markerAddDialog.js | 3 +- src/code/dialogs/sendTargetDialog.js | 3 +- src/code/dialogs/teamMembershipList.js | 2 +- src/code/mapDrawing.js | 3 +- src/code/model/team.ts | 73 +++++++++++++++++--------- 7 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index 7cd1bbb92..b532d3941 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -112,8 +112,7 @@ const AssignDialog = WDialog.extend({ try { // allow teams to be 5 minutes cached const tt = await WasabeeTeam.get(t.teamid, 5 * 60); - const agents = tt.getAgents(); - for (const a of agents) { + for (const a of tt.agents) { if (!alreadyAdded.includes(a.id)) { alreadyAdded.push(a.id); const option = L.DomUtil.create("option", "", select); diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 5f3b0174f..126bf943a 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -136,7 +136,7 @@ const ManageTeamDialog = WDialog.extend({ try { // max 5 seconds cache for this screen const teamdata = await WasabeeTeam.get(this.options.team.ID, 5); - const agents = teamdata.getAgents(); + const agents = teamdata.agents; if (agents && agents.length > 0) { table.items = agents; } diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index 247b82959..7772ddb3b 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -177,8 +177,7 @@ const MarkerAddDialog = WDialog.extend({ try { // allow teams to be 5 minutes cached const tt = await WasabeeTeam.get(t.teamid, 5 * 60); - const agents = tt.getAgents(); - for (const a of agents) { + for (const a of tt.agents) { if (!alreadyAdded.has(a.id)) { alreadyAdded.add(a.id); option = L.DomUtil.create("option"); diff --git a/src/code/dialogs/sendTargetDialog.js b/src/code/dialogs/sendTargetDialog.js index 65068f597..1138ac1f8 100644 --- a/src/code/dialogs/sendTargetDialog.js +++ b/src/code/dialogs/sendTargetDialog.js @@ -105,8 +105,7 @@ const SendTargetDialog = WDialog.extend({ try { // allow teams to be 5 minutes cached const tt = await WasabeeTeam.get(t.teamid, 5 * 60); - const agents = tt.getAgents(); - for (const a of agents) { + for (const a of tt.agents) { if (!alreadyAdded.includes(a.id)) { alreadyAdded.push(a.id); option = L.DomUtil.create("option"); diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index 8413946e6..e3dead71b 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -33,7 +33,7 @@ const TeamMembershipList = WDialog.extend({ const table = this._setupTable(); const team = await WasabeeTeam.get(this.options.teamID, 10); // max cache age of 10 seconds - table.items = team.getAgents(); + table.items = team.agents; const buttons = {}; buttons[wX("OK")] = () => { diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index 631993405..356464379 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -154,8 +154,7 @@ export async function drawSingleTeam(teamID, layerMap, alreadyDone) { // common case: team was enabled here, but was since disabled in another client and the pull returned an error if (team == null) return done; - const agents = team.getAgents(); - for (const agent of agents) { + for (const agent of team.agents) { if (!alreadyDone.includes(agent.id) && _drawAgent(agent, layerMap)) done.push(agent.id); } diff --git a/src/code/model/team.ts b/src/code/model/team.ts index 78583bfd3..88aed338f 100644 --- a/src/code/model/team.ts +++ b/src/code/model/team.ts @@ -1,51 +1,76 @@ -import WasabeeAgent from "./agent"; +import WasabeeAgent, { ServerAgent } from "./agent"; import WasabeeMe from "./me"; import { teamPromise } from "../server"; import db from "../db"; -export default class WasabeeTeam { - fetched: number; - id: string; - name: string; +interface RocksTeam { rc: string; rk: string; +} + +interface VTeam { + vt: string; + vr: string; +} + +interface ServerTeam extends RocksTeam, VTeam { + id: TeamID; + name: string; + agents: ServerAgent[]; + jlt: string; +} + +interface Team extends RocksTeam, VTeam { + id: TeamID; + name: string; + agents: WasabeeAgent[]; + jlt: string; + + fetched?: number; +} + +export default class WasabeeTeam implements Team { + id: TeamID; + name: string; + agents: WasabeeAgent[]; jlt: string; - agents: Array; + // Rocks + rc: string; + rk: string; + // V + vt: string; + vr: string; - _a: Array; + fetched: number; - constructor(data) { + constructor(data: Team | ServerTeam) { if (typeof data == "string") { console.trace("team waits for an object"); return; } let fromServer = false; - if (data.fetched == null) fromServer = true; - this.fetched = data.fetched ? data.fetched : Date.now(); + if ("fetched" in data) { + this.fetched = data.fetched; + } else { + this.fetched = Date.now(); + fromServer = true; + } this.id = data.id; this.name = data.name; this.rc = data.rc; this.rk = data.rk; this.jlt = data.jlt; - this.agents = data.agents; // raw agent data - - // this block (1) adds agent to agents cache and (2) populates _a - // _a is a buffer of pre-built WasabeeAgents we can return via getAgents() w/o having to await - this._a = new Array(); - for (const agent of data.agents) { - agent.fetched = this.fetched; - this._a.push(new WasabeeAgent(agent)); // add to agent cache - } + this.vt = data.vt; + this.vr = data.vr; + this.agents = data.agents.map( + (a) => new WasabeeAgent({ ...a, fetched: this.fetched }) + ); if (fromServer) this._updateCache(); } - getAgents() { - return this._a; - } - async _updateCache() { try { await (await db).put("teams", this); @@ -74,4 +99,4 @@ export default class WasabeeTeam { } return null; } -} \ No newline at end of file +} From e0633a5746fe7ed6a89d9d739bc6fa261aeb3433 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 20:42:13 +0100 Subject: [PATCH 101/275] me.ts rename fields --- src/code/dialogs/defensiveKeysDialog.js | 2 +- src/code/dialogs/keysList.js | 2 +- src/code/dialogs/teamListDialog.js | 37 ++++----- src/code/dialogs/wasabeeDlist.js | 2 +- src/code/model/me.ts | 99 +++++++++++-------------- src/code/model/operation.ts | 6 +- 6 files changed, 65 insertions(+), 83 deletions(-) diff --git a/src/code/dialogs/defensiveKeysDialog.js b/src/code/dialogs/defensiveKeysDialog.js index 0ad3fddee..4da4b6c3c 100644 --- a/src/code/dialogs/defensiveKeysDialog.js +++ b/src/code/dialogs/defensiveKeysDialog.js @@ -37,7 +37,7 @@ const DefensiveKeysDialog = WDialog.extend({ PortalUI.displayFormat(this._selectedPortal, this._smallScreen) ); const mine = await getAgentPortalWasabeeDkeys( - this._me.GoogleID, + this._me.id, this._selectedPortal.id ); if (mine) { diff --git a/src/code/dialogs/keysList.js b/src/code/dialogs/keysList.js index 9a5f28f3b..343022222 100644 --- a/src/code/dialogs/keysList.js +++ b/src/code/dialogs/keysList.js @@ -117,7 +117,7 @@ const KeysList = WDialog.extend({ let gid = "no-user"; if (this._me) { - gid = this._me.GoogleID; + gid = this._me.id; this.sortable.fields = always.concat([ { name: wX("MY_COUNT"), diff --git a/src/code/dialogs/teamListDialog.js b/src/code/dialogs/teamListDialog.js index 12319bd73..e79aeec1d 100644 --- a/src/code/dialogs/teamListDialog.js +++ b/src/code/dialogs/teamListDialog.js @@ -61,14 +61,12 @@ const TeamListDialog = WDialog.extend({ { name: wX("TEAM STATE"), value: (team) => team.State, - sort: (a, b) => a.localeCompare(b), format: (row, value, obj) => { const link = L.DomUtil.create("a", null, row); - let curstate = obj.State; - link.textContent = curstate; - if (curstate == "On") L.DomUtil.addClass(link, "enl"); + link.textContent = value ? "On" : "Off"; + if (value) L.DomUtil.addClass(link, "enl"); link.onclick = async () => { - await this.toggleTeam(obj.ID, curstate); + await this.toggleTeam(obj.ID, value); this.update(); }; }, @@ -76,14 +74,12 @@ const TeamListDialog = WDialog.extend({ { name: "Share W-D Keys", value: (team) => team.ShareWD, - sort: (a, b) => a.localeCompare(b), format: (row, value, obj) => { const link = L.DomUtil.create("a", null, row); - let curshare = obj.ShareWD; - link.textContent = curshare; - if (curshare == "On") L.DomUtil.addClass(link, "enl"); + link.textContent = value ? "On" : "Off"; + if (value) L.DomUtil.addClass(link, "enl"); link.onclick = async () => { - await this.toggleShareWD(obj.ID, curshare); + await this.toggleShareWD(obj.ID, value); this.update(); window.map.fire("wasabee:defensivekeys"); }; @@ -92,14 +88,12 @@ const TeamListDialog = WDialog.extend({ { name: "Load W-D Keys", value: (team) => team.LoadWD, - sort: (a, b) => a.localeCompare(b), format: (row, value, obj) => { const link = L.DomUtil.create("a", null, row); - let curload = obj.LoadWD; - link.textContent = curload; - if (curload == "On") L.DomUtil.addClass(link, "enl"); + link.textContent = value ? "On" : "Off"; + if (value) L.DomUtil.addClass(link, "enl"); link.onclick = async () => { - await this.toggleLoadWD(obj.ID, curload); + await this.toggleLoadWD(obj.ID, value); this.update(); window.map.fire("wasabee:defensivekeys"); }; @@ -107,12 +101,12 @@ const TeamListDialog = WDialog.extend({ }, { name: "", - value: (team) => team.State, + value: () => "", sort: null, format: (row, value, obj) => { const link = L.DomUtil.create("a", null, row); link.textContent = ""; - if (this._me.GoogleID != obj.Owner) { + if (this._me.id != obj.Owner) { link.textContent = wX("LEAVE"); L.DomEvent.on(link, "click", (ev) => { L.DomEvent.stop(ev); @@ -200,8 +194,7 @@ const TeamListDialog = WDialog.extend({ }, toggleTeam: async function (teamID, currentState) { - let newState = "Off"; - if (currentState == "Off") newState = "On"; + const newState = currentState ? "Off" : "On"; try { await SetTeamState(teamID, newState); this._me = await WasabeeMe.waitGet(true); @@ -213,8 +206,7 @@ const TeamListDialog = WDialog.extend({ }, toggleShareWD: async function (teamID, currentState) { - let newState = "Off"; - if (currentState == "Off") newState = "On"; + const newState = currentState ? "Off" : "On"; try { await SetTeamShareWD(teamID, newState); await WasabeeMe.waitGet(true); @@ -226,8 +218,7 @@ const TeamListDialog = WDialog.extend({ }, toggleLoadWD: async function (teamID, currentState) { - let newState = "Off"; - if (currentState == "Off") newState = "On"; + const newState = currentState ? "Off" : "On"; try { await SetTeamLoadWD(teamID, newState); await WasabeeMe.waitGet(true); diff --git a/src/code/dialogs/wasabeeDlist.js b/src/code/dialogs/wasabeeDlist.js index 8f90ccc63..fd5969cc0 100644 --- a/src/code/dialogs/wasabeeDlist.js +++ b/src/code/dialogs/wasabeeDlist.js @@ -90,7 +90,7 @@ const WasabeeDList = WDialog.extend({ ]; content.sortBy = 0; - content.items = await getAgentWasabeeDkeys(this._me.GoogleID); + content.items = await getAgentWasabeeDkeys(this._me.id); return content; }, diff --git a/src/code/model/me.ts b/src/code/model/me.ts index 67dadfcf5..54aa6c53e 100644 --- a/src/code/model/me.ts +++ b/src/code/model/me.ts @@ -2,78 +2,78 @@ import { mePromise } from "../server"; import db from "../db"; import { constants } from "../static"; +import WasabeeAgent from "./agent"; export interface MeTeam { - ID: string, - Name: string, - RocksComm: string, - RocksKey: string, - JoinLinkToken: string, - ShareWD: "On" | "Off", - LoadWD: "On" | "Off", - State: "On" | "Off", - Owner: string, - VTeam: string, - VTeamRole: string, + ID: string; + Name: string; + RocksComm: string; + RocksKey: string; + JoinLinkToken: string; + ShareWD: boolean; + LoadWD: boolean; + State: boolean; + Owner: string; + VTeam: string; + VTeamRole: string; } interface MeOp { - ID: string, + ID: OpID; + Name: string; + IsOwner: boolean; + Color: string; // ?? + TeamID: TeamID; } -export default class WasabeeMe { - GoogleID: string; - name: string; - vname: string; - rocksname: string; - intelname: string; - level: number; - Teams: Array; - Ops: Array; - fetched: number; - Vverified: boolean; - blacklisted: boolean; - enlid: string; - pic: string; - intelfaction: string; - querytoken: string; - - _teamMap: Map; +export default class WasabeeMe extends WasabeeAgent { + querytoken?: string; + lockey?: string; + vapi?: string; + + Telegram: { + ID: string; + Verified: boolean; + Authtoken: string; + }; + + Teams: MeTeam[]; + Ops: MeOp[]; + + _teamMap: Map; constructor(data) { if (typeof data == "string") { console.trace("me waits for an object"); return null; } - this.GoogleID = data.GoogleID; - this.name = data.name; - this.vname = data.vname; - this.rocksname = data.rocksname; - this.intelname = data.intelname; - this.level = data.level ? data.level : 0; - this.Teams = Array(); - this.Ops = Array(); - this.fetched = Date.now(); - this.Vverified = data.Vverified; - this.blacklisted = data.blacklisted; - this.enlid = data.enlid; - this._teamMap = null; - // RAID and RISC are unused by clients + data.id = data.GoogleID || data.id; + super(data); + this.querytoken = data.querytoken; this.pic = data.pic; this.intelfaction = data.intelfaction; - this.querytoken = data.querytoken; + this.lockey = data.lockey; + this.querytoken = data.lockey; + this.vapi = data.vapi; + this.Teams = []; if (data.Teams && data.Teams.length > 0) { for (const team of data.Teams) { + team.ShareWD = team.ShareWD == "On" || team.ShareWD === true; + team.LoadWD = team.LoadWD == "On" || team.LoadWD === true; + team.State = team.State == "On" || team.State === true; this.Teams.push(team); } } + + this.Ops = []; if (data.Ops && data.Ops.length > 0) { for (const op of data.Ops) { this.Ops.push(op); } } this.fetched = data.fetched ? data.fetched : Date.now(); + this._teamMap = null; } static maxCacheAge() { @@ -175,15 +175,6 @@ export default class WasabeeMe { return false; } - teamEnabled(teamID) { - if (this._teamMap == null) this.makeTeamMap(); - if (this._teamMap.has(teamID)) { - const m = this._teamMap.get(teamID); - if (m == "On") return true; - } - return false; - } - makeTeamMap() { this._teamMap = new Map(); for (const t of this.Teams) { diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 13bd28dbb..82cbe7aa6 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -1023,7 +1023,7 @@ export default class WasabeeOp extends Evented implements IOperation { // if current user is op creator, it is always writable const me = WasabeeMe.cacheGet(); if (!me) return false; - if (me.GoogleID == this.creator) return true; + if (me.id == this.creator) return true; // if the user has no teams enabled, it can't be writable if (!me.Teams || me.Teams.length == 0) return false; // if on a write-allowed team, is writable @@ -1054,7 +1054,7 @@ export default class WasabeeOp extends Evented implements IOperation { // if current user is op creator, it is always writable const me = WasabeeMe.cacheGet(); if (!me) return "read"; // fail safe - if (me.GoogleID == this.creator) return "write"; + if (me.id == this.creator) return "write"; const teamsID = new Set(me.Teams.map((t) => t.ID)); // look for team permission @@ -1082,7 +1082,7 @@ export default class WasabeeOp extends Evented implements IOperation { const me = WasabeeMe.cacheGet(); if (!me) return false; - if (me.GoogleID == this.creator) return true; + if (me.id == this.creator) return true; return false; } From ddd6b428d6d8babdcd70946e7f47ea4bbdc11df9 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 21:54:27 +0100 Subject: [PATCH 102/275] fix: agent marker not removed --- src/code/mapDrawing.js | 13 +++++++------ src/code/ui/agent.js | 9 +++++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.js index 356464379..3b91daf50 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.js @@ -126,17 +126,17 @@ export async function drawAgents() { // remove those not found in this fetch for (const d of doneAgents) layerMap.delete(d); - for (const agent in layerMap) { - console.debug("removing stale agent", agent); - Wasabee.agentLayerGroup.removeLayer(agent); + for (const [aid, lid] of layerMap) { + console.debug("removing stale agent", aid); + Wasabee.agentLayerGroup.removeLayer(lid); } } // map agent GID to leaflet layer ID function agentLayerMap() { const layerMap = new Map(); - for (const agent of Wasabee.agentLayerGroup.getLayers()) { - layerMap.set(agent.options.id, agent._leaflet_id); + for (const marker of Wasabee.agentLayerGroup.getLayers()) { + layerMap.set(marker.options.id, Wasabee.agentLayerGroup.getLayerId(marker)); } return layerMap; } @@ -174,7 +174,7 @@ export async function drawSingleAgent(gid) { // returns true if drawn, false if ignored function _drawAgent(agent, layerMap = agentLayerMap()) { - if (!agent.id || !agent.lat || !agent.lng) { + if (!agent.id || (!agent.lat && !agent.lng)) { return false; } @@ -182,6 +182,7 @@ function _drawAgent(agent, layerMap = agentLayerMap()) { // new, add to map const marker = new AgentUI.WLAgent(agent); marker.addTo(Wasabee.agentLayerGroup); + layerMap.set(agent.id, Wasabee.agentLayerGroup.getLayerId(marker)); } else { // move existing icons, if they actually moved const a = layerMap.get(agent.id); diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index 8322836ba..32962887e 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -47,7 +47,7 @@ function formatDisplay(agent) { function timeSinceformat(agent) { if (!agent.date) return ""; - const date = Date.parse(agent.date + " UTC"); + const date = Date.parse(agent.date + "Z"); if (Number.isNaN(date)) return `(${agent.date} UTC)`; // FireFox Date.parse no good if (date == 0) return ""; @@ -185,11 +185,16 @@ const WLAgent = L.Marker.extend({ const title = L.DomUtil.create("div", "desc", content); title.id = agent.id; title.textContent = agent.getName(); + const time = L.DomUtil.create("div", "desc", content); + time.id = agent.id; + time.textContent = timeSinceformat(agent); WasabeeAgent.get(this.options.id) .then(formatDisplay) .then((fd) => { - title.innerHTML = fd.outerHTML + timeSinceformat(agent); + title.textContent = ""; + title.appendChild(fd); + time.textContent = timeSinceformat(agent); }); const sendTarget = L.DomUtil.create("button", null, content); From 7d2046ab63a7f1b77739736d54b602b8f584d5cd Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 22:00:04 +0100 Subject: [PATCH 103/275] auxiliar.ts --- package.json | 1 + src/code/auxiliar.d.ts | 3 --- src/code/{auxiliar.js => auxiliar.ts} | 6 +++--- 3 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 src/code/auxiliar.d.ts rename src/code/{auxiliar.js => auxiliar.ts} (79%) diff --git a/package.json b/package.json index d213086c0..7302326ef 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "gulpfile.js", "private": true, "devDependencies": { + "@types/color-string": "^1.5.0", "@types/jquery": "^3.5.8", "@types/jqueryui": "^1.12.16", "@types/leaflet": "^1.7.5", diff --git a/src/code/auxiliar.d.ts b/src/code/auxiliar.d.ts deleted file mode 100644 index 9054b1b9c..000000000 --- a/src/code/auxiliar.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare function generateId(len?: number): string; -export declare function newColors(incoming: any): any; -export declare function convertColorToHex(color: any, on_error?: string): any; diff --git a/src/code/auxiliar.js b/src/code/auxiliar.ts similarity index 79% rename from src/code/auxiliar.js rename to src/code/auxiliar.ts index 4ced73101..1055b2555 100644 --- a/src/code/auxiliar.js +++ b/src/code/auxiliar.ts @@ -9,7 +9,7 @@ export function generateId(len = 40) { }).join(""); } -export function newColors(incoming) { +export function newColors(incoming: string) { switch (incoming) { case "groupa": return "orange"; @@ -24,13 +24,13 @@ export function newColors(incoming) { case "groupf": return "fuchsia"; case "main": - return window.plugin.wasabee.skin.defaultOperationColor; + return window.plugin.wasabee.skin.defaultOperationColor as string; default: return incoming; } } -export function convertColorToHex(color, on_error = "#000000") { +export function convertColorToHex(color: string, on_error = "#000000") { try { return colorString.to.hex(colorString.get.rgb(newColors(color))); } catch { From f0d57a7b2c8256b3045d0432e6203bcc96afacb1 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 22:04:52 +0100 Subject: [PATCH 104/275] addButtons.ts --- src/code/addButtons.d.ts | 2 -- src/code/{addButtons.js => addButtons.ts} | 13 +++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) delete mode 100644 src/code/addButtons.d.ts rename src/code/{addButtons.js => addButtons.ts} (75%) diff --git a/src/code/addButtons.d.ts b/src/code/addButtons.d.ts deleted file mode 100644 index e091ae441..000000000 --- a/src/code/addButtons.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function addButtons(): void; -export default addButtons; diff --git a/src/code/addButtons.js b/src/code/addButtons.ts similarity index 75% rename from src/code/addButtons.js rename to src/code/addButtons.ts index 4395a813d..7dc45a9cb 100644 --- a/src/code/addButtons.js +++ b/src/code/addButtons.ts @@ -1,4 +1,4 @@ -import { ButtonsControl } from "./leafletClasses"; +import { ButtonsControl, ButtonsControlOptions } from "./leafletClasses"; import QuickdrawButton from "./buttons/quickdrawButton"; import WasabeeButton from "./buttons/wasabeeButton"; import SyncButton from "./buttons/syncButton"; @@ -13,11 +13,12 @@ export function addButtons() { return; } - const options = {}; - // XXX next refactor pass, don't require a container to be passed in, get the formatting on ButtonsControl.onAdd() - options.container = L.DomUtil.create("ul", "leaflet-bar"); - options.position = "topleft"; - options.buttons = new Map(); + const options: ButtonsControlOptions = { + // XXX next refactor pass, don't require a container to be passed in, get the formatting on ButtonsControl.onAdd() + container: L.DomUtil.create("ul", "leaflet-bar"), + position: "topleft", + buttons: new Map(), + }; for (const Constructor of [ WasabeeButton, OpButton, From d55f3a9d7588b1b4eb5040b3d7445d7cdf4d0424 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 22:13:53 +0100 Subject: [PATCH 105/275] mapDrawing.ts --- src/code/mapDrawing.d.ts | 7 ----- src/code/{mapDrawing.js => mapDrawing.ts} | 31 +++++++++++++++-------- 2 files changed, 20 insertions(+), 18 deletions(-) delete mode 100644 src/code/mapDrawing.d.ts rename src/code/{mapDrawing.js => mapDrawing.ts} (90%) diff --git a/src/code/mapDrawing.d.ts b/src/code/mapDrawing.d.ts deleted file mode 100644 index 01953e7f1..000000000 --- a/src/code/mapDrawing.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as L from "leaflet"; -export declare function drawMap(): void; -export declare function drawBackgroundOps(opIDs?: string[]): Promise; -export declare function drawBackgroundOp(operation: any, layerGroup?: L.LayerGroup, style?: L.PathOptions): void; -export declare function drawAgents(): Promise; -export declare function drawSingleTeam(teamID: string, layerMap?: Map, alreadyDone?: string[]): Promise; -export declare function drawSingleAgent(gid: any): Promise; diff --git a/src/code/mapDrawing.js b/src/code/mapDrawing.ts similarity index 90% rename from src/code/mapDrawing.js rename to src/code/mapDrawing.ts index 3b91daf50..3e37aab1c 100644 --- a/src/code/mapDrawing.js +++ b/src/code/mapDrawing.ts @@ -9,6 +9,7 @@ import AnchorUI from "./ui/anchor"; import AgentUI from "./ui/agent"; import MarkerUI from "./ui/marker"; import ZoneUI from "./ui/zone"; +import type { PathOptions } from "leaflet"; const Wasabee = window.plugin.wasabee; @@ -22,7 +23,7 @@ export function drawMap() { } // updates all existing markers, adding any that need to be added, removing any that need to be removed -function updateMarkers(op) { +function updateMarkers(op: WasabeeOp) { if (window.isLayerGroupDisplayed("Wasabee Draw Markers") === false) return; // yes, === false, undefined == true if (!op.markers || op.markers.length == 0) { Wasabee.markerLayerGroup.clearLayers(); @@ -43,7 +44,7 @@ function updateMarkers(op) { ll.setState(m.state); layerMap.delete(m.ID); } else { - const lMarker = new MarkerUI.WLMarker(m, op); + const lMarker = new MarkerUI.WLMarker(m); lMarker.addTo(Wasabee.markerLayerGroup); } } @@ -56,7 +57,7 @@ function updateMarkers(op) { } // resetting is consistently 1ms faster than trying to update -function resetLinks(operation) { +function resetLinks(operation: WasabeeOp) { if (window.isLayerGroupDisplayed("Wasabee Draw Links") === false) return; // yes, === false, undefined == true Wasabee.linkLayerGroup.clearLayers(); @@ -68,7 +69,7 @@ function resetLinks(operation) { } } -export async function drawBackgroundOps(opIDs) { +export async function drawBackgroundOps(opIDs?: OpID[]) { if (window.isLayerGroupDisplayed("Wasabee Background Ops") === false) return; Wasabee.backgroundOpsGroup.clearLayers(); @@ -82,7 +83,11 @@ export async function drawBackgroundOps(opIDs) { } } -export function drawBackgroundOp(operation, layerGroup, style) { +export function drawBackgroundOp( + operation?: WasabeeOp, + layerGroup?: L.LayerGroup, + style?: PathOptions +) { if (!operation) return; if (!operation.links || operation.links.length == 0) return; @@ -98,7 +103,7 @@ export function drawBackgroundOp(operation, layerGroup, style) { } } -function resetZones(operation) { +function resetZones(operation: WasabeeOp) { Wasabee.zoneLayerGroup.clearLayers(); if (!operation.zones || operation.zones.length == 0) return; @@ -134,7 +139,7 @@ export async function drawAgents() { // map agent GID to leaflet layer ID function agentLayerMap() { - const layerMap = new Map(); + const layerMap = new Map(); for (const marker of Wasabee.agentLayerGroup.getLayers()) { layerMap.set(marker.options.id, Wasabee.agentLayerGroup.getLayerId(marker)); } @@ -142,7 +147,11 @@ function agentLayerMap() { } // use alreadyDone to reduce processing when using this in a loop, otherwise leave it unset -export async function drawSingleTeam(teamID, layerMap, alreadyDone) { +export async function drawSingleTeam( + teamID: TeamID, + layerMap?: Map, + alreadyDone?: GoogleID[] +) { const done = new Array(); if (window.isLayerGroupDisplayed("Wasabee Agents") === false) return done; // yes, === false, undefined == true if (alreadyDone === undefined) alreadyDone = new Array(); @@ -166,14 +175,14 @@ export async function drawSingleTeam(teamID, layerMap, alreadyDone) { } // draws a single agent -- can be triggered by firebase -export async function drawSingleAgent(gid) { +export async function drawSingleAgent(gid: GoogleID) { if (window.isLayerGroupDisplayed("Wasabee Agents") === false) return; // yes, === false, undefined == true const agent = await WasabeeAgent.get(gid, 10); // cache default is 1 day, we can be faster if firebase tells us of an update if (agent != null) _drawAgent(agent); } // returns true if drawn, false if ignored -function _drawAgent(agent, layerMap = agentLayerMap()) { +function _drawAgent(agent: WasabeeAgent, layerMap = agentLayerMap()) { if (!agent.id || (!agent.lat && !agent.lng)) { return false; } @@ -198,7 +207,7 @@ function _drawAgent(agent, layerMap = agentLayerMap()) { } // update all anchors, adding missing and removing unneeded -function updateAnchors(op) { +function updateAnchors(op: WasabeeOp) { if (window.isLayerGroupDisplayed("Wasabee Draw Portals") === false) return; // yes, === false, undefined == true if (!op.anchors || op.anchors.length == 0) { Wasabee.portalLayerGroup.clearLayers(); From 25f9b375be115e86208bbed363337c94fc7b014b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 12 Nov 2021 22:28:25 +0100 Subject: [PATCH 106/275] selectedOp.ts --- src/code/selectedOp.d.ts | 17 ------------ src/code/{selectedOp.js => selectedOp.ts} | 34 +++++++++++------------ tsconfig.json | 2 +- 3 files changed, 18 insertions(+), 35 deletions(-) delete mode 100644 src/code/selectedOp.d.ts rename src/code/{selectedOp.js => selectedOp.ts} (90%) diff --git a/src/code/selectedOp.d.ts b/src/code/selectedOp.d.ts deleted file mode 100644 index b4fb3d92a..000000000 --- a/src/code/selectedOp.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import WasabeeOp from "./model/operation"; -export declare function getSelectedOperation(): WasabeeOp; -export declare function initSelectedOperation(): Promise; -export declare function changeOpIfNeeded(): Promise; -export declare function loadNewDefaultOp(): Promise; -export declare function makeSelectedOperation(opID: any): Promise; -export declare function setupLocalStorage(): Promise; -export declare function removeOperation(opID: any): Promise; -export declare function showOperation(opID: any): void; -export declare function hideOperation(opID: any): void; -export declare function resetHiddenOps(): void; -export declare function resetOps(): Promise; -export declare function hiddenOpsList(): any; -export declare function setOpBackground(opID: any, background: any): Promise; -export declare function opsList(hidden?: boolean): Promise; -export declare function duplicateOperation(opID: any): Promise; -export declare function removeNonOwnedOps(): Promise; diff --git a/src/code/selectedOp.js b/src/code/selectedOp.ts similarity index 90% rename from src/code/selectedOp.js rename to src/code/selectedOp.ts index 447eed460..2638746aa 100644 --- a/src/code/selectedOp.js +++ b/src/code/selectedOp.ts @@ -4,15 +4,15 @@ import wX from "./wX"; import { generateId } from "./auxiliar"; import { displayError } from "./error"; -function setRestoreOpID(opID) { +function setRestoreOpID(opID: OpID) { localStorage[window.plugin.wasabee.static.constants.SELECTED_OP_KEY] = opID; } -function getRestoreOpID() { +function getRestoreOpID(): OpID { return localStorage[window.plugin.wasabee.static.constants.SELECTED_OP_KEY]; } -export function getSelectedOperation() { +export function getSelectedOperation(): WasabeeOp { return window.plugin.wasabee._selectedOp; } @@ -34,7 +34,7 @@ export async function initSelectedOperation() { } } } - return window.plugin.wasabee._selectedOp; + return getSelectedOperation(); } export async function changeOpIfNeeded() { @@ -44,23 +44,23 @@ export async function changeOpIfNeeded() { if (ops.length == 0) await loadNewDefaultOp(); else await makeSelectedOperation(ops[ops.length - 1]); } - return window.plugin.wasabee._selectedOp; + return getSelectedOperation(); } // create a new op and set it as selected export async function loadNewDefaultOp() { const newOp = new WasabeeOp({ creator: PLAYER.nickname, - name: wX("DEFAULT OP NAME", { date: new Date().toGMTString() }), + name: wX("DEFAULT OP NAME", { date: new Date().toUTCString() }), }); await newOp.store(); await makeSelectedOperation(newOp.ID); - return window.plugin.wasabee._selectedOp; + return getSelectedOperation(); } // this is the function that loads an op from the store, makes it the selected op and draws it to the screen // only this should write to _selectedOp -export async function makeSelectedOperation(opID) { +export async function makeSelectedOperation(opID: OpID) { // _selectedOp is null at first load (or page reload), should never be after that let previousID; if (window.plugin.wasabee._selectedOp != null) { @@ -138,14 +138,14 @@ export async function setupLocalStorage() { } //** This function removes an operation from the main list */ -export async function removeOperation(opID) { +export async function removeOperation(opID: OpID) { await WasabeeOp.delete(opID); WasabeeBlocker.removeBlockers(opID); // no need to await window.map.fire("wasabee:op:delete", opID); } //** This function shows an operation to the main list */ -export function showOperation(opID) { +export function showOperation(opID: OpID) { const hiddenOps = hiddenOpsList(); if (hiddenOps.includes(opID)) { localStorage[window.plugin.wasabee.static.constants.OPS_LIST_HIDDEN_KEY] = @@ -155,7 +155,7 @@ export function showOperation(opID) { } //** This function hides an operation to the main list */ -export function hideOperation(opID) { +export function hideOperation(opID: OpID) { const hiddenOps = hiddenOpsList(); if (!hiddenOps.includes(opID)) { hiddenOps.push(opID); @@ -178,7 +178,7 @@ export async function resetOps() { ops.map(WasabeeBlocker.removeBlockers); // no need to await } -export function hiddenOpsList() { +export function hiddenOpsList(): OpID[] { try { const raw = localStorage[window.plugin.wasabee.static.constants.OPS_LIST_HIDDEN_KEY]; @@ -188,7 +188,7 @@ export function hiddenOpsList() { } } -export async function setOpBackground(opID, background) { +export async function setOpBackground(opID: OpID, background: boolean) { const sop = getSelectedOperation(); const op = sop.ID === opID ? sop : await WasabeeOp.load(opID); if (op.background == background) return; @@ -202,7 +202,7 @@ export async function setOpBackground(opID, background) { export async function opsList(hidden = true) { // after 0.19, remove the list and just query the idb keys - let ops = []; + let ops: OpID[] = []; try { const raw = localStorage[window.plugin.wasabee.static.constants.OPS_LIST_KEY]; @@ -222,8 +222,8 @@ export async function opsList(hidden = true) { return ops; } -export async function duplicateOperation(opID) { - let op = null; +export async function duplicateOperation(opID: OpID) { + let op: WasabeeOp = null; if (opID == window.plugin.wasabee._selectedOp.ID) { op = window.plugin.wasabee._selectedOp; await op.store(); @@ -234,7 +234,7 @@ export async function duplicateOperation(opID) { // XXX op.toExport() might be helpful here op.ID = generateId(); - op.name = op.name + " " + new Date().toGMTString(); + op.name = op.name + " " + new Date().toUTCString(); op.creator = window.PLAYER.nickname; op.teamlist = null; op.fetched = null; diff --git a/tsconfig.json b/tsconfig.json index 27ebd6618..e37bdd922 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "outDir": "./built", "sourceMap": true, - "target": "ES6", + "target": "ES2020", "moduleResolution": "node", "importsNotUsedAsValues": "error", "esModuleInterop": true, From 6665fcc0a3e29dbd02f6b131567d9010e6c28b3f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 13 Nov 2021 10:44:22 +0100 Subject: [PATCH 107/275] sortable.ts --- src/code/sortable.d.ts | 41 ------------------------- src/code/{sortable.js => sortable.ts} | 43 ++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 49 deletions(-) delete mode 100644 src/code/sortable.d.ts rename src/code/{sortable.js => sortable.ts} (83%) diff --git a/src/code/sortable.d.ts b/src/code/sortable.d.ts deleted file mode 100644 index d51f3ea87..000000000 --- a/src/code/sortable.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -interface SortableItem { - obj: T; - row: HTMLTableRowElement; - index: number; - values: unknown[]; - sortValues: unknown[]; -} -export interface SortableField { - name: string; - className?: string; - value: (thing: T) => unknown; - sortValue?: (value: unknown, thing: T) => unknown; - sort?: (a: unknown, b: unknown, aobj?: T, bobj?: T) => number; - format?: (cell: HTMLTableCellElement, value: unknown, thing?: T) => void; - smallScreenHide?: boolean; -} -export default class Sortable { - _items: Array>; - _fields: Array>; - _sortBy: number; - _sortAsc: boolean; - _table: HTMLTableElement; - _head: HTMLTableSectionElement; - _body: HTMLTableSectionElement; - _smallScreen: boolean; - _done: Promise | boolean; - constructor(); - get sortBy(): number; - set sortBy(property: number); - get sortAsc(): boolean; - set sortAsc(b: boolean); - get table(): HTMLTableElement; - get items(): T[]; - set items(incoming: T[]); - get fields(): SortableField[]; - set fields(value: SortableField[]); - get done(): boolean | Promise; - renderHead(): void; - sort(): void; -} -export {}; diff --git a/src/code/sortable.js b/src/code/sortable.ts similarity index 83% rename from src/code/sortable.js rename to src/code/sortable.ts index 30a442d0d..f7606908f 100644 --- a/src/code/sortable.js +++ b/src/code/sortable.ts @@ -1,4 +1,32 @@ -export default class Sortable { +interface SortableItem { + obj: T; + row: HTMLTableRowElement; + index: number; + values: unknown[]; + sortValues: unknown[]; +} + +export interface SortableField { + name: string; + className?: string; + value: (thing: T) => unknown; + sortValue?: (value: unknown, thing: T) => unknown; + sort?: (a: unknown, b: unknown, aobj?: T, bobj?: T) => number; + format?: (cell: HTMLTableCellElement, value: unknown, thing?: T) => void; + smallScreenHide?: boolean; +} + +export default class Sortable { + _items: Array>; + _fields: Array>; + _sortBy: number; + _sortAsc: boolean; + _table: HTMLTableElement; + _head: HTMLTableSectionElement; + _body: HTMLTableSectionElement; + _smallScreen: boolean; + _done: Promise | boolean; + constructor() { this._items = []; this._fields = []; @@ -81,15 +109,14 @@ export default class Sortable { for (const field of this._fields) { // calculate the value using the field's rules let value = field.value(obj); - if (value != null && typeof value.then === "function") - value = await value; // resolve promises + if (value != null && value instanceof Promise) value = await value; // resolve promises data.values.push(value); // calculate sortValue using the field's rules if required let sortValue = value; if (field.sortValue) { sortValue = field.sortValue(value, obj); - if (sortValue != null && typeof sortValue.then === "function") + if (sortValue != null && sortValue instanceof Promise) sortValue = await sortValue; // resolve promises } data.sortValues.push(sortValue); @@ -100,7 +127,7 @@ export default class Sortable { if (field.format) { field.format(cell, value, obj); } else { - cell.textContent = value; + cell.textContent = value as string; } if (field.smallScreenHide && this._smallScreen) { cell.style.display = "none"; @@ -164,9 +191,9 @@ export default class Sortable { (ev) => { L.DomEvent.stop(ev); for (const element of titleRow.children) { - L.DomUtil.removeClass(element, "sorted"); - L.DomUtil.removeClass(element, "asc"); - L.DomUtil.removeClass(element, "desc"); + L.DomUtil.removeClass(element as HTMLElement, "sorted"); + L.DomUtil.removeClass(element as HTMLElement, "asc"); + L.DomUtil.removeClass(element as HTMLElement, "desc"); } if (index == this._sortBy) { this._sortAsc = !this._sortAsc; From 93b7ac642555e8eb4b1f4e24428a9d8911b2c89d Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 13 Nov 2021 17:55:54 +0100 Subject: [PATCH 108/275] skin.ts --- src/code/skin.d.ts | 3 --- src/code/{skin.js => skin.ts} | 16 +++++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) delete mode 100644 src/code/skin.d.ts rename src/code/{skin.js => skin.ts} (92%) diff --git a/src/code/skin.d.ts b/src/code/skin.d.ts deleted file mode 100644 index aea4270eb..000000000 --- a/src/code/skin.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare function initSkin(): void; -export declare function changeSkin(names: any): boolean; -export declare function addToColorList(color: any): void; diff --git a/src/code/skin.js b/src/code/skin.ts similarity index 92% rename from src/code/skin.js rename to src/code/skin.ts index 0d4409797..fd3c7486e 100644 --- a/src/code/skin.js +++ b/src/code/skin.ts @@ -19,7 +19,7 @@ export function initSkin() { } function addCSS(name, content) { - if (!Wasabee._css) Wasabee._css = new Array(); + if (!Wasabee._css) Wasabee._css = []; if (Wasabee._css.includes(name)) { document.getElementById("wasabee-css-" + name).remove(); Wasabee._css.splice(Wasabee._css.indexOf(name)); @@ -36,7 +36,7 @@ function resetCSS() { for (const name of Wasabee._css) { document.getElementById("wasabee-css-" + name).remove(); } - Wasabee._css = new Array(); + Wasabee._css = []; } // const addFallback = () => { @@ -51,7 +51,7 @@ function resetCSS() { // Wasabee.skin.selfBlockStyle = Wasabee.static.selfBlockStyle; // }; -export function changeSkin(names) { +export function changeSkin(names: string[]) { if (!window.plugin.wasabeeSkins) window.plugin.wasabeeSkins = {}; if (names.length == 0) { @@ -117,7 +117,7 @@ function initAnchorIcon() { const tmp = L.DomUtil.create("div"); tmp.innerHTML = iconHTML; - const icon = tmp.firstChild; + const icon = tmp.firstChild as HTMLElement; icon.id = "wasabee-anchor-svg"; document.body.appendChild(icon); } @@ -135,13 +135,15 @@ function initOpsColor() { } } -export function addToColorList(color) { - const datalist = document.getElementById("wasabee-colors-datalist"); +export function addToColorList(color: string) { + const datalist = document.getElementById( + "wasabee-colors-datalist" + ) as HTMLDataListElement; // fail safe if (!datalist) return; for (const c of datalist.children) { - if (c.value == color) { + if ((c as HTMLOptionElement).value == color) { datalist.insertBefore(c, datalist.firstChild); return; } From 2fa590f0abf48a40238248e37652d9e9db70ce9d Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 13 Nov 2021 18:23:41 +0100 Subject: [PATCH 109/275] server.ts --- src/code/dialogs/manageTeamDialog.js | 3 +- src/code/index.d.ts | 2 + src/code/model/task.ts | 6 +- src/code/server.d.ts | 104 ----------- src/code/{server.js => server.ts} | 267 ++++++++++++++++----------- 5 files changed, 164 insertions(+), 218 deletions(-) delete mode 100644 src/code/server.d.ts rename src/code/{server.js => server.ts} (69%) diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 126bf943a..baa9cb343 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -252,8 +252,7 @@ const ManageTeamDialog = WDialog.extend({ joinlinkadd.textContent = "Create"; L.DomEvent.on(joinlinkadd, "click", async (ev) => { L.DomEvent.stop(ev); - const response = await createJoinLinkPromise(this.options.team.ID); - const j = JSON.parse(response); + const j = await createJoinLinkPromise(this.options.team.ID); this.options.team.JoinLinkToken = j.Key; this.update(); }); diff --git a/src/code/index.d.ts b/src/code/index.d.ts index 48d8c0a8c..1b2e29c77 100644 --- a/src/code/index.d.ts +++ b/src/code/index.d.ts @@ -9,4 +9,6 @@ declare global { type MarkerID = TaskID; type GoogleID = string; type ZoneID = number; + + var wasabeewebui: any; } diff --git a/src/code/model/task.ts b/src/code/model/task.ts index 67c6eb6c5..af49951d2 100644 --- a/src/code/model/task.ts +++ b/src/code/model/task.ts @@ -1,5 +1,7 @@ import { generateId } from "../auxiliar"; +export type TaskState = "pending" | "assigned" | "acknowledged" | "completed"; + export default class Task { ID: TaskID; order: number; @@ -8,7 +10,7 @@ export default class Task { completedID?: GoogleID; comment?: string; - _state: "pending" | "assigned" | "acknowledged" | "completed"; + _state: TaskState; constructor(obj: any) { this.ID = obj.ID || generateId(); @@ -39,7 +41,7 @@ export default class Task { return this._state; } - set state(state) { + set state(state: TaskState) { switch (state) { case "assigned": // fall-through case "acknowledged": diff --git a/src/code/server.d.ts b/src/code/server.d.ts deleted file mode 100644 index 42577bfbb..000000000 --- a/src/code/server.d.ts +++ /dev/null @@ -1,104 +0,0 @@ -import WasabeeOp from "./model/operation"; -import WasabeeMarker from "./model/marker"; -import type WasabeeLink from "./model/link"; -import type WasabeePortal from "./model/portal"; -import type { WDKey } from "./wd"; -import WasabeeMe from "./model/me"; -import WasabeeTeam from "./model/team"; -import WasabeeAgent from "./model/agent"; - -interface IServerStatus { - status: string; -} -interface IServerUpdate extends IServerStatus { - updateID: string; -} - -export default function (): string; -export declare function GetWasabeeServer(): string; -export declare function SetWasabeeServer(server: string): void; -export declare function GetUpdateList(): any; - -declare function genericGet(url: string, formData: FormData | string, contentType?: string): Promise; -declare function genericPost(url: string, formData: FormData | string, contentType?: string): Promise; -declare function genericPut(url: string, formData: FormData | string, contentType?: string): Promise; -declare function genericDelete(url: string, formData: FormData | string, contentType?: string): Promise; - -// server config -export declare function loadConfig(): Promise; - -// login/out -export declare function SendAccessTokenAsync(accessToken: string): Promise; -export declare function logoutPromise(): Promise; -export declare function oneTimeToken(token: string): Promise; -// firebase -export declare function sendTokenToWasabee(token: string): Promise; -export declare function getCustomTokenFromServer(): Promise; - -/* me & d */ -// query -export declare function mePromise(): Promise; -export declare function dKeylistPromise(): Promise<{ - DefensiveKeys: WDKey[]; -}>; -// update data -export declare function leaveTeamPromise(teamID: TeamID): Promise; -export declare function locationPromise(lat: number, lng: number): Promise; -export declare function setIntelID(name: string, faction: string, querytoken: string): Promise; -export declare function SetTeamState(teamID: TeamID, state: "On" | "Off"): Promise; -export declare function SetTeamShareWD(teamID: TeamID, state: "On" | "Off"): Promise; -export declare function SetTeamLoadWD(teamID: TeamID, state: "On" | "Off"): Promise; -export declare function dKeyPromise(json: string): Promise; -export declare function dKeyBulkPromise(json: string): Promise; - -/* agent */ -// query -export declare function agentPromise(GID: GoogleID): Promise; -// action -export declare function targetPromise(agentID: GoogleID, portal: WasabeePortal, type?: string): Promise; - - -/* team */ -// query -export declare function teamPromise(teamid: TeamID): Promise; -export declare function createJoinLinkPromise(teamID: TeamID): Promise<{ - Key: string; -}>; -// action -export declare function sendAnnounce(teamID: TeamID, message: string): Promise; -export declare function pullRocks(teamID: TeamID): Promise; -// update data -export declare function newTeamPromise(name: string): Promise; -export declare function renameTeamPromise(teamID: TeamID, name: string): Promise; -export declare function deleteTeamPromise(teamID: TeamID): Promise; -export declare function changeTeamOwnerPromise(teamID: TeamID, newOwner: GoogleID): Promise; -export declare function addAgentToTeamPromise(agentID: GoogleID, teamID: TeamID): Promise; -export declare function removeAgentFromTeamPromise(agentID: GoogleID, teamID: TeamID): Promise; -export declare function rocksPromise(teamID: TeamID, community: string, apikey: string): Promise; -export declare function setAgentTeamSquadPromise(agentID: GoogleID, teamID: TeamID, squad: string): Promise; -export declare function deleteJoinLinkPromise(teamID: TeamID): Promise; - -/* op */ -// query -export declare function opPromise(opID: OpID): Promise; -// special -export declare function uploadOpPromise(): Promise; -export declare function updateOpPromise(operation: WasabeeOp): Promise; -// update data -export declare function deleteOpPromise(opID: OpID): Promise; -export declare function addPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; -export declare function delPermPromise(opID: OpID, teamID: TeamID, role: string, zone: ZoneID): Promise; -export declare function setOpInfo(opID: OpID, info: any): Promise; -// update task -export declare function assignMarkerPromise(opID: OpID, markerID: MarkerID, agentID: GoogleID): Promise; -export declare function assignLinkPromise(opID: OpID, linkID: LinkID, agentID: GoogleID): Promise; -export declare function SetMarkerState(opID: OpID, markerID: MarkerID, state: string): Promise; -export declare function SetLinkState(opID: OpID, linkID: LinkID, state: string): Promise; -export declare function setAssignmentStatus(op: WasabeeOp, object: WasabeeLink | WasabeeMarker, completed: boolean): Promise; -export declare function reverseLinkDirection(opID: OpID, linkID: LinkID): Promise; -export declare function setMarkerComment(opID: OpID, markerID: MarkerID, comment: string): Promise; -export declare function setLinkComment(opID: OpID, linkID: LinkID, desc: string): Promise; -export declare function setLinkZone(opID: OpID, linkID: LinkID, zone: ZoneID): Promise; -export declare function setMarkerZone(opID: OpID, markerID: MarkerID, zone: ZoneID): Promise; -// update keys -export declare function opKeyPromise(opID: OpID, portalID: PortalID, onhand: number, capsule: string): Promise; diff --git a/src/code/server.js b/src/code/server.ts similarity index 69% rename from src/code/server.js rename to src/code/server.ts index 0666122e5..d5fec13b5 100644 --- a/src/code/server.js +++ b/src/code/server.ts @@ -1,8 +1,12 @@ import WasabeeMe from "./model/me"; import WasabeeOp from "./model/operation"; import { getSelectedOperation, removeOperation } from "./selectedOp"; -import WasabeeMarker from "./model/marker"; import { ServerError } from "./error"; +import type { TaskState } from "./model/task"; +import type WasabeePortal from "./model/portal"; +import type WasabeeAgent from "./model/agent"; +import type WasabeeTeam from "./model/team"; +import type { WDKey } from "./wd"; export default function () { return GetWasabeeServer(); @@ -38,6 +42,14 @@ export function SetWasabeeServer(server) { localStorage[window.plugin.wasabee.static.constants.SERVER_BASE_KEY] = server; } +interface IServerStatus { + status: string; +} + +interface IServerUpdate extends IServerStatus { + updateID: string; +} + /* On fail, all promises reject an ServerError { code: number, text: string, error?: string } If http code is 401: request Me.purge (fire wasabee:logout) @@ -84,20 +96,22 @@ export function mePromise() { // returns a promise to a list of defensive keys for all enabled teams export function dKeylistPromise() { - return genericGet("/api/v1/d"); + return genericGet<{ + DefensiveKeys: WDKey[]; + }>("/api/v1/d"); } // removes the agent from the team; return value is status code -export function leaveTeamPromise(teamID) { - return genericDelete(`/api/v1/me/${teamID}`, new FormData()); +export function leaveTeamPromise(teamID: TeamID) { + return genericDelete(`/api/v1/me/${teamID}`); } // updates an agent's location ; return value is status code -export function locationPromise(lat, lng) { +export function locationPromise(lat: number, lng: number) { return genericGet(`/api/v1/me?lat=${lat}&lon=${lng}`); } -export function setIntelID(name, faction, querytoken) { +export function setIntelID(name: string, faction: string, querytoken: string) { const fd = new FormData(); fd.append("name", name); fd.append("faction", faction); @@ -106,37 +120,41 @@ export function setIntelID(name, faction, querytoken) { } // changes agent's team state on the server; return value is status message -export function SetTeamState(teamID, state) { +export function SetTeamState(teamID: TeamID, state: "On" | "Off") { return genericGet(`/api/v1/me/${teamID}?state=${state}`); } -export function SetTeamShareWD(teamID, state) { +export function SetTeamShareWD(teamID: TeamID, state: "On" | "Off") { return genericGet(`/api/v1/me/${teamID}/wdshare?state=${state}`); } -export function SetTeamLoadWD(teamID, state) { +export function SetTeamLoadWD(teamID: TeamID, state: "On" | "Off") { return genericGet(`/api/v1/me/${teamID}/wdload?state=${state}`); } // updates an agent's single defensive key -export function dKeyPromise(json) { +export function dKeyPromise(json: string) { return genericPost("/api/v1/d", json, "application/json;charset=UTF-8"); } // many d-keys at once -export function dKeyBulkPromise(json) { +export function dKeyBulkPromise(json: string) { return genericPost("/api/v1/d/bulk", json, "application/json;charset=UTF-8"); } /* agent */ // returns a promise to get the agent's JSON data from the server -- should be called only by WasabeeAgent.get() -export function agentPromise(GID) { - return genericGet(`/api/v1/agent/${GID}`); +export function agentPromise(GID: GoogleID) { + return genericGet(`/api/v1/agent/${GID}`); } // sends a target (portal) to the server to notify the agent -export function targetPromise(agentID, portal, type = "ad hoc") { +export function targetPromise( + agentID: GoogleID, + portal: WasabeePortal, + type = "ad hoc" +) { return genericPost( `/api/v1/agent/${agentID}/target`, JSON.stringify({ @@ -154,98 +172,104 @@ export function targetPromise(agentID, portal, type = "ad hoc") { // returns a promise to a WasabeeTeam -- used only by WasabeeTeam.get // use WasabeeTeam.get -export function teamPromise(teamid) { - return genericGet(`/api/v1/team/${teamid}`); +export function teamPromise(teamid: TeamID) { + return genericGet(`/api/v1/team/${teamid}`); } -export function sendAnnounce(teamID, message) { +export function sendAnnounce(teamID: TeamID, message: string) { const fd = new FormData(); fd.append("m", message); return genericPost(`/api/v1/team/${teamID}/announce`, fd); } -export function pullRocks(teamID) { +export function pullRocks(teamID: TeamID) { return genericGet(`/api/v1/team/${teamID}/rocks`); } // local change: none // cache: none -export function newTeamPromise(name) { +export function newTeamPromise(name: string) { return genericGet(`/api/v1/team/new?name=${name}`); } // local change: none // cache: none -export function renameTeamPromise(teamID, name) { +export function renameTeamPromise(teamID: TeamID, name: string) { const fd = new FormData(); fd.append("teamname", name); return genericPut(`/api/v1/team/${teamID}/rename`, fd); } // local change: none // cache: none -export function deleteTeamPromise(teamID) { - return genericDelete(`/api/v1/team/${teamID}`, new FormData()); +export function deleteTeamPromise(teamID: TeamID) { + return genericDelete(`/api/v1/team/${teamID}`); } -export function changeTeamOwnerPromise(teamID, newOwner) { +export function changeTeamOwnerPromise(teamID: TeamID, newOwner: GoogleID) { return genericGet(`/api/v1/team/${teamID}/chown?to=${newOwner}`); } // local change: none // cache: none -export function addAgentToTeamPromise(agentID, teamID) { +export function addAgentToTeamPromise(agentID: GoogleID, teamID: TeamID) { return genericPost(`/api/v1/team/${teamID}/${agentID}`, new FormData()); } // removes another agent from an owned team ; return value is status code -export function removeAgentFromTeamPromise(agentID, teamID) { - return genericDelete(`/api/v1/team/${teamID}/${agentID}`, new FormData()); +export function removeAgentFromTeamPromise(agentID: GoogleID, teamID: TeamID) { + return genericDelete(`/api/v1/team/${teamID}/${agentID}`); } // local change: none // cache: none -export function rocksPromise(teamID, community, apikey) { +export function rocksPromise( + teamID: TeamID, + community: string, + apikey: string +) { return genericGet( `/api/v1/team/${teamID}/rockscfg?rockscomm=${community}&rockskey=${apikey}` ); } // local change: none // cache: none -export function setAgentTeamSquadPromise(agentID, teamID, squad) { +export function setAgentTeamSquadPromise( + agentID: GoogleID, + teamID: TeamID, + squad: string +) { const fd = new FormData(); fd.append("squad", squad); return genericPost(`/api/v1/team/${teamID}/${agentID}/squad`, fd); } -export function createJoinLinkPromise(teamID) { - return genericGet(`/api/v1/team/${teamID}/genJoinKey`); +export function createJoinLinkPromise(teamID: TeamID) { + return genericGet<{ Key: string }>(`/api/v1/team/${teamID}/genJoinKey`); } -export function deleteJoinLinkPromise(teamID) { +export function deleteJoinLinkPromise(teamID: TeamID) { return genericGet(`/api/v1/team/${teamID}/delJoinKey`); } // returns a promise to fetch a WasabeeOp // local change: If the server's copy is newer than the local copy, otherwise none // not generic since 304 result processing and If-Modified-Since header -export async function opPromise(opID) { +export async function opPromise(opID: OpID) { let ims = "Sat, 29 Oct 1994 19:43:31 GMT"; // the dawn of time... const localop = await WasabeeOp.load(opID); if (localop != null && localop.fetched) ims = localop.fetched; try { - const raw = await generic({ + const raw = await generic({ url: `/api/v1/draw/${opID}`, method: "GET", headers: localop - ? { - "If-None-Match": localop.lasteditid, - "If-Modified-Since": localop.lasteditid ? null : ims, - } + ? localop.lasteditid + ? { + "If-None-Match": localop.lasteditid, + } + : { + "If-Modified-Since": ims, + } : null, }); - if (raw === 304) { - localop.server = GetWasabeeServer(); - return localop; - } - const newop = new WasabeeOp(raw); newop.localchanged = false; newop.server = GetWasabeeServer(); @@ -263,6 +287,9 @@ export async function opPromise(opID) { ); } switch (e.code) { + case 304: + localop.server = GetWasabeeServer(); + return localop; case 403: // fallthrough case 410: @@ -280,7 +307,7 @@ export async function uploadOpPromise() { const operation = getSelectedOperation(); const json = operation.toExport(); - const response = await genericPost( + const response = await genericPost( "/api/v1/draw", json, "application/json;charset=UTF-8" @@ -294,18 +321,22 @@ export async function uploadOpPromise() { } // sends a changed op to the server -export async function updateOpPromise(operation) { +export async function updateOpPromise(operation: WasabeeOp) { const json = operation.toExport(); try { - const update = await generic({ + const update = await generic({ url: `/api/v1/draw/${operation.ID}`, method: "PUT", body: json, - headers: { - "Content-Type": "application/json;charset=UTF-8", - "If-Match": operation.lasteditid || null, - }, + headers: operation.lasteditid + ? { + "Content-Type": "application/json;charset=UTF-8", + "If-Match": operation.lasteditid, + } + : { + "Content-Type": "application/json;charset=UTF-8", + }, }); operation.lasteditid = update.updateID; operation.remoteChanged = false; @@ -337,51 +368,69 @@ export async function updateOpPromise(operation) { } // removes an op from the server -export function deleteOpPromise(opID) { - return genericDelete(`/api/v1/draw/${opID}`, new FormData()); +export function deleteOpPromise(opID: OpID) { + return genericDelete(`/api/v1/draw/${opID}`); } -export function setOpInfo(opID, info) { +export function setOpInfo(opID: OpID, info: string) { const fd = new FormData(); fd.append("info", info); return genericPost(`/api/v1/draw/${opID}/info`, fd); } // adds a permission to an op; return value is status code -export function addPermPromise(opID, teamID, role, zone) { +export function addPermPromise( + opID: OpID, + teamID: TeamID, + role: string, + zone: ZoneID +) { const fd = new FormData(); fd.append("team", teamID); fd.append("role", role); - fd.append("zone", zone); + fd.append("zone", `${zone}`); return genericPost(`/api/v1/draw/${opID}/perms`, fd); } // removes a permission from an op; return value is status code -export function delPermPromise(opID, teamID, role, zone) { +export function delPermPromise( + opID: OpID, + teamID: TeamID, + role: string, + zone: ZoneID +) { const fd = new FormData(); fd.append("team", teamID); fd.append("role", role); - fd.append("zone", zone); + fd.append("zone", `${zone}`); return genericDelete(`/api/v1/draw/${opID}/perms`, fd); } // local change: none // cache: none -export function assignMarkerPromise(opID, markerID, agentID) { +export function assignMarkerPromise( + opID: OpID, + markerID: MarkerID, + agentID: GoogleID +) { const fd = new FormData(); fd.append("agent", agentID); return genericPost(`/api/v1/draw/${opID}/marker/${markerID}/assign`, fd); } // performs a link assignment on the server, sending notifications -export function assignLinkPromise(opID, linkID, agentID) { +export function assignLinkPromise(opID: OpID, linkID: LinkID, agentID) { const fd = new FormData(); fd.append("agent", agentID); return genericPost(`/api/v1/draw/${opID}/link/${linkID}/assign`, fd); } // changes a markers status on the server, sending relevant notifications -export function SetMarkerState(opID, markerID, state) { - let action = "incomplete"; +export function SetMarkerState( + opID: OpID, + markerID: MarkerID, + state: TaskState +) { + let action: "incomplete" | "acknowledge" | "complete" = "incomplete"; switch (state) { case "acknowledged": action = "acknowledge"; @@ -400,8 +449,8 @@ export function SetMarkerState(opID, markerID, state) { } // changes a link's status on the server, sending relevant notifications -export function SetLinkState(opID, linkID, state) { - let action = "incomplete"; +export function SetLinkState(opID: OpID, linkID: LinkID, state: TaskState) { + let action: "incomplete" | "acknowledge" | "complete" = "incomplete"; switch (state) { // no acknowledge for links -- use incomplete case "pending": @@ -417,47 +466,47 @@ export function SetLinkState(opID, linkID, state) { return genericGet(`/api/v1/draw/${opID}/link/${linkID}/${action}`); } -export function setAssignmentStatus(op, object, completed) { - let type = "link"; - if (object instanceof WasabeeMarker) type = "marker"; - let c = "incomplete"; - if (completed) c = "complete"; - - return genericGet(`/api/v1/draw/${op.ID}/${type}/${object.ID}/${c}`); -} - -export function reverseLinkDirection(opID, linkID) { +export function reverseLinkDirection(opID: OpID, linkID: LinkID) { return genericGet(`/api/v1/draw/${opID}/link/${linkID}/swap`); } -export function setMarkerComment(opID, markerID, comment) { +export function setMarkerComment( + opID: OpID, + markerID: MarkerID, + comment: string +) { const fd = new FormData(); fd.append("comment", comment); return genericPost(`/api/v1/draw/${opID}/marker/${markerID}/comment`, fd); } -export function setLinkComment(opID, linkID, desc) { +export function setLinkComment(opID: OpID, linkID: LinkID, desc: string) { const fd = new FormData(); fd.append("desc", desc); return genericPost(`/api/v1/draw/${opID}/link/${linkID}/desc`, fd); } -export function setLinkZone(opID, linkID, zone) { +export function setLinkZone(opID: OpID, linkID: LinkID, zone: ZoneID) { const fd = new FormData(); - fd.append("zone", zone); + fd.append("zone", `${zone}`); return genericPost(`/api/v1/draw/${opID}/link/${linkID}/zone`, fd); } -export function setMarkerZone(opID, markerID, zone) { +export function setMarkerZone(opID: OpID, markerID: MarkerID, zone: ZoneID) { const fd = new FormData(); - fd.append("zone", zone); + fd.append("zone", `${zone}`); return genericPost(`/api/v1/draw/${opID}/marker/${markerID}/zone`, fd); } // updates an agent's key count, return value is status code -export function opKeyPromise(opID, portalID, onhand, capsule) { +export function opKeyPromise( + opID: OpID, + portalID: PortalID, + onhand: number, + capsule: string +) { const fd = new FormData(); - fd.append("count", onhand); + fd.append("count", `${onhand}`); fd.append("capsule", capsule); return genericPost(`/api/v1/draw/${opID}/portal/${portalID}/keyonhand`, fd); } @@ -465,7 +514,7 @@ export function opKeyPromise(opID, portalID, onhand, capsule) { /* The following are for Wasabee-WebUI and not used in Wasabee-IITC */ // in the service-worker for IITC -export function sendTokenToWasabee(token) { +export function sendTokenToWasabee(token: string) { // no need for a form-data, just send the raw token return genericPost(`/api/v1/me/firebase`, token); } @@ -481,19 +530,16 @@ export function getCustomTokenFromServer() { /* generic method */ /** * Generic fetch method against wasabee server - * - * @param {Object} request - * @param {string} request.url - * @param {string} request.method - * @param {string | FormData} [request.body] - * @param {HeadersInit} [request.headers] - * @param {boolean} [request.raw] - * @param {boolean} [request.retried] - * @returns {Promise<304 | string | Object>} */ -async function generic(request) { - /** @type RequestInit */ - const requestInit = { +async function generic(request: { + url: string; + method: "GET" | "POST" | "PUT" | "DELETE"; + body?: FormData | string; + headers?: HeadersInit; + raw?: boolean; + retried?: boolean; +}): Promise { + const requestInit: RequestInit = { method: request.method, mode: "cors", cache: "default", @@ -507,16 +553,16 @@ async function generic(request) { try { const response = await fetch(GetWasabeeServer() + request.url, requestInit); /** @type Object | string */ - const payload = await response.text(); + const payload: string = await response.text(); let jsonPayload; if (!request.raw) { if (!payload && !request.retried && response.ok) { // server shouldn't reply empty string console.warn( - `server answers is empty on [${request.url}], retry once, just in case` + `server answers is empty on[${request.url}], retry once, just in case ` ); - return generic({ ...request, retried: true }); + return generic({ ...request, retried: true }); } try { jsonPayload = JSON.parse(payload); @@ -535,11 +581,8 @@ async function generic(request) { case 200: if (!request.raw && jsonPayload.updateID) GetUpdateList().set(jsonPayload.updateID, Date.now()); - return Promise.resolve(request.raw ? payload : jsonPayload); + return Promise.resolve((request.raw ? payload : jsonPayload) as T); // break; - case 304: // If-None-Match or If-Modified-Since replied NotModified - return Promise.resolve(304); - // break case 401: WasabeeMe.purge(); // fallthrough; @@ -549,6 +592,8 @@ async function generic(request) { // fallthrough case 412: // mismatch etag // fallthrough + case 304: // If-None-Match or If-Modified-Since replied NotModified + // fallthrough; default: return Promise.reject( new ServerError({ @@ -569,15 +614,19 @@ async function generic(request) { } } -function genericGet(url) { - return generic({ +function genericGet(url: string) { + return generic({ method: "GET", url: url, }); } -function genericPost(url, formData, contentType) { - return generic({ +function genericPost( + url: string, + formData: FormData | string, + contentType?: string +) { + return generic({ url: url, method: "POST", body: formData, @@ -585,20 +634,18 @@ function genericPost(url, formData, contentType) { }); } -function genericPut(url, formData, contentType) { - return generic({ +function genericPut(url: string, formData: FormData) { + return generic({ url: url, method: "PUT", body: formData, - headers: contentType ? { "Content-Type": contentType } : null, }); } -function genericDelete(url, formData, contentType) { - return generic({ +function genericDelete(url: string, formData?: FormData) { + return generic({ url: url, method: "DELETE", body: formData, - headers: contentType ? { "Content-Type": contentType } : null, }); } From e80bf1b994e9623755e9220eb291d836ab78c981 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 14 Nov 2021 12:35:22 +0100 Subject: [PATCH 110/275] wd.ts --- src/code/wd.d.ts | 15 -------- src/code/{wd.js => wd.ts} | 81 +++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 53 deletions(-) delete mode 100644 src/code/wd.d.ts rename src/code/{wd.js => wd.ts} (69%) diff --git a/src/code/wd.d.ts b/src/code/wd.d.ts deleted file mode 100644 index 6e961e1ee..000000000 --- a/src/code/wd.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -export declare type WDKey = { - Name: string; - PortalID: string; - GID: string; - Lat: string; - Lng: string; - Count: number; - CapID: string; -}; -export declare function initWasabeeD(): void; -export declare function getAllWasabeeDkeys(): Promise; -export declare function getAgentWasabeeDkeys(gid: string): Promise; -export declare function getAllPortalWasabeeDkeys(portalid: string): Promise; -export declare function getAgentPortalWasabeeDkeys(gid: string, portalid: string): Promise; -export declare function drawWasabeeDkeys(): Promise; diff --git a/src/code/wd.js b/src/code/wd.ts similarity index 69% rename from src/code/wd.js rename to src/code/wd.ts index 0024c1882..e4cc01d86 100644 --- a/src/code/wd.js +++ b/src/code/wd.ts @@ -5,52 +5,62 @@ import wX from "./wX"; // import { getPortalDetails } from "./uiCommands"; import AgentUI from "./ui/agent"; +import type { LayerEvent, LayerGroup } from "leaflet"; + +import db from "./db"; + +export type WDKey = { + Name: string; + PortalID: string; + GID: string; + Lat: string; + Lng: string; + Count: number; + CapID: string; +}; + +let defensiveLayer: LayerGroup; // setup function export function initWasabeeD() { - window.plugin.wasabee.defensiveLayers = new L.LayerGroup(); - window.addLayerGroup( - "Wasabee-D Keys", - window.plugin.wasabee.defensiveLayers, - false - ); + window.plugin.wasabee.defensiveLayers = defensiveLayer = new L.LayerGroup(); + window.addLayerGroup("Wasabee-D Keys", defensiveLayer, false); // hook called in init.js after load window.map.on("wasabee:defensivekeys", drawWasabeeDkeys); - window.map.on("layeradd", (obj) => { - if (obj.layer === window.plugin.wasabee.defensiveLayers) { + window.map.on("layeradd", (obj: LayerEvent) => { + if (obj.layer === defensiveLayer) { window.map.fire("wasabee:defensivekeys"); } }); - window.map.on("layerremove", (obj) => { - if (obj.layer === window.plugin.wasabee.defensiveLayers) { + window.map.on("layerremove", (obj: LayerEvent) => { + if (obj.layer === defensiveLayer) { // clearLayers doesn't actually remove the data, just hides it from the map - window.plugin.wasabee.defensiveLayers.clearLayers(); + defensiveLayer.clearLayers(); } }); } -export function getAllWasabeeDkeys() { - return window.plugin.wasabee.idb.getAll("defensivekeys"); +export async function getAllWasabeeDkeys() { + return (await db).getAll("defensivekeys"); } -export async function getAgentWasabeeDkeys(gid) { +export async function getAgentWasabeeDkeys(gid: GoogleID) { const dks = await getAllWasabeeDkeys(); return dks.filter((dk) => dk.GID == gid); } -export function getAllPortalWasabeeDkeys(portalid) { - return window.plugin.wasabee.idb.getAllFromIndex( - "defensivekeys", - "PortalID", - portalid - ); +export async function getAllPortalWasabeeDkeys(portalid: PortalID) { + return (await db).getAllFromIndex("defensivekeys", "PortalID", portalid); } -export function getAgentPortalWasabeeDkeys(gid, portalid) { - return window.plugin.wasabee.idb.get("defensivekeys", [gid, portalid]); +export async function getAgentPortalWasabeeDkeys( + gid: GoogleID, + portalid: PortalID +) { + return (await db).get("defensivekeys", [gid, portalid]); } // This is the primary hook that is called on map refresh @@ -59,7 +69,7 @@ export function getAgentPortalWasabeeDkeys(gid, portalid) { export async function drawWasabeeDkeys() { if (window.isLayerGroupDisplayed("Wasabee-D Keys") === false) return; console.debug("running drawWasabeeDkeys"); - window.plugin.wasabee.defensiveLayers.clearLayers(); + defensiveLayer.clearLayers(); if (WasabeeMe.isLoggedIn()) { try { @@ -85,25 +95,20 @@ export async function drawWasabeeDkeys() { // draws each distinct portalID once async function drawMarkers() { const dks = await getAllWasabeeDkeys(); - const done = new Map(); + const done = new Set(); for (const dk of dks) { if (done.has(dk.PortalID)) continue; - done.set(dk.PortalID, true); + done.add(dk.PortalID); drawMarker(dk); } } // remove and re-add each marker -function drawMarker(dk) { - if ( - window.plugin.wasabee.defensiveLayers[dk.PortalID] && - window.plugin.wasabee.defensiveLayers[dk.PortalID]._leaflet_id - ) - window.plugin.wasabee.defensiveLayers.removeLayer( - window.plugin.wasabee.defensiveLayers[dk.PortalID] - ); - - const marker = L.marker([dk.Lat, dk.Lng], { +function drawMarker(dk: WDKey) { + if (defensiveLayer[dk.PortalID] && defensiveLayer[dk.PortalID]._leaflet_id) + defensiveLayer.removeLayer(defensiveLayer[dk.PortalID]); + + const marker = L.marker([+dk.Lat, +dk.Lng], { title: dk.Name, icon: L.divIcon({ className: "wasabee-defense-icon", @@ -113,8 +118,8 @@ function drawMarker(dk) { popupAnchor: L.point(-1, -48), }), }); - window.plugin.wasabee.defensiveLayers[dk.PortalID] = marker; - marker.addTo(window.plugin.wasabee.defensiveLayers); + defensiveLayer[dk.PortalID] = marker; + marker.addTo(defensiveLayer); window.registerMarkerForOMS(marker); marker.bindPopup("loading...", { @@ -143,7 +148,7 @@ function drawMarker(dk) { } // draw the popup, display the individual agents and their counts -async function getMarkerPopup(PortalID) { +async function getMarkerPopup(PortalID: PortalID) { const container = L.DomUtil.create("div", "wasabee-wd-popup"); // leaflet-draw-tooltip would be cool const ul = L.DomUtil.create("ul", null, container); From 6c2cde9fd97f5badd861b370adc7cbae18b59163 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 14 Nov 2021 12:40:14 +0100 Subject: [PATCH 111/275] toolbox.ts --- src/code/toolbox.d.ts | 1 - src/code/{toolbox.js => toolbox.ts} | 0 2 files changed, 1 deletion(-) delete mode 100644 src/code/toolbox.d.ts rename src/code/{toolbox.js => toolbox.ts} (100%) diff --git a/src/code/toolbox.d.ts b/src/code/toolbox.d.ts deleted file mode 100644 index 1a0053459..000000000 --- a/src/code/toolbox.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare function setupToolbox(): void; diff --git a/src/code/toolbox.js b/src/code/toolbox.ts similarity index 100% rename from src/code/toolbox.js rename to src/code/toolbox.ts From bee8418592012378e618bfbea6f4e823b73a8b64 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 14 Nov 2021 12:46:59 +0100 Subject: [PATCH 112/275] firebase.ts --- src/code/firebaseSupport.d.ts | 2 -- .../{firebaseSupport.js => firebaseSupport.ts} | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) delete mode 100644 src/code/firebaseSupport.d.ts rename src/code/{firebaseSupport.js => firebaseSupport.ts} (94%) diff --git a/src/code/firebaseSupport.d.ts b/src/code/firebaseSupport.d.ts deleted file mode 100644 index 466c320fb..000000000 --- a/src/code/firebaseSupport.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function initFirebase(): void; -export declare function postToFirebase(message: any): void; diff --git a/src/code/firebaseSupport.js b/src/code/firebaseSupport.ts similarity index 94% rename from src/code/firebaseSupport.js rename to src/code/firebaseSupport.ts index 6812ef0e7..35be8428e 100644 --- a/src/code/firebaseSupport.js +++ b/src/code/firebaseSupport.ts @@ -27,8 +27,8 @@ export function initFirebase() { const server = GetWasabeeServer(); const iframe = L.DomUtil.create("iframe"); - iframe.width = 0; - iframe.height = 0; + iframe.width = "0"; + iframe.height = "0"; iframe.src = server + "/static/firebase/index.html"; iframe.id = frameID; @@ -122,7 +122,16 @@ export function initFirebase() { }); } -export function postToFirebase(message) { +interface FirebaseMessage { + id: string; + method: string; + action: string; + error: string; + app_name: string; + app_version: string; +} + +export function postToFirebase(message: Partial) { // prevent analytics data from being sent if not enabled by the user: GPDR /* if ( message.id == "analytics" && From 933653e7123e854c6024ce2e4910890ace97823e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 14 Nov 2021 13:55:38 +0100 Subject: [PATCH 113/275] static.ts --- src/code/static.d.ts | 3 --- src/code/{static.js => static.ts} | 9 ++++++++- 2 files changed, 8 insertions(+), 4 deletions(-) delete mode 100644 src/code/static.d.ts rename src/code/{static.js => static.ts} (96%) diff --git a/src/code/static.d.ts b/src/code/static.d.ts deleted file mode 100644 index 683a3dd8d..000000000 --- a/src/code/static.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare const statics: any; -export declare const constants: any; -export default statics; diff --git a/src/code/static.js b/src/code/static.ts similarity index 96% rename from src/code/static.js rename to src/code/static.ts index 5d743d63e..f87fab7b5 100644 --- a/src/code/static.js +++ b/src/code/static.ts @@ -1,4 +1,11 @@ -const statics = { +// todo complete/rework +type Statics = { + CSS: { [name: string]: string }; + dialogNames: { [name: string]: string }; + [name: string]: any; +} + +const statics: Statics = { CSS: { main: require("./css/wasabee.css"), autodraws: require("./css/autodraws.css"), From a8bc0269b688730de5ddb5ff74af6497e952a5c7 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 14 Nov 2021 15:13:18 +0100 Subject: [PATCH 114/275] init.ts --- src/code/index.d.ts | 1 + src/code/init.d.ts | 1 - src/code/{init.js => init.ts} | 31 +++++++++++++++++++++++------- src/code/leafletClasses.js | 2 +- src/types/iitc/core/constants.d.ts | 4 ++-- src/types/iitc/core/main.d.ts | 6 +++++- webpack.config.js | 2 +- 7 files changed, 34 insertions(+), 13 deletions(-) delete mode 100644 src/code/init.d.ts rename src/code/{init.js => init.ts} (89%) diff --git a/src/code/index.d.ts b/src/code/index.d.ts index 1b2e29c77..095943f71 100644 --- a/src/code/index.d.ts +++ b/src/code/index.d.ts @@ -10,5 +10,6 @@ declare global { type GoogleID = string; type ZoneID = number; + const plugin_info: any; var wasabeewebui: any; } diff --git a/src/code/init.d.ts b/src/code/init.d.ts deleted file mode 100644 index cb0ff5c3b..000000000 --- a/src/code/init.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/src/code/init.js b/src/code/init.ts similarity index 89% rename from src/code/init.js rename to src/code/init.ts index 84a1c54c2..98812906c 100644 --- a/src/code/init.js +++ b/src/code/init.ts @@ -21,8 +21,25 @@ import WasabeeOp from "./model/operation"; import db from "./db"; import polyfill from "./polyfill"; import { displayError } from "./error"; +import type { FeatureGroup, LayerEvent, LayerGroup } from "leaflet"; -const Wasabee = window.plugin.wasabee; +type Awaited = T extends PromiseLike ? U : T; +interface Wasabee { + static: any; + _inited: boolean; + _selectedOp: WasabeeOp; + _updateList: Map; + idb: Awaited; + portalDetailQueue: PortalID[]; + portalLayerGroup: LayerGroup; + linkLayerGroup: LayerGroup; + markerLayerGroup: LayerGroup; + agentLayerGroup: LayerGroup; + zoneLayerGroup: FeatureGroup; + backgroundOpsGroup: LayerGroup; +} + +const Wasabee: Wasabee = window.plugin.wasabee; Wasabee.static = statics; window.plugin.wasabee.init = async () => { @@ -62,7 +79,7 @@ window.plugin.wasabee.init = async () => { await initSelectedOperation(); initServer(); - const skins = []; + const skins: string[] = []; const ss = localStorage[Wasabee.static.constants.SKIN_KEY]; try { const l = JSON.parse(ss); @@ -159,7 +176,7 @@ window.plugin.wasabee.init = async () => { } // hooks called when layers are enabled/disabled - window.map.on("layeradd", (obj) => { + window.map.on("layeradd", (obj: LayerEvent) => { if ( obj.layer === Wasabee.portalLayerGroup || obj.layer === Wasabee.linkLayerGroup || @@ -173,14 +190,14 @@ window.plugin.wasabee.init = async () => { } }); - window.map.on("layerremove", (obj) => { + window.map.on("layerremove", (obj: LayerEvent) => { if ( obj.layer === Wasabee.portalLayerGroup || obj.layer === Wasabee.linkLayerGroup || obj.layer === Wasabee.markerLayerGroup || obj.layer === Wasabee.zoneLayerGroup ) { - obj.layer.clearLayers(); + (obj.layer as LayerGroup).clearLayers(); } }); @@ -219,8 +236,8 @@ window.plugin.wasabee.init = async () => { window.map.fire("wasabee:defensivekeys"); } - window.map.on("wdialog", (dialog) => { - postToFirebase({ id: "analytics", action: dialog.constructor.TYPE }); + window.map.on("wdialog", (event) => { + postToFirebase({ id: "analytics", action: event.dialogType }); }); }; diff --git a/src/code/leafletClasses.js b/src/code/leafletClasses.js index f862a0407..f63ff2e73 100644 --- a/src/code/leafletClasses.js +++ b/src/code/leafletClasses.js @@ -100,7 +100,7 @@ export const WDialog = L.Handler.extend({ L.setOptions(this, options); // determine large or small screen dialog sizes this._smallScreen = this._isMobile(); - window.map.fire("wdialog", this); + window.map.fire("wdialog", { dialogType: this.constructor.TYPE }); this.options.usePane = this.options.usePane && window.isSmartphone() && diff --git a/src/types/iitc/core/constants.d.ts b/src/types/iitc/core/constants.d.ts index 86be064d6..d515bbe6c 100755 --- a/src/types/iitc/core/constants.d.ts +++ b/src/types/iitc/core/constants.d.ts @@ -3,8 +3,8 @@ import { IITC, PortalGUID } from "./iitctypes"; export {}; declare global { - const script_info: any; - const iitcBuildDate: string; + var script_info: any; + var iitcBuildDate: string; // CONFIG OPTIONS //////////////////////////////////////////////////// const REFRESH: number; /** @default = 30; // refresh view every 30s (base time) */ diff --git a/src/types/iitc/core/main.d.ts b/src/types/iitc/core/main.d.ts index 49a1db7da..ad6c6b9c4 100755 --- a/src/types/iitc/core/main.d.ts +++ b/src/types/iitc/core/main.d.ts @@ -3,9 +3,13 @@ import * as jQuery from "jquery"; import { Intel } from "./inteltypes"; import { MapDataRequest } from "./map_data_request"; +export interface IPlugin { + [pluginName: string]: any; +} + declare global { /** All iitc Pluigns */ - var plugin: any; + var plugin: IPlugin; /** iitc-Pluigns setup/initialize function */ var bootPlugins: BootCallback[]; diff --git a/webpack.config.js b/webpack.config.js index 6f6493d4d..fc431fd5c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -132,7 +132,7 @@ class IITCScript { const config = { entry: { - init: "./src/code/init.js", + init: "./src/code/init.ts", }, output: { filename: "wasabee.user.js", From 83f492ff2570552ead98180d74536aaa829d5441 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 14 Nov 2021 15:36:44 +0100 Subject: [PATCH 115/275] uiCommands.ts --- src/code/uiCommands.d.ts | 25 ----------- src/code/{uiCommands.js => uiCommands.ts} | 55 +++++++++++++---------- 2 files changed, 32 insertions(+), 48 deletions(-) delete mode 100644 src/code/uiCommands.d.ts rename src/code/{uiCommands.js => uiCommands.ts} (92%) diff --git a/src/code/uiCommands.d.ts b/src/code/uiCommands.d.ts deleted file mode 100644 index b62d1ae10..000000000 --- a/src/code/uiCommands.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -export declare function addPortal(operation: any, portal: any): void; -export declare function swapPortal(operation: any, portal: any): void; -export declare function deletePortal(operation: any, portal: any): void; -export declare function deleteMarker(operation: any, marker: any, portal: any): void; -export declare function clearAllItems(operation: any): void; -export declare function clearAllLinks(operation: any): void; -export declare function clearAllMarkers(operation: any): void; -export declare function listenForAddedPortals(newPortal: any): void; -export declare function listenForPortalDetails(e: any): void; -export declare function getPortalDetails(guid: any): void; -export declare function loadFaked(operation: any, force?: boolean): void; -export declare function loadBlockerFaked(operation: any, force?: boolean): Promise; -export declare function sendLocation(): void; -export declare function getAllPortalsOnScreen(operation: any): any[]; -export declare function getAllPortalsLinked(operation: any, originPortal: any): any[]; -export declare function testPortal(recursed?: boolean): any; -export declare function blockerAutomark(operation: any, first?: boolean): Promise; -export declare function zoomToOperation(operation: any): void; -export declare function updateLocalOp(local: any, remote: any): Promise; -export declare function fullSync(): Promise; -export declare function syncOp(opID: any): Promise; -export declare function deleteLocalOp(opname: any, opid: any): void; -export declare function resetCaches(): Promise; -export declare function setMarkersToZones(): void; -export declare function setLinksToZones(): void; diff --git a/src/code/uiCommands.js b/src/code/uiCommands.ts similarity index 92% rename from src/code/uiCommands.js rename to src/code/uiCommands.ts index 288e438c2..58e932187 100644 --- a/src/code/uiCommands.js +++ b/src/code/uiCommands.ts @@ -25,7 +25,7 @@ import { ServerError, } from "./error"; -export function addPortal(operation, portal) { +export function addPortal(operation: WasabeeOp, portal: WasabeePortal) { if (!portal) { displayError(wX("SELECT PORTAL")); return; @@ -33,7 +33,7 @@ export function addPortal(operation, portal) { operation.addPortal(portal); } -export function swapPortal(operation, portal) { +export function swapPortal(operation: WasabeeOp, portal: WasabeePortal) { const selectedPortal = PortalUI.getSelected(); if (!selectedPortal) { displayError(wX("SELECT PORTAL")); @@ -61,7 +61,7 @@ export function swapPortal(operation, portal) { con.enable(); } -export function deletePortal(operation, portal) { +export function deletePortal(operation: WasabeeOp, portal: WasabeePortal) { const pr = L.DomUtil.create("div", null); pr.textContent = wX("DELETE ANCHOR PROMPT"); pr.appendChild(PortalUI.displayFormat(portal)); @@ -77,7 +77,11 @@ export function deletePortal(operation, portal) { con.enable(); } -export function deleteMarker(operation, marker, portal) { +export function deleteMarker( + operation: WasabeeOp, + marker: WasabeeMarker, + portal: WasabeePortal +) { const pr = L.DomUtil.create("div", null); pr.textContent = wX("DELETE MARKER PROMPT"); pr.appendChild(PortalUI.displayFormat(portal)); @@ -93,7 +97,7 @@ export function deleteMarker(operation, marker, portal) { con.enable(); } -export function clearAllItems(operation) { +export function clearAllItems(operation: WasabeeOp) { const con = new ConfirmDialog({ title: `Clear: ${operation.name}`, label: `Do you want to reset ${operation.name}?`, @@ -106,7 +110,7 @@ export function clearAllItems(operation) { con.enable(); } -export function clearAllLinks(operation) { +export function clearAllLinks(operation: WasabeeOp) { const con = new ConfirmDialog({ title: `Clear Links: ${operation.name}`, label: `Do you want to remove all links from ${operation.name}?`, @@ -119,7 +123,7 @@ export function clearAllLinks(operation) { con.enable(); } -export function clearAllMarkers(operation) { +export function clearAllMarkers(operation: WasabeeOp) { const con = new ConfirmDialog({ title: `Clear Markers: ${operation.name}`, label: `Do you want to remove all markers from ${operation.name}?`, @@ -208,7 +212,7 @@ function pdqDoNext() { } // load faked op portals -export function loadFaked(operation, force = false) { +export function loadFaked(operation: WasabeeOp, force = false) { const flag = localStorage[window.plugin.wasabee.static.constants.AUTO_LOAD_FAKED] || false; @@ -222,7 +226,7 @@ export function loadFaked(operation, force = false) { } // load faked blocker portals -export async function loadBlockerFaked(operation, force = false) { +export async function loadBlockerFaked(operation: WasabeeOp, force = false) { const flag = localStorage[window.plugin.wasabee.static.constants.AUTO_LOAD_FAKED] || false; @@ -259,7 +263,7 @@ export function sendLocation() { ); } -export function getAllPortalsOnScreen(operation) { +export function getAllPortalsOnScreen(operation: WasabeeOp) { const bounds = window.map.getBounds(); const x = []; for (const portal in window.portals) { @@ -278,11 +282,19 @@ export function getAllPortalsOnScreen(operation) { return x; } -export function getAllPortalsLinked(operation, originPortal) { +export function getAllPortalsLinked( + operation: WasabeeOp, + originPortal: WasabeePortal +) { const x = []; for (const link in window.links) { const p = window.links[link]; + if ( + operation.containsLinkFromTo(p.options.data.oGuid, p.options.data.dGuid) + ) + continue; + const linkPortal1 = new WasabeePortal({ id: p.options.data.oGuid, lat: (p.options.data.oLatE6 / 1e6).toFixed(6), @@ -299,9 +311,6 @@ export function getAllPortalsLinked(operation, originPortal) { comment: "out", }); - if (operation.containsLinkFromTo(linkPortal1, linkPortal2)) { - continue; - } if (linkPortal1.id === originPortal.id) { x.push(linkPortal2); } @@ -345,7 +354,7 @@ export function testPortal(recursed = false) { } // recursive function to auto-mark blockers -export async function blockerAutomark(operation, first = true) { +export async function blockerAutomark(operation: WasabeeOp, first = true) { const blockers = await WasabeeBlocker.getAll(operation); if (first) { operation.startBatchMode(); @@ -370,7 +379,7 @@ export async function blockerAutomark(operation, first = true) { } } // build count list - const portals = new Array(); + const portals: PortalID[] = []; for (const b of blockers) { if ( !operation.containsMarkerByID( @@ -387,7 +396,7 @@ export async function blockerAutomark(operation, first = true) { ) portals.push(b.to); } - const reduced = {}; + const reduced: { [id: PortalID]: number } = {}; for (const p of portals) { if (!reduced[p]) reduced[p] = 0; reduced[p]++; @@ -431,10 +440,10 @@ export async function blockerAutomark(operation, first = true) { if (first) operation.endBatchMode(); } -export function zoomToOperation(operation) { +export function zoomToOperation(operation: WasabeeOp) { if (!operation) return; const mbr = operation.mbr; - if (mbr && isFinite(mbr._southWest.lat) && isFinite(mbr._northEast.lat)) { + if (mbr && mbr.isValid()) { window.map.fitBounds(mbr); } } @@ -485,7 +494,6 @@ export async function fullSync() { try { let reloadOpID = null; const me = await WasabeeMe.waitGet(true); - const promises = new Array(); const opsID = new Set(me.Ops.map((o) => o.ID)); // delete operations absent from server unless the owner @@ -513,12 +521,13 @@ export async function fullSync() { serverOps.map((op) => op.ID) ); + const promises: Promise[] = []; for (const opID of opsID) { promises.push(opPromise(opID)); } const ops = (await Promise.allSettled(promises)) .filter((p) => p.status === "fulfilled") - .map((p) => p.value); + .map((p: PromiseFulfilledResult) => p.value); for (const newop of ops) { const localOp = await WasabeeOp.load(newop.ID); const reloadSO = await updateLocalOp(localOp, newop); @@ -546,7 +555,7 @@ export async function fullSync() { } } -export async function syncOp(opID) { +export async function syncOp(opID: OpID) { const localOp = await WasabeeOp.load(opID); const remoteOp = await opPromise(opID); if (remoteOp.lasteditid != localOp.lasteditid) { @@ -562,7 +571,7 @@ export async function syncOp(opID) { } } -export function deleteLocalOp(opname, opid) { +export function deleteLocalOp(opname: string, opid: OpID) { const con = new ConfirmDialog({ title: wX("REM_LOC_CP", { opName: opname }), label: wX("YESNO_DEL", { opName: opname }), From c431b56ffec054262fd4f978786400372968167d Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 14 Nov 2021 17:40:29 +0100 Subject: [PATCH 116/275] remove wild&unused arg --- src/code/dialogs/settingsDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index 0f69b4330..e97b4fb07 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -173,7 +173,7 @@ const SettingsDialog = WDialog.extend({ skinsButton.textContent = wX("SKINS_BUTTON"); L.DomEvent.on(skinsButton, "click", (ev) => { L.DomEvent.stop(ev); - const skinDialog = new SkinDialog(window.map); + const skinDialog = new SkinDialog(); skinDialog.enable(); }); From 1f59ea7b26f526b9e9de666325f73b5c2de88003 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 14 Nov 2021 19:01:17 +0100 Subject: [PATCH 117/275] removeNonOwnedOps on wasabee:logout event --- src/code/buttons/wasabeeButton.js | 5 +---- src/code/init.ts | 8 +++++++- src/code/model/me.ts | 3 ++- src/code/selectedOp.ts | 13 ++++++++++--- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/code/buttons/wasabeeButton.js b/src/code/buttons/wasabeeButton.js index 046da41fa..bb2bf16b8 100644 --- a/src/code/buttons/wasabeeButton.js +++ b/src/code/buttons/wasabeeButton.js @@ -6,7 +6,7 @@ import AuthDialog from "../dialogs/authDialog"; import ConfirmDialog from "../dialogs/confirmDialog"; import NewopDialog from "../dialogs/newopDialog"; import SettingsDialog from "../dialogs/settingsDialog.js"; -import { resetOps, setupLocalStorage, removeNonOwnedOps } from "../selectedOp"; +import { resetOps, setupLocalStorage } from "../selectedOp"; import DefensiveKeysDialog from "../dialogs/defensiveKeysDialog"; import { wX } from "../wX"; import { logoutPromise } from "../server"; @@ -106,9 +106,6 @@ const WasabeeButton = WButton.extend({ text: wX("LOG_OUT"), callback: async () => { try { - // if not actually logged in, this removes ALL server ops - // but this button _should_ not be visible in that case - await removeNonOwnedOps(); await logoutPromise(); } catch (e) { console.error(e); diff --git a/src/code/init.ts b/src/code/init.ts index 98812906c..22903598b 100644 --- a/src/code/init.ts +++ b/src/code/init.ts @@ -1,7 +1,11 @@ import statics from "./static"; import { initCrossLinks } from "./crosslinks"; import initServer from "./server"; -import { setupLocalStorage, initSelectedOperation } from "./selectedOp"; +import { + setupLocalStorage, + initSelectedOperation, + removeNonOwnedOps, +} from "./selectedOp"; import { drawMap, drawAgents, @@ -142,6 +146,8 @@ window.plugin.wasabee.init = async () => { window.map.on("wasabee:agentlocations", drawAgents); window.map.on("wasabee:logout", drawAgents); + window.map.on("wasabee:logout", removeNonOwnedOps); + // when the UI is woken from sleep on many devices window.addResumeFunction(() => { // check if still logged in diff --git a/src/code/model/me.ts b/src/code/model/me.ts index 54aa6c53e..f43fa77e6 100644 --- a/src/code/model/me.ts +++ b/src/code/model/me.ts @@ -154,6 +154,7 @@ export default class WasabeeMe extends WasabeeAgent { } static async purge() { + const me = WasabeeMe.localGet(); delete localStorage[constants.AGENT_INFO_KEY]; delete localStorage["sentToServer"]; // resend firebase token on login @@ -166,7 +167,7 @@ export default class WasabeeMe extends WasabeeAgent { const dkos = tr.objectStore("defensivekeys"); await Promise.all([agentos.clear(), teamos.clear(), dkos.clear(), tr.done]); - window.map.fire("wasabee:logout"); + window.map.fire("wasabee:logout", { GID: me ? me.id : null}); } teamJoined(teamID) { diff --git a/src/code/selectedOp.ts b/src/code/selectedOp.ts index 2638746aa..49328ff6c 100644 --- a/src/code/selectedOp.ts +++ b/src/code/selectedOp.ts @@ -3,6 +3,7 @@ import WasabeeBlocker from "./model/blocker"; import wX from "./wX"; import { generateId } from "./auxiliar"; import { displayError } from "./error"; +import type { LeafletEvent } from "leaflet"; function setRestoreOpID(opID: OpID) { localStorage[window.plugin.wasabee.static.constants.SELECTED_OP_KEY] = opID; @@ -244,12 +245,18 @@ export async function duplicateOperation(opID: OpID) { return op; } -// this checks me from cache; if not logged in, no op is owned and all on server will be deleted, which may confuse users -export async function removeNonOwnedOps() { +// use the provided GID to delete server ops +export async function removeNonOwnedOps( + data: LeafletEvent & { GID: GoogleID } +) { + // no GID provided, likely following a server change while not logged in + if (!data.GID) { + return; + } for (const opID of await opsList()) { const op = await WasabeeOp.load(opID); // don't fire event here - if (!op || !op.isOwnedOp()) { + if (!op || (op.isServerOp() && op.creator !== data.GID)) { await WasabeeOp.delete(opID); WasabeeBlocker.removeBlockers(opID); // no need to await } From 8f6428192dd89381b00a1924656d0bd620f9337e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Dec 2021 21:49:34 +0100 Subject: [PATCH 118/275] fix: hidden undefined marker comment in popup fix #296 --- src/code/css/map.css | 5 +++++ src/code/ui/marker.js | 16 +++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/code/css/map.css b/src/code/css/map.css index 5a5bdee59..66c22f4ec 100644 --- a/src/code/css/map.css +++ b/src/code/css/map.css @@ -87,6 +87,11 @@ .wasabee-marker-popup-comment { font-weight: initial; + cursor: pointer; +} + +.wasabee-marker-popup-comment:hover { + text-decoration: underline; } .wasabee-marker-popup-kind { diff --git a/src/code/ui/marker.js b/src/code/ui/marker.js index 7a1158776..6d0f8c17b 100644 --- a/src/code/ui/marker.js +++ b/src/code/ui/marker.js @@ -86,15 +86,13 @@ const WLMarker = PortalUI.WLPortal.extend({ }, _popupMarkerComment: function (container, marker, canWrite) { - if (marker.comment) { - const comment = L.DomUtil.create( - "div", - "wasabee-marker-popup-comment", - container - ); - comment.textContent = marker.comment; - if (canWrite) L.DomEvent.on(comment, "click", this._setComment, this); - } + const comment = L.DomUtil.create( + "div", + "wasabee-marker-popup-comment", + container + ); + comment.textContent = marker.comment || wX("SET_COMMENT"); + if (canWrite) L.DomEvent.on(comment, "click", this._setComment, this); }, _popupAssignState: async function (container, marker) { From 476bbab8c04872c1d671431cbcc0fa2021de91f1 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 11:40:17 +0100 Subject: [PATCH 119/275] android auth: remove reference to select_account complete aa1b98f8d83a23e232484ea990447c1138de4cb8 --- src/code/dialogs/authDialog.js | 3 --- src/code/translations/danish.json | 1 - src/code/translations/english.json | 1 - src/code/translations/filipino.json | 1 - src/code/translations/french.json | 1 - src/code/translations/german.json | 1 - src/code/translations/italian.json | 1 - src/code/translations/portuguese.json | 1 - src/code/translations/russian.json | 1 - src/code/translations/spanish.json | 1 - 10 files changed, 12 deletions(-) diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index a7bc51e20..5d32a8c49 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -82,9 +82,6 @@ const AuthDialog = WDialog.extend({ if (this._ios) { title.textContent = wX("AUTH IOS"); } - if (this._android) { - title.textContent = wX("AUTH ANDROID"); - } const gapiButton = L.DomUtil.create("button", "gapi", content); gapiButton.textContent = wX("LOG IN"); diff --git a/src/code/translations/danish.json b/src/code/translations/danish.json index 22f9c4751..a9398e42e 100644 --- a/src/code/translations/danish.json +++ b/src/code/translations/danish.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "KT", "ASSIGNED_ONLY": "Kun tildelt", "assigned": "Tildelt", - "AUTH ANDROID": "På Android, prøv 'hurtigt' først. Hvis det mislykkes, prøv hovedlogin med 'vælg_konto'.", "AUTH INCOMPAT": "Du har aktiveret et plugin i TamperMonkey, der er inkompatibelt med Wasabee", "AUTH IOS": "På iOS skal du bruge \"Log ind\". Hvis det mislykkes, skal du bruge 'Webview-login' og derefter bruge 'Verify Webview'-knappen for at fuldføre processen.", "AUTH REQUIRED": "Godkendelse påkrævet", diff --git a/src/code/translations/english.json b/src/code/translations/english.json index b2617b364..c8d58f927 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Assigned Only", "assigned": "Assigned", - "AUTH ANDROID": "On Android, try 'quick' first. If that fails, try the main login with 'select_account'.", "AUTH INCOMPAT": "You have activated a plugin in TamperMonkey that is incompatable with Wasabee", "AUTH IOS": "On iOS, use the main 'Log In' option. If that fails, use 'Webview Login' then use the 'Verify Webview' button to complete the process.", "AUTH REQUIRED": "Authentication Required", diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index 157cb4006..cda8558c4 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Assigned Only", "assigned": "Naitalaga", - "AUTH ANDROID": "Sa Android, subukan muna ang 'quick'. Kung hindi gumana, subukan ang main login gamit ang 'select_account'.", "AUTH INCOMPAT": "May ginagamit kang plugin sa TamperMonkey na hindi angkop sa Wasabee", "AUTH IOS": "Sa iOS, subukan muna ang 'Log In'. Kung hindi gumana, gawin ang 'Webview Log in', mag-log in, tapos gamitin ang 'Verify Webview' button para makumpleto ang proseso.", "AUTH REQUIRED": "Kailangan ng Authentication", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index c962bcd78..749622c73 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Seulement les affectations", "assigned": "Assigné", - "AUTH ANDROID": "On Android, try 'quick' first. If that fails, try the main login with 'select_account'.", "AUTH INCOMPAT": "You have activated a plugin in TamperMonkey that is incompatable with Wasabee", "AUTH IOS": "On iOS, use the main 'Log In' option. If that fails, use 'Webview Login' then use the 'Verify Webview' button to complete the process.", "AUTH REQUIRED": "Autentification requise", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index 086cd7cdd..c84e14310 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Assigned Only", "assigned": "Zugewiesen", - "AUTH ANDROID": "Mit Android versuche 'quick' zuerst. Wenn das fehlschlägt, versuche es mit 'select_account' ", "AUTH INCOMPAT": "Du hast ein Plugin aktiviert welches inkompatibel zu Wasabee ist.", "AUTH IOS": "Mit IOS nutze 'Log in'. Wenn das fehlschlägt nutze 'Webview Log in'; Danach nutze den 'Verify Webview' Knopf um den Prozess abzuschließen", "AUTH REQUIRED": "Authorisierung benötigt", diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index 2000c3823..a099b2240 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Solo Assegnati", "assigned": "Assegnato", - "AUTH ANDROID": "Su Android, prova prima il login 'rapido'. Se fallisce, prova ad accedere con 'select_account'.", "AUTH INCOMPAT": "Hai attivato un plugin in TamperMonkey incompatibile con Wasabee", "AUTH IOS": "Su iOS, usa 'Log In'. Se fallisce, prova 'Webview Log in'; poi premi 'Verify Webview' per completare il processo.", "AUTH REQUIRED": "Autenticazione Richiesta", diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index a8d2d6c8c..310f059c5 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "A", "ASSIGNED_ONLY": "Só Atribuir", "assigned": "Atribuído", - "AUTH ANDROID": "No Android, tentar primeiro 'rápido'. Se isso falhar, tentar o login principal com 'select_account'..", "AUTH INCOMPAT": "Você ativou um plugin no TamperMonkey que é incompatível com o Wasabee", "AUTH IOS": "No iOS, use o 'Login' principal. se isso falhar, faça 'Webview Log in', faça o login; em seguida, use o botão 'Verificar Webview' para concluir o processo.", "AUTH REQUIRED": "Autentificação Requerida", diff --git a/src/code/translations/russian.json b/src/code/translations/russian.json index 08d4f9cd0..a453ff8d9 100644 --- a/src/code/translations/russian.json +++ b/src/code/translations/russian.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Только назначенные", "assigned": "Назначено", - "AUTH ANDROID": "На Android, попробуй сначала 'быстрый логин'. Если не получится, попробуй обычный логин через 'выбери аккаунт'.", "AUTH INCOMPAT": "Ты активировал в TamperMonkey плагин, который несовместим с Wasabee", "AUTH IOS": "На iOS, используй основную опцию 'Логин'. Если не получится, используй 'Логин Webview', а затем кнопку 'Подтвердить Webview' для завершения процесса.", "AUTH REQUIRED": "Необходима аутентификация", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index 055c15334..97f96f26a 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -38,7 +38,6 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Assigned Only", "assigned": "Asignado", - "AUTH ANDROID": "On En Android, prueba 'rápido' primero. Si eso falla, intenta el inicio de sesión principal con 'select_account'.", "AUTH INCOMPAT": "Has activado un plugin en TamperMonkey que es incompatible con Wasabee", "AUTH IOS": "En iOS, usa el 'Iniciar Sesión' principal. Si eso falla intenta usar 'Inicio de Sesión Vista Web'; luego usa el botón 'Verificar Vista Web' para completar el proceso.", "AUTH REQUIRED": "Autenticación Requerida", From cd84bab874cbbaab8073f92db43625ec53e85780 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 18:35:32 +0100 Subject: [PATCH 120/275] fix: incomplete regular expression for hostnames --- src/code/dialogs/importDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/dialogs/importDialog.js b/src/code/dialogs/importDialog.js index 5334467fb..c19173cf9 100644 --- a/src/code/dialogs/importDialog.js +++ b/src/code/dialogs/importDialog.js @@ -104,7 +104,7 @@ const ImportDialog = WDialog.extend({ let string = this._textarea.value; if ( string.match( - new RegExp("^(https?://)?(www\\.)?intel.ingress.com/intel.*") + new RegExp("^(https?://)?(www|intel)\\.ingress\\.com/(intel)?.*") ) ) { displayError(wX("NO_STOCK_INTEL")); From b6144c8e09c09253257d5c678d934c6c0f7352a0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 20:43:56 +0100 Subject: [PATCH 121/275] translations: readd NOT_LOADED --- src/code/translations/english.json | 1 + src/code/translations/filipino.json | 1 + src/code/translations/french.json | 1 + src/code/translations/german.json | 1 + src/code/translations/italian.json | 1 + src/code/translations/portuguese.json | 1 + src/code/translations/spanish.json | 1 + 7 files changed, 7 insertions(+) diff --git a/src/code/translations/english.json b/src/code/translations/english.json index c8d58f927..f74ed6796 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -209,6 +209,7 @@ "NO LONGER AVAILABLE SHORT": "Resource removed from server", "NOT LOGGED IN SHORT": "Not Logged in", "NOT LOGGED IN": "Not Logged in: {error}", + "NOT_LOADED": "Not fully loaded, try again.", "NOT_SET": "not set", "NTNAME": "Name", "OK": "OK", diff --git a/src/code/translations/filipino.json b/src/code/translations/filipino.json index cda8558c4..080b617bf 100644 --- a/src/code/translations/filipino.json +++ b/src/code/translations/filipino.json @@ -208,6 +208,7 @@ "NO LONGER AVAILABLE SHORT": "Resource removed from server", "NOT LOGGED IN SHORT": "Hindi naka-Logged in", "NOT LOGGED IN": "Hindi naka-Logged in {error}", + "NOT_LOADED": "Hindi nai-load, ulitin muli.", "NOT_SET": "hindi naitalaga", "NTNAME": "Pangalan", "OK": "OK", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index 749622c73..d5939d878 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -208,6 +208,7 @@ "NO LONGER AVAILABLE SHORT": "Ressource supprimée du serveur", "NOT LOGGED IN SHORT": "Déconnecté", "NOT LOGGED IN": "Déconnecté : {error}", + "NOT_LOADED": "N'a pas chargé entierement, essayer à nouveau", "NOT_SET": "non défini", "NTNAME": "Nom", "OK": "OK", diff --git a/src/code/translations/german.json b/src/code/translations/german.json index c84e14310..9a9bbd2e1 100644 --- a/src/code/translations/german.json +++ b/src/code/translations/german.json @@ -208,6 +208,7 @@ "NO LONGER AVAILABLE SHORT": "Ressource vom Server entfernt", "NOT LOGGED IN SHORT": "Nicht eingeloggt.", "NOT LOGGED IN": "Nicht eingeloggt: {error}", + "NOT_LOADED": "Nicht vollständig geladen - bitte erneut probieren.", "NOT_SET": "nicht gesetzt", "NTNAME": "Name", "OK": "OK", diff --git a/src/code/translations/italian.json b/src/code/translations/italian.json index a099b2240..39a3ed79f 100644 --- a/src/code/translations/italian.json +++ b/src/code/translations/italian.json @@ -208,6 +208,7 @@ "NO LONGER AVAILABLE SHORT": "Risorsa rimossa dal server", "NOT LOGGED IN SHORT": "Non loggato", "NOT LOGGED IN": "Non loggato: {error}", + "NOT_LOADED": "Caricamento incompleto, riprova.", "NOT_SET": "non impostato", "NTNAME": "Nome", "OK": "OK", diff --git a/src/code/translations/portuguese.json b/src/code/translations/portuguese.json index 310f059c5..845f020b4 100644 --- a/src/code/translations/portuguese.json +++ b/src/code/translations/portuguese.json @@ -208,6 +208,7 @@ "NO LONGER AVAILABLE SHORT": "Recurso removido do servidor", "NOT LOGGED IN SHORT": "Não logado", "NOT LOGGED IN": "Não logado: ${value}", + "NOT_LOADED": "Não totalmente carregado, tente novamente.", "NOT_SET": "não configurado", "NTNAME": "Nome", "OK": "OK", diff --git a/src/code/translations/spanish.json b/src/code/translations/spanish.json index 97f96f26a..df5b86ee9 100644 --- a/src/code/translations/spanish.json +++ b/src/code/translations/spanish.json @@ -208,6 +208,7 @@ "NO LONGER AVAILABLE SHORT": "Recurso eliminado del servidor", "NOT LOGGED IN SHORT": "Sesión No Iniciada", "NOT LOGGED IN": "Sesión No Iniciada: {error}", + "NOT_LOADED": "No está cargado completamente, intentar de nuevo.", "NOT_SET": "no definido", "NTNAME": "Nombre", "OK": "OK", From 96e2e028a1f4e457540e5d0baec64e3200384bc0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 21:10:48 +0100 Subject: [PATCH 122/275] syncOp: fire fullSync even or error --- src/code/uiCommands.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code/uiCommands.ts b/src/code/uiCommands.ts index 58e932187..4f118165a 100644 --- a/src/code/uiCommands.ts +++ b/src/code/uiCommands.ts @@ -542,8 +542,6 @@ export async function fullSync() { if (op !== so) zoomToOperation(op); } - // update UI to reflect new ops list - window.map.fire("wasabee:fullsync"); window.map.fire("wasabee:teams"); // if any team dialogs are open displayInfo(wX("SYNC DONE")); @@ -553,6 +551,8 @@ export async function fullSync() { if (WasabeeMe.isLoggedIn()) displayWarning(wX("NOT_LOADED")); else new AuthDialog().enable(); } + // update UI to reflect new ops list + window.map.fire("wasabee:fullsync"); } export async function syncOp(opID: OpID) { From 20d01f415f051f5445b2454805149fd936f58f11 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 21:25:26 +0100 Subject: [PATCH 123/275] fix: send intel name --- src/code/model/me.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/code/model/me.ts b/src/code/model/me.ts index f43fa77e6..e2de5947e 100644 --- a/src/code/model/me.ts +++ b/src/code/model/me.ts @@ -53,7 +53,6 @@ export default class WasabeeMe extends WasabeeAgent { this.pic = data.pic; this.intelfaction = data.intelfaction; this.lockey = data.lockey; - this.querytoken = data.lockey; this.vapi = data.vapi; this.Teams = []; @@ -167,7 +166,7 @@ export default class WasabeeMe extends WasabeeAgent { const dkos = tr.objectStore("defensivekeys"); await Promise.all([agentos.clear(), teamos.clear(), dkos.clear(), tr.done]); - window.map.fire("wasabee:logout", { GID: me ? me.id : null}); + window.map.fire("wasabee:logout", { GID: me ? me.id : null }); } teamJoined(teamID) { From 69064ae9781af8b69860427b992bf88ad56b74cd Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 22:00:09 +0100 Subject: [PATCH 124/275] error: fix http code == 0 --- src/code/error.ts | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/code/error.ts b/src/code/error.ts index 2a6ecc632..28c3320e4 100644 --- a/src/code/error.ts +++ b/src/code/error.ts @@ -8,25 +8,28 @@ interface IServerError { export function displayInfo(content: string | HTMLElement, isHTML?: boolean) { return window.dialog({ - title: 'Wasabee info', + title: "Wasabee info", text: isHTML ? null : content.toString(), html: isHTML ? content : null, - }) + }); } -export function displayWarning(content: string | HTMLElement, isHTML?: boolean) { +export function displayWarning( + content: string | HTMLElement, + isHTML?: boolean +) { return window.dialog({ - title: 'Wasabee warning', + title: "Wasabee warning", text: isHTML ? null : content.toString(), html: isHTML ? content : null, - }) + }); } export function displayError(err: { toString(): string }) { return window.dialog({ - title: 'Wasabee error', + title: "Wasabee error", text: err.toString(), - }) + }); } // no stacktrace error @@ -39,30 +42,30 @@ export class ServerError implements IServerError { this.code = obj.code; this.text = obj.text; this.error = obj.error; + + if (!this.code) { + this.code = -1; + this.text = "Unknown error"; + } } toString() { switch (this.code) { case 401: - if (this.error) - return wX("NOT LOGGED IN", this); + if (this.error) return wX("NOT LOGGED IN", this); return wX("NOT LOGGED IN SHORT"); case 403: - if (this.error) - return wX("PERM DENIED", this); + if (this.error) return wX("PERM DENIED", this); return wX("PERM DENIED SHORT"); case 410: - if (this.error) - return wX("NO LONGER AVAILABLE", this); + if (this.error) return wX("NO LONGER AVAILABLE", this); return wX("NO LONGER AVAILABLE SHORT"); case 412: // for internal use only - if (this.error) - return 'Mismatch version: ' + this.error; - return 'Mismatch version'; + if (this.error) return "Mismatch version: " + this.error; + return "Mismatch version"; default: - if (this.error) - return this.text + ': ' + this.error; + if (this.error) return this.text + ": " + this.error; return this.text; } } From 72f6e30e6d12e4dba48fc93073e112632c86fc49 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 11 Dec 2021 23:01:02 +0100 Subject: [PATCH 125/275] fix: race when dialog update before full init --- src/code/dialogs/blockersList.js | 3 ++- src/code/dialogs/checklist.js | 1 + src/code/dialogs/linkListDialog.js | 1 + src/code/dialogs/markerList.js | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index 91bb5a53a..f43e1c6c0 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -90,8 +90,9 @@ const BlockerList = WDialog.extend({ // when op changed or crosslink ended update: async function () { - const operation = getSelectedOperation(); if (!this._enabled) return; + if (!this.sortable) return; + const operation = getSelectedOperation(); this.sortable = await this._getListDialogContent( this.sortable.sortBy, this.sortable.sortAsc diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 19a943dcf..95ba88b23 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -88,6 +88,7 @@ const OperationChecklistDialog = WDialog.extend({ }, update: async function () { + if (!this.sortable) return; const operation = getSelectedOperation(); this.setTitle(wX("OP_CHECKLIST", { opName: operation.name })); this.sortable = this.getListDialogContent( diff --git a/src/code/dialogs/linkListDialog.js b/src/code/dialogs/linkListDialog.js index 5255d9246..8ad4a9411 100644 --- a/src/code/dialogs/linkListDialog.js +++ b/src/code/dialogs/linkListDialog.js @@ -78,6 +78,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ }, update: async function () { + if (!this.sortable) return; const operation = getSelectedOperation(); const links = operation.getLinkListFromPortal(this.options.portal); const fromCount = links.filter( diff --git a/src/code/dialogs/markerList.js b/src/code/dialogs/markerList.js index 72c0fa629..3090f1d87 100644 --- a/src/code/dialogs/markerList.js +++ b/src/code/dialogs/markerList.js @@ -40,6 +40,7 @@ const MarkerList = OperationChecklistDialog.extend({ }, update: async function () { + if (!this.sortable) return; const operation = getSelectedOperation(); this.setTitle(wX("MARKER_LIST", { opName: operation.name })); this.sortable = this.getListDialogContent( From e8cc7c66ec9a99d8436747d1298ccf1d2d8d489a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 13:29:12 +0100 Subject: [PATCH 126/275] build: use eval-source for PR --- webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webpack.config.js b/webpack.config.js index fc431fd5c..be7e70d78 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -181,7 +181,7 @@ module.exports = (env, argv) => { Object.assign(meta, pluginConfig.headers.scot); } else if (env.pr) { config.output.path = path.join(outputPath, "dev"); - config.devtool = "inline-source-map"; + config.devtool = "eval-source-map"; Object.assign(meta, pluginConfig.headers.pr); meta.version += env.pr; } else if (argv.mode === "development") { From bf76ad67387289fb3baaa1b815607726f748cd6f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 13 Dec 2021 20:50:23 +0100 Subject: [PATCH 127/275] build: add commit hash into dev builds --- webpack.config.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/webpack.config.js b/webpack.config.js index be7e70d78..67ae6ea5f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,7 @@ const path = require("path"); const outputPath = path.join(__dirname, "releases"); const ESLintPlugin = require("eslint-webpack-plugin"); +const childProcess = require("child_process"); const { ConcatSource } = require("webpack-sources"); const Compilation = require("webpack/lib/Compilation"); @@ -171,10 +172,23 @@ const config = { plugins: [new ESLintPlugin({ fix: true })], }; +function getCommitShort() { + try { + const commit = childProcess + .execSync("git rev-parse --short HEAD") + .toString() + .trim(); + return commit; + } catch { + return null; + } +} + module.exports = (env, argv) => { const pluginConfig = require("./plugin.config.json"); const meta = pluginConfig.headers.common; if (argv.mode === "development") { + const commit = getCommitShort(); if (env.scot) { config.output.path = path.join(outputPath, "scot"); config.devtool = "eval-source-map"; @@ -189,6 +203,7 @@ module.exports = (env, argv) => { config.devtool = "eval-source-map"; Object.assign(meta, pluginConfig.headers.dev); } + if (commit) meta.version += `-${commit}`; } else { config.output.path = path.join(outputPath, "prod"); Object.assign(meta, pluginConfig.headers.prod); From 91e5dfc41b2ce7899f152641122cc00e65b2363c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 27 Nov 2021 18:27:02 +0100 Subject: [PATCH 128/275] remove vscode settings --- .vscode/settings.json | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 4b2836e8b..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "editor.formatOnSave": true, - "javascript.validate.enable": false -} From edcc64d65b89d406b2f190ae2f59b5c048f340f8 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Dec 2021 22:33:39 +0100 Subject: [PATCH 129/275] crosslink: add inField functions --- src/code/crosslinks.ts | 64 +++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/src/code/crosslinks.ts b/src/code/crosslinks.ts index d8e0e6bba..86bf993e0 100644 --- a/src/code/crosslinks.ts +++ b/src/code/crosslinks.ts @@ -8,14 +8,16 @@ import PortalUI from "./ui/portal"; // from iitc rework : https://github.com/IITC-CE/ingress-intel-total-conversion/pull/333 const d2r = Math.PI / 180; -function toCartesian(lat: number, lng: number): [number, number, number] { +type Vec3 = [number, number, number]; + +function toCartesian(lat: number, lng: number): Vec3 { lat *= d2r; lng *= d2r; var o = Math.cos(lat); return [o * Math.cos(lng), o * Math.sin(lng), Math.sin(lat)]; } -function cross(t: [number, number, number], n: [number, number, number]): [number, number, number] { +function cross(t: Vec3, n: Vec3): Vec3 { return [ t[1] * n[2] - t[2] * n[1], t[2] * n[0] - t[0] * n[2], @@ -23,10 +25,14 @@ function cross(t: [number, number, number], n: [number, number, number]): [numbe ]; } -function dot(t: [number, number, number], n: [number, number, number]) { +function dot(t: Vec3, n: Vec3) { return t[0] * n[0] + t[1] * n[1] + t[2] * n[2]; } +function det(a: Vec3, b: Vec3, c: Vec3) { + return dot(cross(a, b), c); +} + function equals(a: L.LatLng, b: L.LatLng) { return a.lat === b.lat && a.lng === b.lng; } @@ -34,7 +40,39 @@ function equals(a: L.LatLng, b: L.LatLng) { // take L.LatLng // note: cache cos/sin calls in the object, in order to be efficient, try using same LatLng objects across calls, like using latLng from WasabeePortal attached to an op interface LLC extends L.LatLng { - _cartesian?: [number, number, number], + _cartesian?: Vec3; +} + +export function extendLatLngToLLC(ll: LLC) { + if (ll._cartesian) return ll; + ll._cartesian = toCartesian(ll.lat, ll.lng); + return ll; +} + +export function fieldSign( + a: WasabeePortal, + b: WasabeePortal, + c: WasabeePortal +) { + const ca = extendLatLngToLLC(a.latLng)._cartesian; + const cb = extendLatLngToLLC(b.latLng)._cartesian; + const cc = extendLatLngToLLC(c.latLng)._cartesian; + if (det(ca, cb, cc) > 0) return 1; + return -1; +} + +export function portalInField( + a: WasabeePortal, + b: WasabeePortal, + c: WasabeePortal, + portal: WasabeePortal +) { + const sign = fieldSign(a, b, c); + return ( + fieldSign(a, b, portal) * sign > 0 && + fieldSign(b, c, portal) * sign > 0 && + fieldSign(c, a, portal) * sign > 0 + ); } export function greatCircleArcIntersectByLatLngs(a0: LLC, a1: LLC, b0: LLC, b1: LLC) { @@ -52,18 +90,10 @@ export function greatCircleArcIntersectByLatLngs(a0: LLC, a1: LLC, b0: LLC, b1: if (Math.max(a0.lng, a1.lng) < Math.min(b0.lng, b1.lng)) return false; // a) convert into 3D coordinates on a unit sphere & cache into latLng object - const ca0 = (a0._cartesian = a0._cartesian - ? a0._cartesian - : toCartesian(a0.lat, a0.lng)); - const ca1 = (a1._cartesian = a1._cartesian - ? a1._cartesian - : toCartesian(a1.lat, a1.lng)); - const cb0 = (b0._cartesian = b0._cartesian - ? b0._cartesian - : toCartesian(b0.lat, b0.lng)); - const cb1 = (b1._cartesian = b1._cartesian - ? b1._cartesian - : toCartesian(b1.lat, b1.lng)); + const ca0 = extendLatLngToLLC(a0)._cartesian; + const ca1 = extendLatLngToLLC(a1)._cartesian; + const cb0 = extendLatLngToLLC(b0)._cartesian; + const cb1 = extendLatLngToLLC(b1)._cartesian; // b) two planes: ca0,ca1,0/0/0 and cb0,cb1,0/0/0 // find the intersetion line @@ -361,4 +391,4 @@ export class GeodesicLine { const x = this.sinLat2CosLat1 - this.sinLat1CosLat2 * Math.cos(dLng); return Math.atan2(y, x); } -} \ No newline at end of file +} From eb7a726f7cb501ddb4f76152a241afe6068e5990 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Dec 2021 22:45:07 +0100 Subject: [PATCH 130/275] crosslink: types remove indirect calls to getSelectedOp (on WasabeeLink.getLatLngs()) --- src/code/crosslinks.ts | 66 ++++++++++++++++++++++++++++++------------ src/code/model/link.ts | 2 +- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/code/crosslinks.ts b/src/code/crosslinks.ts index 86bf993e0..a69f650b6 100644 --- a/src/code/crosslinks.ts +++ b/src/code/crosslinks.ts @@ -4,6 +4,9 @@ import WasabeeBlocker from "./model/blocker"; import { getSelectedOperation } from "./selectedOp"; import PortalUI from "./ui/portal"; +import type WasabeeOp from "./model/operation"; +import type { IITC } from "../types/iitc"; +import type WasabeeLink from "./model/link"; // from iitc rework : https://github.com/IITC-CE/ingress-intel-total-conversion/pull/333 const d2r = Math.PI / 180; @@ -75,7 +78,15 @@ export function portalInField( ); } -export function greatCircleArcIntersectByLatLngs(a0: LLC, a1: LLC, b0: LLC, b1: LLC) { +export function greatCircleArcIntersectByLatLngs(a0: LLC[], a1: LLC[]): boolean; +export function greatCircleArcIntersectByLatLngs( + a0: LLC, + a1: LLC, + b0: LLC, + b1: LLC +): boolean; +export function greatCircleArcIntersectByLatLngs(...args: (LLC | LLC[])[]) { + const [a0, a1, b0, b1] = args.flat(); // 0) quick checks // zero length line if (equals(a0, a1)) return false; @@ -166,8 +177,17 @@ export function greatCircleArcIntersect(existing, drawn) { return greatCircleArcIntersectByLatLngs(a0, a1, b0, b1); } -function testPolyLine(wasabeeLink, realLink, operation) { - if (greatCircleArcIntersect(realLink, wasabeeLink)) { +function testPolyLine( + wasabeeLink: WasabeeLink, + realLink: IITC.Link, + operation: WasabeeOp +) { + if ( + greatCircleArcIntersectByLatLngs( + realLink.getLatLngs(), + wasabeeLink.getLatLngs(operation) + ) + ) { if (!operation.markers || operation.markers.length == 0) { return true; } @@ -191,9 +211,9 @@ function testPolyLine(wasabeeLink, realLink, operation) { return false; } -function showCrossLink(link, operation) { +function showCrossLink(link: IITC.Link) { // this should be in static.js or skin - const blocked = L.geodesicPolyline(link.getLatLngs(operation), { + const blocked = L.geodesicPolyline(link.getLatLngs(), { color: "#d22", opacity: 0.7, weight: 5, @@ -206,7 +226,7 @@ function showCrossLink(link, operation) { window.plugin.wasabee._crosslinkCache.set(link.options.guid, blocked); } -function testLink(link, operation) { +function testLink(link: IITC.Link, operation: WasabeeOp) { // if the crosslink already exists, do not recheck if (window.plugin.wasabee._crosslinkCache.has(link.options.guid)) { return; @@ -214,7 +234,7 @@ function testLink(link, operation) { for (const drawnLink of operation.links) { if (testPolyLine(drawnLink, link, operation)) { - showCrossLink(link, operation); + showCrossLink(link); let fromPortal = PortalUI.get(link.options.data.oGuid); if (!fromPortal) fromPortal = WasabeePortal.fake( @@ -235,18 +255,19 @@ function testLink(link, operation) { } } -function testSelfBlock(incoming, operation) { +export function testSelfBlock(incoming: WasabeeLink, operation: WasabeeOp) { for (const against of operation.links) { if (incoming.ID == against.ID) continue; - if (greatCircleArcIntersect(against, incoming)) { - const blocked = L.geodesicPolyline( + if ( + greatCircleArcIntersectByLatLngs( against.getLatLngs(operation), - window.plugin.wasabee.skin.selfBlockStyle - ); - blocked.options.interactive = false; - blocked.addTo(window.plugin.wasabee.crossLinkLayers); + incoming.getLatLngs(operation) + ) + ) { + return true; } } + return false; } // lets see if using a generator makes the GUI more responsive on large ops @@ -277,12 +298,19 @@ export function checkAllLinks() { } for (const l of operation.links) { - testSelfBlock(l, operation); + if (testSelfBlock(l, operation)) { + const blocked = L.geodesicPolyline( + l.getLatLngs(operation), + window.plugin.wasabee.skin.selfBlockStyle + ); + blocked.options.interactive = false; + blocked.addTo(window.plugin.wasabee.crossLinkLayers); + } } window.map.fire("wasabee:crosslinks:done"); } -function onLinkAdded(data) { +function onLinkAdded(data: EventLinkAdded) { testLink(data.link, getSelectedOperation()); } @@ -363,9 +391,9 @@ export class GeodesicLine { return this.lng1 == this.lng2; } - latAtLng(lng) { + latAtLng(lng: number) { lng = (lng * Math.PI) / 180; //to radians - let lat; + let lat: number; // if we're testing the start/end point, return that directly rather than calculating // 1. this may be fractionally faster, no complex maths // 2. there's odd rounding issues that occur on some browsers (noticed on IITC MObile) for very short links - this may help @@ -377,7 +405,7 @@ export class GeodesicLine { lat = Math.atan( (this.sinLat1CosLat2 * Math.sin(lng - this.lng2) - this.sinLat2CosLat1 * Math.sin(lng - this.lng1)) / - this.cosLat1CosLat2SinDLng + this.cosLat1CosLat2SinDLng ); } return (lat * 180) / Math.PI; // return value in degrees diff --git a/src/code/model/link.ts b/src/code/model/link.ts index ee01efa82..2babbf600 100644 --- a/src/code/model/link.ts +++ b/src/code/model/link.ts @@ -51,7 +51,7 @@ export default class WasabeeLink extends Task { getLatLngs(operation: WasabeeOp) { operation = operation || getSelectedOperation(); - const returnArray = Array(); + const returnArray: L.LatLng[] = []; const fromPortal = operation.getPortal(this.fromPortalId); if (!fromPortal || !fromPortal.lat) { From e5aed77fd5d94947be2aaaa8cafa336e4950ffe6 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Dec 2021 22:58:35 +0100 Subject: [PATCH 131/275] autodraw: algorithm & draw routines --- src/code/dialogs/autodraws/algorithm.ts | 169 +++++++++++++++++++++ src/code/dialogs/autodraws/drawRoutines.ts | 67 ++++++++ 2 files changed, 236 insertions(+) create mode 100644 src/code/dialogs/autodraws/algorithm.ts create mode 100644 src/code/dialogs/autodraws/drawRoutines.ts diff --git a/src/code/dialogs/autodraws/algorithm.ts b/src/code/dialogs/autodraws/algorithm.ts new file mode 100644 index 000000000..f94fd9534 --- /dev/null +++ b/src/code/dialogs/autodraws/algorithm.ts @@ -0,0 +1,169 @@ +import { fieldSign } from "../../crosslinks"; +import type WasabeePortal from "../../model/portal"; + +type Poset = Map; + +// given two anchor, build a map that shows which and how many portals are covered by each possible field by guid +// note: a portal always covers itself +export function buildPoset( + anchor1: WasabeePortal, + anchor2: WasabeePortal, + portals: WasabeePortal[] +) { + const posetPositive: Poset = new Map(); + const posetNegative: Poset = new Map(); + + for (const i of portals) { + if (i.id === anchor1.id || i.id === anchor2.id) continue; + const result = []; + const sign = fieldSign(anchor1, anchor2, i); + for (const j of portals) { + if (j.id === anchor1.id || j.id === anchor2.id) continue; + if (i === j) result.push(j.id); + else if ( + fieldSign(anchor1, anchor2, j) * sign > 0 && + fieldSign(anchor2, i, j) * sign > 0 && + fieldSign(i, anchor1, j) * sign > 0 + ) + result.push(j.id); + } + if (sign > 0) posetPositive.set(i.id, result); + else posetNegative.set(i.id, result); + } + + return [posetPositive, posetNegative]; +} + +// given a poset, compute the maximal paths from all elements +// the result contains a map that gives for any element the next ones and the list of the elements +// that have the longest paths +interface LongestSequences { + children: T[]; + length: number; + number: number; +} +function longestSequencesPoset(poset: Poset) { + const alreadyCalculatedChildren = new Map< + T | "__start__", + LongestSequences + >(); + const preds_from = (c: T | "__start__") => { + if (alreadyCalculatedChildren.get(c) === undefined) { + const res: LongestSequences = { + children: [], + length: 1, + number: 1, + }; + const preds = + c === "__start__" + ? Array.from(poset.keys()) + : poset.get(c).filter((i) => i !== c); + for (const id of preds) { + const val = preds_from(id); + if (val.length + 1 > res.length) { + res.length = val.length + 1; + res.children = []; + res.number = 0; + } + if (val.length + 1 == res.length) { + res.children.push(id); + res.number += val.number; + } + } + alreadyCalculatedChildren.set(c, res); + } + return alreadyCalculatedChildren.get(c); + }; + + return { + maxima: preds_from("__start__").children, + poset: alreadyCalculatedChildren, + number: preds_from("__start__").number, + }; +} + +// given a poset, find the longest sequence p1,p2,...pk such that poset(p2) contains p1, poset(p3) contains p2 etc +// that minimizes the flight distance +// notes: +// - the result is an empty sequence only if the poset is empty or if poset(p) is empty for any p +// - if the poset is given by buildPOSet, the first element is the guid of a portal that doesn't cover any other portal, +// and the last element is the portal that covers all portals of the sequence and isn't covered by any other portal +// (inner to outer) +interface LongestSequence { + seq: T[]; + dist: number; +} +export function longestSequence( + poset: Poset, + start?: T, + dist?: (a: T, b: T) => number +) { + const maximalPaths = longestSequencesPoset(poset); + if (!maximalPaths.maxima.length) return []; + const alreadyCalculatedSequences = new Map>(); + if (!dist) dist = () => 0; + const sequence_from = (c: T) => { + if (alreadyCalculatedSequences.get(c) === undefined) { + const mP = maximalPaths.poset.get(c); + if (mP.length == 1) + alreadyCalculatedSequences.set(c, { seq: [c], dist: 0 }); + else { + const best = mP.children + .map(sequence_from) + .reduce((S1, S2) => + S1.dist + dist(c, S1.seq[S1.seq.length - 1]) < + S2.dist + dist(c, S2.seq[S2.seq.length - 1]) + ? S1 + : S2 + ); + const res = { + seq: Array.from(best.seq), + dist: best.dist, + }; + res.dist += dist(res.seq[res.seq.length - 1], c); + res.seq.push(c); + alreadyCalculatedSequences.set(c, res); + } + } + return alreadyCalculatedSequences.get(c); + }; + + if (start) { + console.debug( + maximalPaths.poset.get(start).number, + "possible paths from the given start" + ); + return sequence_from(start).seq; + } + + console.debug(maximalPaths.number, "possible paths"); + return maximalPaths.maxima + .map(sequence_from) + .reduce((S1, S2) => (S1.dist < S2.dist ? S1 : S2)).seq; +} + +export function getSignedSpine( + pOne: WasabeePortal, + pTwo: WasabeePortal, + portals: WasabeePortal[], + bothSide = false +) { + const portalsMap = new Map(portals.map((p) => [p.id, p])); + const [pPos, pNeg] = buildPoset(pOne, pTwo, portals); + const sequencePos = longestSequence(pPos, null, (a, b) => + window.map.distance(portalsMap.get(a).latLng, portalsMap.get(b).latLng) + ); + const sequenceNeg = longestSequence(pNeg, null, (a, b) => + window.map.distance(portalsMap.get(a).latLng, portalsMap.get(b).latLng) + ); + + if (bothSide) + return [ + sequencePos.map((id) => portalsMap.get(id)), + sequenceNeg.map((id) => portalsMap.get(id)), + ]; + + const sequence = + sequencePos.length > sequenceNeg.length ? sequencePos : sequenceNeg; + return [sequence.map((id) => portalsMap.get(id))]; +} diff --git a/src/code/dialogs/autodraws/drawRoutines.ts b/src/code/dialogs/autodraws/drawRoutines.ts new file mode 100644 index 000000000..2d641c6b3 --- /dev/null +++ b/src/code/dialogs/autodraws/drawRoutines.ts @@ -0,0 +1,67 @@ +import type WasabeeLink from "../../model/link"; +import type WasabeeOp from "../../model/operation"; +import type WasabeePortal from "../../model/portal"; + +function getSpineLinks( + anchor1: WasabeePortal, + anchor2: WasabeePortal, + spine: WasabeePortal[], + options: { + backlink?: boolean; + } = {} +) { + const linksDesc: { + from: WasabeePortal; + to: WasabeePortal; + back?: boolean; + }[] = []; + let prev = null; + for (const p of spine) { + linksDesc.push({ from: p, to: anchor1 }); + linksDesc.push({ from: p, to: anchor2 }); + if (options.backlink && prev) + linksDesc.push({ from: p, to: prev, back: true }); + } + return linksDesc; +} + +export function insertLinks( + op: WasabeeOp, + links: WasabeeLink[], + order: number +) { + for (const l of links) l.order = 0; + // shift current op tasks order + if (order < op.nextOrder - 1) { + for (const l of op.links) if (l.order > order) l.order += links.length; + for (const m of op.markers) if (m.order > order) m.order += links.length; + } + for (const l of links) l.order = ++order; + return order; +} + +export function drawSpine( + op: WasabeeOp, + anchor1: WasabeePortal, + anchor2: WasabeePortal, + spine: WasabeePortal[], + order: number, + options: { + backlink?: boolean; + commentPrefix?: string; + noShift?: boolean; + } = {} +) { + const links = getSpineLinks(anchor1, anchor2, spine, options); + + const commentPrefix = options.commentPrefix || ""; + const wlinks = links + .map((l) => + op.addLink(l.from, l.to, { + description: commentPrefix + (l.back ? "backlink" : "link"), + }) + ) + .filter((l) => l); + + return insertLinks(op, wlinks, order); +} From 4fa6804307b9a9a8ce393232c517f34b3d4631ec Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Dec 2021 23:00:06 +0100 Subject: [PATCH 132/275] autodraw: use suited crosslink API testSelfBlock/greatCircleArcIntersectByLatLngs/portalInField --- src/code/dialogs/autodraws/fanfield.js | 4 +-- src/code/dialogs/autodraws/homogeneous.js | 43 ++++------------------- src/code/dialogs/autodraws/onionfield.js | 10 ++++-- 3 files changed, 16 insertions(+), 41 deletions(-) diff --git a/src/code/dialogs/autodraws/fanfield.js b/src/code/dialogs/autodraws/fanfield.js index bf439682a..3e073d95a 100644 --- a/src/code/dialogs/autodraws/fanfield.js +++ b/src/code/dialogs/autodraws/fanfield.js @@ -1,7 +1,7 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; -import { greatCircleArcIntersect, GeodesicLine } from "../../crosslinks"; +import { GeodesicLine, testSelfBlock } from "../../crosslinks"; import WasabeeLink from "../../model/link"; import { clearAllLinks } from "../../uiCommands"; import wX from "../../wX"; @@ -182,7 +182,7 @@ const FanfieldDialog = AutoDraw.extend({ for (const real of op.links) { // Check links to anchor only if (real.toPortalId != this._anchor.id) continue; - if (greatCircleArcIntersect(real, testlink)) { + if (testSelfBlock(testlink, op)) { crossed = true; break; } diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index 30cfaf882..57a8a3bd4 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -1,13 +1,11 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; -import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; -// import WasabeeLink from "../model/link"; import { - clearAllLinks, - getAllPortalsOnScreen, - testPortal, -} from "../../uiCommands"; + greatCircleArcIntersectByLatLngs, + portalInField, +} from "../../crosslinks"; +import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; import PortalUI from "../../ui/portal"; @@ -26,8 +24,6 @@ const HomogeneousDialog = AutoDraw.extend({ if (p) this._anchorTwo = new WasabeePortal(p); p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_THREE_KEY]; if (p) this._anchorThree = new WasabeePortal(p); - - this._urp = L.latLng(testPortal()); this._failed = 0; }, @@ -149,14 +145,7 @@ const HomogeneousDialog = AutoDraw.extend({ const portals = new Array(); for (const p of getAllPortalsOnScreen(this._operation)) { - if ( - this._fieldCovers( - this._anchorOne, - this._anchorTwo, - this._anchorThree, - p - ) - ) + if (portalInField(this._anchorOne, this._anchorTwo, this._anchorThree, p)) portals.push(p); } @@ -193,14 +182,7 @@ const HomogeneousDialog = AutoDraw.extend({ const portals = new Array(); for (const p of getAllPortalsOnScreen(this._operation)) { - if ( - this._fieldCovers( - this._anchorOne, - this._anchorTwo, - this._anchorThree, - p - ) - ) + if (portalInField(this._anchorOne, this._anchorTwo, this._anchorThree, p)) portals.push(p); } @@ -776,19 +758,6 @@ const HomogeneousDialog = AutoDraw.extend({ const point = L.point((A.x + B.x + C.x) / 3, (A.y + B.y + C.y) / 3); return window.map.unproject(point); }, - - _fieldCovers: function (a, b, c, p) { - const urp = this._urp; - - let crossings = 0; - if (greatCircleArcIntersectByLatLngs(urp, p.latLng, a.latLng, b.latLng)) - crossings++; - if (greatCircleArcIntersectByLatLngs(urp, p.latLng, a.latLng, c.latLng)) - crossings++; - if (greatCircleArcIntersectByLatLngs(urp, p.latLng, b.latLng, c.latLng)) - crossings++; - return crossings == 1; // crossing 0 or 2 is OK, crossing 3 is - }, }); export default HomogeneousDialog; diff --git a/src/code/dialogs/autodraws/onionfield.js b/src/code/dialogs/autodraws/onionfield.js index 3571adaf2..f5567a7fa 100644 --- a/src/code/dialogs/autodraws/onionfield.js +++ b/src/code/dialogs/autodraws/onionfield.js @@ -1,7 +1,7 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; -import { greatCircleArcIntersect } from "../../crosslinks"; +import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; import WasabeeLink from "../../model/link"; import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; @@ -284,7 +284,13 @@ const OnionfieldDialog = AutoDraw.extend({ // looks only at links in current (not op or live data) _testBlock: function (current, testing) { for (const against of current) { - if (greatCircleArcIntersect(against, testing)) return true; + if ( + greatCircleArcIntersectByLatLngs( + testing.getLatLngs(this._operation), + against.getLatLngs(this._operation) + ) + ) + return true; } return false; }, From 137f573368d4a6e3dedaf04ec46058c0b1278895 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Dec 2021 23:15:52 +0100 Subject: [PATCH 133/275] autodraw: use algo/draw routines in madrid.js --- src/code/dialogs/autodraws/madrid.js | 171 ++++++++++++++------------- 1 file changed, 91 insertions(+), 80 deletions(-) diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index c3d45fa48..868019da9 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -1,7 +1,10 @@ +import { portalInField } from "../../crosslinks"; import { displayError, displayInfo } from "../../error"; import { getSelectedOperation } from "../../selectedOp"; import { clearAllLinks } from "../../uiCommands"; import wX from "../../wX"; +import { getSignedSpine } from "./algorithm"; +import { drawSpine, insertLinks } from "./drawRoutines"; import MultimaxDialog from "./multimaxDialog"; // now that the formerly external mm functions are in the class, some of the logic can be cleaned up @@ -96,6 +99,36 @@ const MadridDialog = MultimaxDialog.extend({ }); }, + getSpines: function (anchorOne, anchorTwo, setOne, setTwo, setThree) { + const [spineThree] = getSignedSpine(anchorOne, anchorTwo, setThree, false); + const lastThree = spineThree[spineThree.length - 1]; + + const [spineOne] = getSignedSpine( + anchorTwo, + lastThree, + setOne.filter( + (p) => + anchorOne.id == p.id || + portalInField(anchorTwo, lastThree, p, anchorOne) + ), + false + ); + const lastOne = spineOne[spineOne.length - 1]; + + const [spineTwo] = getSignedSpine( + lastThree, + lastOne, + setTwo.filter( + (p) => + anchorTwo.id == p.id || + portalInField(lastThree, lastOne, p, anchorTwo) + ), + false + ); + + return [spineOne, spineTwo, spineThree]; + }, + doBalancedMadrid: function () { // Calculate the multimax if ( @@ -122,36 +155,13 @@ const MadridDialog = MultimaxDialog.extend({ ) this._portalSets.setTwo.portals.push(this._anchorTwo); - const spineThree = this.getSpine( + const spines = this.getSpines( this._anchorOne, this._anchorTwo, + this._portalSets.setOne.portals, + this._portalSets.setTwo.portals, this._portalSets.setThree.portals ); - const lastThree = spineThree[spineThree.length - 1]; - - const spineOne = this.getSpine( - this._anchorTwo, - lastThree, - this._portalSets.setOne.portals.filter( - (p) => - this._anchorOne.id == p.id || - this.fieldCoversPortal(this._anchorTwo, lastThree, p, this._anchorOne) - ) - ); - const lastOne = spineOne[spineOne.length - 1]; - - const spineTwo = this.getSpine( - lastThree, - lastOne, - this._portalSets.setTwo.portals.filter( - (p) => - this._anchorTwo.id == p.id || - this.fieldCoversPortal(lastThree, lastOne, p, this._anchorTwo) - ) - ); - // const lastTwo = spineTwo[spineTwo.length - 1]; - - const spines = [spineOne, spineTwo, spineThree]; const step = spines.map((s) => 1 / s.length); this._operation.startBatchMode(); @@ -181,7 +191,7 @@ const MadridDialog = MultimaxDialog.extend({ // hackish, I have no proof of this working in all cases for ( let i = 0; - (!p || !this.fieldCoversPortal(p, pTwo, pThree, pOne)) && i < 3; + (!p || !portalInField(p, pTwo, pThree, pOne)) && i < 3; i++ ) { this._operation.setPortalComment(pOne, "point of disbalance"); @@ -192,7 +202,7 @@ const MadridDialog = MultimaxDialog.extend({ pTwo = spines[spineOrder[1]][indices[spineOrder[1]] - 1]; pThree = spines[spineOrder[2]][indices[spineOrder[2]] - 1]; } - if (!this.fieldCoversPortal(p, pTwo, pThree, pOne)) + if (!portalInField(p, pTwo, pThree, pOne)) console.log("well, this doesn't work here..."); const toTwo = this._operation.addLink(p, pTwo, { description: "link" }); const toThree = this._operation.addLink(p, pThree, { @@ -209,9 +219,6 @@ const MadridDialog = MultimaxDialog.extend({ return indices[0] + indices[1] + indices[2] - 2; }, - // fieldCoversPortal inherited from MultimaxDialog - // MM " - doMadrid: function () { // Calculate the multimax if ( @@ -224,47 +231,12 @@ const MadridDialog = MultimaxDialog.extend({ displayError(wX("INVALID REQUEST")); return 0; } - this._operation.startBatchMode(); // bypass save and crosslinks checks - this._operation.addLink(this._anchorOne, this._anchorTwo, { - description: "madrid base", - order: 1, - }); - - let len = 0; - const [len1, order1, last1] = this.MM( - this._anchorOne, - this._anchorTwo, - this._portalSets.setThree.portals, - 1, - false, - "madrid protocol " - ); - len += len1; - - const newThree = last1; // the set 1 must contain anchor 1 (first back link) if ( this._portalSets.setOne.portals.find((p) => this._anchorOne.id == p.id) == undefined ) this._portalSets.setOne.portals.push(this._anchorOne); - - const [len2, order2, last2] = this.MM( - this._anchorTwo, - newThree, - this._portalSets.setOne.portals.filter( - (p) => - this._anchorOne.id == p.id || - this.fieldCoversPortal(this._anchorTwo, newThree, p, this._anchorOne) - ), - order1, - false, - "madrid protocol " - ); - len += len2 - 1; - - // _anchorOne is no longer useful, use last2 - const newOne = last2; // the set 2 must contain anchor 2 (first back link) if ( this._portalSets.setTwo.portals.find((p) => this._anchorTwo.id == p.id) == @@ -272,23 +244,62 @@ const MadridDialog = MultimaxDialog.extend({ ) this._portalSets.setTwo.portals.push(this._anchorTwo); - const len3 = this.MM( - newThree, - newOne, - this._portalSets.setTwo.portals.filter( - (p) => - this._anchorTwo.id == p.id || - this.fieldCoversPortal(newThree, newOne, p, this._anchorTwo) - ), - order2, - false, - "madrid protocol " - )[0]; - len += len3 - 1; + const spines = this.getSpines( + this._anchorOne, + this._anchorTwo, + this._portalSets.setOne.portals, + this._portalSets.setTwo.portals, + this._portalSets.setThree.portals + ); + + this._operation.startBatchMode(); // bypass save and crosslinks checks + let order = insertLinks( + this._operation, + [ + this._operation.addLink(this._anchorOne, this._anchorTwo, { + description: "madrid base", + }), + ], + this._operation.nextOrder - 1 + ); + + order = drawSpine( + this._operation, + this._anchorOne, + this._anchorTwo, + spines[2], + order, + { + commentPrefix: "madrid ", + backlink: this._flcheck, + } + ); + order = drawSpine( + this._operation, + this._anchorTwo, + spines[2][spines[2].length - 1], + spines[0].slice(1), + order, + { + commentPrefix: "madrid ", + backlink: this._flcheck, + } + ); + /* order = */ drawSpine( + this._operation, + spines[2][spines[2].length - 1], + spines[0][spines[0].length - 1], + spines[1].slice(1), + order, + { + commentPrefix: "madrid ", + backlink: this._flcheck, + } + ); this._operation.endBatchMode(); // save and run crosslinks - return len; + return spines[0].length + spines[1].length + spines[2].length - 2; }, }); From 1cb86460151b2206d5a5a2e22c16dddac8a3cbd0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Dec 2021 23:20:42 +0100 Subject: [PATCH 134/275] autodraw: use algo/draw routines in multimax --- .../dialogs/autodraws/multimaxDialog.d.ts | 16 +- src/code/dialogs/autodraws/multimaxDialog.js | 222 +++--------------- 2 files changed, 39 insertions(+), 199 deletions(-) diff --git a/src/code/dialogs/autodraws/multimaxDialog.d.ts b/src/code/dialogs/autodraws/multimaxDialog.d.ts index fa8064003..7675adbfe 100644 --- a/src/code/dialogs/autodraws/multimaxDialog.d.ts +++ b/src/code/dialogs/autodraws/multimaxDialog.d.ts @@ -6,21 +6,7 @@ export default class MultimaxDialog extends AutoDraw { _anchorTwo: WasabeePortal; _flcheck: boolean; _orderFromEnd: boolean; - _urp: L.LatLng; + _bothSide: boolean; constructor(); - MM( - pOne: WasabeePortal, - pTwo: WasabeePortal, - portals: WasabeePortal[], - order?: number, - base?: boolean, - commentPrefix?: string - ): any[]; - fieldCoversPortal(a: any, b: any, c: any, p: any): boolean; - getSpine( - one: WasabeePortal, - two: WasabeePortal, - portals: WasabeePortal[] - ): WasabeePortal[]; } diff --git a/src/code/dialogs/autodraws/multimaxDialog.js b/src/code/dialogs/autodraws/multimaxDialog.js index 0c38539a0..d414e3a4f 100644 --- a/src/code/dialogs/autodraws/multimaxDialog.js +++ b/src/code/dialogs/autodraws/multimaxDialog.js @@ -2,9 +2,10 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import wX from "../../wX"; -import { testPortal, clearAllLinks } from "../../uiCommands"; -import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; +import { clearAllLinks } from "../../uiCommands"; import { displayError, displayInfo } from "../../error"; +import { getSignedSpine } from "./algorithm"; +import { drawSpine, insertLinks } from "./drawRoutines"; // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX @@ -19,7 +20,6 @@ const MultimaxDialog = AutoDraw.extend({ if (p) this._anchorOne = new WasabeePortal(p); p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; if (p) this._anchorTwo = new WasabeePortal(p); - this._urp = L.latLng(testPortal()); }, addHooks: function () { @@ -65,6 +65,14 @@ const MultimaxDialog = AutoDraw.extend({ true ); + this._addCheckbox( + wX("MM_BOTH_SIDE"), + "wasabee-multimax-both-side", + "_bothSide", + container, + false + ); + this._addSelectSet(wX("MM_SPINE"), "spine", container, "all"); // Go button @@ -72,7 +80,7 @@ const MultimaxDialog = AutoDraw.extend({ button.textContent = wX("MULTI_M"); L.DomEvent.on(button, "click", () => { const total = this.doMultimax.call(this); - displayInfo(`Multimax found ${total} layers`); + displayInfo(`Multimax found ${total.join(" and ")} layers`); // this.closeDialog(); }); @@ -100,16 +108,6 @@ const MultimaxDialog = AutoDraw.extend({ }); }, - getSpine: function (pOne, pTwo, portals) { - const portalsMap = new Map(portals.map((p) => [p.id, p])); - const poset = this.buildPOSet(pOne, pTwo, portals); - const sequence = this.longestSequence(poset, null, (a, b) => - window.map.distance(portalsMap.get(a).latLng, portalsMap.get(b).latLng) - ); - - return sequence.map((id) => portalsMap.get(id)); - }, - /* Calculate, given two anchors and a set of portals, the deepest sequence of nested fields. */ @@ -119,61 +117,33 @@ const MultimaxDialog = AutoDraw.extend({ portals, order = 0, // first link is order + 1 base = true, - commentPrefix = "multimax " + commentPrefix = "multimax ", + bothSide = false ) { - const sequence = this.getSpine(pOne, pTwo, portals); - - // shift current op tasks order - if (order < this._operation.nextOrder - 1) { - let diff = sequence.length * 2 + 1; - if (this._flcheck.checked) diff += sequence.length - 1; - for (const l of this._operation.links) { - // skip base - if (l.toPortalId === pOne.id && l.fromPortalId === pTwo.id) continue; - if (l.fromPortalId === pOne.id && l.toPortalId === pTwo.id) continue; - if (l.order > order) l.order += diff; - } - for (const m of this._operation.markers) { - if (m.order > order) m.order += diff; - } - } - - if (base) - this._operation.addLink(pOne, pTwo, { - description: commentPrefix + "base", - order: ++order, - }); - - if (!Array.isArray(sequence) || !sequence.length) { - // displayInfo("No layers found"); - return [0, order, null]; + const spines = getSignedSpine(pOne, pTwo, portals, bothSide); + + if (base) { + order = insertLinks( + this._operation, + [ + this._operation.addLink(pOne, pTwo, { + description: commentPrefix + "base", + }), + ], + order + ); } - let prev = null; - - for (const p of sequence) { - this._operation.addLink(p, pOne, { - description: commentPrefix + "link", - order: ++order, + for (const s of spines) { + order = drawSpine(this._operation, pOne, pTwo, s, order, { + commentPrefix: "multimax ", + backlink: this._flcheck, }); - this._operation.addLink(p, pTwo, { - description: commentPrefix + "link", - order: ++order, - }); - if (this._flcheck.checked && prev) { - this._operation.addLink(p, prev, { - description: commentPrefix + "back link", - order: ++order, - }); - } - prev = p; } - // return number of layers, last link order and last portal - return [sequence.length, order, prev]; + return spines.map((s) => s.length); }, doMultimax: function () { - // this._operation is OK here const portals = this._portalSets.spine.portals; // Calculate the multimax @@ -185,136 +155,20 @@ const MultimaxDialog = AutoDraw.extend({ this._operation.startBatchMode(); console.log("starting multimax"); - const length = this.MM( + const lengths = this.MM( this._anchorOne, this._anchorTwo, portals, - this._orderFromEnd.checked ? this._operation.nextOrder - 1 : 0 - )[0]; + this._orderFromEnd ? this._operation.nextOrder - 1 : 0, + true, + "multimax ", + this._bothSide + ); console.log("multimax done"); this._operation.endBatchMode(); // save and run crosslinks - return length; - }, - - fieldCoversPortal: function (a, b, c, p) { - const urp = this._urp; - - let crossings = 0; - if (greatCircleArcIntersectByLatLngs(urp, p.latLng, a.latLng, b.latLng)) - crossings++; - if (greatCircleArcIntersectByLatLngs(urp, p.latLng, a.latLng, c.latLng)) - crossings++; - if (greatCircleArcIntersectByLatLngs(urp, p.latLng, b.latLng, c.latLng)) - crossings++; - return crossings == 1; // crossing 0 or 2 is OK, crossing 3 is impossible - }, - - // given two anchor, build a map that shows which and how many portals are covered by each possible field by guid - // note: a portal always covers itself - buildPOSet: function (anchor1, anchor2, visible) { - const poset = new Map(); - - for (const i of visible) { - const result = []; - for (const j of visible) { - if (i === j) result.push(j.id); - else if (this.fieldCoversPortal(anchor1, anchor2, i, j)) - result.push(j.id); - } - poset.set(i.id, result); - } - - return poset; - }, - - // given a poset, compute the maximal paths from all elements - // the result contains a map that gives for any element the next ones and the list of the elements - // that have the longest paths - longestSequencesPoset: function (poset) { - const alreadyCalculatedChildren = new Map(); - const preds_from = (c) => { - if (alreadyCalculatedChildren.get(c) === undefined) { - const res = { - children: [], - length: 1, - number: 1, - }; - for (const id of poset.get(c).filter((i) => i !== c)) { - const val = preds_from(id); - if (val.length + 1 > res.length) { - res.length = val.length + 1; - res.children = []; - res.number = 0; - } - if (val.length + 1 == res.length) { - res.children.push(id); - res.number += val.number; - } - } - alreadyCalculatedChildren.set(c, res); - } - return alreadyCalculatedChildren.get(c); - }; - - poset.set("__start__", Array.from(poset.keys())); - return { - maxima: preds_from("__start__").children, - poset: alreadyCalculatedChildren, - number: preds_from("__start__").number, - }; - }, - - // given a poset, find the longest sequence p1,p2,...pk such that poset(p2) contains p1, poset(p3) contains p2 etc - // that minimizes the flight distance - // notes: - // - the result is an empty sequence only if the poset is empty or if poset(p) is empty for any p - // - if the poset is given by buildPOSet, the first element is the guid of a portal that doesn't cover any other portal, - // and the last element is the portal that covers all portals of the sequence and isn't covered by any other portal - // (inner to outer) - longestSequence: function (poset, start, dist) { - const maximalPaths = this.longestSequencesPoset(poset); - const alreadyCalculatedSequences = new Map(); - if (!dist) dist = () => 0; - const sequence_from = (c) => { - if (alreadyCalculatedSequences.get(c) === undefined) { - const mP = maximalPaths.poset.get(c); - if (mP.length == 1) - alreadyCalculatedSequences.set(c, { seq: [c], dist: 0 }); - else { - const best = mP.children - .map(sequence_from) - .reduce((S1, S2) => - S1.dist + dist(c, S1.seq[S1.seq.length - 1]) < - S2.dist + dist(c, S2.seq[S2.seq.length - 1]) - ? S1 - : S2 - ); - const res = { - seq: Array.from(best.seq), - dist: best.dist, - }; - res.dist += dist(res.seq[res.seq.length - 1], c); - res.seq.push(c); - alreadyCalculatedSequences.set(c, res); - } - } - return alreadyCalculatedSequences.get(c); - }; - - if (start) { - console.debug( - maximalPaths.poset.get(start).number, - "possible paths from the given start" - ); - return sequence_from(start).seq; - } - - console.debug(maximalPaths.number, "possible paths"); - return maximalPaths.maxima - .map(sequence_from) - .reduce((S1, S2) => (S1.dist < S2.dist ? S1 : S2)).seq; + return lengths; }, }); From d3fa2ee32a1a94243ea8975e137a249a67ce7cb0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 8 Dec 2021 23:23:06 +0100 Subject: [PATCH 135/275] crosslink: remove unused greatCircleArcIntersect --- src/code/crosslinks.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/code/crosslinks.ts b/src/code/crosslinks.ts index a69f650b6..a06293c17 100644 --- a/src/code/crosslinks.ts +++ b/src/code/crosslinks.ts @@ -164,19 +164,6 @@ export function greatCircleArcIntersectByLatLngs(...args: (LLC | LLC[])[]) { return false; } -// takes WasabeeLink or L.geodesicPolyline format -export function greatCircleArcIntersect(existing, drawn) { - const eLL = existing.getLatLngs(); - const dLL = drawn.getLatLngs(); - - const a0 = eLL[0]; - const a1 = eLL[1]; - const b0 = dLL[0]; - const b1 = dLL[1]; - - return greatCircleArcIntersectByLatLngs(a0, a1, b0, b1); -} - function testPolyLine( wasabeeLink: WasabeeLink, realLink: IITC.Link, From 758f9635d08e503c7368309db693c374391dc012 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 27 Nov 2021 18:31:12 +0100 Subject: [PATCH 136/275] autodraw: fix checkboxes inconsitency --- src/code/dialogs/autodraws/madrid.js | 2 +- src/code/dialogs/autodraws/tools.js | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index 868019da9..1da2b095f 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -67,7 +67,7 @@ const MadridDialog = MultimaxDialog.extend({ button.textContent = wX("MADRID"); L.DomEvent.on(button, "click", () => { this._operation = getSelectedOperation(); - const total = this._balancedcheck.checked + const total = this._balancedcheck ? this.doBalancedMadrid.call(this) : this.doMadrid.call(this); displayInfo(`Madrid found ${total} layers`); diff --git a/src/code/dialogs/autodraws/tools.js b/src/code/dialogs/autodraws/tools.js index ae6594a7c..d751e2c57 100644 --- a/src/code/dialogs/autodraws/tools.js +++ b/src/code/dialogs/autodraws/tools.js @@ -126,10 +126,13 @@ export const AutoDraw = WDialog.extend({ const label = L.DomUtil.create("label", "checkbox-label", container); label.textContent = text; label.htmlFor = id; - this[thisKey] = L.DomUtil.create("input", "checkbox-input", container); - this[thisKey].type = "checkbox"; - this[thisKey].id = id; - this[thisKey].checked = defaultValue; + const checkbox = L.DomUtil.create("input", "checkbox-input", container); + checkbox.type = "checkbox"; + checkbox.id = id; + checkbox.checked = defaultValue; + L.DomEvent.on(checkbox, "change", () => { + this[thisKey] = checkbox.checked; + }); }, _addSelectSet: function (text, setKey, container, defaultValue) { From 9e4c9d86524fb08850d815f55d5ef7a3bf4ba1c4 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 27 Nov 2021 18:36:12 +0100 Subject: [PATCH 137/275] drop urp --- src/code/dialogs/settingsDialog.js | 14 -------------- src/code/static.ts | 3 +-- src/code/uiCommands.ts | 31 ------------------------------ 3 files changed, 1 insertion(+), 47 deletions(-) diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index e97b4fb07..15335c299 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -108,20 +108,6 @@ const SettingsDialog = WDialog.extend({ window.plugin.wasabee.static.constants.SEND_ANALYTICS_KEY ); - const urpKey = - window.plugin.wasabee.static.constants.MULTIMAX_UNREACHABLE_KEY; - if (!localStorage[urpKey]) { - localStorage[urpKey] = '{"lat": -74.2,"lng:"-143.4}'; - } - const pairs = [ - ["Antarctic West", '{"lat":-74.2,"lng":-143.4}'], - ["Antarctic East", '{"lat":-74.2,"lng":30.0}'], - ["Equatorial Atlantic", '{"lat":-2.66,"lng":-4.28}'], - ["Arctic West", '{"lat":74.2,"lng":-143.4}'], - ["Arctic East", '{"lat":78.5,"lng":143.4}'], - ]; - this._addSelect(container, "Multimax test point", urpKey, pairs); - this._addCheckBox( container, wX("MERGE ON UPDATE"), diff --git a/src/code/static.ts b/src/code/static.ts index f87fab7b5..ae799befb 100644 --- a/src/code/static.ts +++ b/src/code/static.ts @@ -3,7 +3,7 @@ type Statics = { CSS: { [name: string]: string }; dialogNames: { [name: string]: string }; [name: string]: any; -} +}; const statics: Statics = { CSS: { @@ -55,7 +55,6 @@ const statics: Statics = { LANGUAGE_KEY: "wasabee-language", DEFAULT_LANGUAGE: "English", AGENT_INFO_KEY: "wasabee-me", - MULTIMAX_UNREACHABLE_KEY: "wasabee-mm-unreachable", LINK_SOURCE_KEY: "wasabee-link-source", ANCHOR_ONE_KEY: "wasabee-anchor-1", ANCHOR_TWO_KEY: "wasabee-anchor-2", diff --git a/src/code/uiCommands.ts b/src/code/uiCommands.ts index 4f118165a..a207b245d 100644 --- a/src/code/uiCommands.ts +++ b/src/code/uiCommands.ts @@ -322,37 +322,6 @@ export function getAllPortalsLinked( return x; } -// this is the test point used in several auto-draws -// settings allow there to be several different due to -// rouding errors resulting from long distances -export function testPortal(recursed = false) { - let urp = - localStorage[ - window.plugin.wasabee.static.constants.MULTIMAX_UNREACHABLE_KEY - ]; - if (!urp) { - urp = '{"lat":-74.2,"lng":-143.4}'; - localStorage[ - window.plugin.wasabee.static.constants.MULTIMAX_UNREACHABLE_KEY - ] = urp; - } - - let parsed = null; - try { - parsed = JSON.parse(urp); - } catch (err) { - if (!recursed) { - delete localStorage[ - window.plugin.wasabee.static.constants.MULTIMAX_UNREACHABLE_KEY - ]; - return testPortal(true); - } - } - - // if recrused and still getting garbage, we have a problem - return parsed; -} - // recursive function to auto-mark blockers export async function blockerAutomark(operation: WasabeeOp, first = true) { const blockers = await WasabeeBlocker.getAll(operation); From 9e3e51c5c4292b70c9f33d40a40fa451cd2992a4 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 27 Nov 2021 18:40:02 +0100 Subject: [PATCH 138/275] MM: add both side string --- src/code/translations/english.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code/translations/english.json b/src/code/translations/english.json index f74ed6796..c2ecb6c25 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -183,6 +183,7 @@ "MIN_SRC_PORT_LVL": "Minimum level required on source portal", "MINUTES": " ({minutes} minutes ago)", "MM": "Multimax", + "MM_BOTH_SIDE": "Use both base sides", "MM_INSERT_ORDER": "Insert at the end", "MM_SET_ALL_PORTALS": "All visible portals", "MM_SET_ALL_KEYS": "All GetKey Markers", From c55b8819732afb859386694e9216c358cda125a7 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 14:08:36 +0100 Subject: [PATCH 139/275] crosslink: add fieldCenter --- src/code/crosslinks.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/code/crosslinks.ts b/src/code/crosslinks.ts index a06293c17..a9527237c 100644 --- a/src/code/crosslinks.ts +++ b/src/code/crosslinks.ts @@ -78,6 +78,22 @@ export function portalInField( ); } +export function fieldCenter( + a: WasabeePortal, + b: WasabeePortal, + c: WasabeePortal +) { + const ca = extendLatLngToLLC(a.latLng)._cartesian; + const cb = extendLatLngToLLC(b.latLng)._cartesian; + const cc = extendLatLngToLLC(c.latLng)._cartesian; + const ccenter: Vec3 = [ + ca[0]+cb[0]+cc[0], + ca[1]+cb[1]+cc[1], + ca[2]+cb[2]+cc[2], + ]; + return ccenter; +} + export function greatCircleArcIntersectByLatLngs(a0: LLC[], a1: LLC[]): boolean; export function greatCircleArcIntersectByLatLngs( a0: LLC, From 774dbb42615d775b2b36007dd79a5e7f367e7cb8 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 14:09:05 +0100 Subject: [PATCH 140/275] homogeneous: extract algo only functions --- src/code/dialogs/autodraws/homogeneous.js | 347 ++++++++++------------ 1 file changed, 162 insertions(+), 185 deletions(-) diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index 57a8a3bd4..4575d588c 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -8,9 +8,166 @@ import { import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; -import PortalUI from "../../ui/portal"; import { displayError, displayWarning } from "../../error"; +/** + * Split a set of portals inside a field into three sets with respect to a portal in the field + * @param {WasabeePortal} centerPoint Portal inside the field one/two/three + * @param {WasabeePortal[]} possibles Portals inside the field one/two/three + * @param {WasabeePortal} one + * @param {WasabeePortal} two + * @param {WasabeePortal} three + * @returns {[WasabeePortal[],WasabeePortal[],WasabeePortal[]]} Sets of portals inside one/two/centerPoint, two/three/centerPoint and three/one/centerPoint + */ +function getSubregions(centerPoint, possibles, one, two, three) { + const possibleExceptAnchors = new Array(); + for (const p of possibles) { + const guid = p.id || p.options.guid; + if ( + guid !== centerPoint.id && + guid !== one.id && + guid !== two.id && + guid !== three.id + ) + possibleExceptAnchors.push(p); + } + + const onePortals = new Array(); + const twoPortals = new Array(); + const threePortals = new Array(); + for (const p of possibleExceptAnchors) { + if ( + greatCircleArcIntersectByLatLngs( + p.latLng, + one.latLng, + centerPoint.latLng, + two.latLng + ) || + greatCircleArcIntersectByLatLngs( + p.latLng, + one.latLng, + centerPoint.latLng, + three.latLng + ) + ) + twoPortals.push(p); + else if ( + greatCircleArcIntersectByLatLngs( + p.latLng, + two.latLng, + centerPoint.latLng, + one.latLng + ) || + greatCircleArcIntersectByLatLngs( + p.latLng, + two.latLng, + centerPoint.latLng, + three.latLng + ) + ) + threePortals.push(p); + else onePortals.push(p); + } + + return [onePortals, twoPortals, threePortals]; +} + +/** + * + * @param {WasabeePortal[]} portalsCovered + * @param {WasabeePortal} one + * @param {WasabeePortal} two + * @param {WasabeePortal} three + * @param {number} depth + * @returns + */ +function fullRecurser(portalsCovered, one, two, three, depth) { + const alreadyCalculatedCover = new Map(); + const getNbSplitPerDepth = (depth) => (3 ** (depth - 1) - 1) / 2; + + console.log( + "Expect at least", + Math.max(0, getNbSplitPerDepth(depth) - portalsCovered.length), + "missing splits" + ); + + const homogeneousFrom = (depth, portalsCovered, one, two, three) => { + if (depth <= 1) + return { success: true, anchors: [one, two, three], split: 0 }; + + const key = [depth, one.id, two.id, three.id].sort().toString(); + if (alreadyCalculatedCover.get(key) === undefined) { + const maxNbSplit = Math.min( + getNbSplitPerDepth(depth), + portalsCovered.length + ); + let bestResult = { + success: false, + anchors: [one, two, three], + split: 0, + portal: null, + children: null, + }; + for (const wp of portalsCovered) { + const subregions = getSubregions( + wp, + new Array(...portalsCovered), + one, + two, + three + ); + const maxNbSplitSubregions = + Math.min(getNbSplitPerDepth(depth - 1), subregions[0].length) + + Math.min(getNbSplitPerDepth(depth - 1), subregions[1].length) + + Math.min(getNbSplitPerDepth(depth - 1), subregions[2].length); + if (maxNbSplitSubregions + 1 <= bestResult.split) { + // Skip the portal since it will induce less splits than the current best choice + continue; + } + + let ret1 = homogeneousFrom( + depth - 1, + new Array(...subregions[0]), + one, + two, + wp + ); + let ret2 = homogeneousFrom( + depth - 1, + new Array(...subregions[1]), + two, + three, + wp + ); + let ret3 = homogeneousFrom( + depth - 1, + new Array(...subregions[2]), + one, + three, + wp + ); + + const nbSplit = ret1.split + ret2.split + ret3.split + 1; + + if (nbSplit > bestResult.split) { + bestResult.success = ret1.success && ret2.success && ret3.success; + bestResult.split = nbSplit; + bestResult.portal = wp; + bestResult.children = [ret1, ret2, ret3]; + } + + if (nbSplit == maxNbSplit) { + // we cannot do more split so it is one of the best choice + break; + } + } + alreadyCalculatedCover.set(key, bestResult); + } + return alreadyCalculatedCover.get(key); + }; + return homogeneousFrom(depth, portalsCovered, one, two, three); +} + const HomogeneousDialog = AutoDraw.extend({ statics: { TYPE: "HomogeneousDialog", @@ -187,11 +344,12 @@ const HomogeneousDialog = AutoDraw.extend({ } console.time("HF deep recurser"); - const tree = this._fullRecurser( + const tree = fullRecurser( portals, this._anchorOne, this._anchorTwo, - this._anchorThree + this._anchorThree, + +this.depthMenu.value ); console.timeEnd("HF deep recurser"); @@ -294,7 +452,7 @@ const HomogeneousDialog = AutoDraw.extend({ for (const [k, wp] of sorted) { // silence lint this._trash = k; - const subregions = this._getSubregions( + const subregions = getSubregions( wp, new Array(...portalsCovered), one, @@ -345,134 +503,6 @@ const HomogeneousDialog = AutoDraw.extend({ return bestResult; }, - _fullRecurser: function (portalsCovered, one, two, three) { - const alreadyCalculatedCover = new Map(); - const getNbSplitPerDepth = (depth) => (3 ** (depth - 1) - 1) / 2; - - console.log( - "Expect at least", - Math.max( - 0, - getNbSplitPerDepth(this.depthMenu.value) - portalsCovered.length - ), - "missing splits" - ); - - const homogeneousFrom = (depth, portalsCovered, one, two, three) => { - if (depth <= 1) - return { success: true, anchors: [one, two, three], split: 0 }; - - const key = [depth, one.id, two.id, three.id].sort().toString(); - if (alreadyCalculatedCover.get(key) === undefined) { - // sort portals according to the balance between the regions - const m = new Map(); - // for each of the portals in play - for (const wp of portalsCovered) { - const subregions = this._getSubregions( - wp, - new Array(...portalsCovered), - one, - two, - three - ); - // one of the regions didn't have enough - if (!subregions) continue; - // is this one better than the previous? - // smallest difference in the number of portals between the greatest and least, 0 being ideal - const differential = - Math.max( - subregions[0].length, - subregions[1].length, - subregions[2].length - ) - - Math.min( - subregions[0].length, - subregions[1].length, - subregions[2].length - ); - m.set(wp.id, differential); - } - - const sorted = new Map([...m.entries()].sort((a, b) => a[1] - b[1])); - - const maxNbSplit = Math.min( - getNbSplitPerDepth(depth), - portalsCovered.length - ); - let bestResult = { - success: false, - anchors: [one, two, three], - split: 0, - portal: null, - children: null, - }; - for (const k of sorted.keys()) { - const wp = PortalUI.get(k); - const subregions = this._getSubregions( - wp, - new Array(...portalsCovered), - one, - two, - three - ); - const maxNbSplitSubregions = - Math.min(getNbSplitPerDepth(depth - 1), subregions[0].length) + - Math.min(getNbSplitPerDepth(depth - 1), subregions[1].length) + - Math.min(getNbSplitPerDepth(depth - 1), subregions[2].length); - if (maxNbSplitSubregions + 1 <= bestResult.split) { - // Skip the portal since it will induce less splits than the current best choice - continue; - } - - let ret1 = homogeneousFrom( - depth - 1, - new Array(...subregions[0]), - one, - two, - wp - ); - let ret2 = homogeneousFrom( - depth - 1, - new Array(...subregions[1]), - two, - three, - wp - ); - let ret3 = homogeneousFrom( - depth - 1, - new Array(...subregions[2]), - one, - three, - wp - ); - - const nbSplit = ret1.split + ret2.split + ret3.split + 1; - - if (nbSplit > bestResult.split) { - bestResult.success = ret1.success && ret2.success && ret3.success; - bestResult.split = nbSplit; - bestResult.portal = wp; - bestResult.children = [ret1, ret2, ret3]; - } - - if (nbSplit == maxNbSplit) { - // we cannot do more split so it is one of the best choice - break; - } - } - alreadyCalculatedCover.set(key, bestResult); - } - return alreadyCalculatedCover.get(key); - }; - return homogeneousFrom( - this.depthMenu.value, - portalsCovered, - one, - two, - three - ); - }, - _drawTreeCore: function (tree) { const depthValue = +this.depthMenu.value - 1; const [one, two, three] = tree.anchors; @@ -697,59 +727,6 @@ const HomogeneousDialog = AutoDraw.extend({ draw(1, tree, one, two); }, - _getSubregions: function (centerPoint, possibles, one, two, three) { - const possibleExceptAnchors = new Array(); - for (const p of possibles) { - const guid = p.id || p.options.guid; - if ( - guid !== centerPoint.id && - guid !== one.id && - guid !== two.id && - guid !== three.id - ) - possibleExceptAnchors.push(p); - } - - const onePortals = new Array(); - const twoPortals = new Array(); - const threePortals = new Array(); - for (const p of possibleExceptAnchors) { - if ( - greatCircleArcIntersectByLatLngs( - p.latLng, - one.latLng, - centerPoint.latLng, - two.latLng - ) || - greatCircleArcIntersectByLatLngs( - p.latLng, - one.latLng, - centerPoint.latLng, - three.latLng - ) - ) - twoPortals.push(p); - else if ( - greatCircleArcIntersectByLatLngs( - p.latLng, - two.latLng, - centerPoint.latLng, - one.latLng - ) || - greatCircleArcIntersectByLatLngs( - p.latLng, - two.latLng, - centerPoint.latLng, - three.latLng - ) - ) - threePortals.push(p); - else onePortals.push(p); - } - - return [onePortals, twoPortals, threePortals]; - }, - _getCenter: function (a, b, c) { const A = window.map.project(a.latLng || a._latlng); const B = window.map.project(b.latLng || b._latlng); From 1e527e9b8db824a9be453fae8f1234e5460ba4cd Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 18:58:46 +0100 Subject: [PATCH 141/275] crosslink: more 3d tools + field center --- src/code/crosslinks.ts | 46 +++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/code/crosslinks.ts b/src/code/crosslinks.ts index a9527237c..54f610da9 100644 --- a/src/code/crosslinks.ts +++ b/src/code/crosslinks.ts @@ -10,8 +10,12 @@ import type WasabeeLink from "./model/link"; // from iitc rework : https://github.com/IITC-CE/ingress-intel-total-conversion/pull/333 const d2r = Math.PI / 180; +const r2d = 180 / Math.PI; type Vec3 = [number, number, number]; +interface LLC extends L.LatLng { + _cartesian?: Vec3; +} function toCartesian(lat: number, lng: number): Vec3 { lat *= d2r; @@ -20,6 +24,15 @@ function toCartesian(lat: number, lng: number): Vec3 { return [o * Math.cos(lng), o * Math.sin(lng), Math.sin(lat)]; } +export function toLatLng(xyz: Vec3): LLC { + const lat = Math.atan2(xyz[2], Math.sqrt(xyz[0] * xyz[0] + xyz[1] * xyz[1])); + const lng = Math.atan2(xyz[1], xyz[0]); + + const ll: LLC = L.latLng({ lat: lat * r2d, lng: lng * r2d }); + ll._cartesian = [...xyz]; + return ll; +} + function cross(t: Vec3, n: Vec3): Vec3 { return [ t[1] * n[2] - t[2] * n[1], @@ -36,15 +49,34 @@ function det(a: Vec3, b: Vec3, c: Vec3) { return dot(cross(a, b), c); } +function norm2(a: Vec3) { + return a[0] * a[0] + a[1] * a[1] + a[2] * a[2]; +} + +function norm(a: Vec3) { + return Math.hypot(...a); +} + +// where is the fast inverse square root when we need it ? +export function normalize(a: Vec3): Vec3 { + const n = 1 / norm(a); + return [a[0] * n, a[1] * n, a[2] * n]; +} + +export function dist2(a: Vec3, b: Vec3) { + return norm2([ + a[0] - b[0], + a[1] - b[1], + a[2] - b[2], + ]) +} + function equals(a: L.LatLng, b: L.LatLng) { return a.lat === b.lat && a.lng === b.lng; } // take L.LatLng // note: cache cos/sin calls in the object, in order to be efficient, try using same LatLng objects across calls, like using latLng from WasabeePortal attached to an op -interface LLC extends L.LatLng { - _cartesian?: Vec3; -} export function extendLatLngToLLC(ll: LLC) { if (ll._cartesian) return ll; @@ -87,11 +119,11 @@ export function fieldCenter( const cb = extendLatLngToLLC(b.latLng)._cartesian; const cc = extendLatLngToLLC(c.latLng)._cartesian; const ccenter: Vec3 = [ - ca[0]+cb[0]+cc[0], - ca[1]+cb[1]+cc[1], - ca[2]+cb[2]+cc[2], + ca[0] + cb[0] + cc[0], + ca[1] + cb[1] + cc[1], + ca[2] + cb[2] + cc[2], ]; - return ccenter; + return toLatLng(ccenter); } export function greatCircleArcIntersectByLatLngs(a0: LLC[], a1: LLC[]): boolean; From 65f1fe785d7677704ead137b4987c3e0ead1b20a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 19:00:03 +0100 Subject: [PATCH 142/275] homogeneous: sort by distance to center (full recurser) --- src/code/dialogs/autodraws/homogeneous.d.ts | 14 +++++++++ src/code/dialogs/autodraws/homogeneous.js | 33 ++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/code/dialogs/autodraws/homogeneous.d.ts b/src/code/dialogs/autodraws/homogeneous.d.ts index b219dddb0..527df4402 100644 --- a/src/code/dialogs/autodraws/homogeneous.d.ts +++ b/src/code/dialogs/autodraws/homogeneous.d.ts @@ -1,6 +1,20 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; +/** Tree-like strucure holding a HF configuration */ +export interface Tree { + /** true if complete with respect to the request depth */ + success: boolean; + /** anchors of the field */ + anchors: [WasabeePortal, WasabeePortal, WasabeePortal]; + /** number of split found (tree size) */ + split: number; + /** portal used to split the field into three sub field */ + portal: WasabeePortal; + /** sub tree using `portal` */ + children: [Tree, Tree, Tree]; +} + export default class HomogeneousDialog extends AutoDraw { _anchorOne: WasabeePortal; _anchorTwo: WasabeePortal; diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index 4575d588c..43b9b772b 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -2,8 +2,11 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; import { + extendLatLngToLLC, greatCircleArcIntersectByLatLngs, portalInField, + dist2, + fieldCenter, } from "../../crosslinks"; import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; @@ -72,6 +75,23 @@ function getSubregions(centerPoint, possibles, one, two, three) { return [onePortals, twoPortals, threePortals]; } +/** + * Sort in place by distance to point + * @param {WasabeePortal[]} portals + * @param {import("leaflet").LatLng} point + */ +function sortByDistance(portals, point) { + // straight square distance is good enough in 3D + const cp = extendLatLngToLLC(point)._cartesian; + const cPs = new Map( + portals.map((p) => [ + p.id, + dist2(cp, extendLatLngToLLC(p.latLng)._cartesian), + ]) + ); + return portals.sort((a, b) => cPs.get(a.id) - cPs.get(b.id)); +} + /** * * @param {WasabeePortal[]} portalsCovered @@ -79,7 +99,7 @@ function getSubregions(centerPoint, possibles, one, two, three) { * @param {WasabeePortal} two * @param {WasabeePortal} three * @param {number} depth - * @returns + * @returns {import("./homogeneous").Tree} */ function fullRecurser(portalsCovered, one, two, three, depth) { const alreadyCalculatedCover = new Map(); @@ -91,6 +111,15 @@ function fullRecurser(portalsCovered, one, two, three, depth) { "missing splits" ); + /** + * Find one of the best (in terms of splits) HF configuration as a Tree decomposition + * @param {number} depth + * @param {WasabeePortal[]} portalsCovered + * @param {WasabeePortal} one + * @param {WasabeePortal} two + * @param {WasabeePortal} three + * @returns {import("./homogeneous").Tree} + */ const homogeneousFrom = (depth, portalsCovered, one, two, three) => { if (depth <= 1) return { success: true, anchors: [one, two, three], split: 0 }; @@ -101,6 +130,7 @@ function fullRecurser(portalsCovered, one, two, three, depth) { getNbSplitPerDepth(depth), portalsCovered.length ); + /** @type {import("./homogeneous").Tree} */ let bestResult = { success: false, anchors: [one, two, three], @@ -108,6 +138,7 @@ function fullRecurser(portalsCovered, one, two, three, depth) { portal: null, children: null, }; + sortByDistance(portalsCovered, fieldCenter(one, two, three)); for (const wp of portalsCovered) { const subregions = getSubregions( wp, From 2c58c71a8d1ac3681a2b3a91b8dfcb692a0bff3d Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 19:22:38 +0100 Subject: [PATCH 143/275] homogeneous: move greedy outside UI class --- src/code/dialogs/autodraws/homogeneous.js | 189 +++++++++++----------- 1 file changed, 91 insertions(+), 98 deletions(-) diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index 43b9b772b..ed175e202 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -93,7 +93,7 @@ function sortByDistance(portals, point) { } /** - * + * Find one of the best (in terms of splits) HF configuration as a Tree decomposition * @param {WasabeePortal[]} portalsCovered * @param {WasabeePortal} one * @param {WasabeePortal} two @@ -199,6 +199,91 @@ function fullRecurser(portalsCovered, one, two, three, depth) { return homogeneousFrom(depth, portalsCovered, one, two, three); } +/** + * Find a HF Tree decomposition with a greedy heuristic, may fail even if HF exists + * @param {WasabeePortal[]} portalsCovered + * @param {WasabeePortal} one + * @param {WasabeePortal} two + * @param {WasabeePortal} three + * @param {number} depth + * @returns {import("./homogeneous").Tree} + */ +function greedy(portalsCovered, one, two, three, depth) { + if (depth <= 1) + return { success: true, anchors: [one, two, three], split: 0 }; + + // empty tree + /** @type {import("./homogeneous").Tree} */ + let bestResult = { + success: false, + anchors: [one, two, three], + split: 0, + portal: null, + children: null, + }; + + if (!portalsCovered.length) { + return bestResult; + } + + // sort first by distance to center + sortByDistance(portalsCovered, fieldCenter(one, two, three)); + + // greedy heuristic: + // find the portal that divides the area into regions with the closest number of portals + // starts at the center-most and works outwards + let differential = portalsCovered.length; + let best = []; + let bestp = {}; + // for each of the portals in play + for (const wp of portalsCovered) { + const subregions = getSubregions( + wp, + new Array(...portalsCovered), + one, + two, + three + ); + // smallest difference in the number of portals between the greatest and least, 0 being ideal + const temp = + Math.max( + subregions[0].length, + subregions[1].length, + subregions[2].length + ) - + Math.min( + subregions[0].length, + subregions[1].length, + subregions[2].length + ); + if (temp < differential) { + best = subregions; + differential = temp; + bestp = wp; + } + // found one with equal number of portals in all 3, quit digging + if (differential == 0) break; + } + + bestResult.portal = bestp; + + bestResult.children = [ + greedy(new Array(...best[0]), one, two, bestp, depth - 1), + greedy(new Array(...best[1]), two, three, bestp, depth - 1), + greedy(new Array(...best[2]), one, three, bestp, depth - 1), + ]; + bestResult.success = + bestResult.children[0].success && + bestResult.children[1].success && + bestResult.children[2].success; + bestResult.split = + 1 + + bestResult.children[0].split + + bestResult.children[1].split + + bestResult.children[2].split; + return bestResult; +} + const HomogeneousDialog = AutoDraw.extend({ statics: { TYPE: "HomogeneousDialog", @@ -337,15 +422,15 @@ const HomogeneousDialog = AutoDraw.extend({ portals.push(p); } - console.time("HF recurser"); - const tree = this._recurser( - 1, + console.time("HF greedy"); + const tree = greedy( portals, this._anchorOne, this._anchorTwo, - this._anchorThree + this._anchorThree, + this.depthMenu.value ); - console.timeEnd("HF recurser"); + console.timeEnd("HF greedy"); this._tree = tree; this._failed = (3 ** (+this.depthMenu.value - 1) - 1) / 2 - tree.split; @@ -442,98 +527,6 @@ const HomogeneousDialog = AutoDraw.extend({ this._redrawButton.style.display = ""; }, - _recurser: function (depth, portalsCovered, one, two, three) { - if (depth >= this.depthMenu.value) - return { success: true, anchors: [one, two, three], split: 0 }; - - // empty tree - let bestResult = { - success: false, - anchors: [one, two, three], - split: 0, - portal: null, - children: null, - }; - - // console.log(depth, "portals in consideration", portalsCovered); - - // build a map of all portals coverd by field one,two,three - // keyed by distance to the centeroid of the field - // does this get us much in reality? doesn't seem like it - const m = new Map(); - const center = this._getCenter(one, two, three); - for (const p of portalsCovered) { - if (p.id === one.id || p.id === two.id || p.id === three.id) continue; - const cDist = window.map.distance(center, p.latLng || p._latlng); - m.set(cDist, p); - } - // sort by distance to centeroid the field - const sorted = new Map([...m.entries()].sort((a, b) => a[0] - b[0])); - if (sorted.size == 0) { - // console.log("empty set"); - return bestResult; - } - - // find the portal that divides the area into regions with the closest number of portals - // starts at the center-most and works outwards - let differential = portalsCovered.length; - let best = []; - let bestp = {}; - // for each of the portals in play - for (const [k, wp] of sorted) { - // silence lint - this._trash = k; - const subregions = getSubregions( - wp, - new Array(...portalsCovered), - one, - two, - three - ); - // one of the regions didn't have enough - // if (!subregions) continue; // never - // is this one better than the previous? - // smallest difference in the number of portals between the greatest and least, 0 being ideal - const temp = - Math.max( - subregions[0].length, - subregions[1].length, - subregions[2].length - ) - - Math.min( - subregions[0].length, - subregions[1].length, - subregions[2].length - ); - if (temp < differential) { - best = subregions; - differential = temp; - bestp = wp; - } - // found one with equal number of portals in all 3, quit digging - // if (differential == 0) break; - } - - // console.log("best balance: ", bestp.name, differential, best); - bestResult.portal = bestp; - - bestResult.children = [ - this._recurser(depth + 1, new Array(...best[0]), one, two, bestp), - this._recurser(depth + 1, new Array(...best[1]), two, three, bestp), - this._recurser(depth + 1, new Array(...best[2]), one, three, bestp), - ]; - bestResult.success = - bestResult.children[0].success && - bestResult.children[1].success && - bestResult.children[2].success; - bestResult.split = - 1 + - bestResult.children[0].split + - bestResult.children[1].split + - bestResult.children[2].split; - return bestResult; - }, - _drawTreeCore: function (tree) { const depthValue = +this.depthMenu.value - 1; const [one, two, three] = tree.anchors; From 247ba9c02604e22e315b53c02a36f7925a7a46b5 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 19:26:40 +0100 Subject: [PATCH 144/275] checklist: use more accurate field sign --- src/code/dialogs/checklist.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 95ba88b23..df0778ccc 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -20,6 +20,7 @@ import wX from "../wX"; import PortalUI from "../ui/portal"; import LinkUI from "../ui/link"; import { displayInfo, displayWarning } from "../error"; +import { fieldSign } from "../crosslinks"; const OperationChecklistDialog = WDialog.extend({ statics: { @@ -338,10 +339,8 @@ const OperationChecklistDialog = WDialog.extend({ // ignore earth curvature (todo: use it) for (const pid of intersect) { const p = operation.getPortal(pid); - const det = - (p1.lat - p2.lat) * (p.lng - p2.lng) - - (p1.lng - p2.lng) * (p.lat - p2.lat); - if (det > 0) positive.push(p); + const sign = fieldSign(p, p1, p2); + if (sign > 0) positive.push(p); else negative.push(p); } if (positive.length) fieldCount += 1; From fbab93ac423580083cdb7d80540288ab05a5c7ff Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 20:14:34 +0100 Subject: [PATCH 145/275] checklist: move count field to operation model + add link from covered portal --- src/code/css/wasabee.css | 4 ++ src/code/dialogs/checklist.js | 83 ++++++++++++---------------------- src/code/model/operation.ts | 84 +++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 55 deletions(-) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index dad395df9..82ed0d76d 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -514,6 +514,10 @@ a.wasabee-portal.res { color: rgb(0, 135, 255) !important; } padding-left: 1em; } +.field-count li.inner-link > div { + display: inline; +} + .field-count ul { padding-left: 1em; } diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index df0778ccc..019840145 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -20,7 +20,6 @@ import wX from "../wX"; import PortalUI from "../ui/portal"; import LinkUI from "../ui/link"; import { displayInfo, displayWarning } from "../error"; -import { fieldSign } from "../crosslinks"; const OperationChecklistDialog = WDialog.extend({ statics: { @@ -304,60 +303,17 @@ const OperationChecklistDialog = WDialog.extend({ }, countFields: function (operation, doAlert) { - const links = Array.from(operation.links); - links.sort((a, b) => a.order - b.order); + const { + fieldCount, + emptyCount, + emptyFieldLinks, + linksFromInner, + coveredPortals, + } = operation.getOrderInfo(); - let fieldCount = 0; - let emptyCount = 0; - - // maps a portal id to its linked portals - const portalLinks = new Map(); - const emptyFieldLinks = []; - for (const link of links) { - if (!portalLinks.has(link.fromPortalId)) - portalLinks.set(link.fromPortalId, new Set()); - if (!portalLinks.has(link.toPortalId)) - portalLinks.set(link.toPortalId, new Set()); - const a = portalLinks.get(link.fromPortalId); - const b = portalLinks.get(link.toPortalId); - - // common neighbors portal - const intersect = new Set(); - for (const p of a) if (b.has(p)) intersect.add(p); - - // update the mapping - a.add(link.toPortalId); - b.add(link.fromPortalId); - - // ignore link with order 0 - if (link.order > 0) { - // the link closes at least one field - const p1 = operation.getPortal(link.fromPortalId); - const p2 = operation.getPortal(link.toPortalId); - const positive = []; - const negative = []; - // ignore earth curvature (todo: use it) - for (const pid of intersect) { - const p = operation.getPortal(pid); - const sign = fieldSign(p, p1, p2); - if (sign > 0) positive.push(p); - else negative.push(p); - } - if (positive.length) fieldCount += 1; - if (negative.length) fieldCount += 1; - // if the link closes multiple fields on the same side of the link, we have empty fields. - if (positive.length > 1 || negative.length > 1) { - let count = 0; - if (positive.length > 1) count += positive.length - 1; - if (negative.length > 1) count += negative.length - 1; - emptyFieldLinks.push([link, count]); - emptyCount += count; - } - } - } if (doAlert) { - if (emptyFieldLinks.length > 0) { - const container = L.DomUtil.create("div", "field-count"); + const container = L.DomUtil.create("div", "field-count"); + if (emptyFieldLinks.length) { const header = L.DomUtil.create("div", null, container); header.textContent = `Found ${fieldCount} fields and ${emptyCount} empty field(s) on ${emptyFieldLinks.length} link(s)`; const content = L.DomUtil.create("ul", null, container); @@ -366,12 +322,29 @@ const OperationChecklistDialog = WDialog.extend({ li.textContent = c; li.appendChild(LinkUI.displayFormat(link, operation)); } + } else { + const header = L.DomUtil.create("div", null, container); + header.textContent = `Found ${fieldCount} fields and no empty field`; + } + if (linksFromInner.length) { + const header = L.DomUtil.create("div", null, container); + header.textContent = `Found ${linksFromInner.length} links from covered portals`; + const content = L.DomUtil.create("ul", null, container); + for (const link of linksFromInner) { + const cl = coveredPortals.get(link.fromPortalId); + const li = L.DomUtil.create("li", "inner-link", content); + li.append(`${link.order}: `); + li.appendChild(LinkUI.displayFormat(link, operation)); + li.append(` at ${cl.order} by link `); + li.appendChild(LinkUI.displayFormat(cl, operation)); + } + } + if (emptyFieldLinks.length || linksFromInner.length) { displayWarning(container, true); } else { - displayInfo(`Found ${fieldCount} fields and no empty fields.`); + displayInfo(container, true); } } - return { field: fieldCount, empty: emptyCount }; }, }); diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 82cbe7aa6..629ba73b6 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -13,6 +13,7 @@ import db from "../db"; import WasabeeBlocker from "./blocker"; import type Task from "./task"; import { displayWarning } from "../error"; +import { fieldSign, portalInField } from "../crosslinks"; export type KeyOnHand = { portalId: string; @@ -1562,4 +1563,87 @@ export default class WasabeeOp extends Evented implements IOperation { // default to primary zone return 1; } + + getOrderInfo() { + const links = Array.from(this.links); + links.sort((a, b) => a.order - b.order); + + // map portal id to link they got covered + const coveredPortals = new Map(); + const linksFromInner: WasabeeLink[] = []; + + let fieldCount = 0; + let emptyCount = 0; + + // maps a portal id to its linked portals + const portalLinks = new Map>(); + const emptyFieldLinks: [WasabeeLink, number][] = []; + for (const link of links) { + if (!portalLinks.has(link.fromPortalId)) + portalLinks.set(link.fromPortalId, new Set()); + if (!portalLinks.has(link.toPortalId)) + portalLinks.set(link.toPortalId, new Set()); + const a = portalLinks.get(link.fromPortalId); + const b = portalLinks.get(link.toPortalId); + + // common neighbors portal + const intersect = new Set(); + for (const p of a) if (b.has(p)) intersect.add(p); + + // update the mapping + a.add(link.toPortalId); + b.add(link.fromPortalId); + + // ignore link with order 0 + if (link.order > 0) { + // the link closes at least one field + const p1 = this.getPortal(link.fromPortalId); + const p2 = this.getPortal(link.toPortalId); + const positive: WasabeePortal[] = []; + const negative: WasabeePortal[] = []; + // ignore earth curvature (todo: use it) + for (const pid of intersect) { + const p = this.getPortal(pid); + const sign = fieldSign(p, p1, p2); + if (sign > 0) positive.push(p); + else negative.push(p); + } + if (positive.length) fieldCount += 1; + if (negative.length) fieldCount += 1; + // if the link closes multiple fields on the same side of the link, we have empty fields. + // doesn't support crossed links configuration yet + if (positive.length > 1 || negative.length > 1) { + let count = 0; + if (positive.length > 1) count += positive.length - 1; + if (negative.length > 1) count += negative.length - 1; + emptyFieldLinks.push([link, count]); + emptyCount += count; + } + + // record covering time + for (const pid of intersect) { + const p = this.getPortal(pid); + for (const a of this.anchors) { + if (a === pid || a === p1.id || a === p2.id) continue; + if (!coveredPortals.has(a)) { + const ap = this.getPortal(a); + if (portalInField(p1, p2, p, ap)) coveredPortals.set(a, link); + } + } + } + } + + if (coveredPortals.has(link.fromPortalId)) { + linksFromInner.push(link); + } + } + + return { + fieldCount, + emptyFieldLinks, + emptyCount, + linksFromInner, + coveredPortals, + }; + } } From 4cd77f50ea2fe17c2e26785b49cdc1ba210476a4 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 13 Dec 2021 21:27:38 +0100 Subject: [PATCH 146/275] fan/flip: move common to algorithm --- src/code/dialogs/autodraws/algorithm.ts | 65 ++++++++++++++++++++++++- src/code/dialogs/autodraws/fanfield.js | 60 +++-------------------- src/code/dialogs/autodraws/flipflop.js | 41 +--------------- 3 files changed, 73 insertions(+), 93 deletions(-) diff --git a/src/code/dialogs/autodraws/algorithm.ts b/src/code/dialogs/autodraws/algorithm.ts index f94fd9534..e6284c049 100644 --- a/src/code/dialogs/autodraws/algorithm.ts +++ b/src/code/dialogs/autodraws/algorithm.ts @@ -1,4 +1,4 @@ -import { fieldSign } from "../../crosslinks"; +import { fieldSign, GeodesicLine } from "../../crosslinks"; import type WasabeePortal from "../../model/portal"; type Poset = Map; @@ -167,3 +167,66 @@ export function getSignedSpine( sequencePos.length > sequenceNeg.length ? sequencePos : sequenceNeg; return [sequence.map((id) => portalsMap.get(id))]; } + +/** Returns bearing of link a-p */ +export function angle(a: WasabeePortal, p: WasabeePortal) { + if (a.id == p.id) throw Error("same portal"); + if (a.latLng.lng == p.latLng.lng) { + if (a.latLng.lat > p.latLng.lat) return 0; + else return Math.PI; + } + const link = new GeodesicLine(a.latLng, p.latLng); + return link.bearing(); +} + +/** Sort portals by angle from anchor */ +export function sortPortalsByAngle( + anchor: WasabeePortal, + portals: WasabeePortal[] +) { + const good = new Map(); + for (const p of portals) { + if (p.id == anchor.id) continue; + const pAngle = angle(anchor, p); + good.set(pAngle, p); + } + + const sorted = new Array(...good.entries()) + .sort((a, b) => a[0] - b[0]) + .map((v) => v[1]); + + return sorted; +} + +/** + * Select portals in the interval start-end wrt their angle from anchor. + * The portals must be sorted by angle and contains start/end + */ +export function selectAngleInterval( + anchor: WasabeePortal, + portalsSorted: WasabeePortal[], + start: WasabeePortal, + end: WasabeePortal +) { + const startAngle = angle(anchor, start); + const endAngle = angle(anchor, end); + + // swap start/end if more than 180° + if ( + (((endAngle - startAngle) % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI) > + Math.PI + ) { + [start, end] = [end, start]; + } + + // Build the sequence of portals between start/end + const slice = new Array(); + let s = 0; + for (s = 0; portalsSorted[s].id != start.id; s++); + for (; portalsSorted[s % portalsSorted.length].id != end.id; s++) { + slice.push(portalsSorted[s % portalsSorted.length]); + } + slice.push(end); + + return slice; +} diff --git a/src/code/dialogs/autodraws/fanfield.js b/src/code/dialogs/autodraws/fanfield.js index 3e073d95a..9cd69c51c 100644 --- a/src/code/dialogs/autodraws/fanfield.js +++ b/src/code/dialogs/autodraws/fanfield.js @@ -1,63 +1,19 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; -import { GeodesicLine, testSelfBlock } from "../../crosslinks"; +import { testSelfBlock } from "../../crosslinks"; import WasabeeLink from "../../model/link"; import { clearAllLinks } from "../../uiCommands"; import wX from "../../wX"; import { displayError, displayInfo } from "../../error"; -export function angle(a, p) { - if (a.id == p.id) throw Error("same portal"); - if (a.latLng.lng == p.latLng.lng) { - if (a.latLng.lat > p.latLng.lat) return 0; - else return Math.PI; - } - const link = new GeodesicLine(a.latLng, p.latLng); - return link.bearing(); -} +import { sortPortalsByAngle, selectAngleInterval } from "./algorithm"; -export function sortPortalsByAngle(anchor, portals, start, end) { - const startAngle = angle(anchor, start); - const endAngle = angle(anchor, end); - - // swap start/end if more than 180° - let invert = false; - if ( - (((endAngle - startAngle) % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI) > - Math.PI - ) { - invert = true; - } - - const good = new Map(); - for (const p of portals) { - if (p.id == anchor.id) continue; - const pAngle = angle(anchor, p); - - good.set(pAngle, p); // what are the odds of two having EXACTLY the same angle? - } - // add start and end portals just in case - good.set(startAngle, start); - good.set(endAngle, end); - - const sorted = new Array(...good.entries()) - .sort((a, b) => a[0] - b[0]) - .map((v) => v[1]); - - if (invert) { - sorted.reverse(); - } - // Build the sequence of portals between start/end - const slice = new Array(); - let s = 0; - for (s = 0; sorted[s].id != start.id; s++); - for (; sorted[s % sorted.length].id != end.id; s++) { - slice.push(sorted[s % sorted.length]); - } - slice.push(end); - - return slice; +export function sortPortals(anchor, portals, start, end) { + if (!portals.find((p) => p.id === start.id)) portals.push(start); + if (!portals.find((p) => p.id === end.id)) portals.push(end); + const sorted = sortPortalsByAngle(anchor, portals); + return selectAngleInterval(anchor, sorted, start, end); } const FanfieldDialog = AutoDraw.extend({ @@ -143,7 +99,7 @@ const FanfieldDialog = AutoDraw.extend({ return; } - const steps = sortPortalsByAngle( + const steps = sortPortals( this._anchor, this._portalSets["set"].portals, this._start, diff --git a/src/code/dialogs/autodraws/flipflop.js b/src/code/dialogs/autodraws/flipflop.js index b6c9da176..788654f7d 100644 --- a/src/code/dialogs/autodraws/flipflop.js +++ b/src/code/dialogs/autodraws/flipflop.js @@ -6,49 +6,10 @@ import { getAllPortalsOnScreen, clearAllLinks } from "../../uiCommands"; import WasabeePortal from "../../model/portal"; import WasabeeMarker from "../../model/marker"; -import { angle } from "./fanfield"; +import { selectAngleInterval, sortPortalsByAngle } from "./algorithm"; import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; import { displayError, displayInfo } from "../../error"; -function selectAngleInterval(anchor, portalsSorted, start, end) { - const startAngle = angle(anchor, start); - const endAngle = angle(anchor, end); - - // swap start/end if more than 180° - if ( - (((endAngle - startAngle) % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI) > - Math.PI - ) { - [start, end] = [end, start]; - } - - // Build the sequence of portals between start/end - const slice = new Array(); - let s = 0; - for (s = 0; portalsSorted[s].id != start.id; s++); - for (; portalsSorted[s % portalsSorted.length].id != end.id; s++) { - slice.push(portalsSorted[s % portalsSorted.length]); - } - slice.push(end); - - return slice; -} - -function sortPortalsByAngle(anchor, portals) { - const good = new Map(); - for (const p of portals) { - if (p.id == anchor.id) continue; - const pAngle = angle(anchor, p); - good.set(pAngle, p); - } - - const sorted = new Array(...good.entries()) - .sort((a, b) => a[0] - b[0]) - .map((v) => v[1]); - - return sorted; -} - function fastFan(anchor, two, three, portalsSorted, offset, revSortAngle) { const res = []; const inserted = [two, three]; From f0e1e107def71ab2da4ffd41ceb122319d2d3a34 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 13 Dec 2021 21:50:58 +0100 Subject: [PATCH 147/275] madrid: dependence on algorithm --- src/code/dialogs/autodraws/madrid.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index 1da2b095f..ec46689ec 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -5,15 +5,31 @@ import { clearAllLinks } from "../../uiCommands"; import wX from "../../wX"; import { getSignedSpine } from "./algorithm"; import { drawSpine, insertLinks } from "./drawRoutines"; -import MultimaxDialog from "./multimaxDialog"; +import { AutoDraw } from "./tools"; +import WasabeePortal from "../../model/portal"; // now that the formerly external mm functions are in the class, some of the logic can be cleaned up // to not require passing values around when we can get them from this.XXX -const MadridDialog = MultimaxDialog.extend({ +const MadridDialog = AutoDraw.extend({ statics: { TYPE: "madridDialog", }, + initialize: function (options) { + AutoDraw.prototype.initialize.call(this, options); + let p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY]; + if (p) this._anchorOne = new WasabeePortal(p); + p = localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY]; + if (p) this._anchorTwo = new WasabeePortal(p); + }, + + addHooks: function () { + AutoDraw.prototype.addHooks.call(this); + + this._displayDialog(); + this._updatePortalSet(); + }, + _buildContent: function () { const container = L.DomUtil.create("div", "container"); const description = L.DomUtil.create("div", "desc", container); From aaa98947116dadd41538696f07184b91cf56b6d6 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 14 Dec 2021 21:40:43 +0100 Subject: [PATCH 148/275] fix: operation update after link color change --- src/code/model/link.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code/model/link.ts b/src/code/model/link.ts index ee01efa82..6ae60d0d6 100644 --- a/src/code/model/link.ts +++ b/src/code/model/link.ts @@ -73,6 +73,7 @@ export default class WasabeeLink extends Task { setColor(color: string, operation: WasabeeOp) { this.color = color; if (this.color == operation.color) this.color = "main"; + operation.update(); } getColor(operation: WasabeeOp) { From 59f11bce10bf50785dc6f9c133dee22ed9d3f03e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 20 Dec 2021 18:44:46 +0100 Subject: [PATCH 149/275] blockers: hide automark if no permission --- src/code/dialogs/blockersList.js | 29 +++++++++++++++++------------ src/code/dialogs/trawl.js | 6 ++++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index f43e1c6c0..f507da570 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -51,10 +51,13 @@ const BlockerList = WDialog.extend({ buttons[wX("OK")] = () => { this.closeDialog(); }; - buttons[wX("AUTOMARK")] = () => { - const operation = getSelectedOperation(); - blockerAutomark(operation); - }; + // doesn't support op select event + if (operation.canWrite()) { + buttons[wX("AUTOMARK")] = () => { + const operation = getSelectedOperation(); + blockerAutomark(operation); + }; + } buttons[wX("RESET")] = async () => { const operation = getSelectedOperation(); await WasabeeBlocker.removeBlockers(operation.ID); @@ -69,14 +72,16 @@ const BlockerList = WDialog.extend({ const td = new TrawlDialog(); td.enable(); }; - buttons["Clear Automark"] = () => { - const operation = getSelectedOperation(); - operation.startBatchMode(); - for (const m of operation.markers) { - if (m.comment == "auto-marked") operation.removeMarker(m); - } - operation.endBatchMode(); - }; + if (operation.canWrite()) { + buttons["Clear Automark"] = () => { + const operation = getSelectedOperation(); + operation.startBatchMode(); + for (const m of operation.markers) { + if (m.comment == "auto-marked") operation.removeMarker(m); + } + operation.endBatchMode(); + }; + } this.createDialog({ title: wX("KNOWN_BLOCK", { opName: operation.name }), diff --git a/src/code/dialogs/trawl.js b/src/code/dialogs/trawl.js index cafe9ecc7..59a8ba998 100644 --- a/src/code/dialogs/trawl.js +++ b/src/code/dialogs/trawl.js @@ -200,11 +200,13 @@ const TrawlDialog = WDialog.extend({ // WDialog is a leaflet L.Handler, which takes add/removeHooks addHooks: function () { WDialog.prototype.addHooks.call(this); + window.map.on("wasabee:op:select", this.closeDialog, this); this._displayDialog(); }, // define our work in _displayDialog _displayDialog: function () { + const operation = getSelectedOperation(); const container = L.DomUtil.create("div", "container"); const options = L.DomUtil.create("div", null, container); @@ -224,6 +226,10 @@ const TrawlDialog = WDialog.extend({ this.automark.checked = false; this.automark.id = "wasabee-trawl-automark"; + if (!operation.canWrite()) { + options.style.display = "none"; + } + const warning = L.DomUtil.create("h4", null, container); warning.textContent = wX("TRAWL WARNING"); From f60b6833e3c004e494cd862fbd91caeeffad6f80 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 18:49:43 +0100 Subject: [PATCH 150/275] add dummy quick delete button --- src/code/addButtons.ts | 2 + src/code/buttons/quickdelete.ts | 68 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/code/buttons/quickdelete.ts diff --git a/src/code/addButtons.ts b/src/code/addButtons.ts index 7dc45a9cb..7ce3427df 100644 --- a/src/code/addButtons.ts +++ b/src/code/addButtons.ts @@ -6,6 +6,7 @@ import OpButton from "./buttons/opButton"; import LinkButton from "./buttons/linkButton"; import MarkerButton from "./buttons/markerButton"; import UploadButton from "./buttons/uploadButton"; +import QuickDeleteButton from "./buttons/quickdelete"; /* This function adds the plugin buttons on the left side of the screen */ export function addButtons() { @@ -27,6 +28,7 @@ export function addButtons() { MarkerButton, SyncButton, UploadButton, + QuickDeleteButton, ]) { const item = L.DomUtil.create("li", null, options.container); const button = new Constructor(item); diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts new file mode 100644 index 000000000..d259f0bbe --- /dev/null +++ b/src/code/buttons/quickdelete.ts @@ -0,0 +1,68 @@ +import { WButton } from "../leafletClasses"; +import wX from "../wX"; + +class QuickDeleteButton extends WButton { + static TYPE = "QuickdeleteButton"; + + needWritePermission: true; + + constructor(container: HTMLElement) { + super(container); + + this.title = wX("toolbar.quick_delete.title"); + this.type = QuickDeleteButton.TYPE; + + this.button = this._createButton({ + title: this.title, + container: container, + className: "wasabee-toolbar-quickdelete", + context: this, + callback: this._toggleActions, + }); + + this.actionsContainer = this._createSubActions(this.getSubActions()); + + this._container.appendChild(this.actionsContainer); + + // update text + window.map.on("wasabee:ui:skin wasabee:ui:lang", () => { + this.button.title = wX("toolbar.quick_delete.title"); + const newSubActions = this._createSubActions(this.getSubActions()); + this._container.replaceChild(newSubActions, this.actionsContainer); + newSubActions.style.display = this.actionsContainer.style.display; + this.actionsContainer = newSubActions; + }); + + this.update(); + } + + getSubActions() { + const applySubAction = { + title: wX("toolbar.quick_delete.apply.title"), + text: wX("toolbar.quick_delete.apply.text"), + callback: () => {}, + context: null, + }; + + const cancelSubAction = { + title: wX("toolbar.quick_delete.cancel.title"), + text: wX("toolbar.quick_delete.cancel.title"), + callback: () => {}, + context: null, + }; + + return [applySubAction, cancelSubAction]; + } + + enable() { + WButton.prototype.enable.call(this); + this.button.classList.add("active"); + } + + disable() { + WButton.prototype.disable.call(this); + this.button.classList.remove("active"); + } +} + +export default QuickDeleteButton; From d87b6e84c97c358297a1a2777be079580df952f0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 18:57:01 +0100 Subject: [PATCH 151/275] wbutton: don't add dummy button --- src/code/leafletClasses.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/code/leafletClasses.js b/src/code/leafletClasses.js index f63ff2e73..0d012b66d 100644 --- a/src/code/leafletClasses.js +++ b/src/code/leafletClasses.js @@ -301,6 +301,7 @@ export const WButton = L.Class.extend({ this.handler = this._toggleActions; // this.actionsContainer == the sub menu items created by the individual buttons + /* this.button = this._createButton({ container: container, // buttonImage: null, @@ -308,6 +309,7 @@ export const WButton = L.Class.extend({ context: this, // className: ..., }); + */ }, update: function () { From 9570471a3f38ff83b330d1e81c01f03d0ff72dfb Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 20:36:50 +0100 Subject: [PATCH 152/275] quickdelete: add handler --- src/code/buttons/quickdelete.ts | 34 +++++++++++++++++++++++++++++++++ src/code/init.ts | 2 +- src/code/ui/marker.d.ts | 4 ++-- src/code/ui/portal.d.ts | 2 +- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index d259f0bbe..42db5533a 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -1,17 +1,26 @@ import { WButton } from "../leafletClasses"; import wX from "../wX"; +import type { Wasabee } from "../init"; +import type { WLMarker } from "../ui/marker"; + +const W: Wasabee = window.plugin.wasabee; + class QuickDeleteButton extends WButton { static TYPE = "QuickdeleteButton"; needWritePermission: true; + handler: L.Handler; + constructor(container: HTMLElement) { super(container); this.title = wX("toolbar.quick_delete.title"); this.type = QuickDeleteButton.TYPE; + this.handler = new QuickDeleteHandler(); + this.button = this._createButton({ title: this.title, container: container, @@ -24,6 +33,8 @@ class QuickDeleteButton extends WButton { this._container.appendChild(this.actionsContainer); + window.map.on("wasabee:op:change", () => this.disable()); + // update text window.map.on("wasabee:ui:skin wasabee:ui:lang", () => { this.button.title = wX("toolbar.quick_delete.title"); @@ -65,4 +76,27 @@ class QuickDeleteButton extends WButton { } } +class QuickDeleteHandler extends L.Handler { + deletedMarker: Set; + deletedLink: Set; + + constructor() { + super(window.map); + } + + toggleMarker(layer: WLMarker) { + if (this.deletedMarker.has(layer.options.id)) + this.deletedMarker.delete(layer.options.id); + else this.deletedMarker.add(layer.options.id); + } + + addHooks() { + W.markerLayerGroup.eachLayer((layer: WLMarker) => { + layer.on("click", this.toggleMarker, this); + }); + } + + removeHooks() {} +} + export default QuickDeleteButton; diff --git a/src/code/init.ts b/src/code/init.ts index 22903598b..d0760dd06 100644 --- a/src/code/init.ts +++ b/src/code/init.ts @@ -28,7 +28,7 @@ import { displayError } from "./error"; import type { FeatureGroup, LayerEvent, LayerGroup } from "leaflet"; type Awaited = T extends PromiseLike ? U : T; -interface Wasabee { +export interface Wasabee { static: any; _inited: boolean; _selectedOp: WasabeeOp; diff --git a/src/code/ui/marker.d.ts b/src/code/ui/marker.d.ts index 51fee7a00..9d2cec2b6 100644 --- a/src/code/ui/marker.d.ts +++ b/src/code/ui/marker.d.ts @@ -1,6 +1,6 @@ -import PortalUI from "./portal"; +import type { WLPortal } from "./portal"; import type WasabeeMarker from "../model/marker"; -declare class WLMarker extends PortalUI.WLPortal { +export declare class WLMarker extends WLPortal { state: string; constructor(marker: WasabeeMarker); setState(state: string): void; diff --git a/src/code/ui/portal.d.ts b/src/code/ui/portal.d.ts index 14f5530f2..6f213d084 100644 --- a/src/code/ui/portal.d.ts +++ b/src/code/ui/portal.d.ts @@ -15,7 +15,7 @@ interface WLPortalOptions extends L.MarkerOptions { title?: string; id: string; } -declare class WLPortal extends L.Marker { +export declare class WLPortal extends L.Marker { type: string; options: WLPortalOptions; constructor(options: WLPortalOptions); From 006ee44c824930d8c2032a74ae44f046f7251c70 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 23:18:09 +0100 Subject: [PATCH 153/275] draw ui: export type declarations (-declare) --- src/code/ui/agent.d.ts | 14 +++++--------- src/code/ui/anchor.d.ts | 6 +----- src/code/ui/link.d.ts | 21 ++++++++++++--------- src/code/ui/marker.d.ts | 7 ++----- src/code/ui/portal.d.ts | 31 ++++++++++++++----------------- src/code/ui/zone.d.ts | 7 ++----- 6 files changed, 36 insertions(+), 50 deletions(-) diff --git a/src/code/ui/agent.d.ts b/src/code/ui/agent.d.ts index 40d8b0f32..42fbb6ccf 100644 --- a/src/code/ui/agent.d.ts +++ b/src/code/ui/agent.d.ts @@ -1,25 +1,21 @@ import WasabeeAgent from "../model/agent"; -declare function formatDisplay( +export function formatDisplay( agent: WasabeeAgent, teamID?: number | string ): HTMLAnchorElement; -declare function timeSinceformat(agent: WasabeeAgent): string; + +export function timeSinceformat(agent: WasabeeAgent): string; interface WLAgentOptions extends L.MarkerOptions { agent: WasabeeAgent; id: string; zoom: number; } -declare class WLAgent extends L.Marker { + +export class WLAgent extends L.Marker { options: WLAgentOptions; constructor(agent: WasabeeAgent); update(): this; _getPopup(): HTMLDivElement; } -declare const _default: { - formatDisplay: typeof formatDisplay; - timeSinceformat: typeof timeSinceformat; - WLAgent: typeof WLAgent; -}; -export default _default; diff --git a/src/code/ui/anchor.d.ts b/src/code/ui/anchor.d.ts index 246d0391e..426aba2d6 100644 --- a/src/code/ui/anchor.d.ts +++ b/src/code/ui/anchor.d.ts @@ -1,14 +1,10 @@ import type WasabeeOp from "../model/operation"; import PortalUI from "./portal"; -declare class WLAnchor extends PortalUI.WLPortal { +export class WLAnchor extends PortalUI.WLPortal { constructor(portalId: string, operation: WasabeeOp); _popupContent(): any; _linksButton(container: any): void; _swapButton(container: any): void; _deleteAction(): void; } -declare const _default: { - WLAnchor: typeof WLAnchor; -}; -export default _default; diff --git a/src/code/ui/link.d.ts b/src/code/ui/link.d.ts index b866e9184..1f674dbb4 100644 --- a/src/code/ui/link.d.ts +++ b/src/code/ui/link.d.ts @@ -1,22 +1,25 @@ import type WasabeeOp from "../model/operation"; import type WasabeeLink from "../model/link"; -declare function displayFormat( + +export function displayFormat( link: WasabeeLink, operation: WasabeeOp, smallScreen?: boolean ): HTMLDivElement; -declare function minLevel( + +export function minLevel( link: WasabeeLink, operation: WasabeeOp ): HTMLSpanElement; -declare class WLLink extends L.GeodesicPolyline { + +interface WLLinkOptions extends L.PolylineOptions { + opID: OpID; + linkID: LinkID; +} + +export class WLLink extends L.GeodesicPolyline { _wlink: WasabeeLink; + options: WLLinkOptions; constructor(link: WasabeeLink, operation: WasabeeOp); _getPopup(): HTMLDivElement; } -declare const _default: { - displayFormat: typeof displayFormat; - minLevel: typeof minLevel; - WLLink: typeof WLLink; -}; -export default _default; diff --git a/src/code/ui/marker.d.ts b/src/code/ui/marker.d.ts index 9d2cec2b6..fbc4b7edc 100644 --- a/src/code/ui/marker.d.ts +++ b/src/code/ui/marker.d.ts @@ -1,6 +1,7 @@ import type { WLPortal } from "./portal"; import type WasabeeMarker from "../model/marker"; -export declare class WLMarker extends WLPortal { + +export class WLMarker extends WLPortal { state: string; constructor(marker: WasabeeMarker); setState(state: string): void; @@ -12,7 +13,3 @@ export declare class WLMarker extends WLPortal { _setComment(ev: any): void; _setMarkerType(ev: any): void; } -declare const _default: { - WLMarker: typeof WLMarker; -}; -export default _default; diff --git a/src/code/ui/portal.d.ts b/src/code/ui/portal.d.ts index 6f213d084..a38578cf6 100644 --- a/src/code/ui/portal.d.ts +++ b/src/code/ui/portal.d.ts @@ -1,21 +1,28 @@ import WasabeePortal from "../model/portal"; import { IITC } from "../../types/iitc"; -declare function fromIITC(p: IITC.Portal): WasabeePortal; -declare function team(portal: any): string; -declare function displayName(portal: any): any; -declare function displayFormat( +export function fromIITC(p: IITC.Portal): WasabeePortal; + +export function team(portal: any): string; + +export function displayName(portal: any): any; + +export function displayFormat( portal: any, shortName?: boolean ): HTMLAnchorElement; -declare function get(id: any): WasabeePortal; -declare function getSelected(): WasabeePortal; + +export function get(id: any): WasabeePortal; + +export function getSelected(): WasabeePortal; + interface WLPortalOptions extends L.MarkerOptions { portalId: string; title?: string; id: string; } -export declare class WLPortal extends L.Marker { + +export class WLPortal extends L.Marker { type: string; options: WLPortalOptions; constructor(options: WLPortalOptions); @@ -28,13 +35,3 @@ export declare class WLPortal extends L.Marker { _sendTargetButton(container: any, text: any, target: any): void; _mapButton(container: any, text: any): void; } -declare const _default: { - fromIITC: typeof fromIITC; - displayName: typeof displayName; - displayFormat: typeof displayFormat; - get: typeof get; - getSelected: typeof getSelected; - team: typeof team; - WLPortal: typeof WLPortal; -}; -export default _default; diff --git a/src/code/ui/zone.d.ts b/src/code/ui/zone.d.ts index 124d69c35..e51e08f99 100644 --- a/src/code/ui/zone.d.ts +++ b/src/code/ui/zone.d.ts @@ -1,8 +1,5 @@ import type WasabeeZone from "../model/zone"; -declare class WLZone extends L.LayerGroup { + +export class WLZone extends L.LayerGroup { constructor(zone: WasabeeZone); } -declare const _default: { - WLZone: typeof WLZone; -}; -export default _default; From be1b7b128dcd37905ea7c0f6d19a51d12080bc47 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 23:18:47 +0100 Subject: [PATCH 154/275] quick delete: toggle link/marker --- src/code/buttons/quickdelete.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index 42db5533a..b4cde55cc 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -3,6 +3,8 @@ import wX from "../wX"; import type { Wasabee } from "../init"; import type { WLMarker } from "../ui/marker"; +import type { WLLink } from "../ui/link"; +import type { LeafletMouseEvent } from "leaflet"; const W: Wasabee = window.plugin.wasabee; @@ -84,19 +86,37 @@ class QuickDeleteHandler extends L.Handler { super(window.map); } - toggleMarker(layer: WLMarker) { + toggleMarker(event: LeafletMouseEvent) { + const layer = event.target as WLMarker; if (this.deletedMarker.has(layer.options.id)) this.deletedMarker.delete(layer.options.id); else this.deletedMarker.add(layer.options.id); } + toggleLink(event: LeafletMouseEvent) { + const layer = event.target as WLLink; + if (this.deletedLink.has(layer.options.linkID)) + this.deletedLink.delete(layer.options.linkID); + else this.deletedLink.add(layer.options.linkID); + } + addHooks() { W.markerLayerGroup.eachLayer((layer: WLMarker) => { layer.on("click", this.toggleMarker, this); }); + W.linkLayerGroup.eachLayer((layer: WLLink) => { + layer.on("click", this.toggleLink, this); + }); } - removeHooks() {} + removeHooks() { + W.markerLayerGroup.eachLayer((layer: WLMarker) => { + layer.off("click", this.toggleMarker, this); + }); + W.linkLayerGroup.eachLayer((layer: WLLink) => { + layer.off("click", this.toggleLink, this); + }); + } } export default QuickDeleteButton; From b21305e1bc51a632616885f625530b02e13f0ef2 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 23:40:18 +0100 Subject: [PATCH 155/275] quick delete: add actions --- src/code/buttons/quickdelete.ts | 60 ++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index b4cde55cc..3ea0e31c6 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -5,6 +5,7 @@ import type { Wasabee } from "../init"; import type { WLMarker } from "../ui/marker"; import type { WLLink } from "../ui/link"; import type { LeafletMouseEvent } from "leaflet"; +import { getSelectedOperation } from "../selectedOp"; const W: Wasabee = window.plugin.wasabee; @@ -13,7 +14,7 @@ class QuickDeleteButton extends WButton { needWritePermission: true; - handler: L.Handler; + handler: QuickDeleteHandler; constructor(container: HTMLElement) { super(container); @@ -49,19 +50,38 @@ class QuickDeleteButton extends WButton { this.update(); } + actionApply() { + const operation = getSelectedOperation(); + operation.markers = operation.markers.filter( + (m) => !this.handler.deletedMarker.has(m.ID) + ); + operation.links = operation.links.filter( + (l) => !this.handler.deletedLink.has(l.ID) + ); + operation.cleanAnchorList(); + operation.cleanPortalList(); + operation.update(true); + operation.updateBlockers(); + this.disable(); + } + + actionCancel() { + this.disable(); + } + getSubActions() { const applySubAction = { title: wX("toolbar.quick_delete.apply.title"), text: wX("toolbar.quick_delete.apply.text"), - callback: () => {}, - context: null, + callback: this.actionApply, + context: this, }; const cancelSubAction = { title: wX("toolbar.quick_delete.cancel.title"), text: wX("toolbar.quick_delete.cancel.title"), - callback: () => {}, - context: null, + callback: this.actionCancel, + context: this, }; return [applySubAction, cancelSubAction]; @@ -70,11 +90,13 @@ class QuickDeleteButton extends WButton { enable() { WButton.prototype.enable.call(this); this.button.classList.add("active"); + this.handler.enable(); } disable() { WButton.prototype.disable.call(this); this.button.classList.remove("active"); + this.handler.disable(); } } @@ -84,20 +106,36 @@ class QuickDeleteHandler extends L.Handler { constructor() { super(window.map); + this.deletedMarker = new Set(); + this.deletedLink = new Set(); } toggleMarker(event: LeafletMouseEvent) { const layer = event.target as WLMarker; - if (this.deletedMarker.has(layer.options.id)) + layer.closePopup(); + if (this.deletedMarker.has(layer.options.id)) { this.deletedMarker.delete(layer.options.id); - else this.deletedMarker.add(layer.options.id); + layer.setOpacity(1); + } else { + this.deletedMarker.add(layer.options.id); + layer.setOpacity(0.5); + } } toggleLink(event: LeafletMouseEvent) { const layer = event.target as WLLink; - if (this.deletedLink.has(layer.options.linkID)) + layer.closePopup(); + if (this.deletedLink.has(layer.options.linkID)) { this.deletedLink.delete(layer.options.linkID); - else this.deletedLink.add(layer.options.linkID); + layer.setStyle({ + opacity: 1, + }); + } else { + this.deletedLink.add(layer.options.linkID); + layer.setStyle({ + opacity: 0.5, + }); + } } addHooks() { @@ -112,9 +150,13 @@ class QuickDeleteHandler extends L.Handler { removeHooks() { W.markerLayerGroup.eachLayer((layer: WLMarker) => { layer.off("click", this.toggleMarker, this); + layer.setOpacity(1); }); W.linkLayerGroup.eachLayer((layer: WLLink) => { layer.off("click", this.toggleLink, this); + layer.setStyle({ + opacity: 1, + }); }); } } From e7b9187c8434bb2e79282e56fac111b5dcdeb24c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 9 Dec 2021 23:44:34 +0100 Subject: [PATCH 156/275] quick delete: add basic strings --- src/code/addButtons.ts | 2 +- src/code/translations/english.json | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/code/addButtons.ts b/src/code/addButtons.ts index 7ce3427df..16635974d 100644 --- a/src/code/addButtons.ts +++ b/src/code/addButtons.ts @@ -24,11 +24,11 @@ export function addButtons() { WasabeeButton, OpButton, QuickdrawButton, + QuickDeleteButton, LinkButton, MarkerButton, SyncButton, UploadButton, - QuickDeleteButton, ]) { const item = L.DomUtil.create("li", null, options.container); const button = new Constructor(item); diff --git a/src/code/translations/english.json b/src/code/translations/english.json index f74ed6796..9b02913d1 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -336,6 +336,11 @@ "TEAMS BUTTON TITLE": "List Wasabee Teams", "TEAMS BUTTON": "Teams", "TO_PORT": "To Portal", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", From d73b8082213efaf82510d05ae934c54973cfeab2 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 10 Dec 2021 00:05:37 +0100 Subject: [PATCH 157/275] quick delete: add ugly icon --- src/code/css/toolbar.css | 4 ++++ src/code/images/toolbar_quickdelete.svg | 7 +++++++ 2 files changed, 11 insertions(+) create mode 100644 src/code/images/toolbar_quickdelete.svg diff --git a/src/code/css/toolbar.css b/src/code/css/toolbar.css index fbb5fae18..46681304b 100644 --- a/src/code/css/toolbar.css +++ b/src/code/css/toolbar.css @@ -119,6 +119,10 @@ background-image: url(../images/toolbar_quickdraw.svg); background-size: 60%; } +.wasabee-toolbar-quickdelete { + background-image: url(../images/toolbar_quickdelete.svg); + background-size: 60%; +} .wasabee-toolbar-link { background-image: url(../images/toolbar_addlinks.svg) } diff --git a/src/code/images/toolbar_quickdelete.svg b/src/code/images/toolbar_quickdelete.svg new file mode 100644 index 000000000..15035f468 --- /dev/null +++ b/src/code/images/toolbar_quickdelete.svg @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file From 98c492b0c9f384161f2965411674023194faaa5b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 10 Dec 2021 00:20:53 +0100 Subject: [PATCH 158/275] quick delete: handle anchors --- src/code/buttons/quickdelete.ts | 56 +++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index 3ea0e31c6..c70ca0e05 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -6,6 +6,7 @@ import type { WLMarker } from "../ui/marker"; import type { WLLink } from "../ui/link"; import type { LeafletMouseEvent } from "leaflet"; import { getSelectedOperation } from "../selectedOp"; +import type { WLAnchor } from "../ui/anchor"; const W: Wasabee = window.plugin.wasabee; @@ -110,9 +111,14 @@ class QuickDeleteHandler extends L.Handler { this.deletedLink = new Set(); } - toggleMarker(event: LeafletMouseEvent) { + clickMarker(event: LeafletMouseEvent) { + if (!this.enabled()) return; const layer = event.target as WLMarker; layer.closePopup(); + this.toggleMarker(layer); + } + + toggleMarker(layer: WLMarker) { if (this.deletedMarker.has(layer.options.id)) { this.deletedMarker.delete(layer.options.id); layer.setOpacity(1); @@ -122,9 +128,14 @@ class QuickDeleteHandler extends L.Handler { } } - toggleLink(event: LeafletMouseEvent) { + clickLink(event: LeafletMouseEvent) { + if (!this.enabled()) return; const layer = event.target as WLLink; layer.closePopup(); + this.toggleLink(layer); + } + + toggleLink(layer: WLLink) { if (this.deletedLink.has(layer.options.linkID)) { this.deletedLink.delete(layer.options.linkID); layer.setStyle({ @@ -138,26 +149,59 @@ class QuickDeleteHandler extends L.Handler { } } + clickAnchor(event: LeafletMouseEvent) { + if (!this.enabled()) return; + const layer = event.target as WLAnchor; + layer.closePopup(); + this.toggleAnchor(layer); + } + + toggleAnchor(layer: WLAnchor) { + const operation = getSelectedOperation(); + const portal = operation.getPortal(layer.options.portalId); + const links = operation.getLinkListFromPortal(portal); + // toggle all links if all deleted + if (links.every((l) => this.deletedLink.has(l.ID))) { + W.linkLayerGroup.eachLayer((layer: WLLink) => { + if (links.find((l) => l.ID == layer.options.linkID)) + this.toggleLink(layer); + }); + } else { + // delete all links + W.linkLayerGroup.eachLayer((layer: WLLink) => { + if (!this.deletedLink.has(layer.options.linkID)) + if (links.find((l) => l.ID == layer.options.linkID)) + this.toggleLink(layer); + }); + } + } + addHooks() { W.markerLayerGroup.eachLayer((layer: WLMarker) => { - layer.on("click", this.toggleMarker, this); + layer.on("click", this.clickMarker, this); }); W.linkLayerGroup.eachLayer((layer: WLLink) => { - layer.on("click", this.toggleLink, this); + layer.on("click", this.clickLink, this); + }); + W.portalLayerGroup.eachLayer((layer: WLAnchor) => { + layer.on("click", this.clickAnchor, this); }); } removeHooks() { W.markerLayerGroup.eachLayer((layer: WLMarker) => { - layer.off("click", this.toggleMarker, this); + layer.off("click", this.clickMarker, this); layer.setOpacity(1); }); W.linkLayerGroup.eachLayer((layer: WLLink) => { - layer.off("click", this.toggleLink, this); + layer.off("click", this.clickLink, this); layer.setStyle({ opacity: 1, }); }); + W.portalLayerGroup.eachLayer((layer: WLAnchor) => { + layer.off("click", this.clickAnchor, this); + }); } } From b4c20366225a79f949460b1e15a4e13f5d94f02b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 10 Dec 2021 00:43:10 +0100 Subject: [PATCH 159/275] quick delete: active is red --- src/code/css/toolbar.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/code/css/toolbar.css b/src/code/css/toolbar.css index 46681304b..2ae1fa43d 100644 --- a/src/code/css/toolbar.css +++ b/src/code/css/toolbar.css @@ -72,6 +72,10 @@ background-color: #3c9; } +.wasabee-buttons.leaflet-control a.wasabee-toolbar-quickdelete.active { + background-color: #e66; +} + /* align verticaly button subactions */ .wasabee-actions li { display: block; From 4b7032390f04d3b4f9d48dfd1460a1b133f75b0b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 11 Dec 2021 23:08:54 +0100 Subject: [PATCH 160/275] quick delete: use siperfied click --- src/code/buttons/quickdelete.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index c70ca0e05..dbbc8673f 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -139,12 +139,12 @@ class QuickDeleteHandler extends L.Handler { if (this.deletedLink.has(layer.options.linkID)) { this.deletedLink.delete(layer.options.linkID); layer.setStyle({ - opacity: 1, + opacity: window.plugin.wasabee.skin.linkStyle.opacity || 1, }); } else { this.deletedLink.add(layer.options.linkID); layer.setStyle({ - opacity: 0.5, + opacity: 0.5 * (window.plugin.wasabee.skin.linkStyle.opacity || 1), }); } } @@ -177,31 +177,31 @@ class QuickDeleteHandler extends L.Handler { } addHooks() { + W.portalLayerGroup.eachLayer((layer: WLAnchor) => { + layer.on("spiderfiedclick", this.clickAnchor, this); + }); W.markerLayerGroup.eachLayer((layer: WLMarker) => { - layer.on("click", this.clickMarker, this); + layer.on("spiderfiedclick", this.clickMarker, this); }); W.linkLayerGroup.eachLayer((layer: WLLink) => { layer.on("click", this.clickLink, this); }); - W.portalLayerGroup.eachLayer((layer: WLAnchor) => { - layer.on("click", this.clickAnchor, this); - }); } removeHooks() { + W.portalLayerGroup.eachLayer((layer: WLAnchor) => { + layer.off("spiderfiedclick", this.clickAnchor, this); + }); W.markerLayerGroup.eachLayer((layer: WLMarker) => { - layer.off("click", this.clickMarker, this); + layer.off("spiderfiedclick", this.clickMarker, this); layer.setOpacity(1); }); W.linkLayerGroup.eachLayer((layer: WLLink) => { layer.off("click", this.clickLink, this); layer.setStyle({ - opacity: 1, + opacity: window.plugin.wasabee.skin.linkStyle.opacity || 1, }); }); - W.portalLayerGroup.eachLayer((layer: WLAnchor) => { - layer.off("click", this.clickAnchor, this); - }); } } From 44e467c6e220aac2c8f9c143a4a021570768dd64 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 12 Dec 2021 13:27:37 +0100 Subject: [PATCH 161/275] type: wasabee layers --- src/code/init.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/code/init.ts b/src/code/init.ts index d0760dd06..4effe145b 100644 --- a/src/code/init.ts +++ b/src/code/init.ts @@ -25,7 +25,13 @@ import WasabeeOp from "./model/operation"; import db from "./db"; import polyfill from "./polyfill"; import { displayError } from "./error"; + import type { FeatureGroup, LayerEvent, LayerGroup } from "leaflet"; +import type { WLAnchor } from "./ui/anchor"; +import type { WLLink } from "./ui/link"; +import type { WLMarker } from "./ui/marker"; +import type { WLAgent } from "./ui/agent"; +import type { WLZone } from "./ui/zone"; type Awaited = T extends PromiseLike ? U : T; export interface Wasabee { @@ -35,11 +41,11 @@ export interface Wasabee { _updateList: Map; idb: Awaited; portalDetailQueue: PortalID[]; - portalLayerGroup: LayerGroup; - linkLayerGroup: LayerGroup; - markerLayerGroup: LayerGroup; - agentLayerGroup: LayerGroup; - zoneLayerGroup: FeatureGroup; + portalLayerGroup: LayerGroup; + linkLayerGroup: LayerGroup; + markerLayerGroup: LayerGroup; + agentLayerGroup: LayerGroup; + zoneLayerGroup: FeatureGroup; backgroundOpsGroup: LayerGroup; } From 9ae285b7ce7836a58d9d85bd5d3b20b10cdec677 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 20 Dec 2021 19:46:55 +0100 Subject: [PATCH 162/275] quickdelete: instant delete --- src/code/buttons/quickdelete.ts | 67 ++++++++++++++++++++++++++++++--- src/code/css/toolbar.css | 9 +++++ src/code/model/operation.ts | 17 ++++++++- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index dbbc8673f..248295fee 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -16,6 +16,7 @@ class QuickDeleteButton extends WButton { needWritePermission: true; handler: QuickDeleteHandler; + state: "off" | "on" | "instant"; constructor(container: HTMLElement) { super(container); @@ -23,21 +24,22 @@ class QuickDeleteButton extends WButton { this.title = wX("toolbar.quick_delete.title"); this.type = QuickDeleteButton.TYPE; - this.handler = new QuickDeleteHandler(); + this.handler = new QuickDeleteHandler(this); this.button = this._createButton({ title: this.title, container: container, className: "wasabee-toolbar-quickdelete", context: this, - callback: this._toggleActions, + callback: this.toggleActions, }); + this.state = "off"; this.actionsContainer = this._createSubActions(this.getSubActions()); this._container.appendChild(this.actionsContainer); - window.map.on("wasabee:op:change", () => this.disable()); + window.map.on("wasabee:op:change", this.opChange, this); // update text window.map.on("wasabee:ui:skin wasabee:ui:lang", () => { @@ -51,6 +53,28 @@ class QuickDeleteButton extends WButton { this.update(); } + opChange() { + if (this.state == 'on') this.disable(); + else if (this.state == 'instant') { + this.handler.disable(); + this.handler.enable(); + } + } + + toggleActions() { + if (this.state == "off") { + this.enable(); + this.state = "on"; + } else if (this.state == "on") { + this.disable(); + this.enable(); + this.state = "instant"; + this.button.classList.add("blink"); + } else { + this.disable(); + } + } + actionApply() { const operation = getSelectedOperation(); operation.markers = operation.markers.filter( @@ -89,15 +113,19 @@ class QuickDeleteButton extends WButton { } enable() { - WButton.prototype.enable.call(this); + super.enable(); this.button.classList.add("active"); this.handler.enable(); + return this; } disable() { - WButton.prototype.disable.call(this); + super.disable(); this.button.classList.remove("active"); + this.button.classList.remove("blink"); this.handler.disable(); + this.state = "off"; + return this; } } @@ -105,10 +133,13 @@ class QuickDeleteHandler extends L.Handler { deletedMarker: Set; deletedLink: Set; - constructor() { + control: QuickDeleteButton; + + constructor(control: QuickDeleteButton) { super(window.map); this.deletedMarker = new Set(); this.deletedLink = new Set(); + this.control = control; } clickMarker(event: LeafletMouseEvent) { @@ -119,6 +150,11 @@ class QuickDeleteHandler extends L.Handler { } toggleMarker(layer: WLMarker) { + if (this.control.state == "instant") { + const operation = getSelectedOperation(); + return operation.removeMarkerByID(layer.options.id); + } + if (this.deletedMarker.has(layer.options.id)) { this.deletedMarker.delete(layer.options.id); layer.setOpacity(1); @@ -136,6 +172,11 @@ class QuickDeleteHandler extends L.Handler { } toggleLink(layer: WLLink) { + if (this.control.state == "instant") { + const operation = getSelectedOperation(); + return operation.removeLinkByID(layer.options.linkID); + } + if (this.deletedLink.has(layer.options.linkID)) { this.deletedLink.delete(layer.options.linkID); layer.setStyle({ @@ -158,6 +199,9 @@ class QuickDeleteHandler extends L.Handler { toggleAnchor(layer: WLAnchor) { const operation = getSelectedOperation(); + if (this.control.state == "instant") + return operation.removeAnchor(layer.options.portalId); + const portal = operation.getPortal(layer.options.portalId); const links = operation.getLinkListFromPortal(portal); // toggle all links if all deleted @@ -176,6 +220,15 @@ class QuickDeleteHandler extends L.Handler { } } + keyUpListener(e) { + if (!this.enabled()) return; + + // [esc] + if (e.originalEvent.keyCode === 27) { + this.control.disable(); + } + } + addHooks() { W.portalLayerGroup.eachLayer((layer: WLAnchor) => { layer.on("spiderfiedclick", this.clickAnchor, this); @@ -186,6 +239,7 @@ class QuickDeleteHandler extends L.Handler { W.linkLayerGroup.eachLayer((layer: WLLink) => { layer.on("click", this.clickLink, this); }); + window.map.on("keyup", this.keyUpListener, this); } removeHooks() { @@ -202,6 +256,7 @@ class QuickDeleteHandler extends L.Handler { opacity: window.plugin.wasabee.skin.linkStyle.opacity || 1, }); }); + window.map.off("keyup", this.keyUpListener, this); } } diff --git a/src/code/css/toolbar.css b/src/code/css/toolbar.css index 2ae1fa43d..095514c74 100644 --- a/src/code/css/toolbar.css +++ b/src/code/css/toolbar.css @@ -76,6 +76,15 @@ background-color: #e66; } +.wasabee-buttons.leaflet-control a.wasabee-toolbar-quickdelete.active.blink { + animation: blink 2s infinite; +} +@keyframes blink { + 50% { + background-color: red; + } +} + /* align verticaly button subactions */ .wasabee-actions li { display: block; diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 82cbe7aa6..3a06c5c78 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -442,15 +442,19 @@ export default class WasabeeOp extends Evented implements IOperation { this.updateBlockers(); } - removeMarker(marker: WasabeeMarker) { + removeMarkerByID(markerID: MarkerID) { this.markers = this.markers.filter(function (listMarker) { - return listMarker.ID !== marker.ID; + return listMarker.ID !== markerID; }); this.cleanPortalList(); this.update(true); this.updateBlockers(); } + removeMarker(marker: WasabeeMarker) { + this.removeMarkerByID(marker.ID); + } + setMarkerComment(marker: WasabeeMarker, comment: string) { for (const v of this.markers) { if (v.ID == marker.ID) { @@ -531,6 +535,15 @@ export default class WasabeeOp extends Evented implements IOperation { } } + + removeLinkByID(linkID: LinkID) { + this.links = this.links.filter((l) => l.ID != linkID); + this.cleanAnchorList(); + this.cleanPortalList(); + this.update(true); + this.updateBlockers(); + } + //Passed in are the start, end, and portal the link is being removed from(so the other portal can be removed if no more links exist to it) removeLink(startPortal: PortalID, endPortal: PortalID) { const newLinks = []; From d0efde0ec484e82914fe91acd54755707bf03d82 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 20 Dec 2021 23:18:33 +0100 Subject: [PATCH 163/275] quickdelete: analytics --- src/code/buttons/quickdelete.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index 248295fee..c0561a906 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -7,6 +7,7 @@ import type { WLLink } from "../ui/link"; import type { LeafletMouseEvent } from "leaflet"; import { getSelectedOperation } from "../selectedOp"; import type { WLAnchor } from "../ui/anchor"; +import { postToFirebase } from "../firebaseSupport"; const W: Wasabee = window.plugin.wasabee; @@ -65,10 +66,12 @@ class QuickDeleteButton extends WButton { if (this.state == "off") { this.enable(); this.state = "on"; + postToFirebase({ id: 'analytics', action: 'quickdelete' }); } else if (this.state == "on") { this.disable(); this.enable(); this.state = "instant"; + postToFirebase({ id: 'analytics', action: 'quickdelete:instant' }); this.button.classList.add("blink"); } else { this.disable(); From 1b7dc653cc48131c43e6c7209bba943da60a3a57 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 26 Dec 2021 16:08:21 +0100 Subject: [PATCH 164/275] autodrw: use noshift --- src/code/dialogs/autodraws/drawRoutines.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/code/dialogs/autodraws/drawRoutines.ts b/src/code/dialogs/autodraws/drawRoutines.ts index 2d641c6b3..1ec2539a9 100644 --- a/src/code/dialogs/autodraws/drawRoutines.ts +++ b/src/code/dialogs/autodraws/drawRoutines.ts @@ -2,6 +2,7 @@ import type WasabeeLink from "../../model/link"; import type WasabeeOp from "../../model/operation"; import type WasabeePortal from "../../model/portal"; +// get the list of links from a spine to anchors function getSpineLinks( anchor1: WasabeePortal, anchor2: WasabeePortal, @@ -25,14 +26,16 @@ function getSpineLinks( return linksDesc; } +// insert an array of wasabee link into an draw after the given order export function insertLinks( op: WasabeeOp, links: WasabeeLink[], - order: number + order: number, + noShift = false ) { for (const l of links) l.order = 0; // shift current op tasks order - if (order < op.nextOrder - 1) { + if (!noShift && order < op.nextOrder - 1) { for (const l of op.links) if (l.order > order) l.order += links.length; for (const m of op.markers) if (m.order > order) m.order += links.length; } @@ -40,6 +43,7 @@ export function insertLinks( return order; } +// draw a spine into an op, with order and comment export function drawSpine( op: WasabeeOp, anchor1: WasabeePortal, @@ -63,5 +67,5 @@ export function drawSpine( ) .filter((l) => l); - return insertLinks(op, wlinks, order); + return insertLinks(op, wlinks, order, options.noShift); } From 45faecc15fea6bc00f252f4c3213fa37caa681c2 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 26 Dec 2021 18:09:04 +0100 Subject: [PATCH 165/275] fanfield: extract algorithm --- src/code/dialogs/autodraws/fanfield.js | 140 ++++++++++++++----------- 1 file changed, 79 insertions(+), 61 deletions(-) diff --git a/src/code/dialogs/autodraws/fanfield.js b/src/code/dialogs/autodraws/fanfield.js index 9cd69c51c..42b650d2d 100644 --- a/src/code/dialogs/autodraws/fanfield.js +++ b/src/code/dialogs/autodraws/fanfield.js @@ -1,21 +1,83 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; -import { testSelfBlock } from "../../crosslinks"; -import WasabeeLink from "../../model/link"; +import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; import { clearAllLinks } from "../../uiCommands"; import wX from "../../wX"; import { displayError, displayInfo } from "../../error"; import { sortPortalsByAngle, selectAngleInterval } from "./algorithm"; +import { insertLinks } from "./drawRoutines"; -export function sortPortals(anchor, portals, start, end) { +function sortPortals(anchor, portals, start, end) { if (!portals.find((p) => p.id === start.id)) portals.push(start); if (!portals.find((p) => p.id === end.id)) portals.push(end); const sorted = sortPortalsByAngle(anchor, portals); return selectAngleInterval(anchor, sorted, start, end); } +/** + * Return the link descriptions for fanfield + * @param {WasabeePortal} anchor + * @param {WasabeePortal[]} portals + * @param {WasabeePortal} start + * @param {WasabeePortal} end + * @returns {[{ from: WasabeePortal, to: WasabeePortal, comment: string}[], number]} + */ +function fanfield(anchor, portals, start, end) { + let fields = 0; + const links = []; + + const sorted = sortPortals(anchor, portals, start, end); + + const available = Array.from(sorted); + available.reverse(); + + for (let i = available.length - 1; i >= 0; i--) { + const wp = available[i]; + links.push({ from: wp, to: anchor, comment: "anchor" }); + + if (i + 1 == available.length) continue; + + // Find the interval of portals that are linkable + let j = i + 1; + let prev = null; + for (; j < available.length; j++) { + const p = available[j]; + if ( + prev && + greatCircleArcIntersectByLatLngs( + anchor.latLng, + prev.latLng, + wp.latLng, + p.latLng + ) + ) + break; + prev = p; + } + j--; + links.push({ + from: wp, + to: available[j], + comment: "subfield", + }); + fields++; + + for (var k = j - 1; k > i; k--) { + links.push({ + from: wp, + to: available[k], + comment: "double subfield", + }); + fields += 2; + } + // remove covered portals + available.splice(i + 1, j - i - 1); + } + return [links, fields]; +} + const FanfieldDialog = AutoDraw.extend({ statics: { TYPE: "FanfieldDialog", @@ -99,75 +161,31 @@ const FanfieldDialog = AutoDraw.extend({ return; } - const steps = sortPortals( + const [links, fields] = fanfield( this._anchor, this._portalSets["set"].portals, this._start, this._end ); - this._draw(steps); - }, - // draw takes the sorted list of poratls and draws the links - // determining any sub-fields can be added - _draw: function (sorted) { const op = getSelectedOperation(); + op.startBatchMode(); - let order = 0; - let fields = 0; - - const available = Array.from(sorted); - available.reverse(); - - for (let i = available.length - 1; i >= 0; i--) { - const wp = available[i]; - order++; - op.addLink(wp, this._anchor, { description: "fan anchor", order: order }); - - // skip back links if first portal - if (i + 1 == available.length) continue; - - // Find the interval of portals that are linkable - let j = i + 1; - for (; j < available.length; j++) { - const testlink = new WasabeeLink( - { fromPortalId: wp.id, toPortalId: available[j].id }, - op - ); - let crossed = false; - for (const real of op.links) { - // Check links to anchor only - if (real.toPortalId != this._anchor.id) continue; - if (testSelfBlock(testlink, op)) { - crossed = true; - break; - } - } - if (crossed) break; - } - j--; - op.addLink(wp, available[j], { - description: "fan subfield", - order: ++order, - }); - fields++; - - for (var k = j - 1; k > i; k--) { - const check = available[k]; - op.addLink(wp, check, { - description: "fan double subfield", - order: ++order, - }); - fields += 2; - } - // remove covered portals - available.splice(i + 1, j - i - 1); - } + const wlinks = links + .map((l) => + op.addLink(l.from, l.to, { + description: "fanfield " + l.comment, + }) + ) + .filter((l) => l); + + insertLinks(op, wlinks, 0); op.endBatchMode(); - const ap = 313 * order + 1250 * fields; + + const ap = 313 * links.length + 1250 * fields; // too many parameters for wX(); displayInfo( - `Fanfield found ${order} links and ${fields} fields for ${ap} AP` + `Fanfield found ${links.length} links and ${fields} fields for ${ap} AP` ); }, }); From 2ddfaea07eb3507a4118ca9693a04b5932262b8c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 26 Dec 2021 18:09:23 +0100 Subject: [PATCH 166/275] fix copypaste strings --- src/code/dialogs/autodraws/flipflop.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code/dialogs/autodraws/flipflop.js b/src/code/dialogs/autodraws/flipflop.js index 788654f7d..ab1503e1e 100644 --- a/src/code/dialogs/autodraws/flipflop.js +++ b/src/code/dialogs/autodraws/flipflop.js @@ -48,7 +48,7 @@ function fastFan(anchor, two, three, portalsSorted, offset, revSortAngle) { // to not require passing values around when we can get them from this.XXX const FlipFlopDialog = AutoDraw.extend({ statics: { - TYPE: "madridDialog", + TYPE: "flipflopDialog", }, initialize: function (options) { @@ -89,7 +89,7 @@ const FlipFlopDialog = AutoDraw.extend({ // Go button const button = L.DomUtil.create("button", "drawb", container); - button.textContent = wX("FANFIELD"); + button.textContent = wX("DRAW"); L.DomEvent.on(button, "click", () => { const total = this.doFanGun(); displayInfo(`Flip flop: found ${total} links`); From 511d630939349fc0a063950152970bb1c191b38d Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 26 Dec 2021 18:35:35 +0100 Subject: [PATCH 167/275] madrid: extract getSpines --- src/code/dialogs/autodraws/madrid.js | 78 ++++++++++++++++------------ 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index ec46689ec..605a8b7fd 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -8,8 +8,48 @@ import { drawSpine, insertLinks } from "./drawRoutines"; import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; -// now that the formerly external mm functions are in the class, some of the logic can be cleaned up -// to not require passing values around when we can get them from this.XXX +/** + * Return the spines in set 1, 2 and 3: + * - 1: starting from anchorOne, with anchorTwo and last portal of spine 3 as anchors + * - 2: starting from anchortwo, with last portals of spines 1/3 as anchors + * - 3: in set 3, with anchorOne and anchorTwo as anchors + * Spines are thrown in order 3-1-2 + * @param {WasabeePortal} anchorOne + * @param {WasabeePortal} anchorTwo + * @param {WasabeePortal[]} setOne + * @param {WasabeePortal[]} setTwo + * @param {WasabeePortal[]} setThree + * @returns {[WasabeePortal[], WasabeePortal[], WasabeePortal[]]} + */ +function getSpines(anchorOne, anchorTwo, setOne, setTwo, setThree) { + const [spineThree] = getSignedSpine(anchorOne, anchorTwo, setThree, false); + const lastThree = spineThree[spineThree.length - 1]; + + const [spineOne] = getSignedSpine( + anchorTwo, + lastThree, + setOne.filter( + (p) => + anchorOne.id == p.id || + portalInField(anchorTwo, lastThree, p, anchorOne) + ), + false + ); + const lastOne = spineOne[spineOne.length - 1]; + + const [spineTwo] = getSignedSpine( + lastThree, + lastOne, + setTwo.filter( + (p) => + anchorTwo.id == p.id || portalInField(lastThree, lastOne, p, anchorTwo) + ), + false + ); + + return [spineOne, spineTwo, spineThree]; +} + const MadridDialog = AutoDraw.extend({ statics: { TYPE: "madridDialog", @@ -115,36 +155,6 @@ const MadridDialog = AutoDraw.extend({ }); }, - getSpines: function (anchorOne, anchorTwo, setOne, setTwo, setThree) { - const [spineThree] = getSignedSpine(anchorOne, anchorTwo, setThree, false); - const lastThree = spineThree[spineThree.length - 1]; - - const [spineOne] = getSignedSpine( - anchorTwo, - lastThree, - setOne.filter( - (p) => - anchorOne.id == p.id || - portalInField(anchorTwo, lastThree, p, anchorOne) - ), - false - ); - const lastOne = spineOne[spineOne.length - 1]; - - const [spineTwo] = getSignedSpine( - lastThree, - lastOne, - setTwo.filter( - (p) => - anchorTwo.id == p.id || - portalInField(lastThree, lastOne, p, anchorTwo) - ), - false - ); - - return [spineOne, spineTwo, spineThree]; - }, - doBalancedMadrid: function () { // Calculate the multimax if ( @@ -171,7 +181,7 @@ const MadridDialog = AutoDraw.extend({ ) this._portalSets.setTwo.portals.push(this._anchorTwo); - const spines = this.getSpines( + const spines = getSpines( this._anchorOne, this._anchorTwo, this._portalSets.setOne.portals, @@ -260,7 +270,7 @@ const MadridDialog = AutoDraw.extend({ ) this._portalSets.setTwo.portals.push(this._anchorTwo); - const spines = this.getSpines( + const spines = getSpines( this._anchorOne, this._anchorTwo, this._portalSets.setOne.portals, From 5318c97984967cd78c966a565ec8b2326e83ca32 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 26 Dec 2021 18:54:32 +0100 Subject: [PATCH 168/275] HF: let crazy agent do crazy things --- src/code/dialogs/autodraws/homogeneous.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index ed175e202..91a5fdae4 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -338,14 +338,10 @@ const HomogeneousDialog = AutoDraw.extend({ const depthLabel = L.DomUtil.create("label", null, container); depthLabel.textContent = wX("MAX_SPLITS"); - this.depthMenu = L.DomUtil.create("select", null, container); - let dc = 2; - while (dc <= 6) { - const depthOption = L.DomUtil.create("option", null, this.depthMenu); - depthOption.value = dc; - depthOption.textContent = dc; - dc++; - } // no need for an event, we will read the value directly below + this.depthMenu = L.DomUtil.create("input", null, container); + this.depthMenu.type = "number"; + this.depthMenu.min = 2; + this.depthMenu.value = 4; const orderLabel = L.DomUtil.create("label", null, container); orderLabel.textContent = "Order"; @@ -385,8 +381,9 @@ const HomogeneousDialog = AutoDraw.extend({ L.DomEvent.on(drawButton, "click", (ev) => { L.DomEvent.stop(ev); this._operation = getSelectedOperation(); - if (this._fullSearch) this.hdeepfield.call(this); - else this.hfield.call(this); + if (+this.depthMenu.value < 2) return; + if (this._fullSearch) this.hdeepfield(); + else this.hfield(); }); const buttons = {}; @@ -428,7 +425,7 @@ const HomogeneousDialog = AutoDraw.extend({ this._anchorOne, this._anchorTwo, this._anchorThree, - this.depthMenu.value + +this.depthMenu.value ); console.timeEnd("HF greedy"); From 457cc7fb044a06b29c6ec154427bfda6e3acdcad Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 26 Dec 2021 18:59:07 +0100 Subject: [PATCH 169/275] HF: enable full search by default --- src/code/dialogs/autodraws/homogeneous.js | 2 +- src/code/dialogs/autodraws/tools.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index 91a5fdae4..50ab5677d 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -362,7 +362,7 @@ const HomogeneousDialog = AutoDraw.extend({ "wasabee-homogeneous-deep", "_fullSearch", container, - false + true ); const spanRedraw = L.DomUtil.create("div", null, container); diff --git a/src/code/dialogs/autodraws/tools.js b/src/code/dialogs/autodraws/tools.js index d751e2c57..67d2650bf 100644 --- a/src/code/dialogs/autodraws/tools.js +++ b/src/code/dialogs/autodraws/tools.js @@ -130,6 +130,7 @@ export const AutoDraw = WDialog.extend({ checkbox.type = "checkbox"; checkbox.id = id; checkbox.checked = defaultValue; + this[thisKey] = defaultValue; L.DomEvent.on(checkbox, "change", () => { this[thisKey] = checkbox.checked; }); From e45fff31e826a998bf11526d94a17df572e8ff12 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 26 Dec 2021 19:43:27 +0100 Subject: [PATCH 170/275] HF: add portal zone --- src/code/dialogs/autodraws/homogeneous.js | 53 ++++++++++++++++++----- src/code/dialogs/autodraws/tools.d.ts | 3 +- src/code/dialogs/autodraws/tools.js | 3 +- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index 50ab5677d..f851c5b52 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -92,6 +92,10 @@ function sortByDistance(portals, point) { return portals.sort((a, b) => cPs.get(a.id) - cPs.get(b.id)); } +function numInnerPortalsPerDepth(depth) { + return (3 ** (depth - 1) - 1) / 2; +} + /** * Find one of the best (in terms of splits) HF configuration as a Tree decomposition * @param {WasabeePortal[]} portalsCovered @@ -103,11 +107,10 @@ function sortByDistance(portals, point) { */ function fullRecurser(portalsCovered, one, two, three, depth) { const alreadyCalculatedCover = new Map(); - const getNbSplitPerDepth = (depth) => (3 ** (depth - 1) - 1) / 2; console.log( "Expect at least", - Math.max(0, getNbSplitPerDepth(depth) - portalsCovered.length), + Math.max(0, numInnerPortalsPerDepth(depth) - portalsCovered.length), "missing splits" ); @@ -127,7 +130,7 @@ function fullRecurser(portalsCovered, one, two, three, depth) { const key = [depth, one.id, two.id, three.id].sort().toString(); if (alreadyCalculatedCover.get(key) === undefined) { const maxNbSplit = Math.min( - getNbSplitPerDepth(depth), + numInnerPortalsPerDepth(depth), portalsCovered.length ); /** @type {import("./homogeneous").Tree} */ @@ -148,9 +151,9 @@ function fullRecurser(portalsCovered, one, two, three, depth) { three ); const maxNbSplitSubregions = - Math.min(getNbSplitPerDepth(depth - 1), subregions[0].length) + - Math.min(getNbSplitPerDepth(depth - 1), subregions[1].length) + - Math.min(getNbSplitPerDepth(depth - 1), subregions[2].length); + Math.min(numInnerPortalsPerDepth(depth - 1), subregions[0].length) + + Math.min(numInnerPortalsPerDepth(depth - 1), subregions[1].length) + + Math.min(numInnerPortalsPerDepth(depth - 1), subregions[2].length); if (maxNbSplitSubregions + 1 <= bestResult.split) { // Skip the portal since it will induce less splits than the current best choice continue; @@ -305,6 +308,21 @@ const HomogeneousDialog = AutoDraw.extend({ this._layerGroup = new L.LayerGroup(); window.addLayerGroup("Wasabee H-G Debug", this._layerGroup, true); this._displayDialog(); + this._updatePortalSet(); + }, + + _updatePortalSet: function () { + AutoDraw.prototype._updatePortalSet.call(this); + if (this._anchorOne && this._anchorTwo && this._anchorThree) { + this._portalSets.portals.portals = + this._portalSets.portals.portals.filter((p) => + portalInField(this._anchorOne, this._anchorTwo, this._anchorThree, p) + ); + + this._portalSets.portals.display.textContent = wX("PORTAL_COUNT", { + count: this._portalSets.portals.portals.length, + }); + } }, removeHooks: function () { @@ -321,21 +339,27 @@ const HomogeneousDialog = AutoDraw.extend({ wX("ANCHOR_PORTAL"), "_anchorOne", container, - window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY + window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY, + this._updatePortalSet.bind(this) ); this._addSetPortal( wX("ANCHOR_PORTAL2"), "_anchorTwo", container, - window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY + window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY, + this._updatePortalSet.bind(this) ); this._addSetPortal( wX("ANCHOR_PORTAL3"), "_anchorThree", container, - window.plugin.wasabee.static.constants.ANCHOR_THREE_KEY + window.plugin.wasabee.static.constants.ANCHOR_THREE_KEY, + this._updatePortalSet.bind(this) ); + this._addSelectSet(wX("AUTODRAW_PORTALS_SET"), "portals", container, "all"); + this.spanPortalNeeded = L.DomUtil.create("span", "", container); + const depthLabel = L.DomUtil.create("label", null, container); depthLabel.textContent = wX("MAX_SPLITS"); this.depthMenu = L.DomUtil.create("input", null, container); @@ -343,6 +367,12 @@ const HomogeneousDialog = AutoDraw.extend({ this.depthMenu.min = 2; this.depthMenu.value = 4; + L.DomEvent.on(this.depthMenu, "change", () => { + this.spanPortalNeeded.textContent = `(${numInnerPortalsPerDepth( + +this.depthMenu.value + )} needed)`; + }); + const orderLabel = L.DomUtil.create("label", null, container); orderLabel.textContent = "Order"; this.orderMenu = L.DomUtil.create("select", null, container); @@ -430,7 +460,7 @@ const HomogeneousDialog = AutoDraw.extend({ console.timeEnd("HF greedy"); this._tree = tree; - this._failed = (3 ** (+this.depthMenu.value - 1) - 1) / 2 - tree.split; + this._failed = numInnerPortalsPerDepth(+this.depthMenu.value) - tree.split; this._draw(); @@ -467,7 +497,8 @@ const HomogeneousDialog = AutoDraw.extend({ console.timeEnd("HF deep recurser"); this._tree = tree; - this._failed = (3 ** (+this.depthMenu.value - 1) - 1) / 2 - tree.split; + this._failed = + numInnerPortalsPerDepth(+this.depthMenu.value) / 2 - tree.split; this._draw(); diff --git a/src/code/dialogs/autodraws/tools.d.ts b/src/code/dialogs/autodraws/tools.d.ts index 55f257d89..1a651e9b4 100644 --- a/src/code/dialogs/autodraws/tools.d.ts +++ b/src/code/dialogs/autodraws/tools.d.ts @@ -25,7 +25,8 @@ export class AutoDraw extends WDialog { text: string, thisKey: string, container: HTMLDivElement, - storageKey: string + storageKey: string, + callback?: () => void, ): void; _addCheckbox( text: string, diff --git a/src/code/dialogs/autodraws/tools.js b/src/code/dialogs/autodraws/tools.js index 67d2650bf..2ac80dbf9 100644 --- a/src/code/dialogs/autodraws/tools.js +++ b/src/code/dialogs/autodraws/tools.js @@ -93,7 +93,7 @@ export const AutoDraw = WDialog.extend({ } }, - _addSetPortal: function (text, thisKey, container, storageKey) { + _addSetPortal: function (text, thisKey, container, storageKey, callback) { const label = L.DomUtil.create("label", "set-portal-label", container); label.textContent = text; const button = L.DomUtil.create("button", "set-portal-button", container); @@ -119,6 +119,7 @@ export const AutoDraw = WDialog.extend({ display.textContent = wX("NOT_SET"); displayError(wX("PLEASE_SELECT_PORTAL")); } + if (callback) callback(); }); }, From 2c28ce67ebb6274ce8d8e88c78a69ea50eee6e95 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 27 Dec 2021 00:01:38 +0100 Subject: [PATCH 171/275] onion: derecurse add balanced, equilateral (close to previous), "let it grow" (keep adding layer from equilateral) --- src/code/dialogs/autodraws/onionfield.js | 274 ++++++++--------------- 1 file changed, 94 insertions(+), 180 deletions(-) diff --git a/src/code/dialogs/autodraws/onionfield.js b/src/code/dialogs/autodraws/onionfield.js index f5567a7fa..8c1a3f8a5 100644 --- a/src/code/dialogs/autodraws/onionfield.js +++ b/src/code/dialogs/autodraws/onionfield.js @@ -1,8 +1,7 @@ import { AutoDraw } from "./tools"; import WasabeePortal from "../../model/portal"; import { getSelectedOperation } from "../../selectedOp"; -import { greatCircleArcIntersectByLatLngs } from "../../crosslinks"; -import WasabeeLink from "../../model/link"; +import { portalInField } from "../../crosslinks"; import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; import { displayError } from "../../error"; @@ -38,6 +37,19 @@ const OnionfieldDialog = AutoDraw.extend({ window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY ); + const optionLabel = L.DomUtil.create("label", null, container); + optionLabel.textContent = "Options"; // wX + this.optionMenu = L.DomUtil.create("select", null, container); + for (const [text, value] of [ + ["~Equilateral", "equi"], + ["Let it grow", "grow"], + ["Perfect balance", "balanced"], // need wX on first column + ]) { + const option = L.DomUtil.create("option", null, this.optionMenu); + option.value = value; + option.textContent = text; + } + // Go button const button = L.DomUtil.create("button", "drawb", container); button.textContent = wX("ONION"); @@ -69,7 +81,7 @@ const OnionfieldDialog = AutoDraw.extend({ displayError("no anchor selected"); return; } - this._colors = [ + const colors = [ "#f80c12", "#ee1100", "#ff3311", @@ -89,210 +101,112 @@ const OnionfieldDialog = AutoDraw.extend({ "#3b0cbd", "#442299", ]; - this._colorIterator = 0; - this._color = this._colors[this._colorIterator]; const allPortals = getAllPortalsOnScreen(this._operation); - // batch mode isn't strictly necessary since we are loading the links in one operation, but portals are added during the recursion - this._operation.startBatchMode(); - - // add the anchor to the operation, needed to check for crosslinks - this._operation.addPortal(this._anchor); - // start digging for onions - const onion = this._recurser(allPortals, [], this._anchor); + const links = this._recurser( + allPortals, + this._anchor, + this.optionMenu.value + ); - // add all the found links at once - // this is a minor abuse of the _operation object since we aren't using the operation.addLink() method to add links - this._operation.links.push(...onion); - // that didn't add the anchors, so we have to do that here - this._operation.cleanAnchorList(); - // now, remove the portals that are unused - this._operation.cleanPortalList(); - // signal to the operation that we are done abusing it + this._operation.startBatchMode(); + links.forEach((l, i) => + this._operation.addLink(l.from, l.to, { + order: i + 1, + color: colors[i % colors.length], + }) + ); this._operation.endBatchMode(); }, - // no longer operates on a a class var, different paths (if not using the fast route) have different lists - _removeFromList: function (portalsRemaining, guid) { - const x = new Array(); - for (const p of portalsRemaining) { - if (p.id != guid) x.push(p); - } - return x; - }, - // the data passing for this (portalsRemaining, thisPath) // is designed to allow for determining optimum path, the fast route is quick // and gets a reasonable set, optimum path determination is VERY slow and nets // only a few extra layers - _recurser: function (portalsRemaining, thisPath, one, two, three) { - this._colorIterator = (this._colorIterator + 1) % this._colors.length; - this._color = this._colors[this._colorIterator]; + _recurser: function (portalsRemaining, start, type) { + portalsRemaining = portalsRemaining.filter((p) => p.id !== start.id); + if (portalsRemaining.length < 2) return []; - // build a map of all portals still in-play const m = new Map(); for (const p of portalsRemaining) { - if ( - (two && p.id == two.id) || - (three && p.id == three.id) || - p.id == one.id - ) { - portalsRemaining = this._removeFromList(portalsRemaining, p.id); - continue; - } - - const pDist = window.map.distance(one.latLng, p.latLng); + const pDist = window.map.distance(start.latLng, p.latLng); m.set(pDist, p); } - // sort by distance - const sorted = new Map([...m.entries()].sort((a, b) => a[0] - b[0])); - if (sorted.length == 0) return null; - - // for each of the portals in play - for (const [k, wp] of sorted) { - // silence lint - this._trash = k; - - // we need it in the op (this prevents dupes) for links later - this._operation.addPortal(wp); - // unused ones will be purged at the end - - // do the intial field - if (!two) { - portalsRemaining = this._removeFromList(portalsRemaining, wp.id); - const a = new WasabeeLink( - { fromPortalId: one.id, toPortalId: wp.id }, - this._operation - ); - a.color = this._color; - a.throwOrderPos = 1; - thisPath.push(a); - return this._recurser(portalsRemaining, thisPath, one, wp); - } - if (!three) { - portalsRemaining = this._removeFromList(portalsRemaining, wp.id); - const a = new WasabeeLink( - { fromPortalId: one.id, toPortalId: wp.id }, - this._operation - ); - a.color = this._color; - a.throwOrderPos = 2; - thisPath.push(a); - const b = new WasabeeLink( - { fromPortalId: two.id, toPortalId: wp.id }, - this._operation - ); - b.color = this._color; - b.throwOrderPos = 3; - thisPath.push(b); - // now we are bootstrapped, dive in - return this._recurser(portalsRemaining, thisPath, one, two, wp); - } - // initial field done + const sorted = [...m.entries()] + .sort((a, b) => a[0] - b[0]) + .map((a) => a[1]); + + let [one, two, three] = this._sortAnchors(start, sorted[0], sorted[1]); + const path = [ + { + from: two, + to: one, + }, + { + from: three, + to: one, + }, + { + from: three, + to: two, + }, + ]; - // create the three links, this does not add them to the operation - const a = new WasabeeLink( - { fromPortalId: one.id, toPortalId: wp.id }, - this._operation - ); - const b = new WasabeeLink( - { fromPortalId: two.id, toPortalId: wp.id }, - this._operation - ); - const c = new WasabeeLink( - { fromPortalId: three.id, toPortalId: wp.id }, - this._operation - ); - a.color = this._color; - b.color = this._color; - c.color = this._color; + portalsRemaining = portalsRemaining.filter( + (p) => p.id !== two.id && p.id !== three.id + ); - // testBlock does not look in the op or live map data, but in thisPath - const aBlock = this._testBlock(thisPath, a); - const bBlock = this._testBlock(thisPath, b); - const cBlock = this._testBlock(thisPath, c); + const round = type === "grow" ? 3 : 1; - // if none of the links are blocked by existing linkes in thisPath, we found an option - if (!aBlock && !bBlock && !cBlock) { - portalsRemaining = this._removeFromList(portalsRemaining, wp.id); + let running = round; + while (running > 0 && portalsRemaining.length > 0) { + running = running - 1; - let Y = one; - let Z = two; - // determine the widest angle, wp= angTwoThree && angOneTwo >= angThreeOne) { - Y = one; - Z = two; - thisPath.push(a); - a.throwOrderPos = thisPath.length; - thisPath.push(b); - b.throwOrderPos = thisPath.length; - // XXX add back-link to c if requested - } else if (angTwoThree >= angThreeOne) { - Y = two; - Z = three; - thisPath.push(b); - b.throwOrderPos = thisPath.length; - thisPath.push(c); - c.throwOrderPos = thisPath.length; - // XXX add back-link to a if requested + // sorted remaining by distance to one + const m = new Map(); + for (const p of portalsRemaining) { + const pDist = window.map.distance(one.latLng, p.latLng); + m.set(pDist, p); + } + const sorted = [...m.entries()] + .sort((a, b) => a[0] - b[0]) + .map((a) => a[1]); + + // for each of the portals in play + const wp = sorted.find((p) => portalInField(p, two, three, one)); + if (wp) { + running = round; + portalsRemaining = portalsRemaining.filter((p) => p.id !== wp.id); + + path.push({ from: wp, to: two }); + path.push({ from: wp, to: three }); + path.push({ from: wp, to: one }); + + if (type === "balanced") { + [one, two, three] = [two, three, wp]; } else { - Y = three; - Z = one; - thisPath.push(c); - c.throwOrderPos = thisPath.length; - thisPath.push(a); - a.throwOrderPos = thisPath.length; - // XXX add back-link to b if requested + // determine the widest angle, wp<23, use that to determine next covered portal + [one, two, three] = this._sortAnchors(two, three, wp); } - - // allow users to turn this on if they want... - if ( - localStorage["wasabee-onion-recursive"] && - localStorage["wasabee-onion-recursive"] == "slowAF" - ) { - // you might find 2 or 3 more layers on a small field, but it takes an hour to run - // two is enough, three gets crazy even with a small number of portals - const pathOne = this._recurser( - new Array(...portalsRemaining), - new Array(...thisPath), - Y, - Z, - wp - ); - const pathTwo = this._recurser( - new Array(...portalsRemaining), - new Array(...thisPath), - Z, - Y, - wp - ); - // console.log(pathOne.length, pathTwo.length); - if (pathTwo.length > pathOne.lenght) return pathTwo; - return pathOne; + } + if (running < round) { + if (type == "grow") { + // drop the widest angle constraint, take the next one + [one, two, three] = [two, three, one]; } - // default to the fast route, which gets gets us 90+% in my testing - return this._recurser(portalsRemaining, thisPath, Y, Z, wp); } } // console.log("hit bottom", thisPath.length); - return thisPath; + return path; }, - // looks only at links in current (not op or live data) - _testBlock: function (current, testing) { - for (const against of current) { - if ( - greatCircleArcIntersectByLatLngs( - testing.getLatLngs(this._operation), - against.getLatLngs(this._operation) - ) - ) - return true; - } - return false; + _sortAnchors: function (one, two, three) { + const a = [ + [one, this._angle(one, two, three)], + [two, this._angle(two, three, one)], + [three, this._angle(three, one, two)], + ]; + return a.sort((a, b) => b[1] - a[1]).map((a) => a[0]); }, // angle a Date: Mon, 27 Dec 2021 00:11:56 +0100 Subject: [PATCH 172/275] onion: extract algo from class --- src/code/dialogs/autodraws/onionfield.js | 226 ++++++++++++----------- 1 file changed, 117 insertions(+), 109 deletions(-) diff --git a/src/code/dialogs/autodraws/onionfield.js b/src/code/dialogs/autodraws/onionfield.js index 8c1a3f8a5..5cfb6fc99 100644 --- a/src/code/dialogs/autodraws/onionfield.js +++ b/src/code/dialogs/autodraws/onionfield.js @@ -6,6 +6,122 @@ import { clearAllLinks, getAllPortalsOnScreen } from "../../uiCommands"; import wX from "../../wX"; import { displayError } from "../../error"; +/** + * Sort trangle vertices by widest angle + * @param {WasabeePortal} one + * @param {WasabeePortal} two + * @param {WasabeePortal} three + * @returns {[WasabeePortal, WasabeePortal, WasabeePortal]} + */ +function sortAnchors(one, two, three) { + const a = [ + [one, euclideanAngle(one, two, three)], + [two, euclideanAngle(two, three, one)], + [three, euclideanAngle(three, one, two)], + ]; + return a.sort((a, b) => b[1] - a[1]).map((a) => a[0]); +} + +/** + * Returns the angle a p.id !== anchor.id); + if (portals.length < 2) return []; + + const m = new Map(); + for (const p of portals) { + const pDist = window.map.distance(anchor.latLng, p.latLng); + m.set(pDist, p); + } + const sorted = [...m.entries()].sort((a, b) => a[0] - b[0]).map((a) => a[1]); + + let [one, two, three] = sortAnchors(anchor, sorted[0], sorted[1]); + const path = [ + { + from: two, + to: one, + }, + { + from: three, + to: one, + }, + { + from: three, + to: two, + }, + ]; + + portals = portals.filter((p) => p.id !== two.id && p.id !== three.id); + + const round = type === "grow" ? 3 : 1; + + let running = round; + while (running > 0 && portals.length > 0) { + running = running - 1; + + // sorted remaining by distance to one + const m = new Map(); + for (const p of portals) { + const pDist = window.map.distance(one.latLng, p.latLng); + m.set(pDist, p); + } + const sorted = [...m.entries()] + .sort((a, b) => a[0] - b[0]) + .map((a) => a[1]); + + // for each of the portals in play + const wp = sorted.find((p) => portalInField(p, two, three, one)); + if (wp) { + running = round; + portals = portals.filter((p) => p.id !== wp.id); + + path.push({ from: wp, to: two }); + path.push({ from: wp, to: three }); + path.push({ from: wp, to: one }); + + if (type === "balanced") { + [one, two, three] = [two, three, wp]; + } else { + // determine the widest angle, wp<23, use that to determine next covered portal + [one, two, three] = sortAnchors(two, three, wp); + } + } + if (running < round) { + if (type == "grow") { + // drop the widest angle constraint, take the next one + [one, two, three] = [two, three, one]; + } + } + } + // console.log("hit bottom", thisPath.length); + return path; +} + const OnionfieldDialog = AutoDraw.extend({ statics: { TYPE: "OnionDialog", @@ -103,11 +219,7 @@ const OnionfieldDialog = AutoDraw.extend({ ]; const allPortals = getAllPortalsOnScreen(this._operation); - const links = this._recurser( - allPortals, - this._anchor, - this.optionMenu.value - ); + const links = onion(this._anchor, allPortals, this.optionMenu.value); this._operation.startBatchMode(); links.forEach((l, i) => @@ -118,110 +230,6 @@ const OnionfieldDialog = AutoDraw.extend({ ); this._operation.endBatchMode(); }, - - // the data passing for this (portalsRemaining, thisPath) - // is designed to allow for determining optimum path, the fast route is quick - // and gets a reasonable set, optimum path determination is VERY slow and nets - // only a few extra layers - _recurser: function (portalsRemaining, start, type) { - portalsRemaining = portalsRemaining.filter((p) => p.id !== start.id); - if (portalsRemaining.length < 2) return []; - - const m = new Map(); - for (const p of portalsRemaining) { - const pDist = window.map.distance(start.latLng, p.latLng); - m.set(pDist, p); - } - const sorted = [...m.entries()] - .sort((a, b) => a[0] - b[0]) - .map((a) => a[1]); - - let [one, two, three] = this._sortAnchors(start, sorted[0], sorted[1]); - const path = [ - { - from: two, - to: one, - }, - { - from: three, - to: one, - }, - { - from: three, - to: two, - }, - ]; - - portalsRemaining = portalsRemaining.filter( - (p) => p.id !== two.id && p.id !== three.id - ); - - const round = type === "grow" ? 3 : 1; - - let running = round; - while (running > 0 && portalsRemaining.length > 0) { - running = running - 1; - - // sorted remaining by distance to one - const m = new Map(); - for (const p of portalsRemaining) { - const pDist = window.map.distance(one.latLng, p.latLng); - m.set(pDist, p); - } - const sorted = [...m.entries()] - .sort((a, b) => a[0] - b[0]) - .map((a) => a[1]); - - // for each of the portals in play - const wp = sorted.find((p) => portalInField(p, two, three, one)); - if (wp) { - running = round; - portalsRemaining = portalsRemaining.filter((p) => p.id !== wp.id); - - path.push({ from: wp, to: two }); - path.push({ from: wp, to: three }); - path.push({ from: wp, to: one }); - - if (type === "balanced") { - [one, two, three] = [two, three, wp]; - } else { - // determine the widest angle, wp<23, use that to determine next covered portal - [one, two, three] = this._sortAnchors(two, three, wp); - } - } - if (running < round) { - if (type == "grow") { - // drop the widest angle constraint, take the next one - [one, two, three] = [two, three, one]; - } - } - } - // console.log("hit bottom", thisPath.length); - return path; - }, - - _sortAnchors: function (one, two, three) { - const a = [ - [one, this._angle(one, two, three)], - [two, this._angle(two, three, one)], - [three, this._angle(three, one, two)], - ]; - return a.sort((a, b) => b[1] - a[1]).map((a) => a[0]); - }, - - // angle a Date: Mon, 27 Dec 2021 00:19:38 +0100 Subject: [PATCH 173/275] onion: add wX strings --- src/code/dialogs/autodraws/onionfield.js | 8 ++++---- src/code/translations/english.json | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/code/dialogs/autodraws/onionfield.js b/src/code/dialogs/autodraws/onionfield.js index 5cfb6fc99..286d97d29 100644 --- a/src/code/dialogs/autodraws/onionfield.js +++ b/src/code/dialogs/autodraws/onionfield.js @@ -154,12 +154,12 @@ const OnionfieldDialog = AutoDraw.extend({ ); const optionLabel = L.DomUtil.create("label", null, container); - optionLabel.textContent = "Options"; // wX + optionLabel.textContent = wX("autodraw.onion.variant"); this.optionMenu = L.DomUtil.create("select", null, container); for (const [text, value] of [ - ["~Equilateral", "equi"], - ["Let it grow", "grow"], - ["Perfect balance", "balanced"], // need wX on first column + [wX("autodraw.onion.variant.equilateral"), "equi"], + [wX("autodraw.onion.variant.grow"), "grow"], + [wX("autodraw.onion.variant.balanced"), "balanced"], ]) { const option = L.DomUtil.create("option", null, this.optionMenu); option.value = value; diff --git a/src/code/translations/english.json b/src/code/translations/english.json index c2ecb6c25..94ca348f4 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -46,6 +46,10 @@ "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", "AUTODRAW_PORTALS_SET": "Portals", + "autodraw.onion.variant": "Option", + "autodraw.onion.variant.equilateral": "~Equilateral", + "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.balanced": "Perfectly balanced", "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", "AUTOLOAD": "Automatically Load Missing Portal Details", "AUTOMARK STOP": "Auto-Mark stopped due to portals not being loaded", From b13777dc782054e0000a441c078e236164b04267 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 28 Dec 2021 18:15:55 +0100 Subject: [PATCH 174/275] fix: backlink --- src/code/dialogs/autodraws/drawRoutines.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code/dialogs/autodraws/drawRoutines.ts b/src/code/dialogs/autodraws/drawRoutines.ts index 1ec2539a9..4a74a7d94 100644 --- a/src/code/dialogs/autodraws/drawRoutines.ts +++ b/src/code/dialogs/autodraws/drawRoutines.ts @@ -22,6 +22,7 @@ function getSpineLinks( linksDesc.push({ from: p, to: anchor2 }); if (options.backlink && prev) linksDesc.push({ from: p, to: prev, back: true }); + prev = p; } return linksDesc; } From b710a6154e777151365f420f648efd135d0753ff Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 2 Jan 2022 23:30:10 +0100 Subject: [PATCH 175/275] manageTeam: remove MeTeam usage to team --- src/code/dialogs/manageTeamDialog.js | 55 +++++++++------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index baa9cb343..97aacb6ba 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -27,7 +27,7 @@ const ManageTeamDialog = WDialog.extend({ }, options: { - // team + // team : MeTeam }, addHooks: function () { @@ -160,6 +160,9 @@ const ManageTeamDialog = WDialog.extend({ list.appendChild(table.table); await table.done; + const team = await WasabeeTeam.get(this.options.team.ID); + this.options.team.Name = team.name; + const addlabel = L.DomUtil.create("label", null, container); addlabel.textContent = wX("ADD_AGENT"); const addField = L.DomUtil.create("input", null, container); @@ -182,15 +185,14 @@ const ManageTeamDialog = WDialog.extend({ renamelabel.textContent = wX("RENAME_TEAM"); const renameField = L.DomUtil.create("input", null, container); renameField.placeholder = wX("BAT_TOAD"); - renameField.value = this.options.team.Name; + renameField.value = team.name; const renameButton = L.DomUtil.create("button", null, container); renameButton.textContent = wX("RENAME"); L.DomEvent.on(renameButton, "click", async (ev) => { L.DomEvent.stop(ev); try { - await renameTeamPromise(this.options.team.ID, renameField.value); + await renameTeamPromise(team.id, renameField.value); displayInfo(`renamed to ${renameField.value}`); - this.options.team.Name = renameField.value; // for display window.map.fire("wasabee:team:update"); } catch (e) { console.error(e); @@ -202,27 +204,19 @@ const ManageTeamDialog = WDialog.extend({ rockslabel.textContent = wX("ROCKS_COM"); const rockscommField = L.DomUtil.create("input", null, container); rockscommField.placeholder = "xxyyzz.com"; - if (this.options.team.RocksComm) - rockscommField.value = this.options.team.RocksComm; + if (team.rc) rockscommField.value = team.rc; const rocksapilabel = L.DomUtil.create("label", null, container); rocksapilabel.textContent = wX("API_KEY"); const rocksapiField = L.DomUtil.create("input", null, container); rocksapiField.placeholder = "..."; - if (this.options.team.RocksKey) - rocksapiField.value = this.options.team.RocksKey; + if (team.rk) rocksapiField.value = team.rk; const rocksButton = L.DomUtil.create("button", null, container); rocksButton.textContent = wX("SET"); L.DomEvent.on(rocksButton, "click", async (ev) => { L.DomEvent.stop(ev); try { - await rocksPromise( - this.options.team.ID, - rockscommField.value, - rocksapiField.value - ); + await rocksPromise(team.id, rockscommField.value, rocksapiField.value); displayInfo("updated rocks info"); - this.options.team.RocksComm = rockscommField.value; // for display - this.options.team.RocksKey = rocksapiField.value; // for display this.update(); } catch (e) { console.error(e); @@ -232,18 +226,17 @@ const ManageTeamDialog = WDialog.extend({ const joinlinklabel = L.DomUtil.create("label", null, container); joinlinklabel.textContent = "Join Link"; - if (this.options.team.JoinLinkToken != "") { + if (team.jlt) { const joinlink = L.DomUtil.create("input", null, container); const server = GetWasabeeServer(); - joinlink.value = `${server}/api/v1/team/${this.options.team.ID}/join/${this.options.team.JoinLinkToken}`; + joinlink.value = `${server}/api/v1/team/${team.id}/join/${team.jlt}`; joinlink.readOnly = true; L.DomEvent.on(joinlink, "click", (ev) => ev.target.select()); const joinlinkdel = L.DomUtil.create("button", null, container); joinlinkdel.textContent = "Revoke"; L.DomEvent.on(joinlinkdel, "click", async (ev) => { L.DomEvent.stop(ev); - await deleteJoinLinkPromise(this.options.team.ID); - this.options.team.JoinLinkToken = ""; + await deleteJoinLinkPromise(team.id); this.update(); }); } else { @@ -252,8 +245,7 @@ const ManageTeamDialog = WDialog.extend({ joinlinkadd.textContent = "Create"; L.DomEvent.on(joinlinkadd, "click", async (ev) => { L.DomEvent.stop(ev); - const j = await createJoinLinkPromise(this.options.team.ID); - this.options.team.JoinLinkToken = j.Key; + await createJoinLinkPromise(team.id); this.update(); }); } @@ -266,15 +258,15 @@ const ManageTeamDialog = WDialog.extend({ L.DomEvent.stop(ev); const cd = new ConfirmDialog({ title: wX("REMOVE_TEAM_CONFIRM_TITLE", { - teamName: this.options.team.Name, + teamName: team.name, }), label: wX("REMOVE_TEAM_CONFIRM_LABEL", { - teamName: this.options.team.Name, + teamName: team.name, }), callback: async () => { try { - await deleteTeamPromise(this.options.team.ID); - displayInfo(`${this.options.team.Name} removed`); + await deleteTeamPromise(team.id); + displayInfo(`${team.name} removed`); this.closeDialog(); await WasabeeMe.waitGet(true); } catch (e) { @@ -287,19 +279,6 @@ const ManageTeamDialog = WDialog.extend({ cd.enable(); }); - if (this.options.team.jkt) { - const joinLinkLabel = L.DomUtil.create("label", null, container); - joinLinkLabel.textContent = wX("JOIN_LINK"); - const joinLink = L.DomUtil.create("a", null, container); - const jl = - GetWasabeeServer() + - "/api/v1/team/" + - this.options.team.ID + - "/join/" + - this.options.team.jkt; - joinLink.href = jl; - joinLink.textContent = jl; - } return container; }, From aa37cf499ac4aa3cdd503e88f1a17ca49d47c785 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 13 Dec 2021 22:56:37 +0100 Subject: [PATCH 176/275] auth: factor gapi part move to auth.ts --- src/code/auth.ts | 58 +++++++++++++ src/code/dialogs/authDialog.js | 150 ++++++++++----------------------- 2 files changed, 102 insertions(+), 106 deletions(-) create mode 100644 src/code/auth.ts diff --git a/src/code/auth.ts b/src/code/auth.ts new file mode 100644 index 000000000..475732f7c --- /dev/null +++ b/src/code/auth.ts @@ -0,0 +1,58 @@ +import { postToFirebase } from "./firebaseSupport"; +import WasabeeMe from "./model/me"; +import { oneTimeToken, SendAccessTokenAsync } from "./server"; + +/** wrap send access token to get me */ +export async function sendAccessToken(token: string) { + const r = await SendAccessTokenAsync(token); + return r ? new WasabeeMe(r) : await WasabeeMe.waitGet(true); +} + +/** wrap ott to get me */ +export async function sendOneTimeToken(token: string) { + await oneTimeToken(token); + return await WasabeeMe.waitGet(true); +} + +/** GAPI */ + +/** */ +export function isAuthAvailable() { + return !!window.gapi.auth2.getAuthInstance(); +} + +/** Get access token from google */ +export function getAccessToken(selectAccount = false) { + return new Promise((resolve, reject) => { + const options = { + client_id: window.plugin.wasabee.static.constants.OAUTH_CLIENT_ID, + scope: "email profile openid", + response_type: "id_token permission", + prompt: selectAccount ? "select_account" : "none", + }; + + window.gapi.auth2.authorize(options, (response) => { + if (response.error) { + postToFirebase({ id: "exception", error: response.error }); + if (response.error === "idpiframe_initialization_failed") { + return reject("You need enable cookies or allow [*.]google.com"); + } + if (!selectAccount) { + if ( + response.error == "user_logged_out" || + response.error == "immediate_failed" + ) { + // retry with account selection + return getAccessToken(true); + } + } + + const err = `error from gapiAuth: ${response.error}: ${response.error_subtype}`; + postToFirebase({ id: "exception", error: err }); + return reject(err); + } + + resolve(response.access_token); + }); + }); +} diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index 5d32a8c49..1a0a51e26 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -1,17 +1,17 @@ import { WDialog } from "../leafletClasses"; -import { - SendAccessTokenAsync, - GetWasabeeServer, - SetWasabeeServer, - oneTimeToken, - setIntelID, -} from "../server"; +import { GetWasabeeServer, SetWasabeeServer, setIntelID } from "../server"; import PromptDialog from "./promptDialog"; import { sendLocation, fullSync } from "../uiCommands"; import { wX } from "../wX"; import { postToFirebase } from "../firebaseSupport"; import WasabeeMe from "../model/me"; -import { displayError } from "../error"; +import { displayError, ServerError } from "../error"; +import { + isAuthAvailable, + getAccessToken, + sendAccessToken, + sendOneTimeToken, +} from "../auth"; const AuthDialog = WDialog.extend({ statics: { @@ -32,18 +32,17 @@ const AuthDialog = WDialog.extend({ sendLocation(); }, - _successLogin: async function (me) { - const newme = me ? new WasabeeMe(me) : await WasabeeMe.waitGet(true); - newme.store(); + _successLogin: function (me) { + me.store(); window.map.fire("wasabee:login"); this.closeDialog(); fullSync(); - setIntelID(window.PLAYER.nickname, window.PLAYER.team, newme.querytoken); // no need to await + if (me.querytoken) + setIntelID(window.PLAYER.nickname, window.PLAYER.team, me.querytoken); }, _displayDialog: function () { - const syncLoggedIn = window.gapi.auth2.getAuthInstance(); - if (syncLoggedIn) { + if (isAuthAvailable()) { displayError(wX("AUTH INCOMPAT")); return; } @@ -92,7 +91,7 @@ const AuthDialog = WDialog.extend({ L.DomEvent.stop(ev); gapiButton.disabled = true; gapiButton.textContent = "... loading ..."; - this.gapiAuth.call(this); + this.gapiAuth(); }); if (!this._android && !this._ios) { @@ -102,7 +101,7 @@ const AuthDialog = WDialog.extend({ L.DomEvent.stop(ev); gapiSelectButton.disabled = true; gapiSelectButton.textContent = "... loading ..."; - this.gsapiAuthChoose.call(this); + this.gsapiAuthChoose(); }); } @@ -122,7 +121,8 @@ const AuthDialog = WDialog.extend({ L.DomEvent.on(postwebviewButton, "click", async (ev) => { L.DomEvent.stop(ev); try { - await this._successLogin(); + const me = await WasabeeMe.waitGet(true); + this._successLogin(me); postToFirebase({ id: "wasabeeLogin", method: "iOS" }); } catch (e) { console.error(e); @@ -166,8 +166,8 @@ const AuthDialog = WDialog.extend({ callback: async () => { if (ottDialog.inputField.value) { try { - await oneTimeToken(ottDialog.inputField.value); - await this._successLogin(); + const me = await sendOneTimeToken(ottDialog.inputField.value); + this._successLogin(me); postToFirebase({ id: "wasabeeLogin", method: "One Time Token" }); } catch (e) { console.error(e); @@ -198,98 +198,36 @@ const AuthDialog = WDialog.extend({ // this works in most cases // but fails on android if the account logged into intel is different than the one used for Wasabee - gapiAuth: function () { - const options = { - client_id: window.plugin.wasabee.static.constants.OAUTH_CLIENT_ID, - scope: "email profile openid", - response_type: "id_token permission", - prompt: "none", - }; - - window.gapi.auth2.authorize(options, async (response) => { - if (response.error) { - postToFirebase({ id: "exception", error: response.error }); - if (response.error === "idpiframe_initialization_failed") { - displayError("You need enable cookies or allow [*.]google.com"); - } - if ( - response.error == "user_logged_out" || - response.error == "immediate_failed" - ) { - options.prompt = "select_account"; // try again, forces prompt but preserves "immediate" selection - window.gapi.auth2.authorize(options, async (responseSelect) => { - if (responseSelect.error) { - postToFirebase({ id: "exception", error: response.error }); - const err = `error from gapiAuth (immediate_failed): ${responseSelect.error}: ${responseSelect.error_subtype}`; - displayError(err); - console.log(err); - return; - } - try { - const r = await SendAccessTokenAsync(responseSelect.access_token); - await this._successLogin(r); - postToFirebase({ - id: "wasabeeLogin", - method: "gsapiAuth (immediate_failed)", - }); - } catch (e) { - displayError(wX("AUTH TOKEN REJECTED", { error: e.toString() })); - console.error(e); - this.closeDialog(); - } - }); - } else { - this.closeDialog(); - const err = `error from gapiAuth: ${response.error}: ${response.error_subtype}`; - postToFirebase({ id: "exception", error: err }); - console.log(err); - displayError(err); - } - return; - } - try { - const r = await SendAccessTokenAsync(response.access_token); - await this._successLogin(r); - postToFirebase({ id: "wasabeeLogin", method: "gsapiAuth" }); - } catch (e) { - postToFirebase({ id: "exception", error: e.toString() }); - console.error(e); + gapiAuth: async function () { + try { + const token = await getAccessToken(false); + const me = await sendAccessToken(token); + postToFirebase({ id: "wasabeeLogin", method: "gapiAuth" }); + this._successLogin(me); + } catch (e) { + if (e instanceof ServerError) { + displayError(wX("AUTH TOKEN REJECTED", { error: e.toString() })); + } else { displayError(e); - this.closeDialog(); + postToFirebase({ id: "exception", error: e }); } - }); + } }, - gsapiAuthChoose: function () { - window.gapi.auth2.authorize( - { - prompt: "select_account", - client_id: window.plugin.wasabee.static.constants.OAUTH_CLIENT_ID, - scope: "email profile openid", - response_type: "id_token permission", - // immediate: false // this seems to break everything - }, - async (response) => { - if (response.error) { - this.closeDialog(); - const err = `error from gsapiAuthChoose: ${response.error}: ${response.error_subtype}`; - displayError(err); - postToFirebase({ id: "exception", error: err }); - return; - } - try { - const r = await SendAccessTokenAsync(response.access_token); - await this._successLogin(r); - postToFirebase({ id: "wasabeeLogin", method: "gsapiAuthChoose" }); - } catch (e) { - console.error(e); - displayError( - `send access token failed (gsapiAuthChoose): ${e.toString()}` - ); - postToFirebase({ id: "exception", error: e.toString() }); - } + gsapiAuthChoose: async function () { + try { + const token = await getAccessToken(true); + const me = await sendAccessToken(token); + postToFirebase({ id: "wasabeeLogin", method: "gsapiAuthChoose" }); + this._successLogin(me); + } catch (e) { + if (e instanceof ServerError) { + displayError(wX("AUTH TOKEN REJECTED", { error: e.toString() })); + } else { + displayError(e); + postToFirebase({ id: "exception", error: e }); } - ); + } }, }); From 5af2d401853f11cf42d2b116c6d15c945d03ffc0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 13 Dec 2021 23:25:24 +0100 Subject: [PATCH 177/275] auth: add jwt --- src/code/auth.ts | 17 +++++++++++++++++ src/code/init.ts | 3 +++ src/code/server.ts | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/src/code/auth.ts b/src/code/auth.ts index 475732f7c..0a595cc69 100644 --- a/src/code/auth.ts +++ b/src/code/auth.ts @@ -2,9 +2,26 @@ import { postToFirebase } from "./firebaseSupport"; import WasabeeMe from "./model/me"; import { oneTimeToken, SendAccessTokenAsync } from "./server"; +const JWT_KEY = "wasabee-jwt"; + +function storeJWT(jwt) { + localStorage[JWT_KEY] = jwt; +} + +export function deleteJWT() { + localStorage.removeItem(JWT_KEY); +} + +export function getJWT() { + return localStorage.getItem(JWT_KEY); +} + /** wrap send access token to get me */ export async function sendAccessToken(token: string) { const r = await SendAccessTokenAsync(token); + if (r && (r as any).jwt) { + storeJWT((r as any).jwt); + } return r ? new WasabeeMe(r) : await WasabeeMe.waitGet(true); } diff --git a/src/code/init.ts b/src/code/init.ts index 4effe145b..3d250b342 100644 --- a/src/code/init.ts +++ b/src/code/init.ts @@ -25,6 +25,7 @@ import WasabeeOp from "./model/operation"; import db from "./db"; import polyfill from "./polyfill"; import { displayError } from "./error"; +import { deleteJWT } from "./auth"; import type { FeatureGroup, LayerEvent, LayerGroup } from "leaflet"; import type { WLAnchor } from "./ui/anchor"; @@ -154,6 +155,8 @@ window.plugin.wasabee.init = async () => { window.map.on("wasabee:logout", removeNonOwnedOps); + window.map.on("wasabee:logout", deleteJWT); + // when the UI is woken from sleep on many devices window.addResumeFunction(() => { // check if still logged in diff --git a/src/code/server.ts b/src/code/server.ts index d5fec13b5..a4c77e7ea 100644 --- a/src/code/server.ts +++ b/src/code/server.ts @@ -7,6 +7,7 @@ import type WasabeePortal from "./model/portal"; import type WasabeeAgent from "./model/agent"; import type WasabeeTeam from "./model/team"; import type { WDKey } from "./wd"; +import { getJWT } from "./auth"; export default function () { return GetWasabeeServer(); @@ -546,10 +547,16 @@ async function generic(request: { credentials: "include", redirect: "manual", referrerPolicy: "origin", + headers: {}, }; if (request.body) requestInit.body = request.body; if (request.headers) requestInit.headers = request.headers; + if (request.url.startsWith("/api")) { + const jwt = getJWT(); + if (jwt) requestInit.headers["Authorization"] = `Bearer ${jwt}`; + } + try { const response = await fetch(GetWasabeeServer() + request.url, requestInit); /** @type Object | string */ From 5cf4324a96f1154b5157c49cc69323cf29a6dfd2 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 20 Dec 2021 18:09:34 +0100 Subject: [PATCH 178/275] auth: remove iOS unicity --- src/code/dialogs/authDialog.js | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index 1a0a51e26..c5602f165 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -77,15 +77,8 @@ const AuthDialog = WDialog.extend({ } } - const title = L.DomUtil.create("div", "desc", content); - if (this._ios) { - title.textContent = wX("AUTH IOS"); - } - const gapiButton = L.DomUtil.create("button", "gapi", content); gapiButton.textContent = wX("LOG IN"); - // XXX until we can figure out why IITC-M iOS doesn't set the cookie very often - if (this._ios) gapiButton.style.display = "none"; L.DomEvent.on(gapiButton, "click", (ev) => { L.DomEvent.stop(ev); @@ -105,33 +98,6 @@ const AuthDialog = WDialog.extend({ }); } - // webview cannot work on android IITC-M - if (this._ios) { - const webviewButton = L.DomUtil.create("button", "webview", content); - webviewButton.textContent = wX("WEBVIEW"); - L.DomEvent.on(webviewButton, "click", (ev) => { - L.DomEvent.stop(ev); - window.open(GetWasabeeServer()); - webviewButton.style.display = "none"; - postwebviewButton.style.display = "block"; - }); - const postwebviewButton = L.DomUtil.create("button", "webview", content); - postwebviewButton.textContent = wX("WEBVIEW VERIFY"); - postwebviewButton.style.display = "none"; - L.DomEvent.on(postwebviewButton, "click", async (ev) => { - L.DomEvent.stop(ev); - try { - const me = await WasabeeMe.waitGet(true); - this._successLogin(me); - postToFirebase({ id: "wasabeeLogin", method: "iOS" }); - } catch (e) { - console.error(e); - displayError(e); - } - window.map.fire("wasabee:defensivekeys"); - }); - } - const changeServerButton = L.DomUtil.create("button", "server", content); changeServerButton.textContent = wX("CHANGE SERVER"); L.DomEvent.on(changeServerButton, "click", (ev) => { From 7a8b8bc360d2f7fea86a8ccfad17dd5e79e3991e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 2 Jan 2022 18:51:55 +0100 Subject: [PATCH 179/275] firebase: use jwt and cdn2 iframe --- src/code/firebaseSupport.ts | 323 +++++++++++++++++++++++++----------- 1 file changed, 228 insertions(+), 95 deletions(-) diff --git a/src/code/firebaseSupport.ts b/src/code/firebaseSupport.ts index 35be8428e..4b874e644 100644 --- a/src/code/firebaseSupport.ts +++ b/src/code/firebaseSupport.ts @@ -4,124 +4,250 @@ * This way we can setup a service worker under a domain we control and * simply pass the messages along using window.parent.postMessage. */ -import { drawSingleTeam, drawSingleAgent } from "./mapDrawing"; +import { drawSingleTeam } from "./mapDrawing"; import { opPromise, GetWasabeeServer } from "./server"; import { makeSelectedOperation, - getSelectedOperation, removeOperation, - loadNewDefaultOp, + changeOpIfNeeded, } from "./selectedOp"; import { updateLocalOp } from "./uiCommands"; import WasabeeOp from "./model/operation"; import WasabeePortal from "./model/portal"; import PortalUI from "./ui/portal"; -import { displayInfo } from "./error"; +import { displayInfo, displayWarning } from "./error"; +import WasabeeAgent from "./model/agent"; +import { getJWT } from "./auth"; +import WasabeeMe from "./model/me"; // TODO: use a dedicated message channel: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging const frameID = "wasabeeFirebaseFrame"; -export function initFirebase() { - const server = GetWasabeeServer(); +const channel = new MessageChannel(); +const port = channel.port1; +export function initFirebase() { const iframe = L.DomUtil.create("iframe"); iframe.width = "0"; iframe.height = "0"; - iframe.src = server + "/static/firebase/index.html"; + iframe.src = "https://cdn2.wasabee.rocks/iitcplugin/firebase/"; iframe.id = frameID; + iframe.addEventListener("load", () => { + port.onmessage = onMessage; + iframe.contentWindow.postMessage('init', '*', [channel.port2]); + + if (WasabeeMe.isLoggedIn()) { + postToFirebase({ + id: "wasabeeLogin", + method: "auto" + }); + } + }); + $(document.body).append(iframe); +} - window.addEventListener("message", async (event) => { - // ignore anything not from our server - if (event.origin.indexOf(server) === -1) return; - - const operation = getSelectedOperation(); - switch (event.data.data.cmd) { - case "Agent Location Change": - if (event.data.data.gid != null) { - console.debug( - "firebase update of single agent location: ", - event.data.data - ); - drawSingleAgent(event.data.data.gid); - } else { - console.debug( - "firebase update of whole team location: ", - event.data.data - ); - drawSingleTeam(event.data.data.msg); - } - break; - case "Delete": - console.warn("server requested op delete: ", event.data.data.opID); - if (event.data.data.opID == operation.ID) await loadNewDefaultOp(); - await removeOperation(event.data.data.opID); - break; - case "Generic Message": - alert(JSON.stringify(event.data.data)); - break; - case "Login": - console.debug("server reported teammate login: ", event.data.data.gid); - window.map.fire("wasabee:agentlocations"); - break; - case "Map Change": - if (!window.plugin.wasabee._updateList.has(event.data.data.updateID)) { - try { - // update the list to avoid race from slow network - window.plugin.wasabee._updateList.set( - event.data.data.updateID, - Date.now() - ); - const localop = await WasabeeOp.load(event.data.data.opID); - const refreshed = await opPromise(event.data.data.opID); - const reloadSOp = await updateLocalOp(localop, refreshed); - if (reloadSOp) { - console.log( - "firebase trigger reload of current op: ", - event.data.data - ); - await makeSelectedOperation(refreshed.ID); - } else { - console.debug( - "firebase trigger update of op", - event.data.data.opID - ); - } - } catch (e) { - console.error(e); - } +async function onMessage(event: MessageEvent<{ data: WMessage }>) { + const data = event.data.data; + switch (data.cmd) { + case "Agent Location Change": + console.debug("firebase update of whole team location: ", data); + drawSingleTeam(data.msg); + break; + case "Delete": + displayWarning("server requested op delete: " + data.opID); + console.warn("server requested op delete: ", data.opID); + await removeOperation(data.opID); + await changeOpIfNeeded(); + break; + case "Generic Message": + const agent = await WasabeeAgent.get(data.sender); + const name = agent ? agent.name : "[unknown sender]"; + displayInfo(`Team announcement: “${data.msg}” from ${name}`); + break; + case "Login": + console.debug("server reported teammate login: ", data.gid); + window.map.fire("wasabee:agentlocations"); + break; + case "Link Assignment Change": + // fallthrough + case "Link Status Change": + // fallthrough + case "Marker Assignment Change": + // fallthrough + case "Marker Status Change": + // fallthrough + case "Map Change": + opDataChange(data); + break; + case "Target": + try { + const target = JSON.parse(data.msg); + const raw = { + id: target.ID, + name: target.Name, + lat: target.Lat, + lng: target.Lon, + }; + const portal = new WasabeePortal(raw); + const f = PortalUI.displayFormat(portal); + displayInfo(f.outerHTML + "
Sent by: " + target.Sender, true); + } catch (e) { + console.error(e); + } + break; + default: + console.warn("unknown firebase command: ", data); + } +} + +async function opDataChange( + data: LinkAssignment | LinkState | MarkerAssignment | MarkerState | OpChange +) { + let uid = data.updateID; + if (data.cmd !== "Map Change") uid += data.cmd; + + if (window.plugin.wasabee._updateList.has(uid)) { + console.debug( + "skipping firebase requested update of op since it was our change", + data.cmd, + data.updateID + ); + return; + } + // update the list to avoid race from slow network + window.plugin.wasabee._updateList.set(uid, Date.now()); + const operation = WasabeeOp.load(data.opID); + if (!operation) { + console.warn("Got operation change for an unknown op", data.opID); + return; + } + + switch (data.cmd) { + case "Link Assignment Change": + console.log(data); + break; + case "Link Status Change": + console.log(data); + break; + case "Marker Assignment Change": + console.log(data); + break; + case "Marker Status Change": + console.log(data); + break; + case "Map Change": + try { + const localop = await WasabeeOp.load(data.opID); + const refreshed = await opPromise(data.opID); + const reloadSOp = await updateLocalOp(localop, refreshed); + if (reloadSOp) { + console.log("firebase trigger reload of current op: ", data); + await makeSelectedOperation(refreshed.ID); } else { - console.debug( - "skipping firebase requested update of op since it was our change", - event.data.data.updateID - ); - } - break; - case "Target": - try { - const target = JSON.parse(event.data.data.msg); - const raw = { - id: target.ID, - name: target.Name, - lat: target.Lat, - lng: target.Lon, - }; - const portal = new WasabeePortal(raw); - const f = PortalUI.displayFormat(portal); - displayInfo(f.outerHTML + "
Sent by: " + target.Sender, true); - } catch (e) { - console.error(e); + console.debug("firebase trigger update of op", data.opID); } - break; - default: - console.warn("unknown firebase command: ", event.data.data); - } - }); + } catch (e) { + console.error(e); + } + break; + } } +type AgentLocation = { + cmd: "Agent Location Change"; + msg: TeamID; +}; + +type Annoucement = { + cmd: "Generic Message"; + msg: string; + sender: GoogleID; +}; + +type Target = { + cmd: "Target"; + msg: string; +}; + +type Login = { + cmd: "Login"; + gid: GoogleID; +}; + +type DeleteOp = { + cmd: "Delete"; + opID: OpID; +}; + +type Update = { + updateID: string; +}; + +type LinkAssignment = Update & { + cmd: "Link Assignment Change"; + opID: OpID; + linkID: LinkID; + msg: string; +}; + +type LinkState = Update & { + cmd: "Link Status Change"; + opID: OpID; + linkID: LinkID; + msg: string; +}; + +type MarkerAssignment = Update & { + cmd: "Marker Assignment Change"; + opID: OpID; + markerID: MarkerID; + msg: string; +}; + +type MarkerState = Update & { + cmd: "Marker Status Change"; + opID: OpID; + markerID: MarkerID; + msg: string; +}; + +type TaskAssignment = Update & { + cmd: "Task Assignment Change"; + opID: OpID; + taskID: TaskID; + msg: string; +}; + +type TaskState = Update & { + cmd: "Task Status Change"; + opID: OpID; + taskID: TaskID; + msg: string; +}; + +type OpChange = Update & { + cmd: "Map Change"; + opID: OpID; +}; + +type WMessage = + | AgentLocation + | Annoucement + | Target + | Login + | DeleteOp + | LinkAssignment + | LinkState + | MarkerAssignment + | MarkerState + | TaskAssignment + | TaskState + | OpChange; + interface FirebaseMessage { id: string; method: string; @@ -129,19 +255,26 @@ interface FirebaseMessage { error: string; app_name: string; app_version: string; + server: string; + jwt: string; } export function postToFirebase(message: Partial) { // prevent analytics data from being sent if not enabled by the user: GPDR - /* if ( + if ( message.id == "analytics" && localStorage[window.plugin.wasabee.static.constants.SEND_ANALYTICS_KEY] != - "true" + "true" ) - return; */ + return; + + if (message.id == "wasabeeLogin") { + message.server = GetWasabeeServer(); + message.jwt = getJWT(); + } message.app_name = "Wasabee-IITC"; message.app_version = window.plugin.wasabee.info.version; - window.frames[frameID].contentWindow.postMessage(message, GetWasabeeServer()); + port.postMessage(message); } From 4feea19034a1f339f1c0a3ff3a9eff7dac776ed9 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 2 Jan 2022 22:43:45 +0100 Subject: [PATCH 180/275] auth: small hl of server --- src/code/dialogs/authDialog.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index c5602f165..ec8bfacba 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -48,8 +48,9 @@ const AuthDialog = WDialog.extend({ } const content = L.DomUtil.create("div", "content"); - this._server = L.DomUtil.create("div", null, content); - this._server.textContent = GetWasabeeServer(); + this._server = L.DomUtil.create("input", "", content); + this._server.readOnly = true; + this._server.value = GetWasabeeServer(); const ua = L.DomUtil.create("div", "useragent", content); this._android = false; @@ -112,7 +113,7 @@ const AuthDialog = WDialog.extend({ callback: () => { if (serverDialog.inputField.value) { SetWasabeeServer(serverDialog.inputField.value); - this._server.textContent = GetWasabeeServer(); + this._server.value = GetWasabeeServer(); WasabeeMe.purge(); } window.map.fire("wasabee:defensivekeys"); From 9270d0eef7a8160754ef40d1634e7abab3de559e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:43:52 +0100 Subject: [PATCH 181/275] auth: resolve auto select account --- src/code/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/auth.ts b/src/code/auth.ts index 0a595cc69..2802e2353 100644 --- a/src/code/auth.ts +++ b/src/code/auth.ts @@ -60,7 +60,7 @@ export function getAccessToken(selectAccount = false) { response.error == "immediate_failed" ) { // retry with account selection - return getAccessToken(true); + return resolve(getAccessToken(true)); } } From 965c00a3197ff6cb34ca9d57b961a247511961d7 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 3 Jan 2022 20:26:48 +0100 Subject: [PATCH 182/275] auth: redraw dialog on error --- src/code/dialogs/authDialog.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index ec8bfacba..25f965350 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -172,6 +172,8 @@ const AuthDialog = WDialog.extend({ postToFirebase({ id: "wasabeeLogin", method: "gapiAuth" }); this._successLogin(me); } catch (e) { + this.disable(); + this.enable(); if (e instanceof ServerError) { displayError(wX("AUTH TOKEN REJECTED", { error: e.toString() })); } else { @@ -188,6 +190,8 @@ const AuthDialog = WDialog.extend({ postToFirebase({ id: "wasabeeLogin", method: "gsapiAuthChoose" }); this._successLogin(me); } catch (e) { + this.disable(); + this.enable(); if (e instanceof ServerError) { displayError(wX("AUTH TOKEN REJECTED", { error: e.toString() })); } else { From 1073fe306d0350da721efbebd259855a96bb5a08 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 3 Jan 2022 20:22:12 +0100 Subject: [PATCH 183/275] clear all data --- src/code/buttons/wasabeeButton.js | 22 ---------- src/code/db.ts | 7 +++- src/code/dialogs/settingsDialog.js | 5 +++ src/code/init.ts | 4 ++ src/code/toolbox.ts | 8 ++-- src/code/uiCommands.ts | 66 ++++++++++++++++++++++++++++-- 6 files changed, 81 insertions(+), 31 deletions(-) diff --git a/src/code/buttons/wasabeeButton.js b/src/code/buttons/wasabeeButton.js index bb2bf16b8..f89c2cbd6 100644 --- a/src/code/buttons/wasabeeButton.js +++ b/src/code/buttons/wasabeeButton.js @@ -3,15 +3,12 @@ import WasabeeMe from "../model/me"; import TeamListDialog from "../dialogs/teamListDialog"; import OpsDialog from "../dialogs/opsDialog"; import AuthDialog from "../dialogs/authDialog"; -import ConfirmDialog from "../dialogs/confirmDialog"; import NewopDialog from "../dialogs/newopDialog"; import SettingsDialog from "../dialogs/settingsDialog.js"; -import { resetOps, setupLocalStorage } from "../selectedOp"; import DefensiveKeysDialog from "../dialogs/defensiveKeysDialog"; import { wX } from "../wX"; import { logoutPromise } from "../server"; import { postToFirebase } from "../firebaseSupport"; -import { resetCaches } from "../uiCommands"; import { displayError } from "../error"; const WasabeeButton = WButton.extend({ @@ -149,25 +146,6 @@ const WasabeeButton = WButton.extend({ }, context: this, }, - { - title: wX("CLEAROPS BUTTON TITLE"), - text: wX("CLEAROPS BUTTON"), - callback: () => { - this.disable(); - const con = new ConfirmDialog({ - title: wX("CLEAROPS BUTTON TITLE"), - label: wX("CLEAROPS PROMPT"), - type: "operation", - callback: async () => { - await resetCaches(); - await resetOps(); - await setupLocalStorage(); - }, - }); - con.enable(); - }, - context: this, - }, ]; this._Dactions = [ diff --git a/src/code/db.ts b/src/code/db.ts index 741477c2c..ffe77251e 100644 --- a/src/code/db.ts +++ b/src/code/db.ts @@ -1,4 +1,4 @@ -import { openDB } from "idb"; +import { deleteDB, openDB } from "idb"; import type { DBSchema } from "idb"; import type WasabeeAgent from "./model/agent"; @@ -109,4 +109,9 @@ const db = openDB("wasabee", version, { }, }); +export async function deleteDatabase() { + (await db).close(); + return deleteDB("wasabee"); +} + export default db; diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index e97b4fb07..ba99638c3 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -4,6 +4,7 @@ import WasabeeMe from "../model/me"; import { GetWasabeeServer, SetWasabeeServer } from "../server"; import PromptDialog from "./promptDialog"; import SkinDialog from "./skinDialog"; +import { clearAllData } from "../uiCommands"; const SettingsDialog = WDialog.extend({ statics: { @@ -207,6 +208,10 @@ const SettingsDialog = WDialog.extend({ buttons[wX("OK")] = () => { this.closeDialog(); }; + buttons[wX("CLEAROPS BUTTON")] = () => { + this.closeDialog(); + clearAllData(); + }; this.createDialog({ title: wX("SETTINGS"), diff --git a/src/code/init.ts b/src/code/init.ts index 4effe145b..06867a16b 100644 --- a/src/code/init.ts +++ b/src/code/init.ts @@ -32,6 +32,7 @@ import type { WLLink } from "./ui/link"; import type { WLMarker } from "./ui/marker"; import type { WLAgent } from "./ui/agent"; import type { WLZone } from "./ui/zone"; +import type { ButtonsControl } from "./leafletClasses"; type Awaited = T extends PromiseLike ? U : T; export interface Wasabee { @@ -47,6 +48,9 @@ export interface Wasabee { agentLayerGroup: LayerGroup; zoneLayerGroup: FeatureGroup; backgroundOpsGroup: LayerGroup; + buttons: ButtonsControl; + defensiveLayers: LayerGroup; + crossLinkLayers: LayerGroup; } const Wasabee: Wasabee = window.plugin.wasabee; diff --git a/src/code/toolbox.ts b/src/code/toolbox.ts index 4709763b5..23f3e44fc 100644 --- a/src/code/toolbox.ts +++ b/src/code/toolbox.ts @@ -9,7 +9,7 @@ import { displayInfo } from "./error"; export function setupToolbox() { const toolbox = document.getElementById("toolbox"); - const aboutLink = L.DomUtil.create("a", null, toolbox); + const aboutLink = L.DomUtil.create("a", "wasabee", toolbox); aboutLink.href = "#"; aboutLink.textContent = wX("ABOUT_WASABEE"); L.DomEvent.on(aboutLink, "click", (ev) => { @@ -18,7 +18,7 @@ export function setupToolbox() { ad.enable(); }); - const settingsLink = L.DomUtil.create("a", null, toolbox); + const settingsLink = L.DomUtil.create("a", "wasabee", toolbox); settingsLink.href = "#"; settingsLink.textContent = wX("SETTINGS"); @@ -28,7 +28,7 @@ export function setupToolbox() { sd.enable(); }); - const locationLink = L.DomUtil.create("a", null, toolbox); + const locationLink = L.DomUtil.create("a", "wasabee", toolbox); locationLink.textContent = wX("SEND_LOC"); L.DomEvent.on(locationLink, "click", (ev) => { L.DomEvent.stop(ev); @@ -50,7 +50,7 @@ export function setupToolbox() { ); }); - const onlineAgentLink = L.DomUtil.create("a", null, toolbox); + const onlineAgentLink = L.DomUtil.create("a", "wasabee", toolbox); onlineAgentLink.textContent = "Teammates Online"; L.DomEvent.on(onlineAgentLink, "click", (ev) => { L.DomEvent.stop(ev); diff --git a/src/code/uiCommands.ts b/src/code/uiCommands.ts index 4f118165a..99c8ec2db 100644 --- a/src/code/uiCommands.ts +++ b/src/code/uiCommands.ts @@ -24,6 +24,9 @@ import { displayWarning, ServerError, } from "./error"; +import { deleteDatabase } from "./db"; +import { constants } from "./static"; +import type { Wasabee } from "./init"; export function addPortal(operation: WasabeeOp, portal: WasabeePortal) { if (!portal) { @@ -585,10 +588,65 @@ export function deleteLocalOp(opname: string, opid: OpID) { con.enable(); } -export async function resetCaches() { - await window.plugin.wasabee.idb.clear("agents"); - await window.plugin.wasabee.idb.clear("teams"); - await window.plugin.wasabee.idb.clear("defensivekeys"); +export function clearAllData() { + const con = new ConfirmDialog({ + title: wX("CLEAROPS BUTTON TITLE"), + label: wX("CLEAROPS PROMPT"), + type: "operation", + callback: async () => { + // remove database + deleteDatabase(); + // cleanup localStorage + for (const key of [ + constants.SELECTED_OP_KEY, + constants.OPS_LIST_KEY, + constants.OPS_LIST_HIDDEN_KEY, + constants.OPS_SHOW_HIDDEN_OPS, + constants.SEND_LOCATION_KEY, + constants.SEND_ANALYTICS_KEY, + constants.EXPERT_MODE_KEY, + constants.LANGUAGE_KEY, + constants.AGENT_INFO_KEY, + constants.MULTIMAX_UNREACHABLE_KEY, + constants.LINK_SOURCE_KEY, + constants.ANCHOR_ONE_KEY, + constants.ANCHOR_TWO_KEY, + constants.ANCHOR_THREE_KEY, + constants.PORTAL_DETAIL_RATE_KEY, + constants.SKIN_KEY, + constants.LAST_MARKER_KEY, + constants.AUTO_LOAD_FAKED, + constants.TRAWL_SKIP_STEPS, + constants.USE_PANES, + constants.SKIP_CONFIRM, + constants.SERVER_BASE_KEY, + constants.REBASE_UPDATE_KEY, + ]) { + delete localStorage[key]; + } + + const Wasabee: Wasabee = window.plugin.wasabee; + + // remove buttons + Wasabee.buttons.remove(); + + // remove toolbox + document + .querySelectorAll("#toolbox a.wasabee") + .forEach((e) => e.remove()); + + // remove layers + window.removeLayerGroup(Wasabee.portalLayerGroup); + window.removeLayerGroup(Wasabee.linkLayerGroup); + window.removeLayerGroup(Wasabee.markerLayerGroup); + window.removeLayerGroup(Wasabee.agentLayerGroup); + window.removeLayerGroup(Wasabee.zoneLayerGroup); + window.removeLayerGroup(Wasabee.backgroundOpsGroup); + window.removeLayerGroup(Wasabee.defensiveLayers); + window.removeLayerGroup(Wasabee.crossLinkLayers); + }, + }); + con.enable(); } export function setMarkersToZones() { From 1d0e59ef7846610efdc140afe688b6e91b2fedf0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 3 Jan 2022 20:47:31 +0100 Subject: [PATCH 184/275] clear data: update locales --- src/code/translations/english.json | 2 +- src/code/translations/french.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code/translations/english.json b/src/code/translations/english.json index 9b02913d1..70f55b392 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -67,7 +67,7 @@ "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Clear Data", "CLEAROPS BUTTON": "Clear Data", - "CLEAROPS PROMPT": "Clear all local OPS. Ops will be restored at next download.", + "CLEAROPS PROMPT": "Clear all local OPS. Ops will be restored at next download. Wasabee will be disabled until next page reload.", "CLOSE": "Close", "COMMENT": "Comment", "COMPLETED BY": "Completed by {agentName}", diff --git a/src/code/translations/french.json b/src/code/translations/french.json index d5939d878..55563190b 100644 --- a/src/code/translations/french.json +++ b/src/code/translations/french.json @@ -66,7 +66,7 @@ "CLEAR_EVERYTHING": "Supprimer Portails/Links et Marquers", "CLEAROPS BUTTON TITLE": "Supprimer TOUTES les données Wasabee", "CLEAROPS BUTTON": "Supprimer les données Wasabee", - "CLEAROPS PROMPT": "Toutes les opérations et données relatives à Wasabee seront supprimées de cet appareil. Seules les données présentes sur le/les serveurs seront récupérées à la prochaine synchronisation.", + "CLEAROPS PROMPT": "Toutes les opérations et données relatives à Wasabee seront supprimées de cet appareil. Seules les données présentes sur le/les serveurs seront récupérées à la prochaine synchronisation. Wasabee sera désactivé jusqu'au prochain rechargement d'IITC.", "CLOSE": "Fermer", "COMMENT": "Commentaire", "COMPLETED BY": "Fait par {agentName}", From 1ba58880b978068d779000bbc17a79f7c93588d1 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 5 Jan 2022 19:03:32 +0100 Subject: [PATCH 185/275] autodraw: ~jsdoc --- src/code/dialogs/autodraws/algorithm.ts | 31 +++++++++++++--------- src/code/dialogs/autodraws/drawRoutines.ts | 6 ++--- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/code/dialogs/autodraws/algorithm.ts b/src/code/dialogs/autodraws/algorithm.ts index e6284c049..9bdf7bfa2 100644 --- a/src/code/dialogs/autodraws/algorithm.ts +++ b/src/code/dialogs/autodraws/algorithm.ts @@ -3,8 +3,10 @@ import type WasabeePortal from "../../model/portal"; type Poset = Map; -// given two anchor, build a map that shows which and how many portals are covered by each possible field by guid -// note: a portal always covers itself +/** + given two anchor, build a map that shows which and how many portals are covered by each possible field by guid + note: a portal always covers itself +*/ export function buildPoset( anchor1: WasabeePortal, anchor2: WasabeePortal, @@ -34,14 +36,16 @@ export function buildPoset( return [posetPositive, posetNegative]; } -// given a poset, compute the maximal paths from all elements -// the result contains a map that gives for any element the next ones and the list of the elements -// that have the longest paths interface LongestSequences { children: T[]; length: number; number: number; } +/** + given a poset, compute the maximal paths from all elements + the result contains a map that gives for any element the next ones and the list of the elements + that have the longest paths +*/ function longestSequencesPoset(poset: Poset) { const alreadyCalculatedChildren = new Map< T | "__start__", @@ -82,17 +86,19 @@ function longestSequencesPoset(poset: Poset) { }; } -// given a poset, find the longest sequence p1,p2,...pk such that poset(p2) contains p1, poset(p3) contains p2 etc -// that minimizes the flight distance -// notes: -// - the result is an empty sequence only if the poset is empty or if poset(p) is empty for any p -// - if the poset is given by buildPOSet, the first element is the guid of a portal that doesn't cover any other portal, -// and the last element is the portal that covers all portals of the sequence and isn't covered by any other portal -// (inner to outer) interface LongestSequence { seq: T[]; dist: number; } +/** + given a poset, find the longest sequence p1,p2,...pk such that poset(p2) contains p1, poset(p3) contains p2 etc + that minimizes the flight distance + notes: + - the result is an empty sequence only if the poset is empty or if poset(p) is empty for any p + - if the poset is given by buildPOSet, the first element is the guid of a portal that doesn't cover any other portal, + and the last element is the portal that covers all portals of the sequence and isn't covered by any other portal + (inner to outer) +*/ export function longestSequence( poset: Poset, start?: T, @@ -142,6 +148,7 @@ export function longestSequence( .reduce((S1, S2) => (S1.dist < S2.dist ? S1 : S2)).seq; } +/** Returns longest spines from each side of the base `pOne/pTwo` */ export function getSignedSpine( pOne: WasabeePortal, pTwo: WasabeePortal, diff --git a/src/code/dialogs/autodraws/drawRoutines.ts b/src/code/dialogs/autodraws/drawRoutines.ts index 4a74a7d94..daf4a4402 100644 --- a/src/code/dialogs/autodraws/drawRoutines.ts +++ b/src/code/dialogs/autodraws/drawRoutines.ts @@ -2,7 +2,7 @@ import type WasabeeLink from "../../model/link"; import type WasabeeOp from "../../model/operation"; import type WasabeePortal from "../../model/portal"; -// get the list of links from a spine to anchors +/** Return the description of links for the given spine */ function getSpineLinks( anchor1: WasabeePortal, anchor2: WasabeePortal, @@ -27,7 +27,7 @@ function getSpineLinks( return linksDesc; } -// insert an array of wasabee link into an draw after the given order +/** Insert in `op` the links after the order `order` */ export function insertLinks( op: WasabeeOp, links: WasabeeLink[], @@ -44,7 +44,7 @@ export function insertLinks( return order; } -// draw a spine into an op, with order and comment +/** Insert a spine in `op` after order `order` */ export function drawSpine( op: WasabeeOp, anchor1: WasabeePortal, From b77980b39a5de19c0a71eec6f4ba57e93fe6f808 Mon Sep 17 00:00:00 2001 From: Scot Bontrager Date: Wed, 5 Jan 2022 19:59:12 -0600 Subject: [PATCH 186/275] moved to org level repo --- .github/FUNDING.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index f7f53b97c..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -custom: ['https://www.patreon.com/wasabee'] From df8e49fb07a0dd0083a3013e8a3ae223f45c578f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 6 Jan 2022 09:50:38 +0100 Subject: [PATCH 187/275] fix: flipflop init portal set --- src/code/dialogs/autodraws/flipflop.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code/dialogs/autodraws/flipflop.js b/src/code/dialogs/autodraws/flipflop.js index ab1503e1e..f960345ae 100644 --- a/src/code/dialogs/autodraws/flipflop.js +++ b/src/code/dialogs/autodraws/flipflop.js @@ -60,6 +60,7 @@ const FlipFlopDialog = AutoDraw.extend({ addHooks: function () { AutoDraw.prototype.addHooks.call(this); this._displayDialog(); + this._updatePortalSet(); }, _buildContent: function () { From 43edf41ce251a4220f86a13eb7f9f0ab920e95aa Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 6 Jan 2022 09:50:51 +0100 Subject: [PATCH 188/275] fix: flip flop strings --- src/code/dialogs/autodraws/flipflop.js | 4 ++-- src/code/translations/english.json | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/code/dialogs/autodraws/flipflop.js b/src/code/dialogs/autodraws/flipflop.js index f960345ae..3673eaf2c 100644 --- a/src/code/dialogs/autodraws/flipflop.js +++ b/src/code/dialogs/autodraws/flipflop.js @@ -90,10 +90,10 @@ const FlipFlopDialog = AutoDraw.extend({ // Go button const button = L.DomUtil.create("button", "drawb", container); - button.textContent = wX("DRAW"); + button.textContent = wX("autodraw.common.draw_button"); L.DomEvent.on(button, "click", () => { const total = this.doFanGun(); - displayInfo(`Flip flop: found ${total} links`); + displayInfo(wX("autodraw.flipflop.result", { count: total })); }); return container; diff --git a/src/code/translations/english.json b/src/code/translations/english.json index 571e7037f..43ebdd4a2 100644 --- a/src/code/translations/english.json +++ b/src/code/translations/english.json @@ -46,6 +46,8 @@ "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", "AUTODRAW_PORTALS_SET": "Portals", + "autodraw.common.draw_button": "Draw", + "autodraw.flipflop.result": "Flip flop: found {count} links", "autodraw.onion.variant": "Option", "autodraw.onion.variant.equilateral": "~Equilateral", "autodraw.onion.variant.grow": "Let it grow", From e6e3e8c2b9c3a22da6ec796b96fd3686e2c5f517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20-=20fisher01?= Date: Thu, 6 Jan 2022 13:51:27 +0100 Subject: [PATCH 189/275] Add Crowdin configuration file (#311) * Update Crowdin configuration file --- crowdin.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 crowdin.yml diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..1671e189d --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: /src/code/translations/english.json + translation: /src/code/translations/%language%.json From 72a6e5ca5f39a55b0d03a0d1382a188663e1ca3c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 6 Jan 2022 18:55:59 +0100 Subject: [PATCH 190/275] crowdin: title case for languages --- crowdin.yml | 2 +- src/code/static.ts | 16 +++++++++------- .../translations/{danish.json => Danish.json} | 0 .../translations/{english.json => English.json} | 0 .../{filipino.json => Filipino.json} | 0 .../translations/{french.json => French.json} | 0 .../translations/{german.json => German.json} | 0 .../translations/{italian.json => Italian.json} | 0 .../{portuguese.json => Portuguese.json} | 0 .../translations/{russian.json => Russian.json} | 0 .../translations/{spanish.json => Spanish.json} | 0 11 files changed, 10 insertions(+), 8 deletions(-) rename src/code/translations/{danish.json => Danish.json} (100%) rename src/code/translations/{english.json => English.json} (100%) rename src/code/translations/{filipino.json => Filipino.json} (100%) rename src/code/translations/{french.json => French.json} (100%) rename src/code/translations/{german.json => German.json} (100%) rename src/code/translations/{italian.json => Italian.json} (100%) rename src/code/translations/{portuguese.json => Portuguese.json} (100%) rename src/code/translations/{russian.json => Russian.json} (100%) rename src/code/translations/{spanish.json => Spanish.json} (100%) diff --git a/crowdin.yml b/crowdin.yml index 1671e189d..7be7d6980 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,3 +1,3 @@ files: - - source: /src/code/translations/english.json + - source: /src/code/translations/English.json translation: /src/code/translations/%language%.json diff --git a/src/code/static.ts b/src/code/static.ts index ae799befb..dde9e16f6 100644 --- a/src/code/static.ts +++ b/src/code/static.ts @@ -89,13 +89,15 @@ const statics: Statics = { }; statics.strings = {}; // empty object, fill it below -statics.strings["Deutsch"] = require("./translations/german.json"); -statics.strings["Espanol"] = require("./translations/spanish.json"); -statics.strings["English"] = require("./translations/english.json"); -statics.strings["Italiano"] = require("./translations/italian.json"); -statics.strings["Tagalog"] = require("./translations/filipino.json"); -statics.strings["Français"] = require("./translations/french.json"); -statics.strings["Português"] = require("./translations/portuguese.json"); +statics.strings["Deutsch"] = require("./translations/German.json"); +statics.strings["Espanol"] = require("./translations/Spanish.json"); +statics.strings["English"] = require("./translations/English.json"); +statics.strings["Italiano"] = require("./translations/Italian.json"); +statics.strings["Tagalog"] = require("./translations/Filipino.json"); +statics.strings["Français"] = require("./translations/French.json"); +statics.strings["Português"] = require("./translations/Portuguese.json"); +statics.strings["Русский"] = require("./translations/Russian.json"); +statics.strings["Dansk"] = require("./translations/Danish.json"); statics.defaultOperationColor = "orange"; diff --git a/src/code/translations/danish.json b/src/code/translations/Danish.json similarity index 100% rename from src/code/translations/danish.json rename to src/code/translations/Danish.json diff --git a/src/code/translations/english.json b/src/code/translations/English.json similarity index 100% rename from src/code/translations/english.json rename to src/code/translations/English.json diff --git a/src/code/translations/filipino.json b/src/code/translations/Filipino.json similarity index 100% rename from src/code/translations/filipino.json rename to src/code/translations/Filipino.json diff --git a/src/code/translations/french.json b/src/code/translations/French.json similarity index 100% rename from src/code/translations/french.json rename to src/code/translations/French.json diff --git a/src/code/translations/german.json b/src/code/translations/German.json similarity index 100% rename from src/code/translations/german.json rename to src/code/translations/German.json diff --git a/src/code/translations/italian.json b/src/code/translations/Italian.json similarity index 100% rename from src/code/translations/italian.json rename to src/code/translations/Italian.json diff --git a/src/code/translations/portuguese.json b/src/code/translations/Portuguese.json similarity index 100% rename from src/code/translations/portuguese.json rename to src/code/translations/Portuguese.json diff --git a/src/code/translations/russian.json b/src/code/translations/Russian.json similarity index 100% rename from src/code/translations/russian.json rename to src/code/translations/Russian.json diff --git a/src/code/translations/spanish.json b/src/code/translations/Spanish.json similarity index 100% rename from src/code/translations/spanish.json rename to src/code/translations/Spanish.json From b1b69d28a4333ea562c7b5729afc076384a03469 Mon Sep 17 00:00:00 2001 From: Sebastien - fisher01 Date: Thu, 6 Jan 2022 13:14:40 -0500 Subject: [PATCH 191/275] Add Crowdin badge in README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f09f4bd9e..d3965e852 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ![GitHub issues](https://img.shields.io/github/issues/wasabee-project/Wasabee-IITC.svg) [![Build Status](https://travis-ci.org/wasabee-project/Wasabee-IITC.svg?branch=master)](https://travis-ci.org/wasabee-project/Wasabee-IITC) [![Releases](https://img.shields.io/github/v/release/wasabee-project/Wasabee-IITC)](https://github.com/wasabee-project/Wasabee-IITC/releases) +[![Crowdin](https://badges.crowdin.net/wasabee-iitc/localized.svg)](https://crowdin.com/project/wasabee-iitc) # Wasabee From e24e509106aa0c47cc05cb47f7d883f3d81afa7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20-=20fisher01?= Date: Thu, 6 Jan 2022 20:11:31 +0100 Subject: [PATCH 192/275] New Crowdin updates (#315) * New translations English.json (Spanish) * New translations English.json (Danish) * New translations English.json (German) * New translations English.json (Italian) * New translations English.json (Portuguese) * New translations English.json (Filipino) * New translations English.json (French) * New translations English.json (Russian) --- src/code/translations/Danish.json | 37 ++++++++++++++++-- src/code/translations/Filipino.json | 15 +++++++- src/code/translations/French.json | 43 +++++++++++++-------- src/code/translations/German.json | 17 ++++++++- src/code/translations/Italian.json | 13 +++++++ src/code/translations/Portuguese.json | 55 +++++++++++++++++---------- src/code/translations/Russian.json | 35 +++++++++++++++-- src/code/translations/Spanish.json | 17 ++++++++- 8 files changed, 184 insertions(+), 48 deletions(-) diff --git a/src/code/translations/Danish.json b/src/code/translations/Danish.json index a9398e42e..2df7fe590 100644 --- a/src/code/translations/Danish.json +++ b/src/code/translations/Danish.json @@ -31,7 +31,7 @@ "API_KEY": " api key: ", "ASS_TO": "Tildelt", "ASSIGN LINK PROMPT": "Tilføj link fra: {portalName}", - "ASSIGN MARKER PROMPT": "Tildel markør fra: {portalName}", + "ASSIGN MARKER PROMPT": "Tildel markør fra: {portalName}", "ASSIGN OUTBOUND PROMPT": "Tildel alle udgående links fra: {portalName}", "ASSIGN OUTBOUND": "Tildel udgående links", "ASSIGN": "Tildel", @@ -45,11 +45,18 @@ "AUTH_SELECT_ACCOUNT": "Vælg konto", "AUTO_DRAWS": "Auto-tegne", "AUTODRAWS": "Wasabee Indstillinger for automatisk tegning", + "AUTODRAW_PORTALS_SET": "Portals", + "autodraw.common.draw_button": "Draw", + "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.onion.variant": "Option", + "autodraw.onion.variant.equilateral": "~Equilateral", + "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.balanced": "Perfectly balanced", "AUTOLOAD_RATE": "Rate for anmodning om portaldetaljer (ms)", "AUTOLOAD": "Indlæs automatisk manglende portaloplysninger", "AUTOMARK STOP": "Auto-markering stoppede på grund af, at portaler ikke blev indlæst", "AUTOMARK": "Auto-mærke", - "BAT_TOAD": "Battle Toads/manglende oversættelse", + "BAT_TOAD": "Battle Toads/manglende oversættelse", "BLOCKER LIST TITLE": "Vis alle blokkere", "BLOCKER TITLE": "Blokere", "CANCEL": "Annuller", @@ -63,6 +70,7 @@ "CLEAR LINKS": "Ryd links", "CLEAR MARKERS": "Ryd markører", "CLEAR_EVERYTHING": "Ryd portaler/links/markører for aktuel OP", + "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Ryd Data", "CLEAROPS BUTTON": "Ryd Data", "CLEAROPS PROMPT": "Ryd alle lokale OPS. Ops vil blive gendannet ved næste download.", @@ -97,6 +105,11 @@ "FANFIELD": "Tegn", "FANFIELD2": "Tegne Fan Field", "FarmPortalMarker": "Farm", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "fra basislinie 1-2", "FROM_1-3": "fra basislinie 1-3", "FROM_2-3": "fra basislinie 2-3", @@ -176,6 +189,12 @@ "MIN_SRC_PORT_LVL": "Minimums level påkrævet på kildeportalen", "MINUTES": " ({minutes} minutter siden)", "MM": "Multimax", + "MM_BOTH_SIDE": "Use both base sides", + "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Tegn Max Lag", "MULTI_M": "Tegn", "MUST_NOT_BE_EMPTY": "Må ikke være tom", @@ -193,8 +212,11 @@ "NO_LABEL": "Ingen etiket sat", "NO_STOCK_INTEL": "Wasabee understøtter ikke stock intel tegninger", "NO_TITLE": "Ingen titel angivet", + "NO LONGER AVAILABLE": "Resource removed from server: {error}", + "NO LONGER AVAILABLE SHORT": "Resource removed from server", "NOT LOGGED IN SHORT": "Ikke logget ind", "NOT LOGGED IN": "Ikke logget ind: {error}", + "NOT_LOADED": "Not fully loaded, try again.", "NOT_SET": "ikke indstillet", "NTNAME": "Navn", "OK": "OK", @@ -220,6 +242,8 @@ "OtherPortalAlert": "Andet", "PASTE_INSTRUCT": "Indsæt en Wasabee draw-eksport her.\n\nWasabee kan ikke importere stock intel-formatet.\n\nDer er eksperimentel understøttelse af import af IITC DrawTools-formatet.\n\nFør du importerer DrawTools-formatet, skal du forhåndsvise områderne og sørge for, at alle portalerne indlæses så IITC har dem cachelagret. Alle portaler, der ikke er pre-cached, vil blive forfalsket.\n\nDu bliver nødt til at bruge 'swap'-funktionen til at flytte ankre fra de falske portaler til de rigtige portaler (de bør være på den korrekte placering, bare ikke forbundet med portal.\n\nCachede portaler er muligvis ikke korrekt navngivet.", "pending": "Afventer", + "PERM DENIED": "Permission denied: {error}", + "PERM DENIED SHORT": "Permission denied", "PERMS": "{opName} tilladelser", "PLEASE_SELECT_PORTAL": "Vælg venligst en portal", "PORT_FAKE": " portaler. Forfalsket ", @@ -319,6 +343,11 @@ "TEAMS BUTTON TITLE": "Liste over Wasabee-holdene", "TEAMS BUTTON": "Hold", "TO_PORT": "Til Portal", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip fliser", "TRAWL TITLE": "Trawl baner", "TRAWL WARNING": "Dette vil indlæse flisedataene under alle tegnede links. Dette er en langsom proces.", @@ -334,13 +363,13 @@ "UNKNOWN": "Ukendt", "UPDATE HOVER NOT CHANGED": "{opName} ikke ændret lokalt", "UPDATE HOVER": "OPDATER {opName} på serveren", + "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "OP er blevet ændret på serveren siden sidste synkronisering. Ønsker du at erstatte serverversionen med den nuværende?", "UPDATE_CONFLICT_TITLE": "Konflikt opdaget med server", "UPDATE_COUNT": "Opdater optælling", "UPDATED": "Opdateret", "UpgradePortalAlert": "Upgrader", "UPLOAD BUTTON HOVER": "UPLOAD {opName} (ikke på serveren i øjeblikket)", - "UPLOAD PERM DENIED": "Tilladelse til at uploade nægtet", "UPLOADED": "Uploadet", "USE PANES ON MOBILE": "Brug rammer (skal genindlæses)", "USE_SWAP_INSTRUCT": ". Brug venligst swap-funktionen til at flytte falske portaler til de rigtige portaler på samme sted. Zoom ind på 'Loading'-portalerne i tjeklisten kan tvinge dem til at indlæse.", @@ -387,4 +416,4 @@ "TEAMS BUTTON": "Hold", "WD BUTTON": "W-D Nøgler" } -} +} \ No newline at end of file diff --git a/src/code/translations/Filipino.json b/src/code/translations/Filipino.json index 080b617bf..b80b7c071 100644 --- a/src/code/translations/Filipino.json +++ b/src/code/translations/Filipino.json @@ -46,6 +46,12 @@ "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", "AUTODRAW_PORTALS_SET": "Portals", + "autodraw.common.draw_button": "Draw", + "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.onion.variant": "Option", + "autodraw.onion.variant.equilateral": "~Equilateral", + "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.balanced": "Perfectly balanced", "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", "AUTOLOAD": "Automatically Load Missing Portal Details", "AUTOMARK STOP": "Itinigil ang pag Auto-Mark dahil hindi maiload ang mga portals", @@ -64,6 +70,7 @@ "CLEAR LINKS": "Clear Links", "CLEAR MARKERS": "Clear Markers", "CLEAR_EVERYTHING": "Burahin Portals/Links/Markers", + "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Burahin lahat ng locally stored na operasyon", "CLEAROPS BUTTON": "Burahin Local Ops", "CLEAROPS PROMPT": "Nais mo bang tangalin ang lahat ng opersyon sa local storage? Ang mga Ops na nakalagay sa server ay mababawi sa susunod na sync.", @@ -182,6 +189,7 @@ "MIN_SRC_PORT_LVL": "Pinakamababang level kailangan sa on panimulang portal", "MINUTES": " ({minutes} minutong nakalipas)", "MM": "Multimax", + "MM_BOTH_SIDE": "Use both base sides", "MM_INSERT_ORDER": "Insert at the end", "MM_SET_ALL_PORTALS": "All visible portals", "MM_SET_ALL_KEYS": "All GetKey Markers", @@ -335,6 +343,11 @@ "TEAMS BUTTON TITLE": "I-Lista mga Wasabee Pangkat", "TEAMS BUTTON": "Pangkat", "TO_PORT": "Papunta sa Portal", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", @@ -403,4 +416,4 @@ "TEAMS BUTTON": "Teams", "WD BUTTON": "W-D Keys" } -} +} \ No newline at end of file diff --git a/src/code/translations/French.json b/src/code/translations/French.json index 55563190b..697e71b71 100644 --- a/src/code/translations/French.json +++ b/src/code/translations/French.json @@ -10,7 +10,7 @@ "ADD_MARKER": "+ Marqueur", "ADD_NEW_OP": "Ajouter une nouvelle opé", "ADD_SUCC_INSTR": "L'agent a bien été ajouté à l'équipe. Il doit maintenant l'activer pour pouvoir être affecté à des actions sur les OPs de l'équipe.", - "ADD_ZONE": "Add Zone", + "ADD_ZONE": "Ajouter une zone", "ADD": "Ajouter", "ADD1": "Ajouter le premier lien", "ADD2": "Ajouter le second lien", @@ -20,7 +20,7 @@ "ALREADY_HAS_MARKER": "Ce portail porte déjà un marqueur. Choissisez un autre portail.", "AMAZ_TEAM_NAME": "Nom de l'équipe", "ANCHOR ASSIGNMENT": "tous les liens sortants", - "ANCHOR_GMAP": "Google Map", + "ANCHOR_GMAP": "Google Maps", "ANCHOR_PORTAL": "Portail Ancre", "ANCHOR_PORTAL2": "Portail Ancre 2", "ANCHOR_PORTAL3": "Portail Ancre 3", @@ -45,7 +45,13 @@ "AUTH_SELECT_ACCOUNT": "Sélectionner le compte", "AUTO_DRAWS": "Auto-Draw", "AUTODRAWS": "Choix d'Auto-draw", - "AUTODRAW_PORTALS_SET": "Portals", + "AUTODRAW_PORTALS_SET": "Portails", + "autodraw.common.draw_button": "Draw", + "autodraw.flipflop.result": "Flip flop: {count} liens trouvés", + "autodraw.onion.variant": "Variante", + "autodraw.onion.variant.equilateral": "~Équilatéral", + "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.balanced": "Équilibré", "AUTOLOAD_RATE": "Délai entre deux requêtes", "AUTOLOAD": "Charger automatiquement les données manquantes de portails", "AUTOMARK STOP": "Le processus d'Auto-Mark s'est arrêté suite à l'absence de donnée pour certains portails.", @@ -55,7 +61,7 @@ "BLOCKER TITLE": "Bloquants", "CANCEL": "Annuler", "CAPSULE": "Capsule", - "CapturePortalMarker": "Capture", + "CapturePortalMarker": "Capturer", "CHANGE SERVER PROMPT": "Nouveau serveur Wasabee", "CHANGE SERVER": "Changer de serveur", "CHANGE_WAS_SERVER": "Changer de serveur Wasabee", @@ -64,6 +70,7 @@ "CLEAR LINKS": "Supprimer les liens", "CLEAR MARKERS": "Supprimer les marqueurs", "CLEAR_EVERYTHING": "Supprimer Portails/Links et Marquers", + "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Supprimer TOUTES les données Wasabee", "CLEAROPS BUTTON": "Supprimer les données Wasabee", "CLEAROPS PROMPT": "Toutes les opérations et données relatives à Wasabee seront supprimées de cet appareil. Seules les données présentes sur le/les serveurs seront récupérées à la prochaine synchronisation. Wasabee sera désactivé jusqu'au prochain rechargement d'IITC.", @@ -96,10 +103,10 @@ "EXPORT": "Exporter : ", "FAKED": "Faux [{portalId}]", "FANFIELD": "Draw", - "FANFIELD2": "Draw Fan Field", + "FANFIELD2": "Fan Field", "FarmPortalMarker": "Farm", - "FLIP_FLOP_NAME": "Flip flop", - "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_NAME": "Flip Flop", + "FLIP_FLOP_TITLE": "Flip Flop", "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", @@ -182,11 +189,12 @@ "MIN_SRC_PORT_LVL": "Level minimum requis pour le portail source", "MINUTES": "(il y a {minutes} minute(s))", "MM": "Multimax", - "MM_INSERT_ORDER": "Insert at the end", - "MM_SET_ALL_PORTALS": "All visible portals", - "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_BOTH_SIDE": "Utiliser les deux côtés de la base", + "MM_INSERT_ORDER": "Insérer à la fin", + "MM_SET_ALL_PORTALS": "Tous les portails visibles", + "MM_SET_ALL_KEYS": "Tous les marqueurs GetKey", "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", - "MM_SPINE": "Spine", + "MM_SPINE": "Alignement", "MULTI_M_TITLE": "Dessiner le maximum de couches", "MULTI_M": "Draw", "MUST_NOT_BE_EMPTY": "Ne dois pas être vide", @@ -211,7 +219,7 @@ "NOT_LOADED": "N'a pas chargé entierement, essayer à nouveau", "NOT_SET": "non défini", "NTNAME": "Nom", - "OK": "OK", + "OK": "Ok", "ON_HAND": "En main", "ONION_WAS_TAKEN": "Oignon", "ONION": "Draw", @@ -256,7 +264,7 @@ "READ_SHORT": "RO", "READ": "lire", "RechargePortalAlert": "Recharge", - "REFERENCE_TIME": "Reference Time: ", + "REFERENCE_TIME": "Temps de référence : ", "REM_LOC_CP": "Supprimer la copie locale de {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Voulez vous vraiment supprimer {teamName} du serveur Wasabee ?", "REMOVE_TEAM_CONFIRM_TITLE": "supprimer l'équipe {teamName}", @@ -335,6 +343,11 @@ "TEAMS BUTTON TITLE": "Liste des équipes", "TEAMS BUTTON": "Équipes", "TO_PORT": "Vers le portail", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Fouille des bloquants", "TRAWL WARNING": "Ceci va charger les tuiles de données sous les liens dessinés. C'est un processus lent.", @@ -350,13 +363,13 @@ "UNKNOWN": "Inconnu", "UPDATE HOVER NOT CHANGED": "{opName} n'a pas changé localement", "UPDATE HOVER": "Mettre à jour {opName} sur le serveur", + "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "L'opération a été modifié sur le serveur depuis la dernière synchronisation. Voulez-vous écraser la version du serveur par la votre ?", "UPDATE_CONFLICT_TITLE": "Conflit avec le serveur", "UPDATE_COUNT": "Nombre mis un jour", "UPDATED": "Mise à jour reussi", "UpgradePortalAlert": "Upgrade", "UPLOAD BUTTON HOVER": "Envoyer {opName} au serveur", - "UPLOAD PERM DENIED": "Permission d'upload refusée", "UPLOADED": "Envoi reussi", "USE PANES ON MOBILE": "Use panes (need reload)", "USE_SWAP_INSTRUCT": " faux portails ajoutés. Utilisez la fonction de Swap pour placer les faux portails ceux existants (au même positions). Zoomer sur les portails en chargement dans la checklist devrait permettre d'obtenir leurs informations manquantes.", @@ -403,4 +416,4 @@ "TEAMS BUTTON": "Équipe", "WD BUTTON": "Clés W-D" } -} +} \ No newline at end of file diff --git a/src/code/translations/German.json b/src/code/translations/German.json index 9a9bbd2e1..20c458869 100644 --- a/src/code/translations/German.json +++ b/src/code/translations/German.json @@ -46,6 +46,12 @@ "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", "AUTODRAW_PORTALS_SET": "Portals", + "autodraw.common.draw_button": "Draw", + "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.onion.variant": "Option", + "autodraw.onion.variant.equilateral": "~Equilateral", + "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.balanced": "Perfectly balanced", "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", "AUTOLOAD": "Automatically Load Missing Portal Details", "AUTOMARK STOP": "Automatische Markierung gestoppt - Portale nicht vollständig geladen.", @@ -64,6 +70,7 @@ "CLEAR LINKS": "Clear Links", "CLEAR MARKERS": "Clear Markers", "CLEAR_EVERYTHING": "Clear Portals/Links/Markers for current OP", + "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Lösche alle Wasabee Daten", "CLEAROPS BUTTON": "Lösche Wasabee Daten", "CLEAROPS PROMPT": "Das wird alle Wasabee Daten Löschen. Bei dem nächsten Sync wird alles wiederhergestellt.", @@ -182,6 +189,7 @@ "MIN_SRC_PORT_LVL": "Minimum level required on source portal", "MINUTES": "vor ({minutes} Minuten)", "MM": "Maximale Feldanzahl", + "MM_BOTH_SIDE": "Use both base sides", "MM_INSERT_ORDER": "Insert at the end", "MM_SET_ALL_PORTALS": "All visible portals", "MM_SET_ALL_KEYS": "All GetKey Markers", @@ -335,6 +343,11 @@ "TEAMS BUTTON TITLE": "Auflistung Wasabee Teams", "TEAMS BUTTON": "Teams", "TO_PORT": "zu Portal", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", @@ -350,13 +363,13 @@ "UNKNOWN": "Unbekannt", "UPDATE HOVER NOT CHANGED": "{opName} lokal nicht verändert", "UPDATE HOVER": "UPDATE {opName} auf dem Server", + "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "The OP has been modified on server since last sync. Do you want to replace the server version by the current one?", "UPDATE_CONFLICT_TITLE": "Conflict detected with server", "UPDATE_COUNT": "Aktualisiere Anzahl", "UPDATED": "Erfolgreich aktualisiert", "UpgradePortalAlert": "Upgrade", "UPLOAD BUTTON HOVER": "UPLOAD {opName} (aktuell nicht auf dem Server)", - "UPLOAD PERM DENIED": "Keine Berechtigung zum hochladen", "UPLOADED": "Erfolgreich hochgeladen", "USE PANES ON MOBILE": "Use panes (need reload)", "USE_SWAP_INSTRUCT": ".Bitte nutze die Wechsel Funktion, um das verfälschte Portal mit dem korrekten Portal, um Fehler zu beseitigen.", @@ -403,4 +416,4 @@ "TEAMS BUTTON": "Teams", "WD BUTTON": "W-D Keys" } -} +} \ No newline at end of file diff --git a/src/code/translations/Italian.json b/src/code/translations/Italian.json index 39a3ed79f..c48e38632 100644 --- a/src/code/translations/Italian.json +++ b/src/code/translations/Italian.json @@ -46,6 +46,12 @@ "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Opzioni Wasabee Auto-draw", "AUTODRAW_PORTALS_SET": "Portals", + "autodraw.common.draw_button": "Draw", + "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.onion.variant": "Option", + "autodraw.onion.variant.equilateral": "~Equilateral", + "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.balanced": "Perfectly balanced", "AUTOLOAD_RATE": "Frequenza Richiesta dettagli Portali (ms)", "AUTOLOAD": "Carica Automaticamente Dettagli dei Portali Mancanti", "AUTOMARK STOP": "Auto-Mark interrotto, i portali non sono caricati", @@ -64,6 +70,7 @@ "CLEAR LINKS": "Elimina Link", "CLEAR MARKERS": "Elimina Marker", "CLEAR_EVERYTHING": "Elimina tutti i Portali/Link/Marker", + "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Elimina TUTTI i dati di Wasabee", "CLEAROPS BUTTON": "Elimina i dati di Wasabee", "CLEAROPS PROMPT": "Questo eliminerà tutte le OP e i dati relativi a Wasabee. Saranno ripristinati alla prossima sincronizzazione.", @@ -182,6 +189,7 @@ "MIN_SRC_PORT_LVL": "Livello minimo richiesto sul portale d'origine", "MINUTES": " ({minutes} minuti fa)", "MM": "Multimax", + "MM_BOTH_SIDE": "Use both base sides", "MM_INSERT_ORDER": "Insert at the end", "MM_SET_ALL_PORTALS": "All visible portals", "MM_SET_ALL_KEYS": "All GetKey Markers", @@ -335,6 +343,11 @@ "TEAMS BUTTON TITLE": "Lista Team Wasabee", "TEAMS BUTTON": "Team", "TO_PORT": "Al Portale", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Controllo corridoi", "TRAWL WARNING": "Verranno caricati i dati delle tile sotto i link disegnati. Sarà un processo lento.", diff --git a/src/code/translations/Portuguese.json b/src/code/translations/Portuguese.json index 845f020b4..5f8d94eb5 100644 --- a/src/code/translations/Portuguese.json +++ b/src/code/translations/Portuguese.json @@ -46,6 +46,12 @@ "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Opções", "AUTODRAW_PORTALS_SET": "Portals", + "autodraw.common.draw_button": "Draw", + "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.onion.variant": "Option", + "autodraw.onion.variant.equilateral": "~Equilateral", + "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.balanced": "Perfectly balanced", "AUTOLOAD_RATE": "Taxa de solicitação de detalhes do portal (ms)", "AUTOLOAD": "Carregar automaticamente os detalhes do portal em falta", "AUTOMARK STOP": "Auto-Marcar interrompido devido a portais não serem carregados", @@ -64,6 +70,7 @@ "CLEAR LINKS": "Limpar Links", "CLEAR MARKERS": "Limpar Markers", "CLEAR_EVERYTHING": "limpar Portais/Links/Marcadores", + "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "limpar TODOS os dados Wasabee", "CLEAROPS BUTTON": "Limpar dados Wasabee", "CLEAROPS PROMPT": "Isto limpará todas as OPS e dados relacionados a Wasabee. Tudo será restaurado apartir do servidor na próxima sincronização.", @@ -182,6 +189,7 @@ "MIN_SRC_PORT_LVL": "Nível mínimo exigido no portal de origem", "MINUTES": " (${value} minutos atrás)", "MM": "Multimax", + "MM_BOTH_SIDE": "Use both base sides", "MM_INSERT_ORDER": "Insert at the end", "MM_SET_ALL_PORTALS": "All visible portals", "MM_SET_ALL_KEYS": "All GetKey Markers", @@ -335,6 +343,11 @@ "TEAMS BUTTON TITLE": "Listar equipas Wasabee", "TEAMS BUTTON": "Equipas", "TO_PORT": "Para o Portal", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "Isto carregará os dados do bloco em todos os links desenhados. Este é um processo lento.", @@ -350,13 +363,13 @@ "UNKNOWN": "Desconhecido", "UPDATE HOVER NOT CHANGED": "${value} não mudou localmente", "UPDATE HOVER": "UPDATE ${value} no servidor", + "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "A OP foi modificada no servidor desde a última sincronização. Queres substituir a versão do servidor pela atual?", "UPDATE_CONFLICT_TITLE": "Conflito detectado com o servidor", "UPDATE_COUNT": "Contagem de atualização", "UPDATED": "Atualizado com sucesso", "UpgradePortalAlert": "Upgrade", "UPLOAD BUTTON HOVER": "UPLOAD ${value} (atualmente não está no servidor)", - "UPLOAD PERM DENIED": "Permissão para upload negada", "UPLOADED": "Carregado com sucesso", "USE PANES ON MOBILE": "Use panes (need reload)", "USE_SWAP_INSTRUCT": ". Usa o recurso de troca para mover portais falsos para portais reais no mesmo local. Ampliar os portais 'Carregando' na lista de verificação pode forçá-los a carregar.", @@ -377,30 +390,30 @@ "ZONE_DRAW": "Click to set the zone boundaries", "ZONE": "Zone", "smallScreen": { + "ADD_LINKS": "+ Links", + "ADD_MARKER": "+ Marcador", + "BLOCKER TITLE": "Blockers", + "CHECKLIST BUTTON": "Verificar", + "CLEAROPS BUTTON": "Limpar", + "EXPORT OP": "Exportar", + "FAN_FIELD3": "Fan", + "FANFIELD": "Desenhar", + "FANFIELD2": "Desenhar Fan Field", + "KEYS": "Chaves", "LOG IN": "Log In", "LOG_OUT": "Log Out", - "NEWOP BUTTON": "Nova Op", - "CLEAROPS BUTTON": "Limpar", - "TEAMS BUTTON": "Equipas", - "WD BUTTON": "W-D Chaves", - "OPS BUTTON": "Ops", - "CHECKLIST BUTTON": "Verificar", "MARKER LIST": "Marcadores", - "BLOCKER TITLE": "Blockers", - "KEYS": "Chaves", - "EXPORT OP": "Exportar", - "QD END": "Fim", - "ADD_LINKS": "+ Links", + "MARKERS BUTTON TITLE": "Marcadores", + "MAX": "Fan", "MM": "Multi", - "MULTI_M": "Desenhar", "MULTI_M_TITLE": "Desenhar Maximo de Layers", - "STARBURST": "Estrela", + "MULTI_M": "Desenhar", + "NEWOP BUTTON": "Nova Op", + "OPS BUTTON": "Ops", + "QD END": "Fim", "STARBURST_DRAW": "Desenhar", - "ADD_MARKER": "+ Marcador", - "MARKERS BUTTON TITLE": "Marcadores", - "FAN_FIELD3": "Fan", - "FANFIELD": "Desenhar", - "FANFIELD2": "Desenhar Fan Field", - "MAX": "Fan" + "STARBURST": "Estrela", + "TEAMS BUTTON": "Equipas", + "WD BUTTON": "W-D Chaves" } -} +} \ No newline at end of file diff --git a/src/code/translations/Russian.json b/src/code/translations/Russian.json index a453ff8d9..b34f1596d 100644 --- a/src/code/translations/Russian.json +++ b/src/code/translations/Russian.json @@ -20,7 +20,7 @@ "ALREADY_HAS_MARKER": "У этого портала уже есть маркер. Выбери другой портал.", "AMAZ_TEAM_NAME": "Отличное название.", "ANCHOR ASSIGNMENT": " все исходящие линки", - "ANCHOR_GMAP": "Google Map", + "ANCHOR_GMAP": "Google-карты", "ANCHOR_PORTAL": "Опорный портал ", "ANCHOR_PORTAL2": "Опорный портал 2", "ANCHOR_PORTAL3": "Опорный портал 3", @@ -35,7 +35,7 @@ "ASSIGN OUTBOUND PROMPT": "Назначить все исходящие линки с {portalName}", "ASSIGN OUTBOUND": "Назначить исходящие линки", "ASSIGN": "Назначить", - "ASSIGNED_ONLY_SHORT": "AO", + "ASSIGNED_ONLY_SHORT": "Назначенные", "ASSIGNED_ONLY": "Только назначенные", "assigned": "Назначено", "AUTH INCOMPAT": "Ты активировал в TamperMonkey плагин, который несовместим с Wasabee", @@ -45,6 +45,13 @@ "AUTH_SELECT_ACCOUNT": "Выбери аккаунт", "AUTO_DRAWS": "Авто-рисовка", "AUTODRAWS": "Опции авто-рисовки Wasabee", + "AUTODRAW_PORTALS_SET": "Порталы", + "autodraw.common.draw_button": "Нарисовать", + "autodraw.flipflop.result": "Flip flop: найдено {count} линков", + "autodraw.onion.variant": "Опции", + "autodraw.onion.variant.equilateral": "~Равносторонний", + "autodraw.onion.variant.grow": "Пусть растет", + "autodraw.onion.variant.balanced": "Безупречный баланс", "AUTOLOAD_RATE": "Скорость запроса данных портала (ms)", "AUTOLOAD": "Автоматически загружать недостающие данные портала", "AUTOMARK STOP": "Авто-маркировка остановлена, т.к. порталы не были загружены", @@ -63,6 +70,7 @@ "CLEAR LINKS": "Удалить линки", "CLEAR MARKERS": "Удалить маркеры", "CLEAR_EVERYTHING": "Удалить порталы/линки/маркеры для текущей ОПРЦ", + "CLEAR": "Очистить выбор", "CLEAROPS BUTTON TITLE": "Удалить данные", "CLEAROPS BUTTON": "Удалить данные", "CLEAROPS PROMPT": "Удалить все локальные ОПРЦ. ОПРЦ будут восстановлены при следующей загрузке.", @@ -97,6 +105,11 @@ "FANFIELD": "Нарисовать", "FANFIELD2": "Нарисовать Fan Field", "FarmPortalMarker": "Отфармить", + "FLIP_FLOP_NAME": "Flip flop", + "FLIP_FLOP_TITLE": "Flip flop", + "FLIP_FLOP_DESC": "Исходя из заданного опорника, видимых порталов и количества SBUL, найти fanfield, в котором очередность перенавеса с опорника будет идти по уменьшению длины линков для того, чтобы избежать поиска ключей.", + "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", + "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", "FROM_1-2": "от опорного линка 1-2", "FROM_1-3": "от опорного линка 1-3", "FROM_2-3": "от опорного линка 2-3", @@ -176,6 +189,12 @@ "MIN_SRC_PORT_LVL": "Минимальный требуемый уровень портала для линковки", "MINUTES": " ({minutes} минут назад)", "MM": "Multimax", + "MM_BOTH_SIDE": "Use both base sides", + "MM_INSERT_ORDER": "Insert at the end", + "MM_SET_ALL_PORTALS": "All visible portals", + "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", + "MM_SPINE": "Spine", "MULTI_M_TITLE": "Нарисовать максимальное количество слоёв", "MULTI_M": "Нарисовать", "MUST_NOT_BE_EMPTY": "Не должно быть пустым", @@ -193,8 +212,11 @@ "NO_LABEL": "Метка не установлена", "NO_STOCK_INTEL": "Wasabee не поддерживает импорт из Intel", "NO_TITLE": "Название не установлено", + "NO LONGER AVAILABLE": "Resource removed from server: {error}", + "NO LONGER AVAILABLE SHORT": "Resource removed from server", "NOT LOGGED IN SHORT": "Не залогинен", "NOT LOGGED IN": "Не залогинен: {error}", + "NOT_LOADED": "Not fully loaded, try again.", "NOT_SET": "не установлено", "NTNAME": "Название", "OK": "OK", @@ -220,6 +242,8 @@ "OtherPortalAlert": "Другое", "PASTE_INSTRUCT": "Вставь экспортируемые данные Wasabee здесь.\n\nWasabee не может импортировать данные в формате интела.\n\nЕсть эксперементальная поддержка ДТ формата IITC.\n\nПрежде чем импортировать ДТ в формате IITC, просмотрите область ДТ и убедитесь, что все порталы загружены и кэшированы в IITC. Любой неподгруженный портал будет неподгружен.\n\nНужно будет использовать функцию 'замена', чтобы переместить порталы со неподгруженных на настоящие (местоположение порталов будет корректным, однако неподгруженные порталы не будут связаны с реальными).\n\nКэшированные порталы могут некорректно называться.", "pending": "Ожидается", + "PERM DENIED": "Permission denied: {error}", + "PERM DENIED SHORT": "Permission denied", "PERMS": "Разрешения {opName}", "PLEASE_SELECT_PORTAL": "Выбери портал", "PORT_FAKE": " порталов. Неподгружены ", @@ -319,6 +343,11 @@ "TEAMS BUTTON TITLE": "Список команд Wasabee", "TEAMS BUTTON": "Команды", "TO_PORT": "На портал", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Шаг тайлов для выверки", "TRAWL TITLE": "Выверка трасс", "TRAWL WARNING": "Этот метод загрузит данные тайлов под всеми нарисованными линками. Это медленный процесс.", @@ -387,4 +416,4 @@ "TEAMS BUTTON": "Команды", "WD BUTTON": "Ключи на руках" } -} +} \ No newline at end of file diff --git a/src/code/translations/Spanish.json b/src/code/translations/Spanish.json index df5b86ee9..2442782b1 100644 --- a/src/code/translations/Spanish.json +++ b/src/code/translations/Spanish.json @@ -46,6 +46,12 @@ "AUTO_DRAWS": "Auto-draw", "AUTODRAWS": "Wasabee Auto-draw Options", "AUTODRAW_PORTALS_SET": "Portals", + "autodraw.common.draw_button": "Draw", + "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.onion.variant": "Option", + "autodraw.onion.variant.equilateral": "~Equilateral", + "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.balanced": "Perfectly balanced", "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", "AUTOLOAD": "Automatically Load Missing Portal Details", "AUTOMARK STOP": "El Marcado-Automático se detuvo debido a que los portales no estaban cargado", @@ -64,6 +70,7 @@ "CLEAR LINKS": "Clear Links", "CLEAR MARKERS": "Clear Markers", "CLEAR_EVERYTHING": "Borrar Portales/Links/Marcadores", + "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Borrar TODOS los Datos de Wasabee", "CLEAROPS BUTTON": "Borrar Datos de Wasabee", "CLEAROPS PROMPT": "Esta opción borrará todas las OPS y datos relacionados a Wasabee. Todo será restaurado desde el servidor en la próxima sincronización.", @@ -182,6 +189,7 @@ "MIN_SRC_PORT_LVL": "Nivel mínimo requerido para el portal fuente", "MINUTES": "(Hace {minutes} minutos)", "MM": "Multimax", + "MM_BOTH_SIDE": "Use both base sides", "MM_INSERT_ORDER": "Insert at the end", "MM_SET_ALL_PORTALS": "All visible portals", "MM_SET_ALL_KEYS": "All GetKey Markers", @@ -246,11 +254,11 @@ "QD BUTTON END": "Dar click para detener dibujo de campos", "QD BUTTON TOGGLE MODE": "Click to change draw mode", "QD CHANGE COLOR": "Change color", + "QD END": "End", "QD TITLE": "Dibujar Capas Rápido", "QD TOGGLE MODE": "Change mode", "QDBASE": "Link Base", "QDCONT": "Dar click a un portal anidado para dibujar el campo.", - "QDEND": "Dar click nuevamente al mismo portal para finalizar el dibujo.", "QDNEXT": "Dar click al segundo portal ancla.", "QDSTART": "Dar click al primer portal ancla.", "READ_SHORT": "RO", @@ -335,6 +343,11 @@ "TEAMS BUTTON TITLE": "Listar Equipos Wasabee", "TEAMS BUTTON": "Equipos", "TO_PORT": "Hacia el Portal", + "toolbar.quick_delete.apply.text": "Apply", + "toolbar.quick_delete.apply.title": "Delete selected links/markers", + "toolbar.quick_delete.cancel.text": "Cancel", + "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", @@ -403,4 +416,4 @@ "TEAMS BUTTON": "Equipos", "WD BUTTON": "Llaves W-D" } -} +} \ No newline at end of file From 71afe9592ea189d46a41a25102f889b1f3130d33 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 7 Jan 2022 00:22:48 +0100 Subject: [PATCH 193/275] build: drop gulp, add lint/format + lint []/const --- .eslintrc.json | 26 +++++++++++++++++++++-- gulpfile.js | 41 ------------------------------------- package.json | 10 ++++++--- src/code/crosslinks.ts | 14 ++++++------- src/code/init.ts | 2 +- src/code/mapDrawing.ts | 6 +++--- src/code/model/operation.ts | 30 +++++++++++++-------------- src/code/selectedOp.ts | 6 +++--- src/code/uiCommands.ts | 4 ++-- 9 files changed, 62 insertions(+), 77 deletions(-) delete mode 100644 gulpfile.js diff --git a/.eslintrc.json b/.eslintrc.json index 23ba71190..4d0645d1f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -14,6 +14,7 @@ "commonjs": true, "es2020": true }, + "ignorePatterns": ["*.d.ts"], "rules": { "prettier/prettier": ["error", { "endOfLine": "auto" }], "no-console": "off", @@ -42,7 +43,6 @@ "no-self-compare": 1, "no-throw-literal": 1, "no-unused-expressions": 1, - "no-useless-concat": 1, "no-void": 1, "no-sequences": 1, "radix": 1 @@ -51,5 +51,27 @@ "L": "readonly", "PLAYER": "readonly", "android": "readonly" - } + }, + "overrides": [ + { + "files": ["src/**/*.ts"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json" + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "rules": { + "prettier/prettier": 0, + "lines-between-class-members": 0, + "@typescript-eslint/no-array-constructor": 1, + "@typescript-eslint/no-empty-function": 1, + "@typescript-eslint/no-inferrable-types": 1 + } + } + ] } diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 4543f1d1d..000000000 --- a/gulpfile.js +++ /dev/null @@ -1,41 +0,0 @@ -// Requires -const gulp = require("gulp"); -const del = require("del"); -const through2 = require("through2"); - -// locales, key parity -gulp.task("locales", (cb) => { - const english = require("./src/code/translations/english.json"); - function format(buf, ref) { - const parsed = JSON.parse(buf.toString("utf8")); - const result = {}; - for (const key in ref) result[key] = parsed[key] || ref[key]; - return JSON.stringify(result, null, 2) + "\n"; - } - - gulp - .src("./src/code/translations/*.json") - .pipe( - through2.obj(function (file, enc, cb) { - if (file.isBuffer()) { - file.contents = Buffer.from(format(file.contents, english)); - cb(null, file); - } else { - file.contents.pipe( - through2(function (contents) { - file.contents = through2(); - cb(null, file); - file.contents.write(format(contents, english)); - file.contents.end(); - }) - ); - } - }) - ) - .pipe(gulp.dest("./src/code/translations/")); - cb(); -}); - -gulp.task("default", gulp.series(["locales"])); - -gulp.task("clean", () => del(["releases/*"])); diff --git a/package.json b/package.json index 7302326ef..9ed0a1efb 100644 --- a/package.json +++ b/package.json @@ -10,14 +10,15 @@ "@types/jqueryui": "^1.12.16", "@types/leaflet": "^1.7.5", "@types/spectrum": "^1.8.2", + "@typescript-eslint/eslint-plugin": "^5.9.0", + "@typescript-eslint/parser": "^5.9.0", "css-loader": "^5.2.6", "del": "^6.0.0", - "eslint": "^7.28.0", + "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", "eslint-webpack-plugin": "^3.0.1", "fancy-log": "^1.3.3", - "gulp": "^4.0.2", "html-loader": "^2.1.2", "lodash": "^4.17.21", "prettier": "^2.3.1", @@ -38,7 +39,10 @@ "build-dev": "webpack --progress --mode development", "build-scot": "webpack --progress --mode development --env scot", "build-pr": "webpack --progress --mode development --env pr=${PR_NUMBER}", - "locales": "gulp locales" + "format:check": "prettier --check src/code", + "format:run": "prettier --write src/code", + "lint:check": "eslint src", + "lint:fix": "eslint --fix src" }, "repository": { "type": "git", diff --git a/src/code/crosslinks.ts b/src/code/crosslinks.ts index 54f610da9..3cfa18ea4 100644 --- a/src/code/crosslinks.ts +++ b/src/code/crosslinks.ts @@ -20,7 +20,7 @@ interface LLC extends L.LatLng { function toCartesian(lat: number, lng: number): Vec3 { lat *= d2r; lng *= d2r; - var o = Math.cos(lat); + const o = Math.cos(lat); return [o * Math.cos(lng), o * Math.sin(lng), Math.sin(lat)]; } @@ -401,7 +401,7 @@ export class GeodesicLine { cosLat1CosLat2SinDLng: number; constructor(start: L.LatLng, end: L.LatLng) { - let d2r = Math.PI / 180.0; + const d2r = Math.PI / 180.0; // let r2d = 180.0 / Math.PI; //eslint-disable-line // maths based on http://williams.best.vwh.net/avform.htm#Int if (start.lng == end.lng) { @@ -412,11 +412,11 @@ export class GeodesicLine { this.lat2 = end.lat * d2r; this.lng1 = start.lng * d2r; this.lng2 = end.lng * d2r; - let dLng = this.lng1 - this.lng2; - let sinLat1 = Math.sin(this.lat1); - let sinLat2 = Math.sin(this.lat2); - let cosLat1 = Math.cos(this.lat1); - let cosLat2 = Math.cos(this.lat2); + const dLng = this.lng1 - this.lng2; + const sinLat1 = Math.sin(this.lat1); + const sinLat2 = Math.sin(this.lat2); + const cosLat1 = Math.cos(this.lat1); + const cosLat2 = Math.cos(this.lat2); this.sinLat1CosLat2 = sinLat1 * cosLat2; this.sinLat2CosLat1 = sinLat2 * cosLat1; this.cosLat1CosLat2SinDLng = cosLat1 * cosLat2 * Math.sin(dLng); diff --git a/src/code/init.ts b/src/code/init.ts index 06867a16b..aa6559fb1 100644 --- a/src/code/init.ts +++ b/src/code/init.ts @@ -84,7 +84,7 @@ window.plugin.wasabee.init = async () => { Wasabee._selectedOp = null; // the in-memory working op; Wasabee._updateList = new Map(); - Wasabee.portalDetailQueue = new Array(); + Wasabee.portalDetailQueue = []; initSkin(); // can this be moved to the auth dialog? diff --git a/src/code/mapDrawing.ts b/src/code/mapDrawing.ts index 3e37aab1c..957126737 100644 --- a/src/code/mapDrawing.ts +++ b/src/code/mapDrawing.ts @@ -122,7 +122,7 @@ export async function drawAgents() { const layerMap = agentLayerMap(); - let doneAgents = new Array(); + let doneAgents = []; const me = await WasabeeMe.waitGet(); // cache hold-time age is 24 hours... not too frequent for (const t of me.Teams) { const freshlyDone = await drawSingleTeam(t.ID, layerMap, doneAgents); @@ -152,9 +152,9 @@ export async function drawSingleTeam( layerMap?: Map, alreadyDone?: GoogleID[] ) { - const done = new Array(); + const done = []; if (window.isLayerGroupDisplayed("Wasabee Agents") === false) return done; // yes, === false, undefined == true - if (alreadyDone === undefined) alreadyDone = new Array(); + if (alreadyDone === undefined) alreadyDone = []; if (layerMap === undefined) layerMap = agentLayerMap(); /* this also caches the team into Wasabee.teams for uses elsewhere */ diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 638c0b116..8cd63946f 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -91,8 +91,8 @@ export default class WasabeeOp extends Evented implements IOperation { _idToOpportals: Map; _coordsToOpportals: Map; - _dirtyCoordsTable: boolean = false; - _batchmode: boolean = false; + _dirtyCoordsTable = false; + _batchmode = false; constructor(obj) { super(); @@ -104,16 +104,16 @@ export default class WasabeeOp extends Evented implements IOperation { this.ID = obj.ID ? obj.ID : generateId(); this.name = obj.name ? obj.name : "unnamed op"; this.creator = obj.creator ? obj.creator : "unset"; - this.anchors = obj.anchors ? obj.anchors : Array(); + this.anchors = obj.anchors ? obj.anchors : []; this.links = this.convertLinksToObjs(obj.links); this.markers = this.convertMarkersToObjs(obj.markers); this.color = obj.color ? obj.color : "main"; this.comment = obj.comment ? obj.comment : null; - this.teamlist = obj.teamlist ? obj.teamlist : Array(); + this.teamlist = obj.teamlist ? obj.teamlist : []; this.fetched = obj.fetched ? obj.fetched : null; this.stored = obj.stored ? obj.stored : null; this.localchanged = obj.localchanged === false ? obj.localchanged : true; - this.keysonhand = obj.keysonhand ? obj.keysonhand : Array(); + this.keysonhand = obj.keysonhand ? obj.keysonhand : []; this.zones = this.convertZonesToObjs(obj.zones); // this.modified = obj.modified ? obj.modified : null; this.referencetime = obj.referencetime ? obj.referencetime : null; @@ -127,8 +127,8 @@ export default class WasabeeOp extends Evented implements IOperation { this.background = !!obj.background; - if (!this.links) this.links = new Array(); - if (!this.markers) this.markers = new Array(); + if (!this.links) this.links = []; + if (!this.markers) this.markers = []; const opportals = this.convertPortalsToObjs(obj.opportals); this._idToOpportals = new Map(); @@ -297,7 +297,7 @@ export default class WasabeeOp extends Evented implements IOperation { if (this._dirtyCoordsTable) { console.debug("operation: removing duplicates"); - const toRemove = new Array(); + const toRemove = []; const rename = new Map(); for (const [id, p] of this._idToOpportals) { @@ -947,7 +947,7 @@ export default class WasabeeOp extends Evented implements IOperation { } convertLinksToObjs(links: any[]) { - const tmpLinks = new Array(); + const tmpLinks = []; if (!links || links.length == 0) return tmpLinks; for (const l of links) { tmpLinks.push(new WasabeeLink(l)); @@ -956,7 +956,7 @@ export default class WasabeeOp extends Evented implements IOperation { } convertMarkersToObjs(markers: any[]) { - const tmpMarkers = new Array(); + const tmpMarkers = []; if (!markers || markers.length == 0) return tmpMarkers; if (markers) { for (const m of markers) { @@ -967,7 +967,7 @@ export default class WasabeeOp extends Evented implements IOperation { } convertPortalsToObjs(portals: any[]) { - const tmpPortals = Array(); + const tmpPortals = []; if (!portals || portals.length == 0) return tmpPortals; for (const p of portals) { if (p instanceof WasabeePortal) { @@ -988,7 +988,7 @@ export default class WasabeeOp extends Evented implements IOperation { { id: 2, name: "Secondary", color: "yellow" }, ].map((obj) => new WasabeeZone(obj)); } - const tmpZones = Array(); + const tmpZones = []; for (const z of zones) { if (z instanceof WasabeeZone) { tmpZones.push(z); @@ -1246,9 +1246,9 @@ export default class WasabeeOp extends Evented implements IOperation { changes(origin?: WasabeeOp) { const changes = { - addition: new Array(), - edition: new Array(), - deletion: new Array(), + addition: [], + edition: [], + deletion: [], name: null, color: null, comment: null, diff --git a/src/code/selectedOp.ts b/src/code/selectedOp.ts index 49328ff6c..1a8914841 100644 --- a/src/code/selectedOp.ts +++ b/src/code/selectedOp.ts @@ -24,7 +24,7 @@ export async function initSelectedOperation() { await loadNewDefaultOp(); } else { // verify it exists before trying to load - let tmp = await WasabeeOp.load(toLoad); + const tmp = await WasabeeOp.load(toLoad); if (tmp == null) { console.log( "most recently loaded up not present in local store, starting with new default op" @@ -123,7 +123,7 @@ export async function setupLocalStorage() { ops = await opsList(); } - const migrations = Array(); + const migrations = []; for (const opID of ops) { migrations.push(WasabeeOp.migrate(opID)); } @@ -239,7 +239,7 @@ export async function duplicateOperation(opID: OpID) { op.creator = window.PLAYER.nickname; op.teamlist = null; op.fetched = null; - op.keysonhand = new Array(); + op.keysonhand = []; op.cleanAll(); await op.store(); return op; diff --git a/src/code/uiCommands.ts b/src/code/uiCommands.ts index a7e51262e..76fad4f56 100644 --- a/src/code/uiCommands.ts +++ b/src/code/uiCommands.ts @@ -223,7 +223,7 @@ export function loadFaked(operation: WasabeeOp, force = false) { // local storage always returns as string if (flag !== "true" && !force) return; - const f = new Array(); + const f = []; for (const x of operation.fakedPortals) f.push(x.id); if (f.length > 0) getPortalDetails(f); } @@ -470,7 +470,7 @@ export async function fullSync() { // delete operations absent from server unless the owner const ol = await opsList(); - const serverOps = new Array(); + const serverOps = []; for (const opID of ol) { const op = await WasabeeOp.load(opID); if (op && op.server === server && !opsID.has(op.ID)) serverOps.push(op); From 956c4377efce015723cf3b947e539464be787147 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 7 Jan 2022 23:24:02 +0100 Subject: [PATCH 194/275] fix: set comment missing locales --- src/code/dialogs/setCommentDialog.js | 4 ++-- src/code/translations/English.json | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/code/dialogs/setCommentDialog.js b/src/code/dialogs/setCommentDialog.js index 35e892b79..1d893c0d7 100644 --- a/src/code/dialogs/setCommentDialog.js +++ b/src/code/dialogs/setCommentDialog.js @@ -79,7 +79,7 @@ export const SetCommentDialog = WDialog.extend({ const container = L.DomUtil.create("div", "container"); const desc = L.DomUtil.create("div", "desc", container); const input = L.DomUtil.create("input", null, container); - input.placeholder = "comment"; + input.placeholder = wX("COMMENT"); if (this.commentType == "link") { desc.textContent = wX("SET_LINK_COMMENT"); @@ -139,7 +139,7 @@ export const SetCommentDialog = WDialog.extend({ ); const hardnessInput = L.DomUtil.create("input", null, container); - hardnessInput.placeholder = "hardness"; + hardnessInput.placeholder = wX("dialog.setcomment.portal_hardness"); if (this.portal.hardness) hardnessInput.value = this.portal.hardness; hardnessInput.addEventListener( "change", diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 43ebdd4a2..8ec4b9c26 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -94,6 +94,7 @@ "DELETE_OP": "Delete {opName}", "DESCRIP_PLACEHOLD": "Description (optional)", "DestroyPortalAlert": "Destroy", + "dialog.setcomment.portal_hardness": "Hardness", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplicate Operation", "END_PORT": "End Portal", From 65b162d2807b209a200b5dcfe81475249f4a1ac9 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 9 Jan 2022 14:39:15 +0100 Subject: [PATCH 195/275] fix: join link use old path --- src/code/dialogs/manageTeamDialog.js | 7 ++++++- src/code/firebaseSupport.ts | 3 ++- src/code/static.ts | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 97aacb6ba..21f30d408 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -16,6 +16,7 @@ import Sortable from "../sortable"; import PromptDialog from "./promptDialog"; import wX from "../wX"; import ConfirmDialog from "./confirmDialog"; +import { constants } from "../static"; import AgentUI from "../ui/agent"; import { displayError, displayInfo } from "../error"; @@ -229,7 +230,11 @@ const ManageTeamDialog = WDialog.extend({ if (team.jlt) { const joinlink = L.DomUtil.create("input", null, container); const server = GetWasabeeServer(); - joinlink.value = `${server}/api/v1/team/${team.id}/join/${team.jlt}`; + joinlink.value = L.Util.template(constants.JOIN_TEAM_TEMPLATE, { + server: server, + teamid: team.id, + token: team.jlt, + }); joinlink.readOnly = true; L.DomEvent.on(joinlink, "click", (ev) => ev.target.select()); const joinlinkdel = L.DomUtil.create("button", null, container); diff --git a/src/code/firebaseSupport.ts b/src/code/firebaseSupport.ts index 4b874e644..dc500090e 100644 --- a/src/code/firebaseSupport.ts +++ b/src/code/firebaseSupport.ts @@ -20,6 +20,7 @@ import { displayInfo, displayWarning } from "./error"; import WasabeeAgent from "./model/agent"; import { getJWT } from "./auth"; import WasabeeMe from "./model/me"; +import { constants } from "./static"; // TODO: use a dedicated message channel: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging @@ -32,7 +33,7 @@ export function initFirebase() { const iframe = L.DomUtil.create("iframe"); iframe.width = "0"; iframe.height = "0"; - iframe.src = "https://cdn2.wasabee.rocks/iitcplugin/firebase/"; + iframe.src = constants.FIREBASE_IFRAME; iframe.id = frameID; iframe.addEventListener("load", () => { diff --git a/src/code/static.ts b/src/code/static.ts index dde9e16f6..4c041e6a2 100644 --- a/src/code/static.ts +++ b/src/code/static.ts @@ -80,6 +80,10 @@ const statics: Statics = { smoothFactor: 1, interactive: false, }, + WEBUI_DEFAULT: "https://webui.wasabee.rocks", + JOIN_TEAM_TEMPLATE: + "https://webui.wasabee.rocks/?server={server}#/team/{teamid}/join/{token}", + FIREBASE_IFRAME: "https://cdn2.wasabee.rocks/iitcplugin/firebase/", }, publicServers: [ { name: "Americas", url: "https://am.wasabee.rocks", short: "🇺🇸" }, From 2f9c74bf76e98c6d2aaec5a70eb3cbb5285b88ce Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 12 Jan 2022 10:13:26 +0100 Subject: [PATCH 196/275] update team member list dialog --- src/code/dialogs/manageTeamDialog.js | 11 +++++++++-- src/code/dialogs/teamMembershipList.js | 15 +++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 21f30d408..7469f9384 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -58,7 +58,6 @@ const ManageTeamDialog = WDialog.extend({ name: wX("TEAM STATE"), value: (agent) => agent.shareLocation, sort: (a, b) => a && !b, - // , format: (cell, value) => (cell.textContent = value) }, { name: wX("SQUAD"), @@ -83,6 +82,8 @@ const ManageTeamDialog = WDialog.extend({ displayInfo( `squad updated to ${squadDialog.inputField.value} for ${obj.name}` ); + // refresh team data + await WasabeeTeam.get(this.options.team.ID, 0); } catch (e) { console.error(e); displayError(e); @@ -90,7 +91,7 @@ const ManageTeamDialog = WDialog.extend({ } else { displayInfo(wX("INPUT_SQUAD_NAME")); } - this.update(); + window.map.fire("wasabee:team:update"); }, current: value, placeholder: "boots", @@ -115,6 +116,8 @@ const ManageTeamDialog = WDialog.extend({ callback: async () => { try { await removeAgentFromTeamPromise(value, this.options.team.ID); + // refresh team data + await WasabeeTeam.get(this.options.team.ID, 0); } catch (e) { console.error(e); } @@ -174,6 +177,8 @@ const ManageTeamDialog = WDialog.extend({ L.DomEvent.stop(ev); try { await addAgentToTeamPromise(addField.value, this.options.team.ID); + // refresh team data + await WasabeeTeam.get(this.options.team.ID, 0); displayInfo(wX("ADD_SUCC_INSTR")); window.map.fire("wasabee:team:update"); } catch (e) { @@ -193,6 +198,8 @@ const ManageTeamDialog = WDialog.extend({ L.DomEvent.stop(ev); try { await renameTeamPromise(team.id, renameField.value); + // refresh team data + await WasabeeTeam.get(this.options.team.ID, 0); displayInfo(`renamed to ${renameField.value}`); window.map.fire("wasabee:team:update"); } catch (e) { diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index e3dead71b..d8dc15de5 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -17,6 +17,7 @@ const TeamMembershipList = WDialog.extend({ addHooks: function () { WDialog.prototype.addHooks.call(this); + window.map.on("wasabee:team:update", this.update, this); window.map.on("wasabee:logout", this.closeDialog, this); this._displayDialog().catch((e) => { console.error(e); @@ -26,14 +27,15 @@ const TeamMembershipList = WDialog.extend({ removeHooks: function () { WDialog.prototype.removeHooks.call(this); + window.map.off("wasabee:team:update", this.update, this); window.map.off("wasabee:logout", this.closeDialog, this); }, _displayDialog: async function () { - const table = this._setupTable(); + this._table = this._setupTable(); const team = await WasabeeTeam.get(this.options.teamID, 10); // max cache age of 10 seconds - table.items = team.agents; + this._table.items = team.agents; const buttons = {}; buttons[wX("OK")] = () => { @@ -42,13 +44,19 @@ const TeamMembershipList = WDialog.extend({ this.createDialog({ title: team.name, - html: table.table, + html: this._table.table, width: "auto", dialogClass: "teamlist", buttons: buttons, }); }, + update: async function () { + const team = await WasabeeTeam.get(this.options.teamID, 10); + this._table.items = team.agents; + this.setTitle(team.name); + }, + _setupTable: function () { const table = new Sortable(); table.fields = [ @@ -63,7 +71,6 @@ const TeamMembershipList = WDialog.extend({ name: wX("SQUAD"), value: (agent) => agent.comment, sort: (a, b) => a.localeCompare(b), - // , format: (cell, value) => (cell.textContent = value) }, { name: "Sharing Location", From 9f623c49b6c990a49c96889d890870709a42a74b Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 12 Jan 2022 22:10:10 +0100 Subject: [PATCH 197/275] wtooltip: follow cursor itself this is for now the same as doing it in zone/qd --- src/code/buttons/quickdrawButton.js | 30 ++++++++++------------------- src/code/dialogs/zoneDialog.js | 11 +---------- src/code/leafletClasses.d.ts | 4 ++-- src/code/leafletClasses.js | 10 +++++++++- 4 files changed, 22 insertions(+), 33 deletions(-) diff --git a/src/code/buttons/quickdrawButton.js b/src/code/buttons/quickdrawButton.js index 311b0d8e6..5a911e07a 100644 --- a/src/code/buttons/quickdrawButton.js +++ b/src/code/buttons/quickdrawButton.js @@ -146,7 +146,6 @@ const QuickDrawControl = L.Handler.extend({ window.map.on("wasabee:portal:click", this._portalClicked, this); window.map.on("wasabee:op:select", this._opchange, this); window.map.on("keyup", this._keyUpListener, this); - window.map.on("mousemove", this._onMouseMove, this); }, removeHooks: function () { @@ -169,7 +168,6 @@ const QuickDrawControl = L.Handler.extend({ window.map.off("wasabee:portal:click", this._portalClicked, this); window.map.off("wasabee:op:select", this._opchange, this); window.map.off("keyup", this._keyUpListener, this); - window.map.off("mousemove", this._onMouseMove, this); }, _opchange: function () { @@ -204,14 +202,6 @@ const QuickDrawControl = L.Handler.extend({ } }, - _onMouseMove: function (e) { - if (e.latlng) { - this._tooltip.updatePosition(e.latlng); - this._guideUpdate(e); - } - L.DomEvent.preventDefault(e.originalEvent); - }, - _guideUpdate: function (e) { if (!this._guideLayerGroup) return; for (const l of this._guideLayerGroup.getLayers()) { @@ -238,28 +228,28 @@ const QuickDrawControl = L.Handler.extend({ _getTooltipText: function () { if (this._drawMode === "quickdraw") { - if (!this._anchor1) return { text: wX("QDSTART") }; - if (!this._anchor2) return { text: wX("QDNEXT") }; - return { text: wX("QDCONT") }; + if (!this._anchor1) return wX("QDSTART"); + if (!this._anchor2) return wX("QDNEXT"); + return wX("QDCONT"); } if (this._drawMode === "star") { // XXX wX this - if (!this._anchor) return { text: "Select the star anchor" }; - return { text: "Select a portal" }; + if (!this._anchor) + return wX("toolbar.quick_draw.tooltip.star_mode.anchor"); + return wX("toolbar.quick_draw.tooltip.star_mode.portal"); } // must be in single-link mode // XXX wX this - if (!this._previous) return { text: "Click first portal" }; - return { text: "Click next portal" }; + if (!this._previous) + return wX("toolbar.quick_draw.tooltip.single_mode.first"); + return wX("toolbar.quick_draw.tooltip.single_mode.next"); }, _portalClicked: function (portal) { const selectedPortal = PortalUI.fromIITC(portal); if (!selectedPortal) { // XXX wX this - this._tooltip.updateContent({ - text: "Portal data not loaded, please try again", - }); + this._tooltip.updateContent(wX("toolbar.quick_draw.tooltip.portal_fail")); return; } if (this._drawMode == "quickdraw") { diff --git a/src/code/dialogs/zoneDialog.js b/src/code/dialogs/zoneDialog.js index 1ca3427a1..d731373cd 100644 --- a/src/code/dialogs/zoneDialog.js +++ b/src/code/dialogs/zoneDialog.js @@ -199,7 +199,6 @@ const ZonedrawHandler = L.Handler.extend({ window.map.on("click", this._click, this); window.map.on("wasabee:op:select", this._opchange, this); window.map.on("keyup", this._keyUpListener, this); - window.map.on("mousemove", this._onMouseMove, this); }, removeHooks: function () { @@ -210,7 +209,6 @@ const ZonedrawHandler = L.Handler.extend({ window.map.off("click", this._click, this); window.map.off("wasabee:op:select", this._opchange, this); window.map.off("keyup", this._keyUpListener, this); - window.map.off("mousemove", this._onMouseMove, this); }, _opchange: function () { @@ -236,14 +234,7 @@ const ZonedrawHandler = L.Handler.extend({ getSelectedOperation().addZonePoint(this.zoneID, e.latlng); }, - _onMouseMove: function (e) { - if (e.latlng) { - this._tooltip.updatePosition(e.latlng); - } - L.DomEvent.preventDefault(e.originalEvent); - }, - _getTooltipText: function () { - return { text: wX("ZONE_DRAW") }; + return wX("ZONE_DRAW"); }, }); diff --git a/src/code/leafletClasses.d.ts b/src/code/leafletClasses.d.ts index 0442203eb..212cc533b 100644 --- a/src/code/leafletClasses.d.ts +++ b/src/code/leafletClasses.d.ts @@ -4,9 +4,9 @@ export declare class WTooltip extends L.Class { _pane: HTMLElement; _container: HTMLDivElement; - constructor(); + constructor(map: L.Map); dispose(): void; - updateContent(labelText: any): this; + updateContent(labelText: string): this; updatePosition(latlng: L.LatLngExpression): this; showAsError(): this; removeError(): this; diff --git a/src/code/leafletClasses.js b/src/code/leafletClasses.js index 0d012b66d..c6e91b1e7 100644 --- a/src/code/leafletClasses.js +++ b/src/code/leafletClasses.js @@ -6,19 +6,27 @@ export const WTooltip = L.Class.extend({ this._container = L.DomUtil.create("div", "wasabee-tooltip", this._pane); L.DomUtil.addClass(this._container, "wasabee-tooltip-single"); + window.map.on("mousemove", this._onMouseMove, this); }, dispose: function () { + window.map.off("mousemove", this._onMouseMove, this); this._pane.removeChild(this._container); this._container = null; }, updateContent: function (labelText) { // const span = L.DomUtil.create("span", null, this._container); - this._container.textContent = labelText.text; + this._container.textContent = labelText; return this; }, + _onMouseMove: function (event) { + if (event.layerPoint) { + L.DomUtil.setPosition(this._container, event.layerPoint); + } + }, + updatePosition: function (latlng) { const pos = this._map.latLngToLayerPoint(latlng); L.DomUtil.setPosition(this._container, pos); From 9d6a9fd8d449a7d1089222c4569d350a562c63ac Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 12 Jan 2022 22:12:10 +0100 Subject: [PATCH 198/275] quickdelete: change subaction on instant delete --- src/code/buttons/quickdelete.ts | 35 +++++++++++++++++++----------- src/code/leafletClasses.d.ts | 1 + src/code/leafletClasses.js | 19 ++++++++++++++++ src/code/translations/English.json | 2 ++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index c0561a906..9e089a60b 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -36,7 +36,7 @@ class QuickDeleteButton extends WButton { }); this.state = "off"; - this.actionsContainer = this._createSubActions(this.getSubActions()); + this.setSubActions(this.getSubActions()); this._container.appendChild(this.actionsContainer); @@ -45,18 +45,15 @@ class QuickDeleteButton extends WButton { // update text window.map.on("wasabee:ui:skin wasabee:ui:lang", () => { this.button.title = wX("toolbar.quick_delete.title"); - const newSubActions = this._createSubActions(this.getSubActions()); - this._container.replaceChild(newSubActions, this.actionsContainer); - newSubActions.style.display = this.actionsContainer.style.display; - this.actionsContainer = newSubActions; + this.setSubActions(this.getSubActions()); }); this.update(); } opChange() { - if (this.state == 'on') this.disable(); - else if (this.state == 'instant') { + if (this.state == "on") this.disable(); + else if (this.state == "instant") { this.handler.disable(); this.handler.enable(); } @@ -64,14 +61,16 @@ class QuickDeleteButton extends WButton { toggleActions() { if (this.state == "off") { - this.enable(); this.state = "on"; - postToFirebase({ id: 'analytics', action: 'quickdelete' }); + this.enable(); + this.setSubActions(this.getSubActions()); + postToFirebase({ id: "analytics", action: "quickdelete" }); } else if (this.state == "on") { this.disable(); - this.enable(); this.state = "instant"; - postToFirebase({ id: 'analytics', action: 'quickdelete:instant' }); + this.enable(); + this.setSubActions(this.getSubActions()); + postToFirebase({ id: "analytics", action: "quickdelete:instant" }); this.button.classList.add("blink"); } else { this.disable(); @@ -98,16 +97,26 @@ class QuickDeleteButton extends WButton { } getSubActions() { + if (this.state === "instant") + return [ + { + text: wX("toolbar.quick_delete.stop.text"), + title: wX("toolbar.quick_delete.stop.title"), + callback: this.disable, + context: this, + }, + ]; + const applySubAction = { - title: wX("toolbar.quick_delete.apply.title"), text: wX("toolbar.quick_delete.apply.text"), + title: wX("toolbar.quick_delete.apply.title"), callback: this.actionApply, context: this, }; const cancelSubAction = { + text: wX("toolbar.quick_delete.cancel.text"), title: wX("toolbar.quick_delete.cancel.title"), - text: wX("toolbar.quick_delete.cancel.title"), callback: this.actionCancel, context: this, }; diff --git a/src/code/leafletClasses.d.ts b/src/code/leafletClasses.d.ts index 212cc533b..2cafe09ef 100644 --- a/src/code/leafletClasses.d.ts +++ b/src/code/leafletClasses.d.ts @@ -89,6 +89,7 @@ export declare class WButton extends L.Class { setControl(control: any): void; disable(): void; enable(): void; + setSubActions(actions: ButtonOptions[]): void; _createButton(options: ButtonOptions): HTMLAnchorElement; _createSubActions(buttons: ButtonOptions[]): HTMLUListElement; } diff --git a/src/code/leafletClasses.js b/src/code/leafletClasses.js index c6e91b1e7..bf2a7128b 100644 --- a/src/code/leafletClasses.js +++ b/src/code/leafletClasses.js @@ -359,6 +359,25 @@ export const WButton = L.Class.extend({ } }, + setSubActions: function (actions) { + if (!this.actionsContainer) { + this.actionsContainer = L.DomUtil.create( + "ul", + "wasabee-actions", + this._container + ); + } + this.actionsContainer.textContent = ""; + for (const action of actions) { + const li = L.DomUtil.create( + "li", + "wasabee-subactions", + this.actionsContainer + ); + this._createButton({ ...action, container: li }); + } + }, + _createButton: function (options) { const link = L.DomUtil.create( "a", diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 8ec4b9c26..a72aa130b 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -348,6 +348,8 @@ "toolbar.quick_delete.apply.title": "Delete selected links/markers", "toolbar.quick_delete.cancel.text": "Cancel", "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.stop.text": "Stop", + "toolbar.quick_delete.stop.title": "Exit delete mode", "toolbar.quick_delete.title": "Quick delete", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", From fc81508187700d1a250136cbbbe5ac25b213595f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 12 Jan 2022 22:12:42 +0100 Subject: [PATCH 199/275] quickdelete: add tooltip --- src/code/buttons/quickdelete.ts | 10 +++++++++- src/code/translations/English.json | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/code/buttons/quickdelete.ts b/src/code/buttons/quickdelete.ts index 9e089a60b..86f20b4d7 100644 --- a/src/code/buttons/quickdelete.ts +++ b/src/code/buttons/quickdelete.ts @@ -1,4 +1,4 @@ -import { WButton } from "../leafletClasses"; +import { WButton, WTooltip } from "../leafletClasses"; import wX from "../wX"; import type { Wasabee } from "../init"; @@ -146,6 +146,7 @@ class QuickDeleteHandler extends L.Handler { deletedLink: Set; control: QuickDeleteButton; + tooltip: WTooltip; constructor(control: QuickDeleteButton) { super(window.map); @@ -252,6 +253,12 @@ class QuickDeleteHandler extends L.Handler { layer.on("click", this.clickLink, this); }); window.map.on("keyup", this.keyUpListener, this); + this.tooltip = new WTooltip(window.map); + this.tooltip.updateContent( + this.control.state === "instant" + ? wX("toolbar.quick_delete.tooltip.quick_mode") + : wX("toolbar.quick_delete.tooltip.toggle_mode") + ); } removeHooks() { @@ -269,6 +276,7 @@ class QuickDeleteHandler extends L.Handler { }); }); window.map.off("keyup", this.keyUpListener, this); + this.tooltip.dispose(); } } diff --git a/src/code/translations/English.json b/src/code/translations/English.json index a72aa130b..7467217e5 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -351,6 +351,13 @@ "toolbar.quick_delete.stop.text": "Stop", "toolbar.quick_delete.stop.title": "Exit delete mode", "toolbar.quick_delete.title": "Quick delete", + "toolbar.quick_delete.tooltip.toggle_mode": "Click on features to mark for deletion", + "toolbar.quick_delete.tooltip.quick_mode": "Click on features to delete instantly", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Select the star anchor", + "toolbar.quick_draw.tooltip.star_mode.portal": "Select a portal", + "toolbar.quick_draw.tooltip.single_mode.first": "Click first portal", + "toolbar.quick_draw.tooltip.single_mode.next": "Click next portal", + "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", From 2dddf55283c83a08bfddd4c406ca94b32d5605f2 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 12 Jan 2022 22:21:03 +0100 Subject: [PATCH 200/275] wbutton: use setsubactions method --- src/code/buttons/linkButton.js | 9 ++------- src/code/buttons/markerButton.js | 9 ++------- src/code/buttons/opButton.js | 9 ++------- src/code/buttons/quickdrawButton.js | 9 ++------- src/code/buttons/wasabeeButton.js | 16 +++++----------- src/code/leafletClasses.d.ts | 1 - src/code/leafletClasses.js | 18 ------------------ 7 files changed, 13 insertions(+), 58 deletions(-) diff --git a/src/code/buttons/linkButton.js b/src/code/buttons/linkButton.js index ecf679232..7dec2550f 100644 --- a/src/code/buttons/linkButton.js +++ b/src/code/buttons/linkButton.js @@ -24,16 +24,11 @@ const LinkButton = WButton.extend({ title: this.title, }); - this.actionsContainer = this._createSubActions(this.getSubActions()); - - this._container.appendChild(this.actionsContainer); + this.setSubActions(this.getSubActions()); window.map.on("wasabee:ui:skin wasabee:ui:lang", () => { this.button.title = wX("LINKS BUTTON TITLE"); - const newSubActions = this._createSubActions(this.getSubActions()); - this._container.replaceChild(newSubActions, this.actionsContainer); - newSubActions.style.display = this.actionsContainer.style.display; - this.actionsContainer = newSubActions; + this.setSubActions(this.getSubActions()); }); }, diff --git a/src/code/buttons/markerButton.js b/src/code/buttons/markerButton.js index 5f37b9501..298701a53 100644 --- a/src/code/buttons/markerButton.js +++ b/src/code/buttons/markerButton.js @@ -23,19 +23,14 @@ const MarkerButton = WButton.extend({ title: this.title, }); - this.actionsContainer = this._createSubActions(this.getSubActions()); - - this._container.appendChild(this.actionsContainer); + this.setSubActions(this.getSubActions()); window.map.on("wasabee:ui:skin wasabee:ui:lang", this.update, this); }, update: function () { this.button.title = wX("MARKERS BUTTON TITLE"); - const newSubActions = this._createSubActions(this.getSubActions()); - this._container.replaceChild(newSubActions, this.actionsContainer); - newSubActions.style.display = this.actionsContainer.style.display; - this.actionsContainer = newSubActions; + this.setSubActions(this.getSubActions()); }, getSubActions: function () { diff --git a/src/code/buttons/opButton.js b/src/code/buttons/opButton.js index 2e25a2613..97fe1997f 100644 --- a/src/code/buttons/opButton.js +++ b/src/code/buttons/opButton.js @@ -25,16 +25,11 @@ const OpButton = WButton.extend({ title: this.title, }); - this.actionsContainer = this._createSubActions(this.getSubActions()); - - this._container.appendChild(this.actionsContainer); + this.setSubActions(this.getSubActions()); window.map.on("wasabee:ui:skin wasabee:ui:lang", () => { this.button.title = wX("OP_BUTTON"); - const newSubActions = this._createSubActions(this.getSubActions()); - this._container.replaceChild(newSubActions, this.actionsContainer); - newSubActions.style.display = this.actionsContainer.style.display; - this.actionsContainer = newSubActions; + this.setSubActions(this.getSubActions()); }); }, diff --git a/src/code/buttons/quickdrawButton.js b/src/code/buttons/quickdrawButton.js index 5a911e07a..c4255530c 100644 --- a/src/code/buttons/quickdrawButton.js +++ b/src/code/buttons/quickdrawButton.js @@ -35,16 +35,11 @@ const QuickdrawButton = WButton.extend({ this.handler._nextDrawnLinksColor = ev.target.value; }); - this.actionsContainer = this._createSubActions(this.getSubActions()); - - this._container.appendChild(this.actionsContainer); + this.setSubActions(this.getSubActions()); window.map.on("wasabee:ui:skin wasabee:ui:lang", () => { this.button.title = wX("QD TITLE"); - const newSubActions = this._createSubActions(this.getSubActions()); - this._container.replaceChild(newSubActions, this.actionsContainer); - newSubActions.style.display = this.actionsContainer.style.display; - this.actionsContainer = newSubActions; + this.setSubActions(this.getSubActions()); if (this.handler._enabled) this.handler._tooltip.updateContent(this.handler._getTooltipText()); diff --git a/src/code/buttons/wasabeeButton.js b/src/code/buttons/wasabeeButton.js index f89c2cbd6..4f9a54a12 100644 --- a/src/code/buttons/wasabeeButton.js +++ b/src/code/buttons/wasabeeButton.js @@ -35,23 +35,19 @@ const WasabeeButton = WButton.extend({ this._buildActions(); // build and display as if not logged in - this.actionsContainer = this._getActions(); - this._container.appendChild(this.actionsContainer); + this.setSubActions(this.getSubActions()); // check login state and update if necessary window.map.on("wasabee:ui:skin wasabee:ui:lang", () => { this.button.title = wX("WASABEE BUTTON TITLE"); this._buildActions(); - const newSubActions = this._getActions(); - this._container.replaceChild(newSubActions, this.actionsContainer); - newSubActions.style.display = this.actionsContainer.style.display; - this.actionsContainer = newSubActions; + this.setSubActions(this.getSubActions()); }); this.update(); }, - _getActions: function () { + getSubActions: function () { let tmp = []; if (!this._lastLoginState) { tmp = [this._loginAction]; @@ -70,7 +66,7 @@ const WasabeeButton = WButton.extend({ // settings always at the end tmp = tmp.concat(this._SettingsActions); - return this._createSubActions(tmp); + return tmp; }, _buildActions: function () { @@ -185,9 +181,7 @@ const WasabeeButton = WButton.extend({ if (loggedIn) this.button.classList.add("wasabee-logged-in"); else this.button.classList.remove("wasabee-logged-in"); - const old = this.actionsContainer; - this.actionsContainer = this._getActions(); - old.parentNode.replaceChild(this.actionsContainer, old); + this.setSubActions(this.getSubActions()); this.disable(); } }, diff --git a/src/code/leafletClasses.d.ts b/src/code/leafletClasses.d.ts index 2cafe09ef..c0dadaa19 100644 --- a/src/code/leafletClasses.d.ts +++ b/src/code/leafletClasses.d.ts @@ -91,6 +91,5 @@ export declare class WButton extends L.Class { enable(): void; setSubActions(actions: ButtonOptions[]): void; _createButton(options: ButtonOptions): HTMLAnchorElement; - _createSubActions(buttons: ButtonOptions[]): HTMLUListElement; } export {}; diff --git a/src/code/leafletClasses.js b/src/code/leafletClasses.js index bf2a7128b..68f6e0c0a 100644 --- a/src/code/leafletClasses.js +++ b/src/code/leafletClasses.js @@ -403,22 +403,4 @@ export const WButton = L.Class.extend({ return link; }, - - _createSubActions: function (buttons) { - const container = L.DomUtil.create("ul", "wasabee-actions"); - for (const b of buttons) { - const li = L.DomUtil.create("li", "wasabee-subactions", container); - this._createButton({ - title: b.title, - text: b.text, - html: b.html, - buttonImage: b.img, - container: li, - callback: b.callback, - context: b.context, - className: "wasabee-subactions", - }); - } - return container; - }, }); From bd3020fd92f351f9a6b1da132f2d88fb5459a238 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 13 Jan 2022 00:41:16 +0100 Subject: [PATCH 201/275] remove unused wX strings --- src/code/translations/English.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 7467217e5..5630fcf06 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -39,7 +39,6 @@ "ASSIGNED_ONLY": "Assigned Only", "assigned": "Assigned", "AUTH INCOMPAT": "You have activated a plugin in TamperMonkey that is incompatable with Wasabee", - "AUTH IOS": "On iOS, use the main 'Log In' option. If that fails, use 'Webview Login' then use the 'Verify Webview' button to complete the process.", "AUTH REQUIRED": "Authentication Required", "AUTH TOKEN REJECTED": "Sending auth token to server rejected: {error}", "AUTH_SELECT_ACCOUNT": "Select account", @@ -70,7 +69,6 @@ "CLEAR LINKS": "Clear Links", "CLEAR MARKERS": "Clear Markers", "CLEAR_EVERYTHING": "Clear Portals/Links/Markers for current OP", - "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Clear Data", "CLEAROPS BUTTON": "Clear Data", "CLEAROPS PROMPT": "Clear all local OPS. Ops will be restored at next download. Wasabee will be disabled until next page reload.", @@ -391,8 +389,6 @@ "WASABEE_D_LIST": "Input Defensive Key Count", "WD BUTTON TITLE": "Log Defensive Keys", "WD BUTTON": "W-D Keys", - "WEBVIEW VERIFY": "Verify Webview", - "WEBVIEW": "Webview Log In (iOS)", "WRITE_SHORT": "RW", "WRITE": "write", "WSERVER": "Server: {url}", @@ -406,7 +402,6 @@ "CHECKLIST BUTTON": "Check", "CLEAROPS BUTTON": "Clear", "EXPORT OP": "Xport", - "FAN_FIELD3": "Fan", "FANFIELD": "Draw", "FANFIELD2": "Draw Fan Field", "KEYS": "Keys", From c27f43952c88534f53263879fce5bcaa43ba1767 Mon Sep 17 00:00:00 2001 From: Bill Gillock Date: Thu, 13 Jan 2022 10:27:46 -0600 Subject: [PATCH 202/275] Don't check for existing markers of the same type on the portal --- src/code/dialogs/markerAddDialog.js | 2 -- src/code/model/operation.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index 7772ddb3b..e7afc11fd 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -81,8 +81,6 @@ const MarkerAddDialog = WDialog.extend({ const o = L.DomUtil.create("option", null, this._type); o.value = k; o.textContent = wX(k); - if (markers.has(k)) o.disabled = true; - else if (!defaultType) defaultType = k; } this._type.value = defaultType; } else { diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 638c0b116..7ab301e66 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -857,7 +857,7 @@ export default class WasabeeOp extends Evented implements IOperation { addMarker(markerType: string, portal: WasabeePortal, options) { if (!portal) return false; - if (this.containsMarker(portal, markerType)) return false; + // save a trip to update() this._addPortal(portal); const marker = new WasabeeMarker({ From 32d3d73e602f8fad26eae1dd9b7491ee136d253b Mon Sep 17 00:00:00 2001 From: Bill Gillock Date: Thu, 13 Jan 2022 10:35:36 -0600 Subject: [PATCH 203/275] Keep default setting code --- src/code/dialogs/markerAddDialog.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index e7afc11fd..e5d3afed9 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -81,6 +81,7 @@ const MarkerAddDialog = WDialog.extend({ const o = L.DomUtil.create("option", null, this._type); o.value = k; o.textContent = wX(k); + if (!defaultType) defaultType = k; } this._type.value = defaultType; } else { From 93888287a63787617803bc4cf87f94cf4f31af9b Mon Sep 17 00:00:00 2001 From: Bill Gillock Date: Thu, 13 Jan 2022 16:47:51 -0600 Subject: [PATCH 204/275] Support dups in changeDialog, getPortalMarkers and merging --- src/code/dialogs/markerChangeDialog.js | 1 - src/code/model/operation.ts | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/code/dialogs/markerChangeDialog.js b/src/code/dialogs/markerChangeDialog.js index 27c7723a3..ded8cc9dc 100644 --- a/src/code/dialogs/markerChangeDialog.js +++ b/src/code/dialogs/markerChangeDialog.js @@ -40,7 +40,6 @@ const MarkerChangeDialog = WDialog.extend({ const o = L.DomUtil.create("option", null, this._type); o.value = k; o.textContent = wX(k); - if (markers.has(k) && k != this.options.marker.type) o.disabled = true; } this._type.value = this.options.marker.type; diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 7ab301e66..eb0175b47 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -383,7 +383,7 @@ export default class WasabeeOp extends Evented implements IOperation { if (!portal) return markers; for (const m of this.markers) { if (m.portalId == portal.id) { - markers.set(m.type, m); + markers.set(m.ID, m); } } return markers; @@ -1445,7 +1445,7 @@ export default class WasabeeOp extends Evented implements IOperation { } if (d.type == "marker") { const marker = this.getPortalMarkers(d.marker.portalId).get( - d.marker.type + d.marker.ID ); if (marker) { d.id = marker.ID; @@ -1466,7 +1466,7 @@ export default class WasabeeOp extends Evented implements IOperation { } if (e.type == "marker") { const marker = this.getPortalMarkers(e.marker.portalId).get( - e.marker.type + e.marker.ID ); if (marker) { e.id = marker.ID; From 0eb367ea5762d80c8402f4c7d18be943732105af Mon Sep 17 00:00:00 2001 From: Bill Gillock Date: Thu, 13 Jan 2022 17:53:08 -0600 Subject: [PATCH 205/275] Get rid of markers list where not needed --- src/code/dialogs/markerAddDialog.js | 10 ++-------- src/code/dialogs/markerChangeDialog.js | 6 +----- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index e5d3afed9..a9d34b7b7 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -62,10 +62,6 @@ const MarkerAddDialog = WDialog.extend({ this._selectedPortal.latLng ); - const markers = getSelectedOperation().getPortalMarkers( - this._selectedPortal - ); - let defaultType = window.plugin.wasabee.static.constants.DEFAULT_MARKER_TYPE; if ( @@ -75,13 +71,11 @@ const MarkerAddDialog = WDialog.extend({ defaultType = localStorage[window.plugin.wasabee.static.constants.LAST_MARKER_KEY]; } - defaultType = markers.has(defaultType) ? null : defaultType; for (const k of WasabeeMarker.markerTypes) { const o = L.DomUtil.create("option", null, this._type); o.value = k; o.textContent = wX(k); - if (!defaultType) defaultType = k; } this._type.value = defaultType; } else { @@ -151,12 +145,12 @@ const MarkerAddDialog = WDialog.extend({ // XXX remove comment from args in 0.20 if (operation.addMarker(selectedType, PortalUI.getSelected(), options)) { + localStorage[window.plugin.wasabee.static.constants.LAST_MARKER_KEY] = + selectedType; if (WasabeeMarker.isDestructMarkerType(selectedType)) WasabeeBlocker.removeBlocker(operation, PortalUI.getSelected().id); await this.update(); } else displayError(wX("ALREADY_HAS_MARKER")); - localStorage[window.plugin.wasabee.static.constants.LAST_MARKER_KEY] = - selectedType; }, _getAgentMenu: async function (menu) { diff --git a/src/code/dialogs/markerChangeDialog.js b/src/code/dialogs/markerChangeDialog.js index ded8cc9dc..dc4d3d4cb 100644 --- a/src/code/dialogs/markerChangeDialog.js +++ b/src/code/dialogs/markerChangeDialog.js @@ -35,7 +35,6 @@ const MarkerChangeDialog = WDialog.extend({ this._type = L.DomUtil.create("select", null, content); - const markers = operation.getPortalMarkers(portal); for (const k of WasabeeMarker.markerTypes) { const o = L.DomUtil.create("option", null, this._type); o.value = k; @@ -45,10 +44,7 @@ const MarkerChangeDialog = WDialog.extend({ const buttons = {}; buttons[wX("OK")] = () => { - if ( - WasabeeMarker.markerTypes.has(this._type.value) && - !markers.has(this._type.value) - ) { + if (WasabeeMarker.markerTypes.has(this._type.value)) { operation.startBatchMode(); operation.removeMarker(this.options.marker); operation.addMarker(this._type.value, portal, { From bebcf63da25e77f769163cd93dcf215363a785d1 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 14 Jan 2022 15:12:52 +0100 Subject: [PATCH 206/275] merge: drop support of 0.18 ops 0.18 was changing all IDs on update --- src/code/model/operation.ts | 73 ------------------------------------- 1 file changed, 73 deletions(-) diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index eb0175b47..784141f2d 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -1404,79 +1404,6 @@ export default class WasabeeOp extends Evented implements IOperation { // add missing zones summary.addition.zone = this.mergeZones(op); - // try to detect 0.18 ops with inconsistent IDs - { - const ids = new Set(); - for (const l of this.links) { - ids.add(l.ID); - } - for (const m of this.markers) { - ids.add(m.ID); - } - let foundCollision = false; - for (const d of changes.deletion) { - if (d.type == "link" || d.type == "marker") - if (ids.has(d.id)) { - foundCollision = true; - break; - } - } - if (!foundCollision && op.links.some((l) => ids.has(l.ID))) - foundCollision = true; - if (!foundCollision && op.markers.some((m) => ids.has(m.ID))) - foundCollision = true; - - // foundCollision: either there is a collision in IDs, or everything fine - if (!foundCollision) { - // unless someone deleted everything and rebuild an OP, IDs differ between op and `this` - // we need to use the server IDs so everyone use the same IDs - // this will occur with old client editing the ops, and old ops with always parallel writers (none is sync; bound to disappear) - summary.compatibility.ok = false; - for (const d of changes.deletion) { - if (d.type == "link") { - const link = this.getLinkByPortalIDs( - d.link.fromPortalId, - d.link.toPortalId - ); - if (link) { - d.id = link.ID; - summary.compatibility.rewrite.link += 1; - } - } - if (d.type == "marker") { - const marker = this.getPortalMarkers(d.marker.portalId).get( - d.marker.ID - ); - if (marker) { - d.id = marker.ID; - summary.compatibility.rewrite.marker += 1; - } - } - } - for (const e of changes.edition) { - if (e.type == "link") { - const link = this.getLinkByPortalIDs( - e.link.fromPortalId, - e.link.toPortalId - ); - if (link) { - e.id = link.ID; - summary.compatibility.rewrite.link += 1; - } - } - if (e.type == "marker") { - const marker = this.getPortalMarkers(e.marker.portalId).get( - e.marker.ID - ); - if (marker) { - e.id = marker.ID; - summary.compatibility.rewrite.marker += 1; - } - } - } - } - } - for (const d of changes.deletion) { if (d.type == "link") { const links = this.links.filter((l) => l.ID != d.id); From 906ea4a590c105a68429515f8a4afbc2d8f48678 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 14 Jan 2022 15:13:10 +0100 Subject: [PATCH 207/275] merge: drop duplication check on marker --- src/code/model/operation.ts | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 784141f2d..49c013080 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -378,17 +378,6 @@ export default class WasabeeOp extends Evented implements IOperation { return false; } - getPortalMarkers(portal: WasabeePortal) { - const markers = new Map(); - if (!portal) return markers; - for (const m of this.markers) { - if (m.portalId == portal.id) { - markers.set(m.ID, m); - } - } - return markers; - } - getLinkByPortalIDs(portalId1: PortalID, portalId2: PortalID) { for (const l of this.links) { if ( @@ -1454,18 +1443,10 @@ export default class WasabeeOp extends Evented implements IOperation { let found = false; for (const m of this.markers) { if (m.ID == e.marker.ID) { - const markers = this.getPortalMarkers(e.marker.portalId); - const marker = markers.get(e.marker.type); - if (marker && marker != m) { - // remove the marker if leading to a duplicate - this.markers = this.markers.filter((m) => m.ID != e.marker.ID); - summary.edition.duplicate += 1; - } else { - for (const kv of e.diff) m[kv[0]] = e.marker[kv[0]]; - summary.edition.marker += 1; - if (e.diff.some((kv) => kv[0] == "assignedTo")) - summary.edition.assignment += 1; - } + for (const kv of e.diff) m[kv[0]] = e.marker[kv[0]]; + summary.edition.marker += 1; + if (e.diff.some((kv) => kv[0] == "assignedTo")) + summary.edition.assignment += 1; found = true; break; } From 48089ec6cb8ee0414e03c133543cd4e9e9d2c8c0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 14 Jan 2022 20:39:05 +0100 Subject: [PATCH 208/275] build: add testing --- package.json | 9 +++++---- plugin.config.json | 5 +++++ webpack.config.js | 40 ++++++++++++++++++++++------------------ 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 9ed0a1efb..3bad346ae 100644 --- a/package.json +++ b/package.json @@ -35,10 +35,11 @@ "webpack-cli": "^4.8.0" }, "scripts": { - "build": "webpack --progress --mode production", - "build-dev": "webpack --progress --mode development", - "build-scot": "webpack --progress --mode development --env scot", - "build-pr": "webpack --progress --mode development --env pr=${PR_NUMBER}", + "build": "webpack --progress --env build=prod", + "build-dev": "webpack --progress --env build=dev", + "build-scot": "webpack --progress --env build=scot", + "build-pr": "webpack --progress --env build=pr --env pr=${PR_NUMBER}", + "build-testing": "webpack --progress --env build=testing", "format:check": "prettier --check src/code", "format:run": "prettier --write src/code", "lint:check": "eslint src", diff --git a/plugin.config.json b/plugin.config.json index 22b852d52..6d1c9c8bd 100644 --- a/plugin.config.json +++ b/plugin.config.json @@ -10,6 +10,11 @@ "updateURL": "https://cdn2.wasabee.rocks/iitcplugin/latest/dev/wasabee.meta.js", "version": "0.20.BUILDDATE-dev" }, + "testing": { + "downloadURL": "https://wasabee-project.github.io/Wasabee-IITC/testing/wasabee.user.js", + "updateURL": "https://wasabee-project.github.io/Wasabee-IITC/testing/wasabee.meta.js", + "version": "0.20.BUILDDATE-testing" + }, "pr": { "version": "0.20-pr" }, diff --git a/webpack.config.js b/webpack.config.js index 67ae6ea5f..bdffafe58 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -140,13 +140,13 @@ const config = { }, resolve: { modules: ["node_modules"], - extensions: ['.ts', '.js'], + extensions: [".ts", ".js"], }, module: { rules: [ { test: /\.tsx?$/, - use: 'ts-loader', + use: "ts-loader", exclude: /node_modules/, }, { @@ -187,27 +187,31 @@ function getCommitShort() { module.exports = (env, argv) => { const pluginConfig = require("./plugin.config.json"); const meta = pluginConfig.headers.common; - if (argv.mode === "development") { - const commit = getCommitShort(); - if (env.scot) { - config.output.path = path.join(outputPath, "scot"); - config.devtool = "eval-source-map"; - Object.assign(meta, pluginConfig.headers.scot); - } else if (env.pr) { - config.output.path = path.join(outputPath, "dev"); - config.devtool = "eval-source-map"; - Object.assign(meta, pluginConfig.headers.pr); + const build = env.build; + if (build in pluginConfig.headers) + Object.assign(meta, pluginConfig.headers[build]); + switch (build) { + case "prod": + case "dev": + case "testing": + case "scot": + config.output.path = path.join(outputPath, build); + break; + case "pr": meta.version += env.pr; - } else if (argv.mode === "development") { config.output.path = path.join(outputPath, "dev"); - config.devtool = "eval-source-map"; - Object.assign(meta, pluginConfig.headers.dev); - } + default: + } + + if (build !== "prod") { + const commit = getCommitShort(); if (commit) meta.version += `-${commit}`; + config.devtool = "eval-source-map"; + config.mode = "development"; } else { - config.output.path = path.join(outputPath, "prod"); - Object.assign(meta, pluginConfig.headers.prod); + config.mode = "production"; } + config.plugins.push(new IITCScript({ meta: meta, withMeta: true })); return config; }; From de2655bafeaba66ac373613fc6e81a27793ecb6c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 14 Jan 2022 20:42:27 +0100 Subject: [PATCH 209/275] build: add testing workflow --- .github/workflows/testing.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/testing.yml diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml new file mode 100644 index 000000000..23f569e9f --- /dev/null +++ b/.github/workflows/testing.yml @@ -0,0 +1,23 @@ +name: Build and Deploy Testing +on: + push: + branches: + - testing +jobs: + build-and-deploy-testing: + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2.3.1 + + - name: Build 🔧 + run: | + npm install + npm run build-testing + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@4.1.1 + with: + branch: dist # The branch the action should deploy to. + folder: releases # The folder the action should deploy. + clean: false # build is already clean (keep prod/dev) From 47765005b6320fcfba71fe44f6d42a3ef082c893 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 15 Jan 2022 10:09:38 +0100 Subject: [PATCH 210/275] fix inconsistency in wX strings --- src/code/dialogs/importDialog.js | 2 +- src/code/translations/English.json | 31 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/code/dialogs/importDialog.js b/src/code/dialogs/importDialog.js index c19173cf9..a2287ecd2 100644 --- a/src/code/dialogs/importDialog.js +++ b/src/code/dialogs/importDialog.js @@ -226,7 +226,7 @@ const ImportDialog = WDialog.extend({ } } displayInfo( - wX("IMP_COMP") + found + wX("PORT_FAKE") + faked + wX("USE_SWAP_INSTRUCT") + wX("dialog.import.success_message", { count: found, faked: faked }) ); // get the op out of batchmode, but do not update UI or run crosslinks yet diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 5630fcf06..177db772e 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -19,16 +19,16 @@ "AGES": " (ages ago)", "ALREADY_HAS_MARKER": "This portal already has a marker. Choose a different portal.", "AMAZ_TEAM_NAME": "Amazing Team Name.", - "ANCHOR ASSIGNMENT": " all outbound links", + "ANCHOR ASSIGNMENT": "Assign all outbound links to: ", "ANCHOR_GMAP": "Google Map", - "ANCHOR_PORTAL": "Anchor Portal ", + "ANCHOR_PORTAL": "Anchor Portal", "ANCHOR_PORTAL2": "Anchor Portal 2", "ANCHOR_PORTAL3": "Anchor Portal 3", - "ANCHOR1": "Anchor 1 ", - "ANCHOR2": "Anchor 2 ", - "ANCHOR3": "Anchor 3 ", + "ANCHOR1": "Anchor 1", + "ANCHOR2": "Anchor 2", + "ANCHOR3": "Anchor 3", "ANCHORS_AS_BOOKMARKS": "Anchors as bookmarks", - "API_KEY": " api key: ", + "API_KEY": "Rocks API key: ", "ASS_TO": "Assigned To", "ASSIGN LINK PROMPT": "Assign link from: {portalName}", "ASSIGN MARKER PROMPT": "Assign marker from: {portalName}", @@ -93,6 +93,7 @@ "DESCRIP_PLACEHOLD": "Description (optional)", "DestroyPortalAlert": "Destroy", "dialog.setcomment.portal_hardness": "Hardness", + "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplicate Operation", "END_PORT": "End Portal", @@ -124,7 +125,7 @@ "HG": "Homogeneous Field", "HOURS": " ({hours} hours ago)", "HOW_TO_VIDS": "

How-To Videos:

", - "IMP_COMP": "Import Complete. Found ", + "IMP_COMP": "", "IMP_NOPE": "Import Failed: {error}", "IMP_WAS_OP": "Import Wasabee Operation", "IMPORT_OP_SUCCESS": "Imported Operation: {opName} successfuly.", @@ -144,9 +145,9 @@ "LANG": "Language", "LEAVE": "Leave", "LetDecayPortalAlert": "Let Decay", - "LINK ASSIGNMENT": " Link Assignment", + "LINK ASSIGNMENT": "Assign link to: ", "LINK STATE PROMPT": "Link State", - "LINK STATE": "Set link status", + "LINK STATE": "Set link status: ", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", @@ -166,11 +167,11 @@ "MADRID": "Draw", "MANAGE_TEAM": "Manage {teamName}", "MANAGE": "Manage", - "MARKER ASSIGNMENT": " Marker Assignment", + "MARKER ASSIGNMENT": "Assign marker to: ", "MARKER LIST TITLE": "Marker List", "MARKER LIST": "Markers", "MARKER STATE PROMPT": "Marker Status", - "MARKER STATE": " Set marker state", + "MARKER STATE": "Set marker state: ", "MARKER_LIST": "Marker List: {opName}", "MARKERS BUTTON TITLE": "Markers", "MAX_SPLITS": "Max Splits", @@ -245,7 +246,7 @@ "PERM DENIED SHORT": "Permission denied", "PERMS": "{opName} permissions", "PLEASE_SELECT_PORTAL": "Please select a portal", - "PORT_FAKE": " portals. Faked ", + "PORT_FAKE": "", "PORTAL KEY LIST": "Key list for portal {portalName}", "PORTAL_COUNT": "{count} portals", "PORTAL": "Portal", @@ -301,7 +302,7 @@ "SET_COMMENT": "Set Comment", "SET_LCOMMENT": "Set Link Comment", "SET_LINK_COMMENT": "Set comment for link: ", - "SET_LINKS_ZONES": "Set Links to Zones ", + "SET_LINKS_ZONES": "Set Links to Zones", "SET_MARKER_COMMENT": "Set comment for marker on: ", "SET_MARKER_TYPE_TITLE": "Change marker type", "SET_MARKERS_ZONES": "Set Markers to Zones", @@ -320,7 +321,7 @@ "SKIP_CONFIRM_ENTITY": "Only ask for team/op", "SKIP_CONFIRM_NEVER": "Always ask", "SKIP_CONFIRM": "Skip confirmation", - "SOURCE_PORT": "Source Portal ", + "SOURCE_PORT": "Source Portal", "SQUAD": "Squad", "STARBURST TITLE": "Starburst", "STARBURST_DRAW": "Draw", @@ -380,7 +381,7 @@ "UPLOAD BUTTON HOVER": "UPLOAD {opName} (not currently on server)", "UPLOADED": "Successfully uploaded", "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": ". Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Please use a valid operation name", "UseVirusPortalAlert": "Use Virus", "VRLA DESC": "Depending on the number and type of Link Amps used, a lower source portal level might suffice.", From 4ea35b9ad528fbff6f5dac1f1bf0686376c6886d Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 15 Jan 2022 22:01:44 +0100 Subject: [PATCH 211/275] fix: addmarker can have concurrent DOM insertion --- src/code/dialogs/markerAddDialog.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index a9d34b7b7..b4afb917c 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -33,10 +33,10 @@ const MarkerAddDialog = WDialog.extend({ }, update: async function () { - this._type.innerHTML = ""; + this._type.textContent = ""; // zones can be populated even if portal not selected - this._zones.innerHTML = ""; // do we need to do this every time? the zone list can change while this dialog is open. + this._zones.textContent = ""; // do we need to do this every time? the zone list can change while this dialog is open. const zoneAll = L.DomUtil.create("option", null, this._zones); zoneAll.value = 0; zoneAll.textContent = "All"; // wX this @@ -47,8 +47,11 @@ const MarkerAddDialog = WDialog.extend({ } // clean and rebuild - this._assign.innerHTML = ""; - await this._getAgentMenu(this._assign); + const options = await this._getAgentMenu(); + this._assign.textContent = ""; + for (const option of options) { + this._assign.appendChild(option); + } this._selectedPortal = PortalUI.getSelected(); if (this._selectedPortal) { @@ -153,15 +156,17 @@ const MarkerAddDialog = WDialog.extend({ } else displayError(wX("ALREADY_HAS_MARKER")); }, - _getAgentMenu: async function (menu) { - let option = menu.appendChild(L.DomUtil.create("option", null)); + _getAgentMenu: async function () { + const options = []; + const option = L.DomUtil.create("option", null); option.value = ""; option.textContent = wX("UNASSIGNED"); + options.push(option); - if (!WasabeeMe.isLoggedIn()) return; + if (!WasabeeMe.isLoggedIn()) return options; const operation = getSelectedOperation(); - if (!operation.isOnCurrentServer()) return; + if (!operation.isOnCurrentServer()) return options; const alreadyAdded = new Set(); const me = await WasabeeMe.waitGet(); @@ -173,16 +178,17 @@ const MarkerAddDialog = WDialog.extend({ for (const a of tt.agents) { if (!alreadyAdded.has(a.id)) { alreadyAdded.add(a.id); - option = L.DomUtil.create("option"); + const option = L.DomUtil.create("option"); option.value = a.id; option.textContent = a.getName(); - menu.appendChild(option); + options.push(option); } } } catch (e) { console.error(e); } } + return options; }, }); From 5ffe347ea8e50eb69cf6408521aaca106dc5f0c0 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 15 Jan 2022 23:47:40 +0100 Subject: [PATCH 212/275] fb: update link/marker of selected op + add task promises --- src/code/firebaseSupport.ts | 85 +++++++++++++++++++++---- src/code/server.ts | 122 +++++++++++++++++++++++++++++++++++- 2 files changed, 193 insertions(+), 14 deletions(-) diff --git a/src/code/firebaseSupport.ts b/src/code/firebaseSupport.ts index dc500090e..e2a18eb8d 100644 --- a/src/code/firebaseSupport.ts +++ b/src/code/firebaseSupport.ts @@ -5,11 +5,17 @@ * simply pass the messages along using window.parent.postMessage. */ import { drawSingleTeam } from "./mapDrawing"; -import { opPromise, GetWasabeeServer } from "./server"; +import { + opPromise, + GetWasabeeServer, + getLinkPromise, + getMarkerPromise, +} from "./server"; import { makeSelectedOperation, removeOperation, changeOpIfNeeded, + getSelectedOperation, } from "./selectedOp"; import { updateLocalOp } from "./uiCommands"; import WasabeeOp from "./model/operation"; @@ -21,6 +27,8 @@ import WasabeeAgent from "./model/agent"; import { getJWT } from "./auth"; import WasabeeMe from "./model/me"; import { constants } from "./static"; +import WasabeeLink from "./model/link"; +import WasabeeMarker from "./model/marker"; // TODO: use a dedicated message channel: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging @@ -37,15 +45,18 @@ export function initFirebase() { iframe.id = frameID; iframe.addEventListener("load", () => { - port.onmessage = onMessage; - iframe.contentWindow.postMessage('init', '*', [channel.port2]); - - if (WasabeeMe.isLoggedIn()) { - postToFirebase({ - id: "wasabeeLogin", - method: "auto" - }); - } + port.onmessage = (ev) => { + if (ev.data === "ready") { + port.onmessage = onMessage; + if (WasabeeMe.isLoggedIn()) { + postToFirebase({ + id: "wasabeeLogin", + method: "auto", + }); + } + } + }; + iframe.contentWindow.postMessage("init", "*", [channel.port2]); }); $(document.body).append(iframe); @@ -79,6 +90,10 @@ async function onMessage(event: MessageEvent<{ data: WMessage }>) { // fallthrough case "Marker Assignment Change": // fallthrough + case "Task Status Change": + // fallthrough + case "Task Assignment Change": + // fallthrough case "Marker Status Change": // fallthrough case "Map Change": @@ -106,7 +121,14 @@ async function onMessage(event: MessageEvent<{ data: WMessage }>) { } async function opDataChange( - data: LinkAssignment | LinkState | MarkerAssignment | MarkerState | OpChange + data: + | LinkAssignment + | LinkState + | MarkerAssignment + | MarkerState + | TaskAssignment + | TaskState + | OpChange ) { let uid = data.updateID; if (data.cmd !== "Map Change") uid += data.cmd; @@ -127,17 +149,24 @@ async function opDataChange( return; } + const sop = getSelectedOperation(); + const cur = sop.ID === data.opID; + switch (data.cmd) { case "Link Assignment Change": + if (cur) handleLinkAssignement(sop, data); console.log(data); break; case "Link Status Change": + if (cur) handleLinkStatus(sop, data); console.log(data); break; case "Marker Assignment Change": + if (cur) handleMarkerAssignement(sop, data); console.log(data); break; case "Marker Status Change": + if (cur) handleMarkerStatus(sop, data); console.log(data); break; case "Map Change": @@ -155,9 +184,41 @@ async function opDataChange( console.error(e); } break; + default: + console.log(data); } } +async function handleLinkAssignement( + operation: WasabeeOp, + data: LinkAssignment +) { + const link = new WasabeeLink(await getLinkPromise(data.opID, data.linkID)); + operation.assignLink(link.ID, link.assignedTo); +} + +async function handleLinkStatus(operation: WasabeeOp, data: LinkState) { + const link = new WasabeeLink(await getLinkPromise(data.opID, data.linkID)); + operation.setLinkState(link.ID, link.state); +} + +async function handleMarkerAssignement( + operation: WasabeeOp, + data: MarkerAssignment +) { + const marker = new WasabeeMarker( + await getMarkerPromise(data.opID, data.markerID) + ); + operation.assignMarker(marker.ID, marker.assignedTo); +} + +async function handleMarkerStatus(operation: WasabeeOp, data: MarkerState) { + const marker = new WasabeeMarker( + await getMarkerPromise(data.opID, data.markerID) + ); + operation.setMarkerState(marker.ID, marker.state); +} + type AgentLocation = { cmd: "Agent Location Change"; msg: TeamID; @@ -265,7 +326,7 @@ export function postToFirebase(message: Partial) { if ( message.id == "analytics" && localStorage[window.plugin.wasabee.static.constants.SEND_ANALYTICS_KEY] != - "true" + "true" ) return; diff --git a/src/code/server.ts b/src/code/server.ts index a4c77e7ea..dc9e035e3 100644 --- a/src/code/server.ts +++ b/src/code/server.ts @@ -8,6 +8,9 @@ import type WasabeeAgent from "./model/agent"; import type WasabeeTeam from "./model/team"; import type { WDKey } from "./wd"; import { getJWT } from "./auth"; +import type Task from "./model/task"; +import type WasabeeLink from "./model/link"; +import type WasabeeMarker from "./model/marker"; export default function () { return GetWasabeeServer(); @@ -407,6 +410,117 @@ export function delPermPromise( return genericDelete(`/api/v1/draw/${opID}/perms`, fd); } +export function getLinkPromise(opID: OpID, taskID: TaskID) { + return genericGet(`/api/v1/draw/${opID}/link/${taskID}`); +} + +export function getMarkerPromise(opID: OpID, taskID: TaskID) { + return genericGet(`/api/v1/draw/${opID}/marker/${taskID}`); +} + +// tasks + +export function taskGetPromise(opID: OpID, taskID: TaskID) { + return genericGet(`/api/v1/draw/${opID}/task/${taskID}`); +} + +export function taskOrderPromise(opID: OpID, taskID: TaskID, order: number) { + const fd = new FormData(); + fd.append("order", `${order}`); + return genericPut( + `/api/v1/draw/${opID}/task/${taskID}/order`, + fd + ); +} + +export function taskAssignPromise( + opID: OpID, + taskID: TaskID, + gids: GoogleID[] +) { + const fd = new FormData(); + for (const gid of gids) { + fd.append("agent[]", gid); + } + return genericPut( + `/api/v1/draw/${opID}/task/${taskID}/assign`, + fd + ); +} + +export function taskDeleteAssignPromise(opID: OpID, taskID: TaskID) { + return genericDelete( + `/api/v1/draw/${opID}/task/${taskID}/assign` + ); +} + +export function taskCommentPromise( + opID: OpID, + taskID: TaskID, + comment: string +) { + const fd = new FormData(); + fd.append("comment", comment); + return genericPut( + `/api/v1/draw/${opID}/task/${taskID}/comment`, + fd + ); +} + +export function taskCompletePromise( + opID: OpID, + taskID: TaskID, + complete: boolean +) { + const action = complete ? "complete" : "incomplete"; + return genericPut( + `/api/v1/draw/${opID}/task/${taskID}/${action}` + ); +} + +export function taskAckPromise(opID: OpID, taskID: TaskID) { + return genericPut( + `/api/v1/draw/${opID}/task/${taskID}/acknowledge` + ); +} + +export function taskRejectPromise(opID: OpID, taskID: TaskID) { + return genericPut( + `/api/v1/draw/${opID}/task/${taskID}/reject` + ); +} + +export function taskClaimPromise(opID: OpID, taskID: TaskID) { + return genericPut(`/api/v1/draw/${opID}/task/${taskID}/claim`); +} + +export function taskZonePromise(opID: OpID, taskID: TaskID, zone: ZoneID) { + const fd = new FormData(); + fd.append("zone", `${zone}`); + return genericPut( + `/api/v1/draw/${opID}/task/${taskID}/zone`, + fd + ); +} + +export function taskDeltaPromise(opID: OpID, taskID: TaskID, delta: number) { + const fd = new FormData(); + fd.append("delta", `${delta}`); + return genericPut(`/api/v1/draw/${opID}/task/${taskID}/delta`); +} + +export function taskAddDependPromise(opID: OpID, taskID: TaskID, dep: TaskID) { + return genericPut( + `/api/v1/draw/${opID}/task/${taskID}/depend/${dep}` + ); +} + +export function taskDelDependPromise(opID: OpID, taskID: TaskID, dep: TaskID) { + return genericDelete( + `/api/v1/draw/${opID}/task/${taskID}/depend/${dep}` + ); +} + // local change: none // cache: none export function assignMarkerPromise( opID: OpID, @@ -419,7 +533,11 @@ export function assignMarkerPromise( } // performs a link assignment on the server, sending notifications -export function assignLinkPromise(opID: OpID, linkID: LinkID, agentID) { +export function assignLinkPromise( + opID: OpID, + linkID: LinkID, + agentID: GoogleID +) { const fd = new FormData(); fd.append("agent", agentID); return genericPost(`/api/v1/draw/${opID}/link/${linkID}/assign`, fd); @@ -641,7 +759,7 @@ function genericPost( }); } -function genericPut(url: string, formData: FormData) { +function genericPut(url: string, formData?: FormData) { return generic({ url: url, method: "PUT", From d9be0a448bd3434c1ad3c4126fffa33d63baf47d Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 15 Jan 2022 23:48:26 +0100 Subject: [PATCH 213/275] fix: task are set to pending on assign and assigned when removing the assignement... --- src/code/model/task.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/model/task.ts b/src/code/model/task.ts index af49951d2..52cb94548 100644 --- a/src/code/model/task.ts +++ b/src/code/model/task.ts @@ -67,7 +67,7 @@ export default class Task { } assign(gid?: GoogleID) { - if (gid !== this.assignedTo) this._state = gid ? "pending" : "assigned"; + if (gid !== this.assignedTo) this._state = gid ? "assigned" : "pending"; this.assignedTo = gid ? gid : null; } From 5a6a50f35508222cf522611da4571438bbccc347 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 16 Jan 2022 00:12:14 +0100 Subject: [PATCH 214/275] fb: warn permission blocked --- src/code/firebaseSupport.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/code/firebaseSupport.ts b/src/code/firebaseSupport.ts index e2a18eb8d..763041bac 100644 --- a/src/code/firebaseSupport.ts +++ b/src/code/firebaseSupport.ts @@ -62,7 +62,16 @@ export function initFirebase() { $(document.body).append(iframe); } -async function onMessage(event: MessageEvent<{ data: WMessage }>) { +async function onMessage( + event: MessageEvent<{ data: WMessage } | "permission-blocked"> +) { + if (event.data === "permission-blocked") { + displayWarning( + `Visit ${constants.FIREBASE_IFRAME} and press the button to authorize live updates. You will need to reload IITC afterward.`, + true + ); + return; + } const data = event.data.data; switch (data.cmd) { case "Agent Location Change": From 6d49d41bd95c193deb8052937bcfbcb51a307612 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 16 Jan 2022 12:20:37 +0100 Subject: [PATCH 215/275] fix: QD guides fixup 9f623c49b6c990a49c96889d890870709a42a74b --- src/code/buttons/quickdrawButton.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/code/buttons/quickdrawButton.js b/src/code/buttons/quickdrawButton.js index c4255530c..74f0199da 100644 --- a/src/code/buttons/quickdrawButton.js +++ b/src/code/buttons/quickdrawButton.js @@ -141,6 +141,7 @@ const QuickDrawControl = L.Handler.extend({ window.map.on("wasabee:portal:click", this._portalClicked, this); window.map.on("wasabee:op:select", this._opchange, this); window.map.on("keyup", this._keyUpListener, this); + window.map.on("mousemove", this._onMouseMove, this); }, removeHooks: function () { @@ -163,6 +164,7 @@ const QuickDrawControl = L.Handler.extend({ window.map.off("wasabee:portal:click", this._portalClicked, this); window.map.off("wasabee:op:select", this._opchange, this); window.map.off("keyup", this._keyUpListener, this); + window.map.off("mousemove", this._onMouseMove, this); }, _opchange: function () { @@ -197,6 +199,12 @@ const QuickDrawControl = L.Handler.extend({ } }, + _onMouseMove: function (e) { + if (e.latlng) { + this._guideUpdate(e); + } + }, + _guideUpdate: function (e) { if (!this._guideLayerGroup) return; for (const l of this._guideLayerGroup.getLayers()) { From eae1a043976a346dd47046759771aed3131555e4 Mon Sep 17 00:00:00 2001 From: Sebastien - fisher01 Date: Sun, 16 Jan 2022 20:12:18 -0500 Subject: [PATCH 216/275] Added the mobile app download link in the about dialog (mobile only) --- src/code/dialogs/about.js | 5 +++++ src/code/translations/English.json | 1 + 2 files changed, 6 insertions(+) diff --git a/src/code/dialogs/about.js b/src/code/dialogs/about.js index aa9223491..930586fce 100644 --- a/src/code/dialogs/about.js +++ b/src/code/dialogs/about.js @@ -29,6 +29,11 @@ const AboutDialog = WDialog.extend({ // wX is the translation call, it looks up the string in the agent's chosen language support.innerHTML = wX("SUPPORT_INSTRUCT"); + if (this._smallScreen) { + const mobileApp = L.DomUtil.create("div", null, html); + mobileApp.innerHTML = wX("WASABEE_MOBILE_APP"); + } + const tips = L.DomUtil.create("div", null, html); tips.innerHTML = "

Show your love

Patreon"; diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 177db772e..c5d7d00f5 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -388,6 +388,7 @@ "VRLA": "L8+some VRLA", "WASABEE BUTTON TITLE": "Wasabee: It is green and makes smurfs cry.", "WASABEE_D_LIST": "Input Defensive Key Count", + "WASABEE_MOBILE_APP": "

Wasabee App:

", "WD BUTTON TITLE": "Log Defensive Keys", "WD BUTTON": "W-D Keys", "WRITE_SHORT": "RW", From 0d557c1f7f4f0e8cbca897190b178b05548b9f24 Mon Sep 17 00:00:00 2001 From: Sebastien - fisher01 Date: Mon, 17 Jan 2022 08:54:23 -0500 Subject: [PATCH 217/275] rename wX string for mobile app DL link --- src/code/dialogs/about.js | 2 +- src/code/translations/English.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code/dialogs/about.js b/src/code/dialogs/about.js index 930586fce..e9cdf3d3b 100644 --- a/src/code/dialogs/about.js +++ b/src/code/dialogs/about.js @@ -31,7 +31,7 @@ const AboutDialog = WDialog.extend({ if (this._smallScreen) { const mobileApp = L.DomUtil.create("div", null, html); - mobileApp.innerHTML = wX("WASABEE_MOBILE_APP"); + mobileApp.innerHTML = wX("dialog.about.download_mobile_app"); } const tips = L.DomUtil.create("div", null, html); diff --git a/src/code/translations/English.json b/src/code/translations/English.json index c5d7d00f5..0f8e7f02e 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -92,6 +92,7 @@ "DELETE_OP": "Delete {opName}", "DESCRIP_PLACEHOLD": "Description (optional)", "DestroyPortalAlert": "Destroy", + "dialog.about.download_mobile_app": "

Wasabee App:

", "dialog.setcomment.portal_hardness": "Hardness", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", "DRAW TOOLS FORMAT": "Draw Tools Format", @@ -388,7 +389,6 @@ "VRLA": "L8+some VRLA", "WASABEE BUTTON TITLE": "Wasabee: It is green and makes smurfs cry.", "WASABEE_D_LIST": "Input Defensive Key Count", - "WASABEE_MOBILE_APP": "

Wasabee App:

", "WD BUTTON TITLE": "Log Defensive Keys", "WD BUTTON": "W-D Keys", "WRITE_SHORT": "RW", From e1b308ed355d3e7c10caf2772685d16ae74c8772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20-=20fisher01?= Date: Mon, 17 Jan 2022 20:38:21 +0100 Subject: [PATCH 218/275] Translations Crowdin updates (#317) --- src/code/translations/Danish.json | 145 +++++++------- src/code/translations/Filipino.json | 49 +++-- src/code/translations/French.json | 155 +++++++-------- src/code/translations/German.json | 181 +++++++++--------- src/code/translations/Italian.json | 185 +++++++++--------- src/code/translations/Portuguese.json | 183 +++++++++--------- src/code/translations/Russian.json | 91 +++++---- src/code/translations/Spanish.json | 263 +++++++++++++------------- 8 files changed, 654 insertions(+), 598 deletions(-) diff --git a/src/code/translations/Danish.json b/src/code/translations/Danish.json index 2df7fe590..682f3b40b 100644 --- a/src/code/translations/Danish.json +++ b/src/code/translations/Danish.json @@ -2,7 +2,7 @@ "ABOUT_WASABEE": "Om Wasabee", "acknowledged": "Anerkendt", "ADD LINK TITLE": "Tilføj Links", - "ADD MARKER TITLE": "Tilføj Markøre", + "ADD MARKER TITLE": "Tilføj Markører", "ADD_AGENT": "Tilføj Agent: ", "ADD_BL": "Tilføj baglinie: ", "ADD_BUTTON_LINKS": "Tilføj alle links med det samme.", @@ -14,21 +14,21 @@ "ADD": "Tilføj", "ADD1": "Tilføj første link", "ADD2": "Tilføj andet link", - "AGENT_STATS": "Agent Stats", + "AGENT_STATS": "Agent Statistik", "AGENT": "Agent", "AGES": " (for længe siden)", "ALREADY_HAS_MARKER": "Denne portal har allerede en markør, vælg en anden Portal.", "AMAZ_TEAM_NAME": "Fantastisk holdnavn.", - "ANCHOR ASSIGNMENT": " Alle udgående links", - "ANCHOR_GMAP": "Google Map", - "ANCHOR_PORTAL": "Anker Portal ", + "ANCHOR ASSIGNMENT": "Tilknyt alle udgående links til: ", + "ANCHOR_GMAP": "Google Maps", + "ANCHOR_PORTAL": "Anker Portal", "ANCHOR_PORTAL2": "Anker Portal 2", "ANCHOR_PORTAL3": "Anker Portal 3", - "ANCHOR1": "Anker 1 ", - "ANCHOR2": "Anker 2 ", - "ANCHOR3": "Anker 3 ", + "ANCHOR1": "Anker 1", + "ANCHOR2": "Anker 2", + "ANCHOR3": "Anker 3", "ANCHORS_AS_BOOKMARKS": "Ankere som bookmarks", - "API_KEY": " api key: ", + "API_KEY": "Rocks API-nøgle: ", "ASS_TO": "Tildelt", "ASSIGN LINK PROMPT": "Tilføj link fra: {portalName}", "ASSIGN MARKER PROMPT": "Tildel markør fra: {portalName}", @@ -39,19 +39,18 @@ "ASSIGNED_ONLY": "Kun tildelt", "assigned": "Tildelt", "AUTH INCOMPAT": "Du har aktiveret et plugin i TamperMonkey, der er inkompatibelt med Wasabee", - "AUTH IOS": "På iOS skal du bruge \"Log ind\". Hvis det mislykkes, skal du bruge 'Webview-login' og derefter bruge 'Verify Webview'-knappen for at fuldføre processen.", "AUTH REQUIRED": "Godkendelse påkrævet", "AUTH TOKEN REJECTED": "Afsendelse af godkendelsestoken til serveren blev afvist: {error}", "AUTH_SELECT_ACCOUNT": "Vælg konto", "AUTO_DRAWS": "Auto-tegne", "AUTODRAWS": "Wasabee Indstillinger for automatisk tegning", - "AUTODRAW_PORTALS_SET": "Portals", - "autodraw.common.draw_button": "Draw", - "autodraw.flipflop.result": "Flip flop: found {count} links", - "autodraw.onion.variant": "Option", - "autodraw.onion.variant.equilateral": "~Equilateral", - "autodraw.onion.variant.grow": "Let it grow", - "autodraw.onion.variant.balanced": "Perfectly balanced", + "AUTODRAW_PORTALS_SET": "Portaler", + "autodraw.common.draw_button": "Tegn", + "autodraw.flipflop.result": "Flip flop: fundet {count} links", + "autodraw.onion.variant": "Valg", + "autodraw.onion.variant.equilateral": "~Ligesidet", + "autodraw.onion.variant.grow": "Lad det vokse", + "autodraw.onion.variant.balanced": "Perfekt balanceret", "AUTOLOAD_RATE": "Rate for anmodning om portaldetaljer (ms)", "AUTOLOAD": "Indlæs automatisk manglende portaloplysninger", "AUTOMARK STOP": "Auto-markering stoppede på grund af, at portaler ikke blev indlæst", @@ -70,7 +69,6 @@ "CLEAR LINKS": "Ryd links", "CLEAR MARKERS": "Ryd markører", "CLEAR_EVERYTHING": "Ryd portaler/links/markører for aktuel OP", - "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Ryd Data", "CLEAROPS BUTTON": "Ryd Data", "CLEAROPS PROMPT": "Ryd alle lokale OPS. Ops vil blive gendannet ved næste download.", @@ -94,6 +92,9 @@ "DELETE_OP": "Slet {opName}", "DESCRIP_PLACEHOLD": "Beskrivelse (valgfri)", "DestroyPortalAlert": "Ødelæg/Skyd", + "dialog.about.download_mobile_app": "

Wasabee App:

", + "dialog.setcomment.portal_hardness": "Sværhedsgrad", + "dialog.import.success_message": "Import fuldført. Fandt {count} portaler og brugte {faked} forfalskede. Brug venligst swap-funktionen til at flytte forfalskede portaler til de rigtige portaler på samme sted. Zoom ind på 'Indlæser' portaler i tjeklisten kan tvinge dem til at indlæse.", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplikere Operation", "END_PORT": "Slut Portal ", @@ -103,13 +104,13 @@ "EXPORT": "Eksporter: ", "FAKED": "forfalsket: [{portalId}]", "FANFIELD": "Tegn", - "FANFIELD2": "Tegne Fan Field", + "FANFIELD2": "Tegn Fan Field", "FarmPortalMarker": "Farm", "FLIP_FLOP_NAME": "Flip flop", "FLIP_FLOP_TITLE": "Flip flop", - "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", - "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", - "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", + "FLIP_FLOP_DESC": "Fra et givet anker, et sæt synlige portaler og et antal SBUL, find et fanefelt til at smide links fra anker ved at mindske afstanden for at undgå at søge nøgler.", + "FLIP_FLOP_INSTRUCTION": "Vælg en portal, zoom for at se nok portaler og tryk på Tegn. Når et fanfelt er fundet, du kan søge efter andre ankre for gentagne linkninger", + "FLIP_FLOP_FIND_ANCHORS": "Find andre ankre", "FROM_1-2": "fra basislinie 1-2", "FROM_1-3": "fra basislinie 1-3", "FROM_2-3": "fra basislinie 2-3", @@ -124,12 +125,12 @@ "HF_REDRAW_BUTTON": "Gentegn", "HG": "Homogent felt", "HOURS": " ({hours} timer siden)", - "HOW_TO_VIDS": "

Sådan gør du videoer:

", - "IMP_COMP": "Import fuldført. Fundet", + "HOW_TO_VIDS": "

Sådan-gør-du videoer:

", + "IMP_COMP": "", "IMP_NOPE": "Import mislykkedes.", "IMP_WAS_OP": "Importer Wasabee Operation", "IMPORT_OP_SUCCESS": "Importeret Operation: {opName} lykkedes.", - "IMPORT_OP_TITLE": "Import Op: {date}", + "IMPORT_OP_TITLE": "Importer Op: {date}", "IMPORT_OP": "Importer Operation", "IMPOSSIBLE": "Umulig", "INGNAME_GID": "Ingress navn eller GoogleID", @@ -145,9 +146,9 @@ "LANG": "Sprog", "LEAVE": "Forlad", "LetDecayPortalAlert": "Lad forfalde", - "LINK ASSIGNMENT": "Link opgave", + "LINK ASSIGNMENT": "Tildel link til: ", "LINK STATE PROMPT": "Link tilstand", - "LINK STATE": "Indstil linkstatus", + "LINK STATE": "Angiv link-status: ", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", @@ -156,26 +157,26 @@ "LOADING1": "Loader: [{portalGuid}]", "LOC_PROC": "Beliggenhed behandlet", "LOCATION SUB": "Lokation registreret", - "LOCFRMSER": " (lokal og fra server)", - "LOG IN": "Log In", + "LOCFRMSER": " (lokalt og fra server)", + "LOG IN": "Log Ind", "LOG_OUT": "Log Ud", "MADRID_SET_1": "Vælg regionen for basislinket Anker 2 til Anker 3", "MADRID_SET_2": "Vælg regionen for basislinket Anker 3 til Anker 1", "MADRID_SET_3": "Vælg regionen for basislinket Anker 1 til Anker 2", - "MADRID_TITLE": "Madrid Protocol", + "MADRID_TITLE": "Madrid Protokol", "MADRID_WAS_TAKEN": "Madrid Protocol", "MADRID": "Tegn", "MANAGE_TEAM": "Administrer {teamName}", "MANAGE": "Administrer", - "MARKER ASSIGNMENT": "Markør Opgave", + "MARKER ASSIGNMENT": "Tildel markør til: ", "MARKER LIST TITLE": "Markør Liste", "MARKER LIST": "Markører", "MARKER STATE PROMPT": "Markør Status", - "MARKER STATE": "Indstil markørtilstand", + "MARKER STATE": "Angiv markørtilstand: ", "MARKER_LIST": "Markør Liste: {opName}", "MARKERS BUTTON TITLE": "Markører", "MAX_SPLITS": "Max Delinger", - "MAX": "Fan Field", + "MAX": "Fane Felt", "MeetAgentPortalMarker": "Mød Agent", "MERGE ON UPDATE": "Flet ved opdatering", "MERGE_CHANGES_LOCAL": "Lokale ændringer", @@ -188,13 +189,13 @@ "MERGE_TITLE": "Flet lokal&fjern OP", "MIN_SRC_PORT_LVL": "Minimums level påkrævet på kildeportalen", "MINUTES": " ({minutes} minutter siden)", - "MM": "Multimax", - "MM_BOTH_SIDE": "Use both base sides", - "MM_INSERT_ORDER": "Insert at the end", - "MM_SET_ALL_PORTALS": "All visible portals", - "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM": "Multimaks", + "MM_BOTH_SIDE": "Brug begge base sider", + "MM_INSERT_ORDER": "Indsæt i slutningen", + "MM_SET_ALL_PORTALS": "Alle synlige portaler", + "MM_SET_ALL_KEYS": "Alle GetKey-Markører", "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", - "MM_SPINE": "Spine", + "MM_SPINE": "Rygrad", "MULTI_M_TITLE": "Tegn Max Lag", "MULTI_M": "Tegn", "MUST_NOT_BE_EMPTY": "Må ikke være tom", @@ -212,25 +213,25 @@ "NO_LABEL": "Ingen etiket sat", "NO_STOCK_INTEL": "Wasabee understøtter ikke stock intel tegninger", "NO_TITLE": "Ingen titel angivet", - "NO LONGER AVAILABLE": "Resource removed from server: {error}", - "NO LONGER AVAILABLE SHORT": "Resource removed from server", + "NO LONGER AVAILABLE": "Ressource fjernet fra serveren: {error}", + "NO LONGER AVAILABLE SHORT": "Ressource fjernet fra serveren", "NOT LOGGED IN SHORT": "Ikke logget ind", "NOT LOGGED IN": "Ikke logget ind: {error}", - "NOT_LOADED": "Not fully loaded, try again.", + "NOT_LOADED": "Ikke fuldt indlæst, prøv igen.", "NOT_SET": "ikke indstillet", "NTNAME": "Navn", "OK": "OK", "ON_HAND": "Har Allerede", - "ONION_WAS_TAKEN": "Onion", - "ONION": "Draw", + "ONION_WAS_TAKEN": "Onion/løg", + "ONION": "Tegn", "ONLY_DT_IMP": " (kun for DrawTools-import)", "OP DELETED": "Operationen fjernet fra serveren: {opID}", "OP PERM DENIED": "Tilladelse nægtet til operationen: {opID}", "OP_BUTTON": "Operation", - "OP_CHECKLIST": "Operation Checklist: {opName}", + "OP_CHECKLIST": "Operation Tjekliste: {opName}", "OP_NAME_UNSET": "Operationsnavn blev deaktiveret", "OP_PERMS": "Op Tilladelser", - "OP_SETTINGS_BUTTON": "Op ⚙", + "OP_SETTINGS_BUTTON": "Op Indstillinger ⚙", "OP_SETTINGS_TITLE": "Op Indstillinger", "OPEN_REQUEST": "[åbn anmodning]", "OPER_COLOR": "Operation Farve: ", @@ -242,11 +243,11 @@ "OtherPortalAlert": "Andet", "PASTE_INSTRUCT": "Indsæt en Wasabee draw-eksport her.\n\nWasabee kan ikke importere stock intel-formatet.\n\nDer er eksperimentel understøttelse af import af IITC DrawTools-formatet.\n\nFør du importerer DrawTools-formatet, skal du forhåndsvise områderne og sørge for, at alle portalerne indlæses så IITC har dem cachelagret. Alle portaler, der ikke er pre-cached, vil blive forfalsket.\n\nDu bliver nødt til at bruge 'swap'-funktionen til at flytte ankre fra de falske portaler til de rigtige portaler (de bør være på den korrekte placering, bare ikke forbundet med portal.\n\nCachede portaler er muligvis ikke korrekt navngivet.", "pending": "Afventer", - "PERM DENIED": "Permission denied: {error}", - "PERM DENIED SHORT": "Permission denied", + "PERM DENIED": "Tilladelse nægtet: {error}", + "PERM DENIED SHORT": "Tilladelse nægtet", "PERMS": "{opName} tilladelser", "PLEASE_SELECT_PORTAL": "Vælg venligst en portal", - "PORT_FAKE": " portaler. Forfalsket ", + "PORT_FAKE": "", "PORTAL KEY LIST": "Nøgleliste for portal {portalName}", "PORTAL_COUNT": "{count} portaler", "PORTAL": "Portal", @@ -263,7 +264,7 @@ "QDSTART": "Klik på den første ankerportal.", "READ_SHORT": "L", "READ": "Læs", - "RechargePortalAlert": "Recharge", + "RechargePortalAlert": "Genoplad", "REFERENCE_TIME": "Referencetid: ", "REM_LOC_CP": "Fjern lokal kopi af {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Vil du permanent fjerne {team Name} fra Wasabi-serveren?", @@ -275,14 +276,14 @@ "REQUIRED": "Påkrævet", "RESET": "Nulstil", "REVERSE": "Endevend", - "ROCKS_COM": "enl.rocks community: ", + "ROCKS_COM": "enl.rocks fællesskab: ", "ROLE": "Rolle", "SAVELINKS TITLE": "Gem Links", "SAVELINKS_DRAW": "Gem Links", "SAVELINKS": "Gem Links", "SECONDS": " ({seconds} sekunder siden)", "SEL_SB_ANCHOR": "Vælg ankerportal.", - "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", + "SEL_SB_ANCHOR2": "Zoom ud. Sørg for, at alle portaler er indlæst, og klik derefter på Tegn.", "SEL_SL_ANCHOR": "Vælg den portal, du vil gemme links til. Klik på knappen Gem links og se på tjeklisten.", "SEL_SRC_ANC2": "Vælg både Kilde og Anker 2", "SEL_SRC_PORT": "Vælg en kildeportal", @@ -290,7 +291,7 @@ "SELECT_FAN_PORTALS": "Vælg en ankerportal, en startportal og en slutportal, og fokuser over markområdet.", "SELECT_FAN_PORTALS2": "Vent på, at alle portaler er indlæst, og klik derefter på tegn.", "SELECT_INSTRUCTIONS": "Vælg to ankerportaler, og zoom derefter over rygsøjlen.", - "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", + "SELECT_ONION_PORTALS": "Lag bygges indefra og ud. Zoom ind til midten, og vælg startportal, og zoom derefter ud til området.", "SELF SWAP": "Kan ikke bytte en portal med sig selv! Vælg en anden portal.", "SEND ANALYTICS": "Send anonyme analysedata", "SEND LOCATION": "Send placering", @@ -302,7 +303,7 @@ "SET_COMMENT": "Indstil kommentar", "SET_LCOMMENT": "Indstil linkkommentar", "SET_LINK_COMMENT": "Indstil kommentar til link: ", - "SET_LINKS_ZONES": "Indstil links til zoner ", + "SET_LINKS_ZONES": "Sæt links til zoner", "SET_MARKER_COMMENT": "Sæt kommentar til markør på: ", "SET_MARKER_TYPE_TITLE": "Skift markørtype", "SET_MARKERS_ZONES": "Indstil markører til zoner", @@ -311,7 +312,7 @@ "SET_PCOMMENT": "Indstil portalkommentar: {portalName}", "SET_PORT_COMMENT": "Indstil kommentar til portal: ", "SET_PORTAL_COMMENT": "Indstil portalkommentar", - "SET": "set", + "SET": "indstil", "SETTINGS": "Wasabee Indstillinger", "SKINS_AVAILABLE": "Der er {count} tilgængelige skins.", "SKINS_BUTTON": "Konfigurer skins", @@ -321,7 +322,7 @@ "SKIP_CONFIRM_ENTITY": "Spørg kun for hold/op", "SKIP_CONFIRM_NEVER": "Spørg altid", "SKIP_CONFIRM": "Spring bekræftelse over", - "SOURCE_PORT": "Kildeportal ", + "SOURCE_PORT": "Kildeportal", "SQUAD": "hold", "STARBURST TITLE": "Starburst", "STARBURST_DRAW": "Tegn", @@ -333,7 +334,7 @@ "SWAP TITLE": "Byt portaler", "SWAP WITH": " med ", "SWAP": "Byt", - "SYNC DONE": "Download Complete
Click HERE for hints, tips, and documentation.", + "SYNC DONE": "Download Komplet
Klik HER for tips, tips og dokumentation.", "SYNC": "Download tilgængelige operationer", "TARGET SENT": "Mål sendt", "TEAM STATE": "Del placering", @@ -343,11 +344,20 @@ "TEAMS BUTTON TITLE": "Liste over Wasabee-holdene", "TEAMS BUTTON": "Hold", "TO_PORT": "Til Portal", - "toolbar.quick_delete.apply.text": "Apply", - "toolbar.quick_delete.apply.title": "Delete selected links/markers", - "toolbar.quick_delete.cancel.text": "Cancel", - "toolbar.quick_delete.cancel.title": "Cancel", - "toolbar.quick_delete.title": "Quick delete", + "toolbar.quick_delete.apply.text": "Anvend", + "toolbar.quick_delete.apply.title": "Slet valgte links/markører", + "toolbar.quick_delete.cancel.text": "Annuller", + "toolbar.quick_delete.cancel.title": "Annuller", + "toolbar.quick_delete.stop.text": "Stop", + "toolbar.quick_delete.stop.title": "Afslut slettetilstand", + "toolbar.quick_delete.title": "Hurtigt slet", + "toolbar.quick_delete.tooltip.toggle_mode": "Click on features to mark for deletion", + "toolbar.quick_delete.tooltip.quick_mode": "Click on features to delete instantly", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Vælg stjerneanker", + "toolbar.quick_draw.tooltip.star_mode.portal": "Vælg en portal", + "toolbar.quick_draw.tooltip.single_mode.first": "Klik på den første portal", + "toolbar.quick_draw.tooltip.single_mode.next": "Klik på den næste portal", + "toolbar.quick_draw.tooltip.portal_fail": "Portaldata ikke indlæst, prøv venligst igen", "TRAWL SKIP TILES": "Trawl Skip fliser", "TRAWL TITLE": "Trawl baner", "TRAWL WARNING": "Dette vil indlæse flisedataene under alle tegnede links. Dette er en langsom proces.", @@ -363,7 +373,7 @@ "UNKNOWN": "Ukendt", "UPDATE HOVER NOT CHANGED": "{opName} ikke ændret lokalt", "UPDATE HOVER": "OPDATER {opName} på serveren", - "UPDATE PERM DENIED": "You do not have permission to update", + "UPDATE PERM DENIED": "Du har ikke rettigheder til at opdatere", "UPDATE_CONFLICT_DESC": "OP er blevet ændret på serveren siden sidste synkronisering. Ønsker du at erstatte serverversionen med den nuværende?", "UPDATE_CONFLICT_TITLE": "Konflikt opdaget med server", "UPDATE_COUNT": "Opdater optælling", @@ -372,7 +382,7 @@ "UPLOAD BUTTON HOVER": "UPLOAD {opName} (ikke på serveren i øjeblikket)", "UPLOADED": "Uploadet", "USE PANES ON MOBILE": "Brug rammer (skal genindlæses)", - "USE_SWAP_INSTRUCT": ". Brug venligst swap-funktionen til at flytte falske portaler til de rigtige portaler på samme sted. Zoom ind på 'Loading'-portalerne i tjeklisten kan tvinge dem til at indlæse.", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Brug venligst et gyldigt operationsnavn", "UseVirusPortalAlert": "Brug Virus", "VRLA DESC": "Afhængigt af antallet og typen af anvendte linkforstærkere kan et lavere kildeportal level være tilstrækkeligt.", @@ -381,8 +391,6 @@ "WASABEE_D_LIST": "Input antal forsvarsnøgler", "WD BUTTON TITLE": "Log forsvarsnøgler", "WD BUTTON": "W-D Nøgler", - "WEBVIEW VERIFY": "Bekræft webvisning", - "WEBVIEW": "Webview Log på (iOS)", "WRITE_SHORT": "S", "WRITE": "Skrive", "WSERVER": "Server: {url}", @@ -396,7 +404,6 @@ "CHECKLIST BUTTON": "Kontrollere", "CLEAROPS BUTTON": "Klar", "EXPORT OP": "Eksporter", - "FAN_FIELD3": "Fan", "FANFIELD": "Tegn", "FANFIELD2": "Tegn Fan Field", "KEYS": "Nøgler", @@ -404,7 +411,7 @@ "LOG_OUT": "Log Ud", "MARKER LIST": "Markørere", "MARKERS BUTTON TITLE": "Markørere", - "MAX": "Fan", + "MAX": "Fan/Vifte", "MM": "Multi", "MULTI_M_TITLE": "Tegn Max Lag", "MULTI_M": "Tegn", @@ -412,7 +419,7 @@ "OPS BUTTON": "Vælg OP", "QD END": "Stop", "STARBURST_DRAW": "Tegn", - "STARBURST": "Star", + "STARBURST": "Stjerne", "TEAMS BUTTON": "Hold", "WD BUTTON": "W-D Nøgler" } diff --git a/src/code/translations/Filipino.json b/src/code/translations/Filipino.json index b80b7c071..781b8dd8f 100644 --- a/src/code/translations/Filipino.json +++ b/src/code/translations/Filipino.json @@ -9,7 +9,7 @@ "ADD_LINKS": "Magdagdag ng Link", "ADD_MARKER": "Magdagdag ng Marker", "ADD_NEW_OP": "Magdagdag ng Bagong Op", - "ADD_SUCC_INSTR": "Matagumpay na naidagdag, kailangan paganahin ng mga miyembro ng pangkat sa Wasabee website bago it lumabas sa listahan nila", + "ADD_SUCC_INSTR": "Matagumpay na naidagdag", "ADD_ZONE": "Add Zone", "ADD": "Magdagdag", "ADD1": "Add first link", @@ -19,16 +19,16 @@ "AGES": " (matagal na panahon)", "ALREADY_HAS_MARKER": "May Marker ang portal na ito. Pumili ng ibang portal.", "AMAZ_TEAM_NAME": "Malupet na Pangalan ng Pangkat", - "ANCHOR ASSIGNMENT": " lahat ng outbound links", + "ANCHOR ASSIGNMENT": "Assign all outbound links to: ", "ANCHOR_GMAP": "Google Map", - "ANCHOR_PORTAL": "Anchor Portal ", + "ANCHOR_PORTAL": "Anchor Portal", "ANCHOR_PORTAL2": "Anchor Portal 2", "ANCHOR_PORTAL3": "Anchor Portal 3", - "ANCHOR1": "Anchor 1 ", - "ANCHOR2": "Anchor 2 ", - "ANCHOR3": "Anchor 3 ", + "ANCHOR1": "Anchor 1", + "ANCHOR2": "Anchor 2", + "ANCHOR3": "Anchor 3", "ANCHORS_AS_BOOKMARKS": "Anchors as bookmarks", - "API_KEY": " api key: ", + "API_KEY": "Rocks API key: ", "ASS_TO": "Nakatalaga kay", "ASSIGN LINK PROMPT": "Magatalaga ng link mula: {portalName}", "ASSIGN MARKER PROMPT": "Magtalaga ng marker mula: {portalName}", @@ -39,7 +39,6 @@ "ASSIGNED_ONLY": "Assigned Only", "assigned": "Naitalaga", "AUTH INCOMPAT": "May ginagamit kang plugin sa TamperMonkey na hindi angkop sa Wasabee", - "AUTH IOS": "Sa iOS, subukan muna ang 'Log In'. Kung hindi gumana, gawin ang 'Webview Log in', mag-log in, tapos gamitin ang 'Verify Webview' button para makumpleto ang proseso.", "AUTH REQUIRED": "Kailangan ng Authentication", "AUTH TOKEN REJECTED": "Pagpapadala ng auth token sa server natanggihan {error}", "AUTH_SELECT_ACCOUNT": "Select account", @@ -70,7 +69,6 @@ "CLEAR LINKS": "Clear Links", "CLEAR MARKERS": "Clear Markers", "CLEAR_EVERYTHING": "Burahin Portals/Links/Markers", - "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Burahin lahat ng locally stored na operasyon", "CLEAROPS BUTTON": "Burahin Local Ops", "CLEAROPS PROMPT": "Nais mo bang tangalin ang lahat ng opersyon sa local storage? Ang mga Ops na nakalagay sa server ay mababawi sa susunod na sync.", @@ -94,6 +92,9 @@ "DELETE_OP": "Tangalin {opName}", "DESCRIP_PLACEHOLD": "Description (opsyonal)", "DestroyPortalAlert": "Sirain", + "dialog.about.download_mobile_app": "

Wasabee App:

", + "dialog.setcomment.portal_hardness": "Hardness", + "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Kopyahin ang Operasyon", "END_PORT": "End Portal ", @@ -125,7 +126,7 @@ "HG": "Homogeneous Field", "HOURS": " ({hours} oras nakalipas)", "HOW_TO_VIDS": "

How-To Videos:

", - "IMP_COMP": "Natapos ang Pag Import. ", + "IMP_COMP": "", "IMP_NOPE": "Pag-I-Import Hindi Matagumpay: {error}", "IMP_WAS_OP": "I-Import ang Wasabee operasyon", "IMPORT_OP_SUCCESS": "Na-Import na Operasyon: {opName} Matagumpay.", @@ -145,9 +146,9 @@ "LANG": "Wika", "LEAVE": "Ialis", "LetDecayPortalAlert": "Ipa-decay", - "LINK ASSIGNMENT": " Link Pagtatalaga", + "LINK ASSIGNMENT": "Assign link to: ", "LINK STATE PROMPT": "estado ng Link", - "LINK STATE": "Italaga estado ng Link", + "LINK STATE": "Set link status: ", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", @@ -167,11 +168,11 @@ "MADRID": "Draw", "MANAGE_TEAM": "Ipamahala {teamName}", "MANAGE": "Ipamahala", - "MARKER ASSIGNMENT": " Marker Pagtatalaga", + "MARKER ASSIGNMENT": "Assign marker to: ", "MARKER LIST TITLE": "Listahan ng Marker", "MARKER LIST": "Markers", "MARKER STATE PROMPT": "Estado ng Marker", - "MARKER STATE": " Italaga estado ng marker", + "MARKER STATE": "Set marker state: ", "MARKER_LIST": "Listahan ng Marker: {opName}", "MARKERS BUTTON TITLE": "Markers", "MAX_SPLITS": "Max Splits", @@ -246,7 +247,7 @@ "PERM DENIED SHORT": "Walang pahintulot", "PERMS": "{opName} permisyo", "PLEASE_SELECT_PORTAL": "Pumili ng portal", - "PORT_FAKE": " portals ang nakita. Faked ", + "PORT_FAKE": "", "PORTAL KEY LIST": "Listahan ng Key para sa Portal {portalName}", "PORTAL_COUNT": "{count} portals", "PORTAL": "Portal", @@ -302,7 +303,7 @@ "SET_COMMENT": "Magatalaga ng Komentayro", "SET_LCOMMENT": "Italaga ang commento sa Link", "SET_LINK_COMMENT": "Komento para sa link: ", - "SET_LINKS_ZONES": "Set Links to Zones ", + "SET_LINKS_ZONES": "Set Links to Zones", "SET_MARKER_COMMENT": "Komento para sa marker: ", "SET_MARKER_TYPE_TITLE": "Change marker type", "SET_MARKERS_ZONES": "Set Markers to Zones", @@ -321,7 +322,7 @@ "SKIP_CONFIRM_ENTITY": "Only ask for team/op", "SKIP_CONFIRM_NEVER": "Always ask", "SKIP_CONFIRM": "Skip confirmation", - "SOURCE_PORT": "Panimulang Portal", + "SOURCE_PORT": "Source Portal", "SQUAD": "Squad", "STARBURST TITLE": "Starburst ", "STARBURST_DRAW": "Iguhit", @@ -347,7 +348,16 @@ "toolbar.quick_delete.apply.title": "Delete selected links/markers", "toolbar.quick_delete.cancel.text": "Cancel", "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.stop.text": "Stop", + "toolbar.quick_delete.stop.title": "Exit delete mode", "toolbar.quick_delete.title": "Quick delete", + "toolbar.quick_delete.tooltip.toggle_mode": "Click on features to mark for deletion", + "toolbar.quick_delete.tooltip.quick_mode": "Click on features to delete instantly", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Select the star anchor", + "toolbar.quick_draw.tooltip.star_mode.portal": "Select a portal", + "toolbar.quick_draw.tooltip.single_mode.first": "Click first portal", + "toolbar.quick_draw.tooltip.single_mode.next": "Click next portal", + "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", @@ -372,7 +382,7 @@ "UPLOAD BUTTON HOVER": "UPLOAD {opName} (kasalukuyang wala sa server)", "UPLOADED": "Matagumpay na i-upload", "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": ". Gamitin ang 'Ipagpalit' na feature para ipalit ang 'faked' portals sa totoong portals. Ang pag zoom sa 'Loading' portals sa listahan ay posibleng ma-'force load' ito.", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Gumamit ng naaayon na pangalan ng operasyon", "UseVirusPortalAlert": "Gumamit ng Virus", "VRLA DESC": "Depende sa dami at uri ng Link Amp, ang mas mababang panimulang portal level ay maaaring piliin.", @@ -381,8 +391,6 @@ "WASABEE_D_LIST": "Ipasok ang Bilang ng Defensive Key", "WD BUTTON TITLE": "Ilagay mga Pangharang na Keys", "WD BUTTON": "W-D Keys", - "WEBVIEW VERIFY": "I-Verify Webview", - "WEBVIEW": "Webview Log In (iOS)", "WRITE_SHORT": "RW", "WRITE": "isulat", "WSERVER": "Server: {url}", @@ -396,7 +404,6 @@ "CHECKLIST BUTTON": "Check", "CLEAROPS BUTTON": "Clear", "EXPORT OP": "Xport", - "FAN_FIELD3": "Fan", "FANFIELD": "Draw", "FANFIELD2": "Draw Fan Field", "KEYS": "Keys", diff --git a/src/code/translations/French.json b/src/code/translations/French.json index 697e71b71..2eb1bc2cd 100644 --- a/src/code/translations/French.json +++ b/src/code/translations/French.json @@ -1,34 +1,34 @@ { - "ABOUT_WASABEE": "Au sujet de Wasabee", + "ABOUT_WASABEE": "À propos de Wasabee", "acknowledged": "Noté", "ADD LINK TITLE": "Ajouter des liens", "ADD MARKER TITLE": "Ajouter des marqueurs", - "ADD_AGENT": "Ajouter agent:", - "ADD_BL": "Ajouter les back links :", + "ADD_AGENT": "Ajouter l'agent : ", + "ADD_BL": "Ajouter les backlinks : ", "ADD_BUTTON_LINKS": "Ajouter les liens", "ADD_LINKS": "Ajouter des liens", "ADD_MARKER": "+ Marqueur", "ADD_NEW_OP": "Ajouter une nouvelle opé", - "ADD_SUCC_INSTR": "L'agent a bien été ajouté à l'équipe. Il doit maintenant l'activer pour pouvoir être affecté à des actions sur les OPs de l'équipe.", + "ADD_SUCC_INSTR": "L'agent a bien été ajouté à l'équipe", "ADD_ZONE": "Ajouter une zone", "ADD": "Ajouter", "ADD1": "Ajouter le premier lien", "ADD2": "Ajouter le second lien", "AGENT_STATS": "Informations de l'agent", "AGENT": "Agent", - "AGES": "(il y a longtemps)", - "ALREADY_HAS_MARKER": "Ce portail porte déjà un marqueur. Choissisez un autre portail.", + "AGES": " (il y a longtemps)", + "ALREADY_HAS_MARKER": "Ce portail porte déjà un marqueur. Choisissez un autre portail.", "AMAZ_TEAM_NAME": "Nom de l'équipe", - "ANCHOR ASSIGNMENT": "tous les liens sortants", + "ANCHOR ASSIGNMENT": "Affecter tous les liens sortants à : ", "ANCHOR_GMAP": "Google Maps", - "ANCHOR_PORTAL": "Portail Ancre", + "ANCHOR_PORTAL": "Ancre", "ANCHOR_PORTAL2": "Portail Ancre 2", "ANCHOR_PORTAL3": "Portail Ancre 3", "ANCHOR1": "Ancre 1", "ANCHOR2": "Ancre 2", "ANCHOR3": "Ancre 3", "ANCHORS_AS_BOOKMARKS": "Ancres vers Bookmarks", - "API_KEY": "Clée API", + "API_KEY": "Clé API Rocks : ", "ASS_TO": "Assigné à", "ASSIGN LINK PROMPT": "Assigner le lien de {portalName}", "ASSIGN MARKER PROMPT": "Assigner le marqueur sur {portalName}", @@ -38,24 +38,23 @@ "ASSIGNED_ONLY_SHORT": "AO", "ASSIGNED_ONLY": "Seulement les affectations", "assigned": "Assigné", - "AUTH INCOMPAT": "You have activated a plugin in TamperMonkey that is incompatable with Wasabee", - "AUTH IOS": "On iOS, use the main 'Log In' option. If that fails, use 'Webview Login' then use the 'Verify Webview' button to complete the process.", - "AUTH REQUIRED": "Autentification requise", - "AUTH TOKEN REJECTED": "Jeton d'autentification rejeté par le serveur : {error}", + "AUTH INCOMPAT": "Vous avez activé un plugin dans TamperMonkey (ou équivalent) qui est incompatible avec Wasabee", + "AUTH REQUIRED": "Authentification requise", + "AUTH TOKEN REJECTED": "Jeton d’authentification rejeté par le serveur : {error}", "AUTH_SELECT_ACCOUNT": "Sélectionner le compte", "AUTO_DRAWS": "Auto-Draw", "AUTODRAWS": "Choix d'Auto-draw", "AUTODRAW_PORTALS_SET": "Portails", - "autodraw.common.draw_button": "Draw", + "autodraw.common.draw_button": "Tracer", "autodraw.flipflop.result": "Flip flop: {count} liens trouvés", "autodraw.onion.variant": "Variante", "autodraw.onion.variant.equilateral": "~Équilatéral", - "autodraw.onion.variant.grow": "Let it grow", + "autodraw.onion.variant.grow": "Un plus grand", "autodraw.onion.variant.balanced": "Équilibré", "AUTOLOAD_RATE": "Délai entre deux requêtes", "AUTOLOAD": "Charger automatiquement les données manquantes de portails", "AUTOMARK STOP": "Le processus d'Auto-Mark s'est arrêté suite à l'absence de donnée pour certains portails.", - "AUTOMARK": "Auto-Mark", + "AUTOMARK": "Auto-Marque", "BAT_TOAD": "Les grenouilles masquées", "BLOCKER LIST TITLE": "Afficher les bloquants", "BLOCKER TITLE": "Bloquants", @@ -69,8 +68,7 @@ "CHECKLIST BUTTON": "Checklist", "CLEAR LINKS": "Supprimer les liens", "CLEAR MARKERS": "Supprimer les marqueurs", - "CLEAR_EVERYTHING": "Supprimer Portails/Links et Marquers", - "CLEAR": "Clear selection", + "CLEAR_EVERYTHING": "Supprimer Portails/Links et Marqueurs", "CLEAROPS BUTTON TITLE": "Supprimer TOUTES les données Wasabee", "CLEAROPS BUTTON": "Supprimer les données Wasabee", "CLEAROPS PROMPT": "Toutes les opérations et données relatives à Wasabee seront supprimées de cet appareil. Seules les données présentes sur le/les serveurs seront récupérées à la prochaine synchronisation. Wasabee sera désactivé jusqu'au prochain rechargement d'IITC.", @@ -83,17 +81,20 @@ "CREATE_NEW_TEAM": "Créer une équipe", "CreateLinkAlert": "Lien", "CUR_USER_INFO": "Information sur l'utilisateur courant", - "D_SHOW_LIST": "Entrer les clées défensive", + "D_SHOW_LIST": "Entrer les clés défensive", "DEFAULT OP NAME": "Opération {date}", "DELETE ANCHOR PROMPT": "Voulez vous supprimer cette ancre et tous les liens associés : ", "DELETE ANCHOR TITLE": "Supprimer une ancre", - "DELETE MARKER PROMPT": "Voulez vous supprimer le marqueur :", + "DELETE MARKER PROMPT": "Voulez vous supprimer le marqueur : ", "DELETE MARKER TITLE": "Supprimer un marqueur", "DELETE_ANCHOR": "Supprimer", "DELETE_LINK": "Supprimer", "DELETE_OP": "Supprimer {opName}", "DESCRIP_PLACEHOLD": "Description (optionnelle)", "DestroyPortalAlert": "Casse", + "dialog.about.download_mobile_app": "

Application Wasabee :

", + "dialog.setcomment.portal_hardness": "Difficulté", + "dialog.import.success_message": "Importation terminée. {count} portails trouvés et {faked} faux portails utilisés. Veuillez utiliser la fonction d'échange pour déplacer les faux portails vers les vrais portails au même endroit. Faire un zoom avant sur les portails 'Chargement' dans la liste de contrôle peut les forcer à charger.", "DRAW TOOLS FORMAT": "Format DrawTools", "DUPE_OP": "Dupliquer l'opération", "END_PORT": "Portail de fin", @@ -102,14 +103,14 @@ "EXPORT OP": "Exporter", "EXPORT": "Exporter : ", "FAKED": "Faux [{portalId}]", - "FANFIELD": "Draw", + "FANFIELD": "Tracer", "FANFIELD2": "Fan Field", - "FarmPortalMarker": "Farm", + "FarmPortalMarker": "Farmer", "FLIP_FLOP_NAME": "Flip Flop", "FLIP_FLOP_TITLE": "Flip Flop", - "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", - "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", - "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", + "FLIP_FLOP_DESC": "À partir d'une ancre, d'un ensemble de portails visibles et d'un nombre de SBUL, cherche un fanfield à tirer depuis l'ancre par distance décroissante pour éviter de rechercher les clés dans le carrousel.", + "FLIP_FLOP_INSTRUCTION": "Sélectionner un portal, se placer dans la zone des portails cibles afin qu'ils soient visibles, puis presser Tracer. Une fois un fanfield trouvé, vous pouvez trouver d'autres ancres compatibles pour des re-tirs consécutifs", + "FLIP_FLOP_FIND_ANCHORS": "Trouver d'autres ancres", "FROM_1-2": "depuis la base 1-2", "FROM_1-3": "depuis la base 1-3", "FROM_2-3": "depuis la base 2-3", @@ -120,12 +121,12 @@ "GotoPortalMarker": "Aller à", "H-GEN_INST": "Choisissez les 3 portails du field englobant, le nombre de couches et cliquez sur Draw.", "HF_DEEP_SEARCH": "Recherche exhaustive", - "HF_DRAW_BUTTON": "Draw", + "HF_DRAW_BUTTON": "Tracer", "HF_REDRAW_BUTTON": "Re-Draw", "HG": "Field homogène", "HOURS": "(il y a {hours} heures)", "HOW_TO_VIDS": "

Tuto:

", - "IMP_COMP": "Importation reussi. ", + "IMP_COMP": "", "IMP_NOPE": "Echec de l'importation: {error}", "IMP_WAS_OP": "Importer les opérations Wasabee", "IMPORT_OP_SUCCESS": "Importer l'opération : {opName} Reussi.", @@ -136,7 +137,7 @@ "INPUT_DT_KEY_COUNT": "Entrer le nombre de clés défensive", "INPUT_SQUAD_NAME": "Entrer le nom de l'équipe", "INVALID REQUEST": "Requête invalide", - "IOS NEED FAKE UA": "You must set a 'Custom UserAgent for Webviews' in the IITC-Mobile settings or login will fail", + "IOS NEED FAKE UA": "Vous devez définir un 'Custom UserAgent for Webviews' dans les options de IITC-Mobile pour que la connexion à Wasabee fonctionne", "KEY_LIST2": "Liste des clées pour l'opération : {opName}", "KEYS": "Clées", "KNOWN_BLOCK": "Liens bloquants connus : {opName}", @@ -145,9 +146,9 @@ "LANG": "Langue", "LEAVE": "Quitter", "LetDecayPortalAlert": "À decay", - "LINK ASSIGNMENT": "Assigner à", + "LINK ASSIGNMENT": "Affecter le lien à : ", "LINK STATE PROMPT": "Statut du lien", - "LINK STATE": "Statut", + "LINK STATE": "Définir l'état du lien : ", "LINKS BUTTON TITLE": "Liens", "LINKS": "Liens", "LINKS2": "{portalName} : Liens ({outgoing}↑/{incoming}↓)", @@ -155,7 +156,7 @@ "LOADING": "[chargement]", "LOADING1": "Chargement: {portalGuid}", "LOC_PROC": "Emplacement traité", - "LOCATION SUB": "Location registered", + "LOCATION SUB": "Position envoyée", "LOCFRMSER": "(Localement et sur le serveur)", "LOG IN": "Connexion", "LOG_OUT": "Déconnexion", @@ -164,17 +165,17 @@ "MADRID_SET_3": "Définir la zone pour le multifield de base 1-2", "MADRID_TITLE": "Madrid Protocol", "MADRID_WAS_TAKEN": "Madrid Protocol", - "MADRID": "Draw", + "MADRID": "Tracer", "MANAGE_TEAM": "Gérer {teamName}", "MANAGE": "Gérer", - "MARKER ASSIGNMENT": "Assigner à", + "MARKER ASSIGNMENT": "Affecter le marqueur à : ", "MARKER LIST TITLE": "Liste des marqueurs", "MARKER LIST": "Marqueurs", "MARKER STATE PROMPT": "Statut du marqueur", - "MARKER STATE": "Définir le type de marqueur", + "MARKER STATE": "Définir l'état du marqueur : ", "MARKER_LIST": "Liste des marqueurs : {opName}", "MARKERS BUTTON TITLE": "Marqueurs", - "MAX_SPLITS": "Max Splits", + "MAX_SPLITS": "Nb Couches", "MAX": "Fan Field", "MeetAgentPortalMarker": "Rencontrer un agent", "MERGE ON UPDATE": "Fusion à la mise à jour d'une OP", @@ -182,12 +183,12 @@ "MERGE_CHANGES_MERGE": "Résultat après fusion", "MERGE_CHANGES_REMOTE": "Changements sur le serveur", "MERGE_LOCAL": "Locale", - "MERGE_MESSAGE": "L'opération \"{opName}\" a changé localement ainsi que sur le serveur. Voulez vous fusionné vos modifications à la version du serveur, ou utiliser la version du server ou bien conserver la version locale intacte ? (ou ne rien faire et laisser ça à plus tard)", + "MERGE_MESSAGE": "L'opération \"{opName}\" a changé localement ainsi que sur le serveur. Voulez vous fusionné vos modifications à la version du serveur, ou utiliser la version du serveur ou bien conserver la version locale intacte ? (ou ne rien faire et laisser ça à plus tard)", "MERGE_REBASE": "Fusion", "MERGE_REPLACE": "Remplacer", "MERGE_TITLE": "Fusion des versions locale et serveur", - "MIN_SRC_PORT_LVL": "Level minimum requis pour le portail source", - "MINUTES": "(il y a {minutes} minute(s))", + "MIN_SRC_PORT_LVL": "Niveau minimum requis pour le portail source", + "MINUTES": " (il y a {minutes} minute(s))", "MM": "Multimax", "MM_BOTH_SIDE": "Utiliser les deux côtés de la base", "MM_INSERT_ORDER": "Insérer à la fin", @@ -196,12 +197,12 @@ "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", "MM_SPINE": "Alignement", "MULTI_M_TITLE": "Dessiner le maximum de couches", - "MULTI_M": "Draw", + "MULTI_M": "Tracer", "MUST_NOT_BE_EMPTY": "Ne dois pas être vide", "MY_CAP_ID": "ID de ma capsule", "MY_COUNT": "Mon nombre de clés", "NAME_REQ": "Nom requis", - "NAME": "Nom :", + "NAME": "Nom : ", "NEW_OP": "Nouvelle opération", "NEW_TEAM_NAME": "Nouveau nom d'équipe", "NEW_TEAM": "Nouvelle équipe", @@ -212,17 +213,17 @@ "NO_LABEL": "Pas de nom donné", "NO_STOCK_INTEL": "Wasabee ne supporte pas les draws de l'intel stock.", "NO_TITLE": "Titre non défini", - "NO LONGER AVAILABLE": "Ressource supprimée du serveur: {error}", + "NO LONGER AVAILABLE": "Ressource supprimée du serveur : {error}", "NO LONGER AVAILABLE SHORT": "Ressource supprimée du serveur", "NOT LOGGED IN SHORT": "Déconnecté", "NOT LOGGED IN": "Déconnecté : {error}", - "NOT_LOADED": "N'a pas chargé entierement, essayer à nouveau", + "NOT_LOADED": "N'a pas chargé entièrement, essayer à nouveau.", "NOT_SET": "non défini", "NTNAME": "Nom", "OK": "Ok", "ON_HAND": "En main", "ONION_WAS_TAKEN": "Oignon", - "ONION": "Draw", + "ONION": "Tracer", "ONLY_DT_IMP": "(Uniquement pour les imports de DrawTools)", "OP DELETED": "Operation supprimée du serveur: {opID}", "OP PERM DENIED": "Permission refusée pour l'opération : {opID}", @@ -240,13 +241,13 @@ "OPS BUTTON": "Ops", "ORDER": "Ordre", "OtherPortalAlert": "Autre", - "PASTE_INSTRUCT": "Paste a Wasabee draw export here.\n\nWasabee cannot import the stock intel format.\n\nThere is experimental support for importing the IITC DrawTools format.\n\nBefore importing DrawTools format, preview the areas and make sure all the portals load so IITC has them cached. Any portals that are not pre-cached will be faked.\n\nYou will need to use the 'swap' feature to move anchors from the faked portals to the real portals (they should be in the correct location, just not associated with the portal.\n\nCached portals might not be properly named.", + "PASTE_INSTRUCT": "Coller un export de dessin Wasabee ici.\n\nWasabee ne peut pas importer le format Intel.\n\nIl existe un support expérimental pour importer le format IITC DrawTools.\n\nAvant d'importer le format DrawTools, prévisualisez les zones et assurez-vous que tous les portails sont chargés de sorte que l'IITC les a mis en cache. Les portails utilisés qui ne sont pas mis en cache correspondront à de faux portails.\n\nVous devrez utiliser la fonctionnalité 'swap' pour déplacer les ancres des faux portails vers les vrais portails (ils devraient être dans les bons emplacements, mais pas associés aux portails).\n\nLes portails mis en cache peuvent ne pas être correctement nommés.", "pending": "En attente", "PERM DENIED": "Permission refusée: {error}", "PERM DENIED SHORT": "Permission refusée", "PERMS": "Permissions de {opName}", "PLEASE_SELECT_PORTAL": "Selectionner un portail", - "PORT_FAKE": "portails trouvés. ", + "PORT_FAKE": "", "PORTAL KEY LIST": "Clés du portail {portalName}", "PORTAL_COUNT": "{count} portails", "PORTAL": "Portail", @@ -276,7 +277,7 @@ "RESET": "Reset", "REVERSE": "Inverser", "ROCKS_COM": "Communauté enl.rocks :", - "ROLE": "Role", + "ROLE": "Rôle", "SAVELINKS TITLE": "Copie de liens", "SAVELINKS_DRAW": "Copier les liens", "SAVELINKS": "Copie de liens intel", @@ -302,10 +303,10 @@ "SET_COMMENT": "Entrer un commentaire", "SET_LCOMMENT": "Commentaires du liens", "SET_LINK_COMMENT": "Entrer un commentaire pour le lien : ", - "SET_LINKS_ZONES": "Set Links to Zones ", + "SET_LINKS_ZONES": "Affecter les liens aux zones", "SET_MARKER_COMMENT": "Entrer un commentaire pour le marqueur : ", "SET_MARKER_TYPE_TITLE": "Changer le type de marqueur", - "SET_MARKERS_ZONES": "Set Markers to Zones", + "SET_MARKERS_ZONES": "Affecter les marqueurs aux zones", "SET_MCOMMENT": "Commentaire pour ce marqueur : {portalName}", "SET_NEW_OP": "Donner un nom à cette nouvelle opération", "SET_PCOMMENT": "Entrer un commentaire pour ce portail : {portalName}", @@ -321,12 +322,12 @@ "SKIP_CONFIRM_ENTITY": "Seulement les OP/équipes", "SKIP_CONFIRM_NEVER": "Tout", "SKIP_CONFIRM": "Demander confirmation pour", - "SOURCE_PORT": "Portail Source", - "SQUAD": "Squad", + "SOURCE_PORT": "Portail source", + "SQUAD": "Commentaire", "STARBURST TITLE": "Starburst", - "STARBURST_DRAW": "Draw", + "STARBURST_DRAW": "Tracer", "STARBURST": "Starburst", - "START_PORT": "Start Portal", + "START_PORT": "Portail de départ", "STATE": "Etat", "SUPPORT_INSTRUCT": "Pour obtenir de l'aide rejoindre ce channel Telegram (en Anglais) The Wasabee User Telegram Channel", "SWAP PROMPT": "Voulez vous remplacer ", @@ -343,12 +344,21 @@ "TEAMS BUTTON TITLE": "Liste des équipes", "TEAMS BUTTON": "Équipes", "TO_PORT": "Vers le portail", - "toolbar.quick_delete.apply.text": "Apply", - "toolbar.quick_delete.apply.title": "Delete selected links/markers", - "toolbar.quick_delete.cancel.text": "Cancel", - "toolbar.quick_delete.cancel.title": "Cancel", - "toolbar.quick_delete.title": "Quick delete", - "TRAWL SKIP TILES": "Trawl Skip Tiles", + "toolbar.quick_delete.apply.text": "Appliquer", + "toolbar.quick_delete.apply.title": "Supprime les liens et marqueurs sélectionnés", + "toolbar.quick_delete.cancel.text": "Annuler", + "toolbar.quick_delete.cancel.title": "Annuler", + "toolbar.quick_delete.stop.text": "Stop", + "toolbar.quick_delete.stop.title": "Quitter le mode Suppression", + "toolbar.quick_delete.title": "Suppression Rapide", + "toolbar.quick_delete.tooltip.toggle_mode": "Sélectionnez les éléments à supprimer", + "toolbar.quick_delete.tooltip.quick_mode": "Cliquez pour supprimer", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Sélectionnez l'ancre de la Starburst", + "toolbar.quick_draw.tooltip.star_mode.portal": "Cliquez sur les autres portails", + "toolbar.quick_draw.tooltip.single_mode.first": "Sélectionnez le premier portail", + "toolbar.quick_draw.tooltip.single_mode.next": "Sélectionnez le portail suivant", + "toolbar.quick_draw.tooltip.portal_fail": "Données de portail incomplètes, réessayez", + "TRAWL SKIP TILES": "Fouille: sauter des tuiles", "TRAWL TITLE": "Fouille des bloquants", "TRAWL WARNING": "Ceci va charger les tuiles de données sous les liens dessinés. C'est un processus lent.", "TRAWL_AUTOMARK": "Marquer automatiquement les portails après la fouille.", @@ -363,16 +373,16 @@ "UNKNOWN": "Inconnu", "UPDATE HOVER NOT CHANGED": "{opName} n'a pas changé localement", "UPDATE HOVER": "Mettre à jour {opName} sur le serveur", - "UPDATE PERM DENIED": "You do not have permission to update", + "UPDATE PERM DENIED": "Vous n'avez pas la permission de mettre à jour", "UPDATE_CONFLICT_DESC": "L'opération a été modifié sur le serveur depuis la dernière synchronisation. Voulez-vous écraser la version du serveur par la votre ?", "UPDATE_CONFLICT_TITLE": "Conflit avec le serveur", "UPDATE_COUNT": "Nombre mis un jour", "UPDATED": "Mise à jour reussi", - "UpgradePortalAlert": "Upgrade", + "UpgradePortalAlert": "Upper", "UPLOAD BUTTON HOVER": "Envoyer {opName} au serveur", "UPLOADED": "Envoi reussi", - "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": " faux portails ajoutés. Utilisez la fonction de Swap pour placer les faux portails ceux existants (au même positions). Zoomer sur les portails en chargement dans la checklist devrait permettre d'obtenir leurs informations manquantes.", + "USE PANES ON MOBILE": "Volet latéral (rechargement nécessaire)", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Utiliser un nom d'opération valide", "UseVirusPortalAlert": "Virus", "VRLA DESC": "Le niveau nécessaire du portail peut être plus faible en fonction du type des Link Amp utilisés.", @@ -381,37 +391,34 @@ "WASABEE_D_LIST": "Entrer le nombre de clés défensive", "WD BUTTON TITLE": "Enregistrer des clés défensives", "WD BUTTON": "Clés W-D", - "WEBVIEW VERIFY": "Verify Webview", - "WEBVIEW": "Webview Log In (iOS)", "WRITE_SHORT": "RW", "WRITE": "modifier", "WSERVER": "Serveur: {url}", "YESNO_DEL": "Voulez vous vraiment supprimer {opName} ?", - "ZONE_DRAW": "Click to set the zone boundaries", + "ZONE_DRAW": "Cliquer pour définir les limites de la zone", "ZONE": "Zone", "smallScreen": { "ADD_LINKS": "+ Liens", "ADD_MARKER": "+ Marqueur", "BLOCKER TITLE": "Bloquants", - "CHECKLIST BUTTON": "Check", + "CHECKLIST BUTTON": "Checklist", "CLEAROPS BUTTON": "Effacer", - "EXPORT OP": "Xport", - "FAN_FIELD3": "Fan", - "FANFIELD": "Draw", - "FANFIELD2": "Draw Fan Field", + "EXPORT OP": "Exporter", + "FANFIELD": "Tracer", + "FANFIELD2": "Fan Field", "KEYS": "Clés", "LOG IN": "Se connecter", "LOG_OUT": "Se déconnecter", "MARKER LIST": "Marqueurs", "MARKERS BUTTON TITLE": "Marqueurs", - "MAX": "Fan", - "MM": "Multi", + "MAX": "Fan Field", + "MM": "MultiMax", "MULTI_M_TITLE": "Maximiser le nombre de couche", - "MULTI_M": "Draw", + "MULTI_M": "Tracer", "NEWOP BUTTON": "+ Op", "OPS BUTTON": "Ops", "QD END": "Fin", - "STARBURST_DRAW": "Draw", + "STARBURST_DRAW": "Tracer", "STARBURST": "Etoile", "TEAMS BUTTON": "Équipe", "WD BUTTON": "Clés W-D" diff --git a/src/code/translations/German.json b/src/code/translations/German.json index 20c458869..354dbddcf 100644 --- a/src/code/translations/German.json +++ b/src/code/translations/German.json @@ -1,61 +1,60 @@ { "ABOUT_WASABEE": "Über Wasabee", - "acknowledged": "Acknowledged", + "acknowledged": "Bestätigt", "ADD LINK TITLE": "Dialog - Links hinzufügen", "ADD MARKER TITLE": "Dialog - Markierung hinzufügen", "ADD_AGENT": "Füge Agent hinzu: ", "ADD_BL": "Füge Portal zur Ankerkette hinzu: ", - "ADD_BUTTON_LINKS": "Add all links at once.", + "ADD_BUTTON_LINKS": "Alle Links auf einmal hinzufügen.", "ADD_LINKS": "Füge Links hinzu", "ADD_MARKER": "Füge Markierung hinzu", "ADD_NEW_OP": "Füge Op hinzu", - "ADD_SUCC_INSTR": "Erfolgreich hinzugefügt. Sie müssen das Team auf der Wassabe Webseite aktivieren, bevor es in der Liste auftaucht.", - "ADD_ZONE": "Add Zone", + "ADD_SUCC_INSTR": "Erfolgreich hinzugefügt", + "ADD_ZONE": "Zone hinzufügen", "ADD": "Hinzufügen", - "ADD1": "Add first link", - "ADD2": "Add second link", + "ADD1": "Ersten Link hinzufügen", + "ADD2": "Zweiten Link hinzufügen", "AGENT_STATS": "Agent Stats", "AGENT": "Agent", "AGES": "vor langer Zeit", "ALREADY_HAS_MARKER": "Dieses Portal hat bereits eine Markierung. Bitte wähle ein anderes Portal.", "AMAZ_TEAM_NAME": "Toller Teamname", - "ANCHOR ASSIGNMENT": " alle ausgehenden Links", + "ANCHOR ASSIGNMENT": "Alle ausgehenden Links zuweisen an: ", "ANCHOR_GMAP": "Google Map", "ANCHOR_PORTAL": "Anker Portal", - "ANCHOR_PORTAL2": "Anchor Portal 2", - "ANCHOR_PORTAL3": "Anchor Portal 3", + "ANCHOR_PORTAL2": "Anker Portal 2", + "ANCHOR_PORTAL3": "Anker Portal 3", "ANCHOR1": "Anker 1", "ANCHOR2": "Anker 2", - "ANCHOR3": "Anchor 3 ", - "ANCHORS_AS_BOOKMARKS": "Anchors as bookmarks", - "API_KEY": " api key: ", + "ANCHOR3": "Anker 3", + "ANCHORS_AS_BOOKMARKS": "Anker als Lesezeichen", + "API_KEY": "Rocks API-Schlüssel: ", "ASS_TO": "Zugewiesen an", "ASSIGN LINK PROMPT": "Link zugewiesenen von: {portalName}", "ASSIGN MARKER PROMPT": "Markierung zugewiesenen von: {portalName}", "ASSIGN OUTBOUND PROMPT": "Alle ausgehenden Links zugewiesenen von: {portalName}", "ASSIGN OUTBOUND": "Ordne ausgehende Links zu", "ASSIGN": "Zuweisen", - "ASSIGNED_ONLY_SHORT": "AO", - "ASSIGNED_ONLY": "Assigned Only", + "ASSIGNED_ONLY_SHORT": "nz", + "ASSIGNED_ONLY": "Nur zugewiesen", "assigned": "Zugewiesen", "AUTH INCOMPAT": "Du hast ein Plugin aktiviert welches inkompatibel zu Wasabee ist.", - "AUTH IOS": "Mit IOS nutze 'Log in'. Wenn das fehlschlägt nutze 'Webview Log in'; Danach nutze den 'Verify Webview' Knopf um den Prozess abzuschließen", "AUTH REQUIRED": "Authorisierung benötigt", "AUTH TOKEN REJECTED": "Senden des Autorisierungcodes ist fehlgeschlagen: {error}", - "AUTH_SELECT_ACCOUNT": "Select account", + "AUTH_SELECT_ACCOUNT": "Benutzerkonto auswählen", "AUTO_DRAWS": "Auto-draw", - "AUTODRAWS": "Wasabee Auto-draw Options", - "AUTODRAW_PORTALS_SET": "Portals", + "AUTODRAWS": "Wasabee Auto-draw Optionen", + "AUTODRAW_PORTALS_SET": "Portale", "autodraw.common.draw_button": "Draw", - "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.flipflop.result": "Flip flop: hat {count} Links gefunden", "autodraw.onion.variant": "Option", - "autodraw.onion.variant.equilateral": "~Equilateral", - "autodraw.onion.variant.grow": "Let it grow", - "autodraw.onion.variant.balanced": "Perfectly balanced", - "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", - "AUTOLOAD": "Automatically Load Missing Portal Details", + "autodraw.onion.variant.equilateral": "~Gleichseitig", + "autodraw.onion.variant.grow": "Los!", + "autodraw.onion.variant.balanced": "Perfekt ausgeglichen", + "AUTOLOAD_RATE": "Portaldetail-Anfragerate (ms)", + "AUTOLOAD": "Fehlende Portal-Details automatisch laden", "AUTOMARK STOP": "Automatische Markierung gestoppt - Portale nicht vollständig geladen.", - "AUTOMARK": "Auto-Mark", + "AUTOMARK": "Auto-Markieren", "BAT_TOAD": "Kampffrösche", "BLOCKER LIST TITLE": "Zeige alle Blocker an", "BLOCKER TITLE": "Blocker", @@ -67,14 +66,13 @@ "CHANGE_WAS_SERVER": "Wechsle Wasabee Server", "CHECKLIST BUTTON TITLE": "Checkliste Operationen", "CHECKLIST BUTTON": "Checliste", - "CLEAR LINKS": "Clear Links", - "CLEAR MARKERS": "Clear Markers", - "CLEAR_EVERYTHING": "Clear Portals/Links/Markers for current OP", - "CLEAR": "Clear selection", + "CLEAR LINKS": "Links löschen", + "CLEAR MARKERS": "Markierung aufheben", + "CLEAR_EVERYTHING": "Lösche Portale/Links/Marker für aktuelle OP", "CLEAROPS BUTTON TITLE": "Lösche alle Wasabee Daten", "CLEAROPS BUTTON": "Lösche Wasabee Daten", "CLEAROPS PROMPT": "Das wird alle Wasabee Daten Löschen. Bei dem nächsten Sync wird alles wiederhergestellt.", - "CLOSE": "Close", + "CLOSE": "Schließen", "COMMENT": "Kommentar", "COMPLETED BY": "Abgeschlossen von {agentName}", "completed": "Abgeschlossen", @@ -83,49 +81,52 @@ "CREATE_NEW_TEAM": "Erstelle neues Team", "CreateLinkAlert": "Link", "CUR_USER_INFO": "Aktuelle Nutzer Informationen", - "D_SHOW_LIST": "Input Defensive Keys", + "D_SHOW_LIST": "Defensive Schlüssel eingeben", "DEFAULT OP NAME": "Neue Operation: {date}", "DELETE ANCHOR PROMPT": "Möchtest du den Anker mit allen zugewiesenen Links löschen? : ", "DELETE ANCHOR TITLE": "Anker löschen", "DELETE MARKER PROMPT": "Möchtest du die Markierung löschen? : ", "DELETE MARKER TITLE": "Markierung löschen", "DELETE_ANCHOR": "Löschen", - "DELETE_LINK": "Delete", - "DELETE_OP": "Delete {opName}", + "DELETE_LINK": "Löschen", + "DELETE_OP": "Lösche {opName}", "DESCRIP_PLACEHOLD": "Beschreibung (optional)", - "DestroyPortalAlert": "Destroy", + "DestroyPortalAlert": "Zerstören", + "dialog.about.download_mobile_app": "

Wasabee App:

", + "dialog.setcomment.portal_hardness": "Schwierigkeitsgrad", + "dialog.import.success_message": "Import abgeschlossen. {count} Portale gefunden und {faked} gefälscht verwendet. Bitte nutze die Swap-Funktion, um gefälschte Portale zu den echten Portalen am gleichen Ort zu bewegen. Das Einzoomen der 'Laden'-Portale in der Checkliste kann sie zum Laden zwingen.", "DRAW TOOLS FORMAT": "Draw Tools Format", - "DUPE_OP": "Duplicate Operation", + "DUPE_OP": "Dupliziere Operation", "END_PORT": "Endportal", - "ExcludeMarker": "Exclude from Auto-Draw/Mark", + "ExcludeMarker": "Von Auto-Draw/Markieren ausschließen", "EXPORT OP TITLE": "Exportiere aktuelle Operation ", "EXPORT OP": "Exportiere Op", "EXPORT": "Exportieren: ", - "FAKED": "Faked: [{portalId}]", + "FAKED": "Gefaked: [{portalId}]", "FANFIELD": "Fächerfeld!", "FANFIELD2": "Fächerfeld", "FarmPortalMarker": "Farm", "FLIP_FLOP_NAME": "Flip flop", "FLIP_FLOP_TITLE": "Flip flop", - "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", - "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", - "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", - "FROM_1-2": "from base 1-2", - "FROM_1-3": "from base 1-3", - "FROM_2-3": "from base 2-3", - "FROM_DEPTH": "from the depth", + "FLIP_FLOP_DESC": "Findet für einen gegebenen Anker, eine Reihe von sichtbaren Portalen und einer Anzahl von SBUL ein Fächer-Feld, um Portale vom Anker in absteigender Reihenfolge (nach Distanz) anzulinken, um die Suche nach dem nächsten korrekten Schlüssel zu vermeiden.", + "FLIP_FLOP_INSTRUCTION": "Wähle ein Portal aus, zoome nach genug, um genug Portale zu sehen und klicke auf Zeichnen. Sobald ein Fächer-Feld gefunden wurde, kannst du nach anderen Ankern für einen darauf folgenden Wiederaufbau suchen", + "FLIP_FLOP_FIND_ANCHORS": "Finde andere Anker", + "FROM_1-2": "von Basis 1-2", + "FROM_1-3": "von Basis 1-3", + "FROM_2-3": "von Basis 2-3", + "FROM_DEPTH": "von innen heraus", "FROM_PORT": "Von Portal", - "GET DT": "Get existing DrawTools draw", - "GetKeyPortalMarker": "Get Keys", - "GotoPortalMarker": "Go To", - "H-GEN_INST": "Set portals for the outside layer. Choose number of splits. Click draw", - "HF_DEEP_SEARCH": "Exhaustive search", - "HF_DRAW_BUTTON": "Draw", - "HF_REDRAW_BUTTON": "Redraw", - "HG": "Homogeneous Field", + "GET DT": "Existierenden DrawTools Draw erhalten", + "GetKeyPortalMarker": "Schlüssel beziehen", + "GotoPortalMarker": "Gehe zu", + "H-GEN_INST": "Portale für das äußere Layer festlegen. Wähle die Anzahl der Aufteilungen. Klicke auf Zeichnen", + "HF_DEEP_SEARCH": "Ausführliche Suche", + "HF_DRAW_BUTTON": "Zeichnen", + "HF_REDRAW_BUTTON": "Neu zeichnen", + "HG": "Homogenes Feld", "HOURS": "vor ({hours} Stunden)", "HOW_TO_VIDS": "

Erklärungsvideos:

", - "IMP_COMP": "Import Komplett. Gefunden ", + "IMP_COMP": "", "IMP_NOPE": "Import Fehlgeschlagen: {error}", "IMP_WAS_OP": "Importiere Wasabee Operation", "IMPORT_OP_SUCCESS": "Importierte Operation: {opName}. Erfolgreich.", @@ -144,54 +145,54 @@ "LA": "L8+ einige LA", "LANG": "Sprache", "LEAVE": "Verlassen", - "LetDecayPortalAlert": "Let Decay", - "LINK ASSIGNMENT": " Link zugewiesenen", - "LINK STATE PROMPT": "Link State", - "LINK STATE": "Set link status", + "LetDecayPortalAlert": "Decayen lassen", + "LINK ASSIGNMENT": "Link zuweisen an: ", + "LINK STATE PROMPT": "Linkstatus", + "LINK STATE": "Linkstatus festlegen: ", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", - "LOAD PORTALS": "Load Portals", + "LOAD PORTALS": "Portale laden", "LOADING": "[laden]", "LOADING1": "Lade: [{portalGuid}]", "LOC_PROC": "Standort verarbeitet", "LOCATION SUB": "Standort registriert", - "LOCFRMSER": " (locally and from server)", + "LOCFRMSER": " (lokal und vom Server)", "LOG IN": "Einloggen", - "LOG_OUT": "Log Out", - "MADRID_SET_1": "Select the region for baselink Anchor 2 to Anchor 3", - "MADRID_SET_2": "Select the region for baselink Anchor 3 to Anchor 1", - "MADRID_SET_3": "Select the region for baselink Anchor 1 to Anchor 2", - "MADRID_TITLE": "Madrid Protocol", - "MADRID_WAS_TAKEN": "Madrid Protocol", - "MADRID": "Draw", + "LOG_OUT": "Ausloggen", + "MADRID_SET_1": "Wähle die Region für den Baselink-Anker 2 zu Anker 3", + "MADRID_SET_2": "Wähle die Region für den Baselink-Anker 3 zu Anker 1", + "MADRID_SET_3": "Wähle die Region für den Baselink-Anker 1 zu Anker 2", + "MADRID_TITLE": "Madrid Protokoll", + "MADRID_WAS_TAKEN": "Madrid Protokoll", + "MADRID": "Zeichnen", "MANAGE_TEAM": "Verwalten {teamName}", "MANAGE": "Verwalten", - "MARKER ASSIGNMENT": " Markierung zugewiesenen", + "MARKER ASSIGNMENT": "Marker zuweisen an: ", "MARKER LIST TITLE": "Liste der Markierungen", "MARKER LIST": "Markierungen", "MARKER STATE PROMPT": "Marker Status", - "MARKER STATE": " Set marker state", + "MARKER STATE": "Marker-Status setzen: ", "MARKER_LIST": "Liste Makerierungen: {opName}", "MARKERS BUTTON TITLE": "Markierungen", - "MAX_SPLITS": "Max Splits", + "MAX_SPLITS": "Max. Aufteilungen", "MAX": "Fächerfeld", - "MeetAgentPortalMarker": "Meet Agent", - "MERGE ON UPDATE": "Merge on update", - "MERGE_CHANGES_LOCAL": "Local changes", - "MERGE_CHANGES_MERGE": "Merge result", - "MERGE_CHANGES_REMOTE": "Remote changes", - "MERGE_LOCAL": "Keep local", + "MeetAgentPortalMarker": "Treffe Agenten", + "MERGE ON UPDATE": "Beim Update zusammenführen", + "MERGE_CHANGES_LOCAL": "Lokale Änderungen", + "MERGE_CHANGES_MERGE": "Ergebnis zusammenführen", + "MERGE_CHANGES_REMOTE": "Änderungen Dritter", + "MERGE_LOCAL": "Lokal speichern", "MERGE_MESSAGE": "It seems that {opName} has local changes. Do you want to merge your modifications with the server OP, replace the local version with the server version, or cancel?", "MERGE_REBASE": "Rebase", "MERGE_REPLACE": "Replace", - "MERGE_TITLE": "Merge local&remote OP", - "MIN_SRC_PORT_LVL": "Minimum level required on source portal", + "MERGE_TITLE": "Lokal&Remote-OP zusammenführen", + "MIN_SRC_PORT_LVL": "Minimaler benötigter Level im Ausgangsportal", "MINUTES": "vor ({minutes} Minuten)", "MM": "Maximale Feldanzahl", - "MM_BOTH_SIDE": "Use both base sides", - "MM_INSERT_ORDER": "Insert at the end", - "MM_SET_ALL_PORTALS": "All visible portals", + "MM_BOTH_SIDE": "Benutze beide Basisseiten", + "MM_INSERT_ORDER": "Am Ende einfügen", + "MM_SET_ALL_PORTALS": "Alle sichtbaren Portale", "MM_SET_ALL_KEYS": "All GetKey Markers", "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", "MM_SPINE": "Spine", @@ -246,7 +247,7 @@ "PERM DENIED SHORT": "Keine Berechtigung", "PERMS": "{opName} permissions", "PLEASE_SELECT_PORTAL": "Bitte wähle ein Portal", - "PORT_FAKE": " Portale. Verfälscht ", + "PORT_FAKE": "", "PORTAL KEY LIST": "Key list for portal {portalName}", "PORTAL_COUNT": "{count} portals", "PORTAL": "Portal", @@ -302,7 +303,7 @@ "SET_COMMENT": "Füge Kommentar hinzu", "SET_LCOMMENT": "Setze Kommentar für Link: ", "SET_LINK_COMMENT": "Set comment for link: ", - "SET_LINKS_ZONES": "Set Links to Zones ", + "SET_LINKS_ZONES": "Set Links to Zones", "SET_MARKER_COMMENT": "Set comment for marker on: ", "SET_MARKER_TYPE_TITLE": "Change marker type", "SET_MARKERS_ZONES": "Set Markers to Zones", @@ -321,7 +322,7 @@ "SKIP_CONFIRM_ENTITY": "Only ask for team/op", "SKIP_CONFIRM_NEVER": "Always ask", "SKIP_CONFIRM": "Skip confirmation", - "SOURCE_PORT": "Quellportal", + "SOURCE_PORT": "Source Portal", "SQUAD": "Kader", "STARBURST TITLE": "Starburst ", "STARBURST_DRAW": "Draw", @@ -347,7 +348,16 @@ "toolbar.quick_delete.apply.title": "Delete selected links/markers", "toolbar.quick_delete.cancel.text": "Cancel", "toolbar.quick_delete.cancel.title": "Cancel", + "toolbar.quick_delete.stop.text": "Stop", + "toolbar.quick_delete.stop.title": "Exit delete mode", "toolbar.quick_delete.title": "Quick delete", + "toolbar.quick_delete.tooltip.toggle_mode": "Click on features to mark for deletion", + "toolbar.quick_delete.tooltip.quick_mode": "Click on features to delete instantly", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Select the star anchor", + "toolbar.quick_draw.tooltip.star_mode.portal": "Select a portal", + "toolbar.quick_draw.tooltip.single_mode.first": "Click first portal", + "toolbar.quick_draw.tooltip.single_mode.next": "Click next portal", + "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", @@ -372,7 +382,7 @@ "UPLOAD BUTTON HOVER": "UPLOAD {opName} (aktuell nicht auf dem Server)", "UPLOADED": "Erfolgreich hochgeladen", "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": ".Bitte nutze die Wechsel Funktion, um das verfälschte Portal mit dem korrekten Portal, um Fehler zu beseitigen.", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Bitte verwende einen gültigen Operationsnamen", "UseVirusPortalAlert": "Use Virus", "VRLA DESC": "Ausgehend von der Anzahl und Typ von Link-Amps könnte ein niedrigeres Portallevel ausreichen", @@ -381,8 +391,6 @@ "WASABEE_D_LIST": "Input Defensive Key Count", "WD BUTTON TITLE": "Speicher Verteidigungs Schlüssel", "WD BUTTON": "W-D Schlüssel", - "WEBVIEW VERIFY": "Verify Webview", - "WEBVIEW": "Webview Log In (iOS)", "WRITE_SHORT": "RW", "WRITE": "schreiben", "WSERVER": "Server: {url}", @@ -396,7 +404,6 @@ "CHECKLIST BUTTON": "Check", "CLEAROPS BUTTON": "Clear", "EXPORT OP": "Xport", - "FAN_FIELD3": "Fan", "FANFIELD": "Draw", "FANFIELD2": "Draw Fan Field", "KEYS": "Keys", diff --git a/src/code/translations/Italian.json b/src/code/translations/Italian.json index c48e38632..47a786a65 100644 --- a/src/code/translations/Italian.json +++ b/src/code/translations/Italian.json @@ -9,8 +9,8 @@ "ADD_LINKS": "Aggiungi Link", "ADD_MARKER": "+ Marker", "ADD_NEW_OP": "Aggiungi Nuova Op", - "ADD_SUCC_INSTR": "Aggiunto con successo, dovrà abilitare il team sul sito di Wasabee per apparire in questa lista", - "ADD_ZONE": "Add Zone", + "ADD_SUCC_INSTR": "Aggiunto con successo", + "ADD_ZONE": "Aggiungi Zona", "ADD": "Aggiungi", "ADD1": "Aggiungi primo link", "ADD2": "Aggiungi secondo link", @@ -19,43 +19,42 @@ "AGES": " (epoche fa)", "ALREADY_HAS_MARKER": "Questo portale ha già un marker. Scegli un altro portale.", "AMAZ_TEAM_NAME": "Fantastico Nome del Team.", - "ANCHOR ASSIGNMENT": " tutti i link a uscire", + "ANCHOR ASSIGNMENT": "Assegna tutti i link in uscita a: ", "ANCHOR_GMAP": "Mappa Google", - "ANCHOR_PORTAL": "Portale Ancora ", + "ANCHOR_PORTAL": "Portale Ancora", "ANCHOR_PORTAL2": "Portale Ancora 2", "ANCHOR_PORTAL3": "Portale Ancora 3", - "ANCHOR1": "Ancora 1 ", - "ANCHOR2": "Ancora 2 ", - "ANCHOR3": "Ancora 3 ", + "ANCHOR1": "Ancora 1", + "ANCHOR2": "Ancora 2", + "ANCHOR3": "Ancora 3", "ANCHORS_AS_BOOKMARKS": "Ancore come bookmark", - "API_KEY": " chiave api: ", + "API_KEY": "Chiave API Rocks: ", "ASS_TO": "Assegnato a", "ASSIGN LINK PROMPT": "Assegna link da: {portalName}", "ASSIGN MARKER PROMPT": "Assegna marker da: {portalName}", "ASSIGN OUTBOUND PROMPT": "Assegna tutti i link in uscita da: {portalName}", "ASSIGN OUTBOUND": "Assegna Link in uscita", "ASSIGN": "Assegna", - "ASSIGNED_ONLY_SHORT": "AO", + "ASSIGNED_ONLY_SHORT": "SA", "ASSIGNED_ONLY": "Solo Assegnati", "assigned": "Assegnato", "AUTH INCOMPAT": "Hai attivato un plugin in TamperMonkey incompatibile con Wasabee", - "AUTH IOS": "Su iOS, usa 'Log In'. Se fallisce, prova 'Webview Log in'; poi premi 'Verify Webview' per completare il processo.", "AUTH REQUIRED": "Autenticazione Richiesta", "AUTH TOKEN REJECTED": "Invio token di autenticazione rifiutato: {error}", "AUTH_SELECT_ACCOUNT": "Seleziona account", - "AUTO_DRAWS": "Auto-draw", + "AUTO_DRAWS": "Auto-disegna", "AUTODRAWS": "Opzioni Wasabee Auto-draw", - "AUTODRAW_PORTALS_SET": "Portals", - "autodraw.common.draw_button": "Draw", - "autodraw.flipflop.result": "Flip flop: found {count} links", - "autodraw.onion.variant": "Option", - "autodraw.onion.variant.equilateral": "~Equilateral", - "autodraw.onion.variant.grow": "Let it grow", - "autodraw.onion.variant.balanced": "Perfectly balanced", + "AUTODRAW_PORTALS_SET": "Portali", + "autodraw.common.draw_button": "Disegna", + "autodraw.flipflop.result": "Flip flop: trovati {count} link", + "autodraw.onion.variant": "Alternativo", + "autodraw.onion.variant.equilateral": "~Equilatero", + "autodraw.onion.variant.grow": "Lascia che cresca", + "autodraw.onion.variant.balanced": "Perfettamente bilanciato", "AUTOLOAD_RATE": "Frequenza Richiesta dettagli Portali (ms)", "AUTOLOAD": "Carica Automaticamente Dettagli dei Portali Mancanti", "AUTOMARK STOP": "Auto-Mark interrotto, i portali non sono caricati", - "AUTOMARK": "Auto-Mark", + "AUTOMARK": "Auto-Segna", "BAT_TOAD": "Rospi da Battaglia", "BLOCKER LIST TITLE": "Mostra tutti i bloccanti", "BLOCKER TITLE": "Bloccanti", @@ -70,7 +69,6 @@ "CLEAR LINKS": "Elimina Link", "CLEAR MARKERS": "Elimina Marker", "CLEAR_EVERYTHING": "Elimina tutti i Portali/Link/Marker", - "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Elimina TUTTI i dati di Wasabee", "CLEAROPS BUTTON": "Elimina i dati di Wasabee", "CLEAROPS PROMPT": "Questo eliminerà tutte le OP e i dati relativi a Wasabee. Saranno ripristinati alla prossima sincronizzazione.", @@ -94,6 +92,9 @@ "DELETE_OP": "Eliminare {opName}", "DESCRIP_PLACEHOLD": "Descrizione (facoltativo)", "DestroyPortalAlert": "Distruggere", + "dialog.about.download_mobile_app": "

Wasabee App:

", + "dialog.setcomment.portal_hardness": "Durezza", + "dialog.import.success_message": "Importazione completata. Trovati {count} portali e usati {faked} finti. Si prega di utilizzare la funzione di scambio per spostare i portali finti sui portali reali alla stessa posizione. Zoomando sui portali 'Caricamento' nella checklist potrebbe forzarne il caricamento.", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplica Operazione", "END_PORT": "Portale di fine ", @@ -107,9 +108,9 @@ "FarmPortalMarker": "Farmare", "FLIP_FLOP_NAME": "Flip flop", "FLIP_FLOP_TITLE": "Flip flop", - "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", - "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", - "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", + "FLIP_FLOP_DESC": "Da una data ancora, un insieme di portali visibili e un certo numero di SBUL, trova un fanfield per tirare link dall'ancora diminuendo la distanza per evitare di cercare chiavi.", + "FLIP_FLOP_INSTRUCTION": "Seleziona un portale, zooma per vedere abbastanza portali e premi Disegna. Una volta trovato un fanfield, puoi cercare altre ancore per tiri successivi", + "FLIP_FLOP_FIND_ANCHORS": "Trova altre ancore", "FROM_1-2": "dalla base 1-2", "FROM_1-3": "dalla base 1-3", "FROM_2-3": "dalla base 2-3", @@ -125,7 +126,7 @@ "HG": "Field Omogeneo", "HOURS": " ({hours} ore fa)", "HOW_TO_VIDS": "

Video tutorial:

", - "IMP_COMP": "Importazione Completata. Trovato ", + "IMP_COMP": "", "IMP_NOPE": "Importazione Fallita: {error}", "IMP_WAS_OP": "Importa Operazione Wasabee", "IMPORT_OP_SUCCESS": "Importata Operazione: {opName} con successo.", @@ -145,12 +146,12 @@ "LANG": "Lingua", "LEAVE": "Esci", "LetDecayPortalAlert": "Lasciare Decadere", - "LINK ASSIGNMENT": " Assegnamento Link", + "LINK ASSIGNMENT": "Assegna link a: ", "LINK STATE PROMPT": "Stato Link", - "LINK STATE": "Imposta stato link", + "LINK STATE": "Imposta stato link: ", "LINKS BUTTON TITLE": "Link", "LINKS": "Link", - "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", + "LINKS2": "{portalName} : Link ({outgoing}↑/{incoming}↓)", "LOAD PORTALS": "Carica Portali", "LOADING": "[caricamento]", "LOADING1": "Caricamento: [{portalGuid}]", @@ -167,21 +168,21 @@ "MADRID": "Disegna", "MANAGE_TEAM": "Gestisci {teamName}", "MANAGE": "Gestisci", - "MARKER ASSIGNMENT": " Assegnamento Marker", + "MARKER ASSIGNMENT": "Assegna marker a: ", "MARKER LIST TITLE": "Lista Marker", "MARKER LIST": "Marker", "MARKER STATE PROMPT": "Stato Marker", - "MARKER STATE": " Imposta stato marker", + "MARKER STATE": "Imposta stato marker: ", "MARKER_LIST": "Lista Marker: {opName}", "MARKERS BUTTON TITLE": "Marker", "MAX_SPLITS": "Più Split possibili", "MAX": "Fan Field", "MeetAgentPortalMarker": "Incontrare Agente", - "MERGE ON UPDATE": "Merge on update", - "MERGE_CHANGES_LOCAL": "Local changes", - "MERGE_CHANGES_MERGE": "Merge result", - "MERGE_CHANGES_REMOTE": "Remote changes", - "MERGE_LOCAL": "Keep local", + "MERGE ON UPDATE": "Unisci all'aggiornamento", + "MERGE_CHANGES_LOCAL": "Modifiche locali", + "MERGE_CHANGES_MERGE": "Risultato unione", + "MERGE_CHANGES_REMOTE": "Modifiche remote", + "MERGE_LOCAL": "Mantieni in locale", "MERGE_MESSAGE": "It seems that {opName} has local changes. Do you want to merge your modifications with the server OP, replace the local version with the server version, or cancel?", "MERGE_REBASE": "Rebase", "MERGE_REPLACE": "Replace", @@ -189,12 +190,12 @@ "MIN_SRC_PORT_LVL": "Livello minimo richiesto sul portale d'origine", "MINUTES": " ({minutes} minuti fa)", "MM": "Multimax", - "MM_BOTH_SIDE": "Use both base sides", - "MM_INSERT_ORDER": "Insert at the end", - "MM_SET_ALL_PORTALS": "All visible portals", - "MM_SET_ALL_KEYS": "All GetKey Markers", - "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", - "MM_SPINE": "Spine", + "MM_BOTH_SIDE": "Usa entrambi i lati della base", + "MM_INSERT_ORDER": "Inserisci alla fine", + "MM_SET_ALL_PORTALS": "Tutti i portali visibili", + "MM_SET_ALL_KEYS": "Tutti i Marker OttieniChiave", + "MM_SET_KEYS_ZONE": "OttieniChiave: {zoneName}", + "MM_SPINE": "Filotto", "MULTI_M_TITLE": "Disegna più strati possibile", "MULTI_M": "Disegna", "MUST_NOT_BE_EMPTY": "Non può essere vuoto", @@ -246,25 +247,25 @@ "PERM DENIED SHORT": "Accesso negato", "PERMS": "{opName} permessi", "PLEASE_SELECT_PORTAL": "Seleziona un portale", - "PORT_FAKE": " portali. Simulati ", + "PORT_FAKE": "", "PORTAL KEY LIST": "Lista Chiavi per Portale: {portalName}", "PORTAL_COUNT": "{count} Portali", "PORTAL": "Portale", - "QD BUTTON CHANGE COLOR": "Click to change next links color", + "QD BUTTON CHANGE COLOR": "Clicca per cambiare il colore dei prossimi link", "QD BUTTON END": "Clicca per interrompere il disegno dei field", - "QD BUTTON TOGGLE MODE": "Click to change draw mode", - "QD CHANGE COLOR": "Change color", + "QD BUTTON TOGGLE MODE": "Clicca per cambiare la modalità di disegno", + "QD CHANGE COLOR": "Cambia colore", "QD END": "Fine", "QD TITLE": "Disegno Rapido Strati", - "QD TOGGLE MODE": "Change mode", + "QD TOGGLE MODE": "Cambia modalità", "QDBASE": "Link Base", "QDCONT": "Clicca su un portale del filotto per disegnare un field.", "QDNEXT": "Clicca il secondo Portale Ancora.", "QDSTART": "Clicca il primo Portale Ancora.", - "READ_SHORT": "RO", + "READ_SHORT": "SL", "READ": "Lettura", "RechargePortalAlert": "Ricaricare", - "REFERENCE_TIME": "Reference Time: ", + "REFERENCE_TIME": "Ora riferimento: ", "REM_LOC_CP": "Elimina copia locale di {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Vuoi eliominare definitivamente {teamName} dal Server Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Elimina team {teamName}", @@ -302,10 +303,10 @@ "SET_COMMENT": "Imposta Commento", "SET_LCOMMENT": "Imposta commento Link", "SET_LINK_COMMENT": "Imposta commento per il link: ", - "SET_LINKS_ZONES": "Set Links to Zones ", + "SET_LINKS_ZONES": "Imposta Link alle Zone", "SET_MARKER_COMMENT": "Imposta commento per il marker su: ", "SET_MARKER_TYPE_TITLE": "Cambia tipo marker", - "SET_MARKERS_ZONES": "Set Markers to Zones", + "SET_MARKERS_ZONES": "Imposta Marker alle Zone", "SET_MCOMMENT": "Imposta commento Marker: {portalName}", "SET_NEW_OP": "Impostare il nuovo Nome Operazione", "SET_PCOMMENT": "Imposta commento Portale: {portalName}", @@ -317,11 +318,11 @@ "SKINS_BUTTON": "Configura Skin", "SKINS_DESCRIPTION": "Gestisci le skin disponibili spostandole nella colonna di sinistra. Le skin più in basso hanno priorità più alta sulla UI.", "SKINS_MANAGE_TITLE": "Gestisci skin", - "SKIP_CONFIRM_ALWAYS": "Never ask (use with caution)", - "SKIP_CONFIRM_ENTITY": "Only ask for team/op", - "SKIP_CONFIRM_NEVER": "Always ask", - "SKIP_CONFIRM": "Skip confirmation", - "SOURCE_PORT": "Portale di Origine ", + "SKIP_CONFIRM_ALWAYS": "Non chiedere mai (usare con cautela)", + "SKIP_CONFIRM_ENTITY": "Chiedi solo per squadra/op", + "SKIP_CONFIRM_NEVER": "Chiedi sempre", + "SKIP_CONFIRM": "Salta conferma", + "SOURCE_PORT": "Portale di Origine", "SQUAD": "Squadra", "STARBURST TITLE": "Starburst ", "STARBURST_DRAW": "Disegna", @@ -339,16 +340,25 @@ "TEAM STATE": "Condividi Posizione", "TEAM_CREATED": "Team {teamName} creato", "TEAM_NAME": "Nome Team", - "TEAM": "Team", + "TEAM": "Squadra", "TEAMS BUTTON TITLE": "Lista Team Wasabee", "TEAMS BUTTON": "Team", "TO_PORT": "Al Portale", - "toolbar.quick_delete.apply.text": "Apply", - "toolbar.quick_delete.apply.title": "Delete selected links/markers", - "toolbar.quick_delete.cancel.text": "Cancel", - "toolbar.quick_delete.cancel.title": "Cancel", - "toolbar.quick_delete.title": "Quick delete", - "TRAWL SKIP TILES": "Trawl Skip Tiles", + "toolbar.quick_delete.apply.text": "Applica", + "toolbar.quick_delete.apply.title": "Elimina link/marker selezionati", + "toolbar.quick_delete.cancel.text": "Annulla", + "toolbar.quick_delete.cancel.title": "Annulla", + "toolbar.quick_delete.stop.text": "Stop", + "toolbar.quick_delete.stop.title": "Esci dalla modalità eliminazione", + "toolbar.quick_delete.title": "Eliminazione rapida", + "toolbar.quick_delete.tooltip.toggle_mode": "Clicca sugli oggetti per segnarli \"da eliminare\"", + "toolbar.quick_delete.tooltip.quick_mode": "Clicca sugli oggetti per eliminarli", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Seleziona l'ancora della star", + "toolbar.quick_draw.tooltip.star_mode.portal": "Seleziona un portale", + "toolbar.quick_draw.tooltip.single_mode.first": "Clicca il primo portale", + "toolbar.quick_draw.tooltip.single_mode.next": "Clicca il portale successivo", + "toolbar.quick_draw.tooltip.portal_fail": "Dati portale non caricati, riprova", + "TRAWL SKIP TILES": "Salta tile durante controllo", "TRAWL TITLE": "Controllo corridoi", "TRAWL WARNING": "Verranno caricati i dati delle tile sotto i link disegnati. Sarà un processo lento.", "TRAWL_AUTOMARK": "Auto-mark dei bloccanti dopo controllo", @@ -363,7 +373,7 @@ "UNKNOWN": "Sconosciuto", "UPDATE HOVER NOT CHANGED": "{opName} non modificato localmente", "UPDATE HOVER": "AGGIORNA {opName} sul server", - "UPDATE PERM DENIED": "You do not have permission to update", + "UPDATE PERM DENIED": "Non hai il permesso di aggiornare", "UPDATE_CONFLICT_DESC": "L'OP è stata modificata sul server dopo la tua ultima sincronizzazione. Vuoi sostituire la versione sul server con la attuale?", "UPDATE_CONFLICT_TITLE": "Rilevato conflitto con il server", "UPDATE_COUNT": "Aggiorna conteggio", @@ -371,8 +381,8 @@ "UpgradePortalAlert": "Upgradare", "UPLOAD BUTTON HOVER": "CARICA {opName} (al momento non sul server)", "UPLOADED": "Caricato con successo", - "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": ". Usare la funzione Scambio per spostare i Portali finti sui Portali veri nella stessa posizione. Zoomare sui Portali 'in caricamento' nella checklist potrebbe forzarli al caricamento.", + "USE PANES ON MOBILE": "Usa riquadri (richiede reload)", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Usa un nome operazione valido", "UseVirusPortalAlert": "Usare Virus", "VRLA DESC": "In base al tipo e al numero di Link Amp usati, potrebbe bastare un portale di origine di livello più basso.", @@ -381,39 +391,36 @@ "WASABEE_D_LIST": "Inserisci numero chiavi difensive", "WD BUTTON TITLE": "Registra chiavi difensive", "WD BUTTON": "Chiavi W-D", - "WEBVIEW VERIFY": "Verifica Webview", - "WEBVIEW": "Log In Webview (iOS)", - "WRITE_SHORT": "RW", + "WRITE_SHORT": "LS", "WRITE": "scrittura", "WSERVER": "Server: {url}", "YESNO_DEL": "Sei sicuro di voler eliminare {opName}?", - "ZONE_DRAW": "Click to set the zone boundaries", + "ZONE_DRAW": "Clicca per impostare i confini della zona", "ZONE": "Area", "smallScreen": { - "ADD_LINKS": "+ Links", + "ADD_LINKS": "+ Link", "ADD_MARKER": "+ Marker", - "BLOCKER TITLE": "Blockers", - "CHECKLIST BUTTON": "Check", - "CLEAROPS BUTTON": "Clear", - "EXPORT OP": "Xport", - "FAN_FIELD3": "Fan", - "FANFIELD": "Draw", - "FANFIELD2": "Draw Fan Field", - "KEYS": "Keys", - "LOG IN": "Log In", - "LOG_OUT": "Log Out", - "MARKER LIST": "Markers", - "MARKERS BUTTON TITLE": "Markers", + "BLOCKER TITLE": "Bloccanti", + "CHECKLIST BUTTON": "Spunta", + "CLEAROPS BUTTON": "Svuota", + "EXPORT OP": "Esporta", + "FANFIELD": "Disegna", + "FANFIELD2": "Disegna Fan Field", + "KEYS": "Chiavi", + "LOG IN": "Accedi", + "LOG_OUT": "Esci", + "MARKER LIST": "Marker", + "MARKERS BUTTON TITLE": "Marker", "MAX": "Fan", "MM": "Multi", - "MULTI_M_TITLE": "Draw Max Layers", - "MULTI_M": "Draw", - "NEWOP BUTTON": "New Op", - "OPS BUTTON": "Select OP", - "QD END": "End", - "STARBURST_DRAW": "Draw", + "MULTI_M_TITLE": "Disegna più strati possibile", + "MULTI_M": "Disegna", + "NEWOP BUTTON": "Nuova Op", + "OPS BUTTON": "Seleziona OP", + "QD END": "Fine", + "STARBURST_DRAW": "Disegna", "STARBURST": "Star", - "TEAMS BUTTON": "Teams", - "WD BUTTON": "W-D Keys" + "TEAMS BUTTON": "Squadre", + "WD BUTTON": "Chiavi W-D" } } \ No newline at end of file diff --git a/src/code/translations/Portuguese.json b/src/code/translations/Portuguese.json index 5f8d94eb5..01adb3e68 100644 --- a/src/code/translations/Portuguese.json +++ b/src/code/translations/Portuguese.json @@ -1,34 +1,34 @@ { "ABOUT_WASABEE": "Sobre Wasabee", "acknowledged": "Reconhecido", - "ADD LINK TITLE": "Adicionar Links Dialogo", - "ADD MARKER TITLE": "Adicionar Marcadores de Dialogo", + "ADD LINK TITLE": "Adicionar Links", + "ADD MARKER TITLE": "Adicionar Marcadores", "ADD_AGENT": "Adicionar Agente: ", - "ADD_BL": "Adicionar links oara trás: ", + "ADD_BL": "Adicionar links traseiros: ", "ADD_BUTTON_LINKS": "Adicionar todos os links de uma vez.", "ADD_LINKS": "Adicionar Links", "ADD_MARKER": "+ Marcador", "ADD_NEW_OP": "Adicionar Nova Op", "ADD_SUCC_INSTR": "Adicionar agente, bem sucedido", - "ADD_ZONE": "Add Zone", + "ADD_ZONE": "Adicionar zona", "ADD": "Adicionar", "ADD1": "Adicionar primeiro link", "ADD2": "Adicionar segundo link", "AGENT_STATS": "Agente Stats", "AGENT": "Agente", - "AGES": " (ages ago)", + "AGES": " (há muito tempo)", "ALREADY_HAS_MARKER": "Este portal já tem um marcador. Escolha um portal diferente.", "AMAZ_TEAM_NAME": "Nome incrível da equipe.", - "ANCHOR ASSIGNMENT": " Todos os links externos", - "ANCHOR_GMAP": "Google Map", - "ANCHOR_PORTAL": "Âncora Portal ", + "ANCHOR ASSIGNMENT": "Atribuir todos os links de saída para: ", + "ANCHOR_GMAP": "Mapa Google", + "ANCHOR_PORTAL": "Portal Âncora", "ANCHOR_PORTAL2": "Âncora Portal 2", "ANCHOR_PORTAL3": "Âncora Portal 3", - "ANCHOR1": "Âncora 1 ", - "ANCHOR2": "Âncora 2 ", - "ANCHOR3": "Âncora 3 ", + "ANCHOR1": "Âncora 1", + "ANCHOR2": "Âncora 2", + "ANCHOR3": "Âncora 3", "ANCHORS_AS_BOOKMARKS": "Âncora como bookmarks", - "API_KEY": " api key: ", + "API_KEY": "Chave API do Rocks: ", "ASS_TO": "Atrubuir a:", "ASSIGN LINK PROMPT": "Atribuir link para: ${value}", "ASSIGN MARKER PROMPT": "Atrubuir marcador para: ${value}", @@ -39,26 +39,25 @@ "ASSIGNED_ONLY": "Só Atribuir", "assigned": "Atribuído", "AUTH INCOMPAT": "Você ativou um plugin no TamperMonkey que é incompatível com o Wasabee", - "AUTH IOS": "No iOS, use o 'Login' principal. se isso falhar, faça 'Webview Log in', faça o login; em seguida, use o botão 'Verificar Webview' para concluir o processo.", "AUTH REQUIRED": "Autentificação Requerida", "AUTH TOKEN REJECTED": "Envio de token de autenticação rejeitado pelo servidor: ${value}", "AUTH_SELECT_ACCOUNT": "Selecionar conta", - "AUTO_DRAWS": "Auto-draw", + "AUTO_DRAWS": "Auto-desenhar", "AUTODRAWS": "Wasabee Auto-draw Opções", - "AUTODRAW_PORTALS_SET": "Portals", - "autodraw.common.draw_button": "Draw", - "autodraw.flipflop.result": "Flip flop: found {count} links", - "autodraw.onion.variant": "Option", - "autodraw.onion.variant.equilateral": "~Equilateral", - "autodraw.onion.variant.grow": "Let it grow", - "autodraw.onion.variant.balanced": "Perfectly balanced", + "AUTODRAW_PORTALS_SET": "Portais", + "autodraw.common.draw_button": "Desenhar", + "autodraw.flipflop.result": "Flip flop: {count} links encontrados", + "autodraw.onion.variant": "Opção", + "autodraw.onion.variant.equilateral": "~Equalizador", + "autodraw.onion.variant.grow": "Deixe crescer", + "autodraw.onion.variant.balanced": "Perfeitamente equilibrado", "AUTOLOAD_RATE": "Taxa de solicitação de detalhes do portal (ms)", "AUTOLOAD": "Carregar automaticamente os detalhes do portal em falta", "AUTOMARK STOP": "Auto-Marcar interrompido devido a portais não serem carregados", "AUTOMARK": "Auto-Marcar", - "BAT_TOAD": "Battle Toads", + "BAT_TOAD": "Brinquedos de batalha", "BLOCKER LIST TITLE": "Mostrar todos os blockers", - "BLOCKER TITLE": "Blockers", + "BLOCKER TITLE": "Bloqueadores", "CANCEL": "Cancelar", "CAPSULE": "Capsula", "CapturePortalMarker": "Capturado", @@ -70,7 +69,6 @@ "CLEAR LINKS": "Limpar Links", "CLEAR MARKERS": "Limpar Markers", "CLEAR_EVERYTHING": "limpar Portais/Links/Marcadores", - "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "limpar TODOS os dados Wasabee", "CLEAROPS BUTTON": "Limpar dados Wasabee", "CLEAROPS PROMPT": "Isto limpará todas as OPS e dados relacionados a Wasabee. Tudo será restaurado apartir do servidor na próxima sincronização.", @@ -94,6 +92,9 @@ "DELETE_OP": "Apagar ${value}", "DESCRIP_PLACEHOLD": "Descrição (opcional)", "DestroyPortalAlert": "Destroir", + "dialog.about.download_mobile_app": "

Wasabee App:

", + "dialog.setcomment.portal_hardness": "Difículdade", + "dialog.import.success_message": "Importação completa. Encontrados {count} portais e usados {faked} falsificados. Por favor, use o recurso de troca para mover portais falsos para os portais reais no mesmo local. Ampliar os portais de 'Carregamento' na lista de verificação pode forçá-los a carregar.", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplicar Operação", "END_PORT": "Portal final ", @@ -105,11 +106,11 @@ "FANFIELD": "Desenhar", "FANFIELD2": "Desenhar Fan Field", "FarmPortalMarker": "Farmar", - "FLIP_FLOP_NAME": "Flip flop", - "FLIP_FLOP_TITLE": "Flip flop", - "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", - "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", - "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", + "FLIP_FLOP_NAME": "Inverter Flop", + "FLIP_FLOP_TITLE": "Inverter Flop", + "FLIP_FLOP_DESC": "De uma determinada âncora, um conjunto de portal visível e um número de SBUL, encontre um fanfield para arremessar links da âncora diminuindo distância para evitar procurar chaves.", + "FLIP_FLOP_INSTRUCTION": "Selecione um portal, zoom para ver portais suficientes e pressione Desenhar. Uma vez que um fanfield for encontrado, você poderá procurar por outras âncoras por jogadas consecutivas", + "FLIP_FLOP_FIND_ANCHORS": "Encontrar outras âncoras", "FROM_1-2": "A Partir da base 1-2", "FROM_1-3": "A Partir da base 1-3", "FROM_2-3": "A Partir da base 2-3", @@ -125,7 +126,7 @@ "HG": "Campo Homogêneo", "HOURS": " (${value} horas atrás)", "HOW_TO_VIDS": "

Vídeos de instruções:

", - "IMP_COMP": "Importação concluída. Encontrada ", + "IMP_COMP": "", "IMP_NOPE": "A Importação Falhou: {error}", "IMP_WAS_OP": "Importar Operação Wasabee", "IMPORT_OP_SUCCESS": "OP Importada: ${value} successfuly.", @@ -145,9 +146,9 @@ "LANG": "Língua", "LEAVE": "Deixar", "LetDecayPortalAlert": "Deixar caír", - "LINK ASSIGNMENT": "Atribuição de Link", + "LINK ASSIGNMENT": "Atribuir link a: ", "LINK STATE PROMPT": "Estado do link", - "LINK STATE": "Definir o status do link", + "LINK STATE": "Definir status do link: ", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": ": Links", @@ -157,8 +158,8 @@ "LOC_PROC": "localização processada", "LOCATION SUB": "Localização registrada", "LOCFRMSER": " (localmente e do servidor)", - "LOG IN": "Log In", - "LOG_OUT": "Log Out", + "LOG IN": "Iniciar Sessão", + "LOG_OUT": "Terminar Sessão", "MADRID_SET_1": "Selecione a região para a ligação de base Âncora 2 à Âncora 3", "MADRID_SET_2": "Selecione a região para a ligação de base Âncora 3 à Âncora 1", "MADRID_SET_3": "Selecione a região para a ligação de base Âncora 1 a Âncora 2", @@ -167,34 +168,34 @@ "MADRID": "Desenhar", "MANAGE_TEAM": "Gerenciar ${value}", "MANAGE": "Gerenciar", - "MARKER ASSIGNMENT": " Atribuição de marcador", + "MARKER ASSIGNMENT": "Atribuir marcador a: ", "MARKER LIST TITLE": "Lista de Marcadores", "MARKER LIST": "Marcadores", "MARKER STATE PROMPT": "Status do marcador", - "MARKER STATE": " Definir estado do marcador", + "MARKER STATE": "Definir estado do marcador: ", "MARKER_LIST": "Lista de Marcadores: ${value}", "MARKERS BUTTON TITLE": "Marcadores", "MAX_SPLITS": "Divisões máximas", "MAX": "Fan Field", "MeetAgentPortalMarker": "Conhecer Agente", - "MERGE ON UPDATE": "Merge on update", - "MERGE_CHANGES_LOCAL": "Local changes", - "MERGE_CHANGES_MERGE": "Merge result", - "MERGE_CHANGES_REMOTE": "Remote changes", - "MERGE_LOCAL": "Keep local", + "MERGE ON UPDATE": "Unir na atualização", + "MERGE_CHANGES_LOCAL": "Alterações locais", + "MERGE_CHANGES_MERGE": "Combinar resultado", + "MERGE_CHANGES_REMOTE": "Mudanças remotas", + "MERGE_LOCAL": "Manter localmente", "MERGE_MESSAGE": "It seems that {opName} has local changes. Do you want to merge your modifications with the server OP, use the server version or keep the local version?", - "MERGE_REBASE": "Merge", - "MERGE_REPLACE": "Use server", - "MERGE_TITLE": "Merge local&remote OP", + "MERGE_REBASE": "Unir", + "MERGE_REPLACE": "Usar servidor", + "MERGE_TITLE": "Combinar OP local&remoto", "MIN_SRC_PORT_LVL": "Nível mínimo exigido no portal de origem", "MINUTES": " (${value} minutos atrás)", - "MM": "Multimax", - "MM_BOTH_SIDE": "Use both base sides", - "MM_INSERT_ORDER": "Insert at the end", - "MM_SET_ALL_PORTALS": "All visible portals", - "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM": "Multimáx", + "MM_BOTH_SIDE": "Usar ambos os lados base", + "MM_INSERT_ORDER": "Inserir no final", + "MM_SET_ALL_PORTALS": "Todos os portais visíveis", + "MM_SET_ALL_KEYS": "Todos os Marcadores GetKey", "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", - "MM_SPINE": "Spine", + "MM_SPINE": "Espinha", "MULTI_M_TITLE": "Desenhar camadas máximas", "MULTI_M": "Desenhar", "MUST_NOT_BE_EMPTY": "Não deve estar vazio", @@ -246,25 +247,25 @@ "PERM DENIED SHORT": "Permissão negada", "PERMS": "${value} permissões", "PLEASE_SELECT_PORTAL": "Seleciona um portal", - "PORT_FAKE": " portais. Falsificado ", + "PORT_FAKE": "", "PORTAL KEY LIST": "Lista de chaves para portal ${value}", "PORTAL_COUNT": "${value} portais", "PORTAL": "Portal", - "QD BUTTON CHANGE COLOR": "Click to change next links color", + "QD BUTTON CHANGE COLOR": "Clique para alterar a cor dos próximos links", "QD BUTTON END": "Clique para parar de desenhar campos", - "QD BUTTON TOGGLE MODE": "Click to change draw mode", - "QD CHANGE COLOR": "Change color", + "QD BUTTON TOGGLE MODE": "Clique para alterar o modo de desenho", + "QD CHANGE COLOR": "Alterar a cor", "QD END": "FIM", "QD TITLE": "Camadas de desenho rápido", - "QD TOGGLE MODE": "Change mode", + "QD TOGGLE MODE": "Alterar o modo", "QDBASE": "Link Base", "QDCONT": "Clica num portal espinha para desenhar um campo.", "QDNEXT": "Clica no segundo portal de âncora.", "QDSTART": "Clica no primeiro portal de âncora.", "READ_SHORT": "Ler Abreviado", "READ": "Ler", - "RechargePortalAlert": "Recharge", - "REFERENCE_TIME": "Reference Time: ", + "RechargePortalAlert": "Recarregar", + "REFERENCE_TIME": "Tempo de Referência: ", "REM_LOC_CP": "Remover cópia local de ${value}", "REMOVE_TEAM_CONFIRM_LABEL": "Você deseja remover permanentemente ${value} do servidor Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipe ${value}", @@ -277,19 +278,19 @@ "REVERSE": "Inverter", "ROCKS_COM": "enl.rocks comunidade: ", "ROLE": "Função", - "SAVELINKS TITLE": "Save Links", - "SAVELINKS_DRAW": "Save Links", - "SAVELINKS": "Save Links", + "SAVELINKS TITLE": "Salvar Links", + "SAVELINKS_DRAW": "Salvar Links", + "SAVELINKS": "Salvar Links", "SECONDS": " (${value} segundos atrás)", "SEL_SB_ANCHOR": "Seleciona a âncora.", "SEL_SB_ANCHOR2": "Reduzir o zoom. Verifica se todos os portais foram carregados e clica em desenhar.", - "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", + "SEL_SL_ANCHOR": "Selecione o portal para salvar os links de. Clique no botão salvar links e veja a lista de seleção.", "SEL_SRC_ANC2": "Selecionar a fonte e a âncora 2", "SEL_SRC_PORT": "Selecionar um portal de origem", "SELECT PORTAL": "Seleciona um portal primeiro", "SELECT_FAN_PORTALS": "Selecionar um portal de âncora, um portal inicial e um portal final e, em seguida, posiciona a visualização sobre a área do campo.", - "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", - "SELECT_INSTRUCTIONS": "Select two anchor portals, then zoom over the spine area.", + "SELECT_FAN_PORTALS2": "Espere todos os portais carregarem e clique em desenhar.", + "SELECT_INSTRUCTIONS": "Selecione dois portais de âncora, e então aumente o zoom sobre a área giratória.", "SELECT_ONION_PORTALS": "As camadas são construídas de dentro para fora. Aumenta o zoom para o centro e seleciona o portal inicial, em seguida, diminui o zoom para a área.", "SELF SWAP": "Não é possível trocar um portal contigo mesmo! Seleciona um portal diferente.", "SEND ANALYTICS": "Enviar análises anônimas", @@ -302,10 +303,10 @@ "SET_COMMENT": "Definir Comentário", "SET_LCOMMENT": "Definir comentário do link", "SET_LINK_COMMENT": "Definir comentário para o link: ", - "SET_LINKS_ZONES": "Set Links to Zones ", + "SET_LINKS_ZONES": "Definir links para zonas", "SET_MARKER_COMMENT": "Definir comentário para marcador em: ", "SET_MARKER_TYPE_TITLE": "Alterar o tipo de marcador", - "SET_MARKERS_ZONES": "Set Markers to Zones", + "SET_MARKERS_ZONES": "Definir Marcadores para Zonas", "SET_MCOMMENT": "Definir comentário do marcador: ${value}", "SET_NEW_OP": "Define o novo nome da operação", "SET_PCOMMENT": "Definir comentário do portal: ${value}", @@ -317,11 +318,11 @@ "SKINS_BUTTON": "Configurar Skins", "SKINS_DESCRIPTION": "Gerenciar as skins disponíveis movendo o tema para a coluna da esquerda. Quanto mais baixo na coluna, maior será a prioridade para o UI.", "SKINS_MANAGE_TITLE": "Gerenciar skins", - "SKIP_CONFIRM_ALWAYS": "Never ask (use with caution)", - "SKIP_CONFIRM_ENTITY": "Only ask for team/op", - "SKIP_CONFIRM_NEVER": "Always ask", - "SKIP_CONFIRM": "Skip confirmation", - "SOURCE_PORT": "Portal Fonte ", + "SKIP_CONFIRM_ALWAYS": "Nunca perguntar (use com cuidado)", + "SKIP_CONFIRM_ENTITY": "Apenas perguntar para equipa/op", + "SKIP_CONFIRM_NEVER": "Perguntar sempre", + "SKIP_CONFIRM": "Confirmação de salto", + "SOURCE_PORT": "Portal Fonte", "SQUAD": "Esquadrão", "STARBURST TITLE": "Starburst", "STARBURST_DRAW": "Desenhar", @@ -343,12 +344,21 @@ "TEAMS BUTTON TITLE": "Listar equipas Wasabee", "TEAMS BUTTON": "Equipas", "TO_PORT": "Para o Portal", - "toolbar.quick_delete.apply.text": "Apply", - "toolbar.quick_delete.apply.title": "Delete selected links/markers", - "toolbar.quick_delete.cancel.text": "Cancel", - "toolbar.quick_delete.cancel.title": "Cancel", - "toolbar.quick_delete.title": "Quick delete", - "TRAWL SKIP TILES": "Trawl Skip Tiles", + "toolbar.quick_delete.apply.text": "Aplicar", + "toolbar.quick_delete.apply.title": "Apagar links/marcadores selecionados", + "toolbar.quick_delete.cancel.text": "Cancelar", + "toolbar.quick_delete.cancel.title": "Cancelar", + "toolbar.quick_delete.stop.text": "Parar", + "toolbar.quick_delete.stop.title": "Sair do modo de eliminação", + "toolbar.quick_delete.title": "Eliminação rápida", + "toolbar.quick_delete.tooltip.toggle_mode": "Clique nos recursos para marcar para exclusão", + "toolbar.quick_delete.tooltip.quick_mode": "Clique nos recursos para excluir instantaneamente", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Selecionar a âncora da Estrela", + "toolbar.quick_draw.tooltip.star_mode.portal": "Selecionar um portal", + "toolbar.quick_draw.tooltip.single_mode.first": "Clique no primeiro portal", + "toolbar.quick_draw.tooltip.single_mode.next": "Clique no próximo portal", + "toolbar.quick_draw.tooltip.portal_fail": "Dados do portal não carregados, por favor, tente novamente", + "TRAWL SKIP TILES": "Pular blocos para armadilha", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "Isto carregará os dados do bloco em todos os links desenhados. Este é um processo lento.", "TRAWL_AUTOMARK": "Auto-mark blockers depois da procura", @@ -363,16 +373,16 @@ "UNKNOWN": "Desconhecido", "UPDATE HOVER NOT CHANGED": "${value} não mudou localmente", "UPDATE HOVER": "UPDATE ${value} no servidor", - "UPDATE PERM DENIED": "You do not have permission to update", + "UPDATE PERM DENIED": "Você não possui permissão para editar", "UPDATE_CONFLICT_DESC": "A OP foi modificada no servidor desde a última sincronização. Queres substituir a versão do servidor pela atual?", "UPDATE_CONFLICT_TITLE": "Conflito detectado com o servidor", "UPDATE_COUNT": "Contagem de atualização", "UPDATED": "Atualizado com sucesso", - "UpgradePortalAlert": "Upgrade", + "UpgradePortalAlert": "Atualizar", "UPLOAD BUTTON HOVER": "UPLOAD ${value} (atualmente não está no servidor)", "UPLOADED": "Carregado com sucesso", - "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": ". Usa o recurso de troca para mover portais falsos para portais reais no mesmo local. Ampliar os portais 'Carregando' na lista de verificação pode forçá-los a carregar.", + "USE PANES ON MOBILE": "Usar painéis (precisa recarregar)", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Usa um nome de operação válido", "UseVirusPortalAlert": "Usar Virus", "VRLA DESC": "Dependendo do número e tipo de Link Amps usados, um nível de portal de origem inferior pode ser suficiente.", @@ -381,27 +391,24 @@ "WASABEE_D_LIST": "Contagem de chaves defensivas de entrada", "WD BUTTON TITLE": "Log de chaves defensivas", "WD BUTTON": "W-D Chaves", - "WEBVIEW VERIFY": "Verificar Webview", - "WEBVIEW": "Login do Webview (iOS)", "WRITE_SHORT": "RW", "WRITE": "escrita", "WSERVER": "Servidor: ${value}", "YESNO_DEL": "Tem certeza de que deseja excluir ${value}?", - "ZONE_DRAW": "Click to set the zone boundaries", - "ZONE": "Zone", + "ZONE_DRAW": "Clique para definir os limites da zona", + "ZONE": "Zona", "smallScreen": { "ADD_LINKS": "+ Links", "ADD_MARKER": "+ Marcador", - "BLOCKER TITLE": "Blockers", + "BLOCKER TITLE": "Bloqueadores", "CHECKLIST BUTTON": "Verificar", "CLEAROPS BUTTON": "Limpar", "EXPORT OP": "Exportar", - "FAN_FIELD3": "Fan", "FANFIELD": "Desenhar", "FANFIELD2": "Desenhar Fan Field", "KEYS": "Chaves", - "LOG IN": "Log In", - "LOG_OUT": "Log Out", + "LOG IN": "Iniciar Sessão", + "LOG_OUT": "Terminar Sessão", "MARKER LIST": "Marcadores", "MARKERS BUTTON TITLE": "Marcadores", "MAX": "Fan", diff --git a/src/code/translations/Russian.json b/src/code/translations/Russian.json index b34f1596d..a585f7722 100644 --- a/src/code/translations/Russian.json +++ b/src/code/translations/Russian.json @@ -19,16 +19,16 @@ "AGES": " (давно)", "ALREADY_HAS_MARKER": "У этого портала уже есть маркер. Выбери другой портал.", "AMAZ_TEAM_NAME": "Отличное название.", - "ANCHOR ASSIGNMENT": " все исходящие линки", + "ANCHOR ASSIGNMENT": "Назначить все исходящие линки: ", "ANCHOR_GMAP": "Google-карты", - "ANCHOR_PORTAL": "Опорный портал ", + "ANCHOR_PORTAL": "Опорный портал", "ANCHOR_PORTAL2": "Опорный портал 2", "ANCHOR_PORTAL3": "Опорный портал 3", - "ANCHOR1": "Опорник 1 ", - "ANCHOR2": "Опорник 2 ", - "ANCHOR3": "Опорник 3 ", + "ANCHOR1": "Опорник 1", + "ANCHOR2": "Опорник 2", + "ANCHOR3": "Опорник 3", "ANCHORS_AS_BOOKMARKS": "Опорники в закладки", - "API_KEY": " ключ api: ", + "API_KEY": "API ключ Rocks: ", "ASS_TO": "Назначено агенту", "ASSIGN LINK PROMPT": "Назначить линк с портала: {portalName}", "ASSIGN MARKER PROMPT": "Назначить маркер с {portalName}", @@ -39,7 +39,6 @@ "ASSIGNED_ONLY": "Только назначенные", "assigned": "Назначено", "AUTH INCOMPAT": "Ты активировал в TamperMonkey плагин, который несовместим с Wasabee", - "AUTH IOS": "На iOS, используй основную опцию 'Логин'. Если не получится, используй 'Логин Webview', а затем кнопку 'Подтвердить Webview' для завершения процесса.", "AUTH REQUIRED": "Необходима аутентификация", "AUTH TOKEN REJECTED": "Отправка аутентификационного токена на сервер отклонена: {error}", "AUTH_SELECT_ACCOUNT": "Выбери аккаунт", @@ -70,7 +69,6 @@ "CLEAR LINKS": "Удалить линки", "CLEAR MARKERS": "Удалить маркеры", "CLEAR_EVERYTHING": "Удалить порталы/линки/маркеры для текущей ОПРЦ", - "CLEAR": "Очистить выбор", "CLEAROPS BUTTON TITLE": "Удалить данные", "CLEAROPS BUTTON": "Удалить данные", "CLEAROPS PROMPT": "Удалить все локальные ОПРЦ. ОПРЦ будут восстановлены при следующей загрузке.", @@ -94,6 +92,9 @@ "DELETE_OP": "Удалить {opName}", "DESCRIP_PLACEHOLD": "Описание (опционально)", "DestroyPortalAlert": "Снести", + "dialog.about.download_mobile_app": "

Приложение Wasabee:

", + "dialog.setcomment.portal_hardness": "Сложность", + "dialog.import.success_message": "Импорт завершён. Найдено {count} порталов и {faked} порталов было не подгружено. Используй функцию замены, чтобы заменить неподгруженные порталы на настоящие на тех же местах. Увеличение масштаба на порталах чек-листа с меткой 'загрузка' может заставить их загрузиться.", "DRAW TOOLS FORMAT": "Формат ДТ", "DUPE_OP": "Дублировать операцию", "END_PORT": "Конечный портал ", @@ -108,8 +109,8 @@ "FLIP_FLOP_NAME": "Flip flop", "FLIP_FLOP_TITLE": "Flip flop", "FLIP_FLOP_DESC": "Исходя из заданного опорника, видимых порталов и количества SBUL, найти fanfield, в котором очередность перенавеса с опорника будет идти по уменьшению длины линков для того, чтобы избежать поиска ключей.", - "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", - "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", + "FLIP_FLOP_INSTRUCTION": "Выбери портал, приблизь карту, чтобы видеть достаточно порталов и нажми Рисовать. Как только fanfield будет найдено, можно будет поискать другие опорники для последовательного перенавеса.", + "FLIP_FLOP_FIND_ANCHORS": "Найти другие опорники", "FROM_1-2": "от опорного линка 1-2", "FROM_1-3": "от опорного линка 1-3", "FROM_2-3": "от опорного линка 2-3", @@ -125,7 +126,7 @@ "HG": "Гомогенное поле", "HOURS": " ({hours} часов назад)", "HOW_TO_VIDS": "

Обучающие видео:

", - "IMP_COMP": "Импорт завершён. Найдено ", + "IMP_COMP": "", "IMP_NOPE": "Ошибка импорта.", "IMP_WAS_OP": "Импортировать ОПРЦ Wasabee", "IMPORT_OP_SUCCESS": "ОПРЦ: {opName} импортирована успешно.", @@ -145,9 +146,9 @@ "LANG": "Язык", "LEAVE": "Выйти", "LetDecayPortalAlert": "Просадить", - "LINK ASSIGNMENT": " Назначение линка", + "LINK ASSIGNMENT": "Назначить линк: ", "LINK STATE PROMPT": "Статус линка", - "LINK STATE": "Установить статус линка", + "LINK STATE": "Установить статус линка: ", "LINKS BUTTON TITLE": "Линки", "LINKS": "Линки", "LINKS2": "{portalName} : Линки ({outgoing}↑/{incoming}↓)", @@ -167,15 +168,15 @@ "MADRID": "Нарисовать", "MANAGE_TEAM": "Редактировать {teamName}", "MANAGE": "Редактировать", - "MARKER ASSIGNMENT": " Назначение маркера", + "MARKER ASSIGNMENT": "Назначить маркер: ", "MARKER LIST TITLE": "Список маркеров", "MARKER LIST": "Маркеры", "MARKER STATE PROMPT": "Статус маркера", - "MARKER STATE": " Установить статус маркера", + "MARKER STATE": "Установить статус маркера: ", "MARKER_LIST": "Список маркеров: {opName}", "MARKERS BUTTON TITLE": "Маркеры", "MAX_SPLITS": "Максимальный уровень", - "MAX": "Fan Field", + "MAX": "FanField", "MeetAgentPortalMarker": "Встретить агента", "MERGE ON UPDATE": "Объединить при обновлении", "MERGE_CHANGES_LOCAL": "Изменения на устройстве", @@ -189,12 +190,12 @@ "MIN_SRC_PORT_LVL": "Минимальный требуемый уровень портала для линковки", "MINUTES": " ({minutes} минут назад)", "MM": "Multimax", - "MM_BOTH_SIDE": "Use both base sides", - "MM_INSERT_ORDER": "Insert at the end", - "MM_SET_ALL_PORTALS": "All visible portals", - "MM_SET_ALL_KEYS": "All GetKey Markers", + "MM_BOTH_SIDE": "Использовать обе стороны опорного линка", + "MM_INSERT_ORDER": "Вставить в конце", + "MM_SET_ALL_PORTALS": "Все видимые порталы", + "MM_SET_ALL_KEYS": "Все маркеры GetKey", "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", - "MM_SPINE": "Spine", + "MM_SPINE": "Грядка", "MULTI_M_TITLE": "Нарисовать максимальное количество слоёв", "MULTI_M": "Нарисовать", "MUST_NOT_BE_EMPTY": "Не должно быть пустым", @@ -212,14 +213,14 @@ "NO_LABEL": "Метка не установлена", "NO_STOCK_INTEL": "Wasabee не поддерживает импорт из Intel", "NO_TITLE": "Название не установлено", - "NO LONGER AVAILABLE": "Resource removed from server: {error}", - "NO LONGER AVAILABLE SHORT": "Resource removed from server", + "NO LONGER AVAILABLE": "Ресурс удален с сервера: {error}", + "NO LONGER AVAILABLE SHORT": "Ресурс удален с сервера", "NOT LOGGED IN SHORT": "Не залогинен", "NOT LOGGED IN": "Не залогинен: {error}", - "NOT_LOADED": "Not fully loaded, try again.", + "NOT_LOADED": "Не полностью загружено, попробуй еще раз.", "NOT_SET": "не установлено", "NTNAME": "Название", - "OK": "OK", + "OK": "ОК", "ON_HAND": "На руках", "ONION_WAS_TAKEN": "Onion", "ONION": "Нарисовать", @@ -240,13 +241,13 @@ "OPS BUTTON": "Выбери ОПРЦ", "ORDER": "Порядок", "OtherPortalAlert": "Другое", - "PASTE_INSTRUCT": "Вставь экспортируемые данные Wasabee здесь.\n\nWasabee не может импортировать данные в формате интела.\n\nЕсть эксперементальная поддержка ДТ формата IITC.\n\nПрежде чем импортировать ДТ в формате IITC, просмотрите область ДТ и убедитесь, что все порталы загружены и кэшированы в IITC. Любой неподгруженный портал будет неподгружен.\n\nНужно будет использовать функцию 'замена', чтобы переместить порталы со неподгруженных на настоящие (местоположение порталов будет корректным, однако неподгруженные порталы не будут связаны с реальными).\n\nКэшированные порталы могут некорректно называться.", + "PASTE_INSTRUCT": "Вставь экспортируемые данные Wasabee здесь.\n\nWasabee не может импортировать данные в формате интела.\n\nЕсть эксперементальная поддержка ДТ формата IITC.\n\nПрежде чем импортировать ДТ в формате IITC, просмотри область ДТ и убедись, что все порталы загружены и кэшированы в IITC. Любой неподгруженный портал будет неподгружен.\n\nНужно будет использовать функцию 'замена', чтобы переместить порталы со неподгруженных на настоящие (местоположение порталов будет корректным, однако неподгруженные порталы не будут связаны с реальными).\n\nКэшированные порталы могут некорректно называться.", "pending": "Ожидается", - "PERM DENIED": "Permission denied: {error}", - "PERM DENIED SHORT": "Permission denied", + "PERM DENIED": "Доступ запрещен: {error}", + "PERM DENIED SHORT": "Доступ запрещен", "PERMS": "Разрешения {opName}", "PLEASE_SELECT_PORTAL": "Выбери портал", - "PORT_FAKE": " порталов. Неподгружены ", + "PORT_FAKE": "", "PORTAL KEY LIST": "Список ключей для портала {portalName}", "PORTAL_COUNT": "{count} порталов", "PORTAL": "Портал", @@ -302,7 +303,7 @@ "SET_COMMENT": "Задать комментарий", "SET_LCOMMENT": "Задать комментарий к линку", "SET_LINK_COMMENT": "Задать комментарий для линка: ", - "SET_LINKS_ZONES": "Задать линкам зоны ", + "SET_LINKS_ZONES": "Задать линкам зоны", "SET_MARKER_COMMENT": "Задать комментарий для маркера на: ", "SET_MARKER_TYPE_TITLE": "Изменить тип маркера", "SET_MARKERS_ZONES": "Задать маркеры в зоны", @@ -321,7 +322,7 @@ "SKIP_CONFIRM_ENTITY": "Спрашивать только для команд/ОПРЦ", "SKIP_CONFIRM_NEVER": "Всегда спрашивать", "SKIP_CONFIRM": "Подтверждение пропуска", - "SOURCE_PORT": "Начальный портал ", + "SOURCE_PORT": "Начальный портал", "SQUAD": "Отряд", "STARBURST TITLE": "Звезда", "STARBURST_DRAW": "Рисовка", @@ -343,11 +344,20 @@ "TEAMS BUTTON TITLE": "Список команд Wasabee", "TEAMS BUTTON": "Команды", "TO_PORT": "На портал", - "toolbar.quick_delete.apply.text": "Apply", - "toolbar.quick_delete.apply.title": "Delete selected links/markers", - "toolbar.quick_delete.cancel.text": "Cancel", - "toolbar.quick_delete.cancel.title": "Cancel", - "toolbar.quick_delete.title": "Quick delete", + "toolbar.quick_delete.apply.text": "Применить", + "toolbar.quick_delete.apply.title": "Удалить выбранные линки/маркеры", + "toolbar.quick_delete.cancel.text": "Отмена", + "toolbar.quick_delete.cancel.title": "Отмена", + "toolbar.quick_delete.stop.text": "Стоп", + "toolbar.quick_delete.stop.title": "Выйти из режима удаления", + "toolbar.quick_delete.title": "Быстрое удаление", + "toolbar.quick_delete.tooltip.toggle_mode": "Кликни на объекты, чтобы выделить их для удаления", + "toolbar.quick_delete.tooltip.quick_mode": "Кликни на объекты, чтобы немедленно удалить их", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Выбери опорник звезды", + "toolbar.quick_draw.tooltip.star_mode.portal": "Выбери портал", + "toolbar.quick_draw.tooltip.single_mode.first": "Нажми на первый портал", + "toolbar.quick_draw.tooltip.single_mode.next": "Нажми на следующий портал", + "toolbar.quick_draw.tooltip.portal_fail": "Данные о портале не загружены, попробуй еще раз", "TRAWL SKIP TILES": "Шаг тайлов для выверки", "TRAWL TITLE": "Выверка трасс", "TRAWL WARNING": "Этот метод загрузит данные тайлов под всеми нарисованными линками. Это медленный процесс.", @@ -372,7 +382,7 @@ "UPLOAD BUTTON HOVER": "ЗАГРУЗИТЬ {opName} на сервер (пока что её там нет)", "UPLOADED": "Успешно загружено на сервер", "USE PANES ON MOBILE": "Использовать панели (нужна перезагрузка)", - "USE_SWAP_INSTRUCT": ". Используй функцию замены, чтобы заменить неподгруженные порталы на настоящие на тех же местах. Увеличение масштаба на порталах чек-листа с меткой 'загрузка' может заставить их загрузиться.", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Используй действительное название операции", "UseVirusPortalAlert": "Использовать вирус", "VRLA DESC": "В зависимости от количества и типа использованных ламп может быть достаточно более низкого уровня портала для линковки.", @@ -381,8 +391,6 @@ "WASABEE_D_LIST": "Ввод количества ключей на руках", "WD BUTTON TITLE": "Список ключей на руках", "WD BUTTON": "Ключи на руках", - "WEBVIEW VERIFY": "Подтвердить Webview", - "WEBVIEW": "Логин Webview (iOS)", "WRITE_SHORT": "RW", "WRITE": "чтение и запись", "WSERVER": "Сервер: {url}", @@ -396,7 +404,6 @@ "CHECKLIST BUTTON": "Чек-лист", "CLEAROPS BUTTON": "Очистить", "EXPORT OP": "Экспортировать", - "FAN_FIELD3": "Fan", "FANFIELD": "Рисовка", "FANFIELD2": "Нарисовать Fan Field", "KEYS": "Ключи", @@ -404,8 +411,8 @@ "LOG_OUT": "Выход", "MARKER LIST": "Маркеры", "MARKERS BUTTON TITLE": "Маркеры", - "MAX": "Fan", - "MM": "Multi", + "MAX": "Fanfield", + "MM": "Multimax", "MULTI_M_TITLE": "Рисовать максимальное количество слоёв", "MULTI_M": "Рисовать", "NEWOP BUTTON": "Новая ОПРЦ", diff --git a/src/code/translations/Spanish.json b/src/code/translations/Spanish.json index 2442782b1..003a68702 100644 --- a/src/code/translations/Spanish.json +++ b/src/code/translations/Spanish.json @@ -1,6 +1,6 @@ { "ABOUT_WASABEE": "Sobre Wasabee", - "acknowledged": "Acknowledged", + "acknowledged": "Recibido", "ADD LINK TITLE": "Texto de Agregar Links", "ADD MARKER TITLE": "Texto de Agregar Marcadores", "ADD_AGENT": "Agregar Agente", @@ -9,53 +9,52 @@ "ADD_LINKS": "Agregar Links", "ADD_MARKER": "Agregar Marcador", "ADD_NEW_OP": "Agregar Nueva Op", - "ADD_SUCC_INSTR": "Agregado satisfactoriamente, se necesitará habilitar al equipo en el sitio web de Wasabee antes de que aparezcan en esta lista", - "ADD_ZONE": "Add Zone", + "ADD_SUCC_INSTR": "Agente añadido correctamente", + "ADD_ZONE": "Añadir Zona", "ADD": "Agregar", - "ADD1": "Add first link", - "ADD2": "Add second link", - "AGENT_STATS": "Agent Stats", + "ADD1": "Añadir primer enlace", + "ADD2": "Añadir segundo enlace", + "AGENT_STATS": "Estadísticas de agente", "AGENT": "Agente", "AGES": "(Hace demasiado tiempo)", "ALREADY_HAS_MARKER": "Este portal ya tiene un marcador. Elige un portal diferente.", "AMAZ_TEAM_NAME": "Excelente nombre de equipo", - "ANCHOR ASSIGNMENT": "todos los links de salida", + "ANCHOR ASSIGNMENT": "Assign all outbound links to: ", "ANCHOR_GMAP": "Google Map", - "ANCHOR_PORTAL": "Portal Ancla", - "ANCHOR_PORTAL2": "Anchor Portal 2", - "ANCHOR_PORTAL3": "Anchor Portal 3", - "ANCHOR1": "Ancla 1", - "ANCHOR2": "Ancla 2", - "ANCHOR3": "Anchor 3 ", - "ANCHORS_AS_BOOKMARKS": "Anchors as bookmarks", - "API_KEY": "api key", + "ANCHOR_PORTAL": "Anchor Portal", + "ANCHOR_PORTAL2": "Portal Ancla 2", + "ANCHOR_PORTAL3": "Portal Ancla 3", + "ANCHOR1": "Anchor 1", + "ANCHOR2": "Anchor 2", + "ANCHOR3": "Anchor 3", + "ANCHORS_AS_BOOKMARKS": "Anclas a Marcadores", + "API_KEY": "Rocks API key: ", "ASS_TO": "Asignado A", "ASSIGN LINK PROMPT": "Asignar link de {portalName}", "ASSIGN MARKER PROMPT": "Asignar marcador de {portalName}", "ASSIGN OUTBOUND PROMPT": "Asignar todos los links de salida de {portalName}", "ASSIGN OUTBOUND": "Asignar Links de salida", "ASSIGN": "Asignar", - "ASSIGNED_ONLY_SHORT": "AO", - "ASSIGNED_ONLY": "Assigned Only", + "ASSIGNED_ONLY_SHORT": "SA", + "ASSIGNED_ONLY": "Sólo asignados", "assigned": "Asignado", "AUTH INCOMPAT": "Has activado un plugin en TamperMonkey que es incompatible con Wasabee", - "AUTH IOS": "En iOS, usa el 'Iniciar Sesión' principal. Si eso falla intenta usar 'Inicio de Sesión Vista Web'; luego usa el botón 'Verificar Vista Web' para completar el proceso.", "AUTH REQUIRED": "Autenticación Requerida", "AUTH TOKEN REJECTED": "Envío de token de autorización al servidor rechazado: {error}", - "AUTH_SELECT_ACCOUNT": "Select account", - "AUTO_DRAWS": "Auto-draw", - "AUTODRAWS": "Wasabee Auto-draw Options", - "AUTODRAW_PORTALS_SET": "Portals", - "autodraw.common.draw_button": "Draw", - "autodraw.flipflop.result": "Flip flop: found {count} links", - "autodraw.onion.variant": "Option", - "autodraw.onion.variant.equilateral": "~Equilateral", - "autodraw.onion.variant.grow": "Let it grow", - "autodraw.onion.variant.balanced": "Perfectly balanced", - "AUTOLOAD_RATE": "Portal Detail Request Rate (ms)", - "AUTOLOAD": "Automatically Load Missing Portal Details", + "AUTH_SELECT_ACCOUNT": "Seleccionar cuenta", + "AUTO_DRAWS": "Autodibujar", + "AUTODRAWS": "Opciones de dibujo automático de Wasabee", + "AUTODRAW_PORTALS_SET": "Portales", + "autodraw.common.draw_button": "Dibujar", + "autodraw.flipflop.result": "Flip flop: encontró {count} enlaces", + "autodraw.onion.variant": "Opción", + "autodraw.onion.variant.equilateral": "~Equilátero", + "autodraw.onion.variant.grow": "Permitir que crezca", + "autodraw.onion.variant.balanced": "Equilibrio perfecto", + "AUTOLOAD_RATE": "Tasa de solicitud de detalles de portales (ms)", + "AUTOLOAD": "Cargar automáticamente los detalles del portal faltante", "AUTOMARK STOP": "El Marcado-Automático se detuvo debido a que los portales no estaban cargado", - "AUTOMARK": "Auto-Mark", + "AUTOMARK": "Automarcar", "BAT_TOAD": "Sapitos de Batalla", "BLOCKER LIST TITLE": "Mostrar todos los bloqueos", "BLOCKER TITLE": "Bloqueos", @@ -67,14 +66,13 @@ "CHANGE_WAS_SERVER": "Cambiar Servidor de Wasabee", "CHECKLIST BUTTON TITLE": "Lista de Verificación de la Operación", "CHECKLIST BUTTON": "Lista de Verificación", - "CLEAR LINKS": "Clear Links", - "CLEAR MARKERS": "Clear Markers", + "CLEAR LINKS": "Borrar Enlaces", + "CLEAR MARKERS": "Borrar marcadores", "CLEAR_EVERYTHING": "Borrar Portales/Links/Marcadores", - "CLEAR": "Clear selection", "CLEAROPS BUTTON TITLE": "Borrar TODOS los Datos de Wasabee", "CLEAROPS BUTTON": "Borrar Datos de Wasabee", "CLEAROPS PROMPT": "Esta opción borrará todas las OPS y datos relacionados a Wasabee. Todo será restaurado desde el servidor en la próxima sincronización.", - "CLOSE": "Close", + "CLOSE": "Cerrar", "COMMENT": "Comentario", "COMPLETED BY": "Completado por {agentName}", "completed": "Completo", @@ -94,38 +92,41 @@ "DELETE_OP": "Borrar {opName}", "DESCRIP_PLACEHOLD": "Descripción (opcional)", "DestroyPortalAlert": "Destruir", - "DRAW TOOLS FORMAT": "Draw Tools Format", + "dialog.about.download_mobile_app": "

Aplicación Wasabee:

", + "dialog.setcomment.portal_hardness": "Dificultad", + "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", + "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplicar Operación", "END_PORT": "Portal de Fin", "ExcludeMarker": "Excluir del Dibujo/Marcado Automático", "EXPORT OP TITLE": "Exportar Op actual", "EXPORT OP": "Exportar Op", "EXPORT": "Exportar", - "FAKED": "Faked: [{portalId}]", + "FAKED": "Virtual: [{portalId}]", "FANFIELD": "¡Dibujar!", "FANFIELD2": "Fanfield", "FarmPortalMarker": "Farmear", "FLIP_FLOP_NAME": "Flip flop", "FLIP_FLOP_TITLE": "Flip flop", - "FLIP_FLOP_DESC": "From a given anchor, a set of visible portal and a number of SBUL, find a fanfield to throw links from the anchor by decreasing distance to avoid searching keys.", + "FLIP_FLOP_DESC": "Dados un ancla determinado, un conjunto de portales visibles y una cantidad de SBUL, encuentra un fanfield para lanzar enlaces desde el ancla en orden de distancia descendente para evitar buscar llaves.", "FLIP_FLOP_INSTRUCTION": "Select a portal, zoom to see enough portals and press Draw. Once a fanfield is found, you can search for other anchors for consecutive rethrow", - "FLIP_FLOP_FIND_ANCHORS": "Find other anchors", - "FROM_1-2": "from base 1-2", - "FROM_1-3": "from base 1-3", - "FROM_2-3": "from base 2-3", - "FROM_DEPTH": "from the depth", + "FLIP_FLOP_FIND_ANCHORS": "Encontrar otros anclas", + "FROM_1-2": "desde la base 1-2", + "FROM_1-3": "desde la base 1-3", + "FROM_2-3": "desde la base 2-3", + "FROM_DEPTH": "desde el interior", "FROM_PORT": "Desde el Portal", - "GET DT": "Get existing DrawTools draw", + "GET DT": "Obtener el dibujo existente de DrawTools", "GetKeyPortalMarker": "Obtener Keys", "GotoPortalMarker": "Ir A", - "H-GEN_INST": "Set portals for the outside layer. Choose number of splits. Click draw", - "HF_DEEP_SEARCH": "Exhaustive search", - "HF_DRAW_BUTTON": "Draw", - "HF_REDRAW_BUTTON": "Redraw", - "HG": "Homogeneous Field", + "H-GEN_INST": "Establece portales para la capa exterior. Elige el número de divisiones. Haz clic en dibujar", + "HF_DEEP_SEARCH": "Búsqueda exhaustiva", + "HF_DRAW_BUTTON": "Dibujar", + "HF_REDRAW_BUTTON": "Redibujar", + "HG": "Campo homogéneo", "HOURS": "(Hace {hours} horas)", "HOW_TO_VIDS": "

Videos de Cómo Se Hace:

", - "IMP_COMP": "Importación Completa. Se encontró", + "IMP_COMP": "", "IMP_NOPE": "Importación Falló: {error}", "IMP_WAS_OP": "Importar Operación Wasabee", "IMPORT_OP_SUCCESS": "Operación {opName} Importada Exitosamente.", @@ -145,13 +146,13 @@ "LANG": "Idioma", "LEAVE": "Salir", "LetDecayPortalAlert": "Dejar Decaer", - "LINK ASSIGNMENT": "Asignación de Link", + "LINK ASSIGNMENT": "Assign link to: ", "LINK STATE PROMPT": "Estado del Link", - "LINK STATE": "Definir estado del link", - "LINKS BUTTON TITLE": "Links", - "LINKS": "Links", - "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", - "LOAD PORTALS": "Load Portals", + "LINK STATE": "Set link status: ", + "LINKS BUTTON TITLE": "Enlaces", + "LINKS": "Enlaces", + "LINKS2": "{portalName}: Enlaces ({outgoing}↑/{incoming}↓)", + "LOAD PORTALS": "Cargar Portales", "LOADING": "[cargando]", "LOADING1": "Cargando: [{portalGuid}]", "LOC_PROC": "ubicación procesada", @@ -162,40 +163,40 @@ "MADRID_SET_1": "Select the region for baselink Anchor 2 to Anchor 3", "MADRID_SET_2": "Select the region for baselink Anchor 3 to Anchor 1", "MADRID_SET_3": "Select the region for baselink Anchor 1 to Anchor 2", - "MADRID_TITLE": "Madrid Protocol", - "MADRID_WAS_TAKEN": "Madrid Protocol", - "MADRID": "Draw", + "MADRID_TITLE": "Protocolo Madrid", + "MADRID_WAS_TAKEN": "Protocolo Madrid", + "MADRID": "Dibujar", "MANAGE_TEAM": "Gestionar {teamName}", "MANAGE": "Gestionar", - "MARKER ASSIGNMENT": "Asignación de Marcador", + "MARKER ASSIGNMENT": "Assign marker to: ", "MARKER LIST TITLE": "Lista de Marcadores", "MARKER LIST": "Marcadores", "MARKER STATE PROMPT": "Estado Del Marcador", - "MARKER STATE": " Definir estado del marcador", + "MARKER STATE": "Set marker state: ", "MARKER_LIST": "Listad de Marcadores {opName}", "MARKERS BUTTON TITLE": "Marcadores", - "MAX_SPLITS": "Max Splits", + "MAX_SPLITS": "Divisiones máximas", "MAX": "Fan Field", "MeetAgentPortalMarker": "Encontrar Agent", - "MERGE ON UPDATE": "Merge on update", - "MERGE_CHANGES_LOCAL": "Local changes", - "MERGE_CHANGES_MERGE": "Merge result", - "MERGE_CHANGES_REMOTE": "Remote changes", - "MERGE_LOCAL": "Keep local", + "MERGE ON UPDATE": "Combinar al actualizar", + "MERGE_CHANGES_LOCAL": "Cambios locales", + "MERGE_CHANGES_MERGE": "Combinar resultado", + "MERGE_CHANGES_REMOTE": "Cambios remotos", + "MERGE_LOCAL": "Mantener local", "MERGE_MESSAGE": "It seems that {opName} has local changes. Do you want to merge your modifications with the server OP, replace the local version with the server version, or cancel?", "MERGE_REBASE": "Rebase", "MERGE_REPLACE": "Replace", - "MERGE_TITLE": "Merge local&remote OP", + "MERGE_TITLE": "Combinar OP local y remota", "MIN_SRC_PORT_LVL": "Nivel mínimo requerido para el portal fuente", "MINUTES": "(Hace {minutes} minutos)", "MM": "Multimax", - "MM_BOTH_SIDE": "Use both base sides", - "MM_INSERT_ORDER": "Insert at the end", - "MM_SET_ALL_PORTALS": "All visible portals", - "MM_SET_ALL_KEYS": "All GetKey Markers", - "MM_SET_KEYS_ZONE": "GetKey: {zoneName}", - "MM_SPINE": "Spine", - "MULTI_M_TITLE": "Draw Max Layers", + "MM_BOTH_SIDE": "Usar ambos lados de la base", + "MM_INSERT_ORDER": "Insertar al final", + "MM_SET_ALL_PORTALS": "Todos los portales visibles", + "MM_SET_ALL_KEYS": "Todos los marcadores de Obtener llave", + "MM_SET_KEYS_ZONE": "Obtener llave: {zoneName}", + "MM_SPINE": "Espinazo", + "MULTI_M_TITLE": "Dibujar Máximas Capas", "MULTI_M": "Multimax", "MUST_NOT_BE_EMPTY": "No Debe Quedar Vacío", "MY_CAP_ID": "ID de Mi Cápsula", @@ -204,7 +205,7 @@ "NAME": "Nombre", "NEW_OP": "Nueva Operación", "NEW_TEAM_NAME": "Nuevo Nombre de Equipo", - "NEW_TEAM": "New Team", + "NEW_TEAM": "Nuevo equipo", "NEW_WAS_SERVER": "Nuevo Servidor de Wasabee", "NEWOP BUTTON TITLE": "Crear una nueva Operación", "NEWOP BUTTON": "Nueva Op", @@ -219,19 +220,19 @@ "NOT_LOADED": "No está cargado completamente, intentar de nuevo.", "NOT_SET": "no definido", "NTNAME": "Nombre", - "OK": "OK", + "OK": "Aceptar", "ON_HAND": "En Mano", "ONION_WAS_TAKEN": "Onion", - "ONION": "Draw", + "ONION": "Dibujar", "ONLY_DT_IMP": "(solo para importaciones de DrawTools)", - "OP DELETED": "Operation removed from server: {opID}", + "OP DELETED": "Operación eliminada del servidor: {opID}", "OP PERM DENIED": "Permiso denegado a la operación: {opID}", - "OP_BUTTON": "Operation", + "OP_BUTTON": "Operación", "OP_CHECKLIST": "Lista de Verificación de la Operación {opName}", "OP_NAME_UNSET": "Se Removió el Nombre de Operación", "OP_PERMS": "Permisos para la Op", "OP_SETTINGS_BUTTON": "Op ⚙", - "OP_SETTINGS_TITLE": "Operation Settings", + "OP_SETTINGS_TITLE": "Ajustes de Operación", "OPEN_REQUEST": "[abrir solicitud]", "OPER_COLOR": "Color de la Operación", "OPER_NAME": "Nombre de la Operación", @@ -246,25 +247,25 @@ "PERM DENIED SHORT": "Permiso denegado", "PERMS": "{opName} permisos", "PLEASE_SELECT_PORTAL": "Por favor, seleccionar un portal", - "PORT_FAKE": "portales. Falsificados", + "PORT_FAKE": "", "PORTAL KEY LIST": "Lista de Llaves del Portal {portalName}", - "PORTAL_COUNT": "{count} portals", + "PORTAL_COUNT": "{count} portales", "PORTAL": "Portal", - "QD BUTTON CHANGE COLOR": "Click to change next links color", + "QD BUTTON CHANGE COLOR": "Haz clic para cambiar el color de los siguientes enlaces", "QD BUTTON END": "Dar click para detener dibujo de campos", - "QD BUTTON TOGGLE MODE": "Click to change draw mode", - "QD CHANGE COLOR": "Change color", - "QD END": "End", + "QD BUTTON TOGGLE MODE": "Haz clic para cambiar el modo de dibujo", + "QD CHANGE COLOR": "Cambiar color", + "QD END": "Finalizar", "QD TITLE": "Dibujar Capas Rápido", - "QD TOGGLE MODE": "Change mode", + "QD TOGGLE MODE": "Cambiar modo", "QDBASE": "Link Base", "QDCONT": "Dar click a un portal anidado para dibujar el campo.", "QDNEXT": "Dar click al segundo portal ancla.", "QDSTART": "Dar click al primer portal ancla.", - "READ_SHORT": "RO", + "READ_SHORT": "SL", "READ": "Leer", "RechargePortalAlert": "Recargar", - "REFERENCE_TIME": "Reference Time: ", + "REFERENCE_TIME": "Hora de referencia: ", "REM_LOC_CP": "Borrar copia local de {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "¿Deseas remover {teamName} permanentemente del Servidor Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipo {teamName}", @@ -273,28 +274,28 @@ "RENAME_TEAM": "Renombrar Equipo", "RENAME": "Renombrar", "REQUIRED": "Requeridas", - "RESET": "Reset", - "REVERSE": "Reverse", + "RESET": "Restablecer", + "REVERSE": "Invertir", "ROCKS_COM": "comunidad enl.rocks", "ROLE": "Rol", - "SAVELINKS TITLE": "Save Links", - "SAVELINKS_DRAW": "Save Links", - "SAVELINKS": "Save Links", + "SAVELINKS TITLE": "Guardar Enlaces", + "SAVELINKS_DRAW": "Guardar Enlaces", + "SAVELINKS": "Guardar Enlaces", "SECONDS": "(Hace {seconds} segundos)", "SEL_SB_ANCHOR": "Selecciona el área del ancla para hacer acercamiento para añadir a la supernova.", - "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", - "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", + "SEL_SB_ANCHOR2": "Aleja el zoom. Asegúrate de que los portales se han cargado completamente y haz clic en Dibujar.", + "SEL_SL_ANCHOR": "Selecciona el portal del que quieres guardar los enlaces. Haz clic en el botón de Guardar Enlaces y revisa la lista de comprobación.", "SEL_SRC_ANC2": "Selecciona tanto la Fuente como el Ancla 2", "SEL_SRC_PORT": "Selecciona un portal fuente", "SELECT PORTAL": "Seleccionar un portal para enviar", "SELECT_FAN_PORTALS": "Selecciona un portal ancla, un portal de inicio y un portal de fin, luego haz un acercamiento en el área para el fan field. Espera hasta que los portales hayan cargado (los portales deben estar en la pantalla para ser considerados) y presiona el botón Fanfield.", - "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", + "SELECT_FAN_PORTALS2": "Espera a que todos los portales se carguen. Luego haz clic en dibujar.", "SELECT_INSTRUCTIONS": "Selecciona dos portales ancla, luego luego haz un acercamiento en el área para los nodos de las capas. Espera hasta que los portales hayan cargado (los portales deben estar en la pantalla para ser considerados) y presiona el botón Multimax.", - "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", + "SELECT_ONION_PORTALS": "Las capas se hacen de dentro hacia afuera. Acércate al centro y selecciona el portal de inicio. Luego aléjate para ver un área mayor.", "SELF SWAP": "¡No se puede intercambiar un portal consigo mismo! Selecciona un portal diferente.", - "SEND ANALYTICS": "Send Anonymous Analytics", + "SEND ANALYTICS": "Enviar analíticas anónimas", "SEND LOCATION": "Enviar Ubicación", - "SEND TARGET AGENT": "Select target recipient", + "SEND TARGET AGENT": "Selecciona un destinatario", "SEND TARGET CONFIRM": "¿Quieres enviar el {portalName} objetivo a {agent}?", "SEND TARGET": "Enviar Objetivo", "SEND_LOC": "Enviar Ubicación", @@ -302,10 +303,10 @@ "SET_COMMENT": "Definir Comentario", "SET_LCOMMENT": "Definir Comentario de Link", "SET_LINK_COMMENT": "Definir comentario para el link", - "SET_LINKS_ZONES": "Set Links to Zones ", + "SET_LINKS_ZONES": "Set Links to Zones", "SET_MARKER_COMMENT": "Definir comentario para el marcador en", - "SET_MARKER_TYPE_TITLE": "Change marker type", - "SET_MARKERS_ZONES": "Set Markers to Zones", + "SET_MARKER_TYPE_TITLE": "Cambiar tipo de marcador", + "SET_MARKERS_ZONES": "Asignar marcadores a zonas", "SET_MCOMMENT": "Definir Comentario de Marcador {portalName}", "SET_NEW_OP": "Por favor, define el Nuevo Nombre de la Operación", "SET_PCOMMENT": "Definir Comentario de Portal {portalName}", @@ -313,18 +314,18 @@ "SET_PORTAL_COMMENT": "Definir comentarios del portal", "SET": "definir", "SETTINGS": "Configuración de Wasabee", - "SKINS_AVAILABLE": "There are {count} available skins.", - "SKINS_BUTTON": "Configure Skins", + "SKINS_AVAILABLE": "Hay {count} skins disponibles.", + "SKINS_BUTTON": "Configurar skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", - "SKINS_MANAGE_TITLE": "Manage skins", - "SKIP_CONFIRM_ALWAYS": "Never ask (use with caution)", - "SKIP_CONFIRM_ENTITY": "Only ask for team/op", - "SKIP_CONFIRM_NEVER": "Always ask", - "SKIP_CONFIRM": "Skip confirmation", - "SOURCE_PORT": "Portal Fuente", + "SKINS_MANAGE_TITLE": "Gestionar skins", + "SKIP_CONFIRM_ALWAYS": "Nunca preguntar (usar con precaución)", + "SKIP_CONFIRM_ENTITY": "Sólo pedir equipo/op", + "SKIP_CONFIRM_NEVER": "Preguntar siempre", + "SKIP_CONFIRM": "Omitir confirmación", + "SOURCE_PORT": "Source Portal", "SQUAD": "Escuadrón", "STARBURST TITLE": "Supernova", - "STARBURST_DRAW": "Draw", + "STARBURST_DRAW": "Dibujar", "STARBURST": "Supernova", "START_PORT": "Portal de Inicio", "STATE": "Estado", @@ -336,18 +337,27 @@ "SYNC DONE": "Descarga Completa
Haga clic AQUÍ para obtener sugerencias, consejos y documentación.", "SYNC": "Descargar Operaciones Disponibles", "TARGET SENT": "Objetivo enviado", - "TEAM STATE": "Share Location", + "TEAM STATE": "Compartir ubicación", "TEAM_CREATED": "Equipo {teamName} creado", "TEAM_NAME": "Nombre de Equipo", "TEAM": "Equipo", "TEAMS BUTTON TITLE": "Listar Equipos Wasabee", "TEAMS BUTTON": "Equipos", "TO_PORT": "Hacia el Portal", - "toolbar.quick_delete.apply.text": "Apply", - "toolbar.quick_delete.apply.title": "Delete selected links/markers", - "toolbar.quick_delete.cancel.text": "Cancel", - "toolbar.quick_delete.cancel.title": "Cancel", - "toolbar.quick_delete.title": "Quick delete", + "toolbar.quick_delete.apply.text": "Aplicar", + "toolbar.quick_delete.apply.title": "Eliminar los enlaces/marcadores seleccionados", + "toolbar.quick_delete.cancel.text": "Cancelar", + "toolbar.quick_delete.cancel.title": "Cancelar", + "toolbar.quick_delete.stop.text": "Parar", + "toolbar.quick_delete.stop.title": "Salir del modo borrar", + "toolbar.quick_delete.title": "Borrado rápido", + "toolbar.quick_delete.tooltip.toggle_mode": "Haz clic en los objetos que quieres marcar para eliminar", + "toolbar.quick_delete.tooltip.quick_mode": "Haz clic en los objetos para eliminar inmediatamente", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Seleccione el ancla de la estrella", + "toolbar.quick_draw.tooltip.star_mode.portal": "Selecciona un portal", + "toolbar.quick_draw.tooltip.single_mode.first": "Haz clic en el primer portal", + "toolbar.quick_draw.tooltip.single_mode.next": "Haz clic en el siguiente portal", + "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", @@ -365,14 +375,14 @@ "UPDATE HOVER": "{opName} en el servidor", "UPDATE PERM DENIED": "Permiso para acutalizar denegado", "UPDATE_CONFLICT_DESC": "The OP has been modified on server since last sync. Do you want to replace the server version by the current one?", - "UPDATE_CONFLICT_TITLE": "Conflict detected with server", + "UPDATE_CONFLICT_TITLE": "Conflicto detectado con el servidor", "UPDATE_COUNT": "Actualizar Conteo", "UPDATED": "Actualizado exitosamente", "UpgradePortalAlert": "Actualizar", "UPLOAD BUTTON HOVER": "CARGAR {opName} (no se encuentra actualmente en el servidor)", "UPLOADED": "Cargado exitosamente", - "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": "Por favor, usa la opción de intercambiar portales para mover los portales falsificados hacia los portales reales en la misma ubicación. Hacer un acercamiento en los portales que están 'Cargando' en la lista de verificación puede forzarlos a cargar.", + "USE PANES ON MOBILE": "Usar paneles (es necesario recargar)", + "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Por favor, utiliza un nombre de operación válido", "UseVirusPortalAlert": "Usar Virus", "VRLA DESC": "Dependiendo del número y tipo de Link Amps usados, un portal de origen de menor nivel puede ser suficiente.", @@ -381,22 +391,19 @@ "WASABEE_D_LIST": "Ingresar Conteo de Llaves de Defensa", "WD BUTTON TITLE": "Registrar Llaves de Defensa", "WD BUTTON": "Llaves W-D", - "WEBVIEW VERIFY": "Verificar Vista Web", - "WEBVIEW": "Iniciar Sesión Vista Web (iOS)", - "WRITE_SHORT": "RW", + "WRITE_SHORT": "LE", "WRITE": "escribir", "WSERVER": "Servidor {url}", "YESNO_DEL": "Estás seguro de querer borrar {opName}", - "ZONE_DRAW": "Click to set the zone boundaries", + "ZONE_DRAW": "Haga clic para establecer los límites de la zona", "ZONE": "Zona", "smallScreen": { - "ADD_LINKS": "+ Links", + "ADD_LINKS": "+ Enlaces", "ADD_MARKER": "+ Marcador", "BLOCKER TITLE": "Bloqueos", "CHECKLIST BUTTON": "Verificar", "CLEAROPS BUTTON": "Borrar", "EXPORT OP": "Exportar", - "FAN_FIELD3": "Fan", "FANFIELD": "Dibujar", "FANFIELD2": "Dibujar Fan Field", "KEYS": "Llaves", From 58e00d57fdee5316f98191d9803f3aa6339fcb7a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 20 Jan 2022 11:26:18 +0100 Subject: [PATCH 219/275] sortable: support basic footer --- src/code/sortable.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/code/sortable.ts b/src/code/sortable.ts index f7606908f..ed6b15e76 100644 --- a/src/code/sortable.ts +++ b/src/code/sortable.ts @@ -14,6 +14,7 @@ export interface SortableField { sort?: (a: unknown, b: unknown, aobj?: T, bobj?: T) => number; format?: (cell: HTMLTableCellElement, value: unknown, thing?: T) => void; smallScreenHide?: boolean; + foot?: (cell: HTMLTableCellElement) => void, } export default class Sortable { @@ -24,6 +25,7 @@ export default class Sortable { _table: HTMLTableElement; _head: HTMLTableSectionElement; _body: HTMLTableSectionElement; + _foot: HTMLTableSectionElement; _smallScreen: boolean; _done: Promise | boolean; @@ -37,6 +39,7 @@ export default class Sortable { // create this once for all this._head = L.DomUtil.create("thead", null, this._table); this._body = L.DomUtil.create("tbody", null, this._table); + this._foot = L.DomUtil.create("tfoot", null, this._table); // if IITC-Mobile is detected... this is a kludge this._smallScreen = window.plugin.userLocation ? true : false; @@ -168,6 +171,7 @@ export default class Sortable { set fields(value) { this._fields = value; this.renderHead(); + this.renderFoot(); } get done() { @@ -209,6 +213,16 @@ export default class Sortable { } } + renderFoot() { + this._foot.textContent = ""; + if (this._fields.every((f) => !f.foot)) return; + const footerRow = this._foot.insertRow(-1); + for (const field of this._fields) { + const cell = L.DomUtil.create("td", field.className, footerRow); + if (field.foot) field.foot(cell); + } + } + sort() { const sortfield = this._fields[this._sortBy]; From 4100bc3cc54615315cc195a9a7b9284cbc3607a5 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 20 Jan 2022 11:27:03 +0100 Subject: [PATCH 220/275] perms: align adding form with the table --- src/code/dialogs/opPerms.js | 108 +++++++++++++++++------------------- 1 file changed, 52 insertions(+), 56 deletions(-) diff --git a/src/code/dialogs/opPerms.js b/src/code/dialogs/opPerms.js index 2e0427e6a..abd92f846 100644 --- a/src/code/dialogs/opPerms.js +++ b/src/code/dialogs/opPerms.js @@ -48,13 +48,14 @@ const OpPermList = WDialog.extend({ const html = this.buildHTML(operation); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; this.createDialog({ title: wX("PERMS", { opName: operation.name }), html: html, + width: "auto", height: "auto", dialogClass: "perms", buttons: buttons, @@ -62,59 +63,8 @@ const OpPermList = WDialog.extend({ }, buildHTML: function (operation) { - const html = L.DomUtil.create("div"); - html.appendChild(this.buildTable(operation)); - - if (this._me && operation.isOwnedOp() && operation.isOnCurrentServer()) { - const already = new Set(); - for (const a of operation.teamlist) already.add(a.teamid); - - const addArea = L.DomUtil.create("div", "add-perm", html); - const teamMenu = L.DomUtil.create("select", null, addArea); - for (const t of this._me.Teams) { - // if (already.has(t.ID)) continue; - const o = L.DomUtil.create("option", null, teamMenu); - o.value = t.ID; - o.textContent = t.Name; - } - const permMenu = L.DomUtil.create("select", null, addArea); - const read = L.DomUtil.create("option", null, permMenu); - read.value = "read"; - read.textContent = wX("READ"); - const write = L.DomUtil.create("option", null, permMenu); - write.value = "write"; - write.textContent = wX("WRITE"); - const ao = L.DomUtil.create("option", null, permMenu); - ao.value = "assignedonly"; - ao.textContent = wX("ASSIGNED_ONLY"); - - const zoneMenu = L.DomUtil.create("select", null, addArea); - const zoneAll = L.DomUtil.create("option", null, zoneMenu); - zoneAll.value = "0"; - zoneAll.textContent = "All"; - for (const oz of operation.zones) { - const z = L.DomUtil.create("option", null, zoneMenu); - z.value = oz.id; - z.textContent = oz.name; - } - - const ab = L.DomUtil.create("button", null, addArea); - ab.type = "button"; - ab.name = "Add"; - ab.value = "Add"; - ab.textContent = wX("ADD"); - - L.DomEvent.on(ab, "click", (ev) => { - L.DomEvent.stop(ev); - this.addPerm(teamMenu.value, permMenu.value, +zoneMenu.value); // async, but no need to await - // addPerm calls wasabee:op:change, which redraws the screen - }); - } - - return html; - }, - - buildTable: function (operation) { + const isOwner = + this._me && operation.isOwnedOp() && operation.isOnCurrentServer(); const sortable = new Sortable(); const fields = [ { @@ -136,24 +86,57 @@ const OpPermList = WDialog.extend({ }, sort: (a, b) => a.localeCompare(b), // , format: (cell, value) => (cell.textContent = value) + foot: (cell) => { + this.teamMenu = L.DomUtil.create("select", null, cell); + for (const t of this._me.Teams) { + const o = L.DomUtil.create("option", null, this.teamMenu); + o.value = t.ID; + o.textContent = t.Name; + } + }, }, { name: wX("ROLE"), value: (perm) => perm.role, sort: (a, b) => a.localeCompare(b), // , format: (cell, value) => (cell.textContent = value) + foot: (cell) => { + this.permMenu = L.DomUtil.create("select", null, cell); + const read = L.DomUtil.create("option", null, this.permMenu); + read.value = "read"; + read.textContent = wX("READ"); + const write = L.DomUtil.create("option", null, this.permMenu); + write.value = "write"; + write.textContent = wX("WRITE"); + const ao = L.DomUtil.create("option", null, this.permMenu); + ao.value = "assignedonly"; + ao.textContent = wX("ASSIGNED_ONLY"); + }, }, { name: "Zone", value: (perm) => operation.zoneName(perm.zone), sort: (a, b) => a.localeCompare(b), // , format: (cell, value) => (cell.textContent = value) + foot: (cell) => { + this.zoneMenu = L.DomUtil.create("select", null, cell); + const zoneAll = L.DomUtil.create("option", null, this.zoneMenu); + zoneAll.value = "0"; + zoneAll.textContent = "All"; + for (const oz of operation.zones) { + const z = L.DomUtil.create("option", null, this.zoneMenu); + z.value = oz.id; + z.textContent = oz.name; + } + }, }, ]; - if (operation.isOwnedOp()) { + if (!isOwner) { + for (const field of fields) delete field.foot; + } else { fields.push({ - name: wX("REMOVE"), + name: "Commands", value: () => wX("REMOVE"), format: (cell, value, obj) => { const link = L.DomUtil.create("a", null, cell); @@ -164,6 +147,19 @@ const OpPermList = WDialog.extend({ this.delPerm(obj); // calls wasabee:op:change -- async but no need to await }); }, + foot: (cell) => { + const link = L.DomUtil.create("a", null, cell); + link.href = "#"; + link.textContent = wX("ADD"); + L.DomEvent.on(link, "click", (ev) => { + L.DomEvent.stop(ev); + this.addPerm( + this.teamMenu.value, + this.permMenu.value, + +this.zoneMenu.value + ); + }); + }, }); } From 065d8c19869148956674da01b6e8fd91eefc3a04 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 18 Jan 2022 21:28:17 +0100 Subject: [PATCH 221/275] wX: popup button != input label --- src/code/translations/English.json | 1 + src/code/ui/marker.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 0f8e7f02e..f5609c7b2 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -247,6 +247,7 @@ "PERM DENIED SHORT": "Permission denied", "PERMS": "{opName} permissions", "PLEASE_SELECT_PORTAL": "Please select a portal", + "popup.marker.state_button": "Set State", "PORT_FAKE": "", "PORTAL KEY LIST": "Key list for portal {portalName}", "PORTAL_COUNT": "{count} portals", diff --git a/src/code/ui/marker.js b/src/code/ui/marker.js index 6d0f8c17b..4398c8dea 100644 --- a/src/code/ui/marker.js +++ b/src/code/ui/marker.js @@ -126,7 +126,7 @@ const WLMarker = PortalUI.WLPortal.extend({ _stateButton: function (container, marker) { const operation = getSelectedOperation(); const stateButton = L.DomUtil.create("button", null, container); - stateButton.textContent = wX("MARKER STATE"); + stateButton.textContent = wX("popup.marker.state_button"); L.DomEvent.on(stateButton, "click", (ev) => { L.DomEvent.stop(ev); const sd = new StateDialog({ target: marker, opID: operation.ID }); From 73a239dc7458a1dcad9625a475b76c633a40acc5 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 18 Jan 2022 22:06:12 +0100 Subject: [PATCH 222/275] wX: add (some) untranslated strings --- src/code/dialogs/autodraws/homogeneous.js | 2 +- src/code/dialogs/autodraws/madrid.js | 2 +- src/code/dialogs/manageTeamDialog.js | 6 +++--- src/code/dialogs/markerAddDialog.js | 2 +- src/code/dialogs/opPerms.js | 7 +++++-- src/code/dialogs/opSettings.js | 2 +- src/code/dialogs/trawl.js | 2 +- src/code/dialogs/zoneDialog.js | 11 +++++++---- src/code/model/operation.ts | 5 ++--- src/code/toolbox.ts | 2 +- src/code/translations/English.json | 15 ++++++++++++++- src/code/ui/anchor.js | 2 +- 12 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index f851c5b52..a8744ed0e 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -374,7 +374,7 @@ const HomogeneousDialog = AutoDraw.extend({ }); const orderLabel = L.DomUtil.create("label", null, container); - orderLabel.textContent = "Order"; + orderLabel.textContent = wX("autodraw.homogeneous.order"); this.orderMenu = L.DomUtil.create("select", null, container); for (const [text, value] of [ [wX("FROM_DEPTH"), "core"], // need wX on first column diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index 605a8b7fd..1a6b439ea 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -94,7 +94,7 @@ const MadridDialog = AutoDraw.extend({ const anchorThreeLabel = L.DomUtil.create("label", null, container); anchorThreeLabel.textContent = wX("ANCHOR3"); const anchorThreeDisplay = L.DomUtil.create("span", null, container); - anchorThreeDisplay.textContent = "Auto-determined"; + anchorThreeDisplay.textContent = wX("autodraw.madrid.auto_determined"); this._addSelectSet(wX("MADRID_SET_3"), "setThree", container, "all"); this._addCheckbox( diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 7469f9384..33ae5bfab 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -233,7 +233,7 @@ const ManageTeamDialog = WDialog.extend({ }); const joinlinklabel = L.DomUtil.create("label", null, container); - joinlinklabel.textContent = "Join Link"; + joinlinklabel.textContent = wX("dialog.team_manage.join_link"); if (team.jlt) { const joinlink = L.DomUtil.create("input", null, container); const server = GetWasabeeServer(); @@ -245,7 +245,7 @@ const ManageTeamDialog = WDialog.extend({ joinlink.readOnly = true; L.DomEvent.on(joinlink, "click", (ev) => ev.target.select()); const joinlinkdel = L.DomUtil.create("button", null, container); - joinlinkdel.textContent = "Revoke"; + joinlinkdel.textContent = wX("dialog.team_manage.join_link.revoke"); L.DomEvent.on(joinlinkdel, "click", async (ev) => { L.DomEvent.stop(ev); await deleteJoinLinkPromise(team.id); @@ -254,7 +254,7 @@ const ManageTeamDialog = WDialog.extend({ } else { L.DomUtil.create("span", null, container).textContent = "not set"; const joinlinkadd = L.DomUtil.create("button", null, container); - joinlinkadd.textContent = "Create"; + joinlinkadd.textContent = wX("dialog.team_manage.join_link.create"); L.DomEvent.on(joinlinkadd, "click", async (ev) => { L.DomEvent.stop(ev); await createJoinLinkPromise(team.id); diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index b4afb917c..9ac8af829 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -39,7 +39,7 @@ const MarkerAddDialog = WDialog.extend({ this._zones.textContent = ""; // do we need to do this every time? the zone list can change while this dialog is open. const zoneAll = L.DomUtil.create("option", null, this._zones); zoneAll.value = 0; - zoneAll.textContent = "All"; // wX this + zoneAll.textContent = wX("dialog.common.zone_all"); for (const z of getSelectedOperation().zones) { const o = L.DomUtil.create("option", null, this._zones); o.value = z.id; diff --git a/src/code/dialogs/opPerms.js b/src/code/dialogs/opPerms.js index abd92f846..b9282cfdd 100644 --- a/src/code/dialogs/opPerms.js +++ b/src/code/dialogs/opPerms.js @@ -115,14 +115,17 @@ const OpPermList = WDialog.extend({ }, { name: "Zone", - value: (perm) => operation.zoneName(perm.zone), + value: (perm) => { + if (perm.zone === 0) return wX("dialog.common.zone_all"); + return operation.zoneName(perm.zone); + }, sort: (a, b) => a.localeCompare(b), // , format: (cell, value) => (cell.textContent = value) foot: (cell) => { this.zoneMenu = L.DomUtil.create("select", null, cell); const zoneAll = L.DomUtil.create("option", null, this.zoneMenu); zoneAll.value = "0"; - zoneAll.textContent = "All"; + zoneAll.textContent = wX("dialog.common.zone_all"); for (const oz of operation.zones) { const z = L.DomUtil.create("option", null, this.zoneMenu); z.value = oz.id; diff --git a/src/code/dialogs/opSettings.js b/src/code/dialogs/opSettings.js index b65dfb5ec..f0315a120 100644 --- a/src/code/dialogs/opSettings.js +++ b/src/code/dialogs/opSettings.js @@ -228,7 +228,7 @@ const OpSettingDialog = WDialog.extend({ const zoneDiv = L.DomUtil.create("div", null, buttonSection); const zoneButton = L.DomUtil.create("button", null, zoneDiv); - zoneButton.textContent = "Zones"; + zoneButton.textContent = wX("dialog.op_settings.zones"); L.DomEvent.on(zoneButton, "click", (ev) => { L.DomEvent.stop(ev); const z = new ZoneDialog(); diff --git a/src/code/dialogs/trawl.js b/src/code/dialogs/trawl.js index 59a8ba998..93d0032dc 100644 --- a/src/code/dialogs/trawl.js +++ b/src/code/dialogs/trawl.js @@ -53,7 +53,7 @@ const TrawlerDialog = WDialog.extend({ // same as dialogs/settings.js const trawlTitle = L.DomUtil.create("label", null, container); - trawlTitle.textContent = "Trawl Skip Tiles"; + trawlTitle.textContent = wX("TRAWL SKIP TILES"); const trawlSelect = L.DomUtil.create("select", null, container); const tss = Number( localStorage[window.plugin.wasabee.static.constants.TRAWL_SKIP_STEPS] diff --git a/src/code/dialogs/zoneDialog.js b/src/code/dialogs/zoneDialog.js index d731373cd..3070d5498 100644 --- a/src/code/dialogs/zoneDialog.js +++ b/src/code/dialogs/zoneDialog.js @@ -78,10 +78,13 @@ const ZoneDialog = WDialog.extend({ L.DomUtil.create("table", "wasabee-table", container) ); const hr = L.DomUtil.create("tr", null, tbody); - L.DomUtil.create("th", null, hr).textContent = "ID"; - L.DomUtil.create("th", null, hr).textContent = "Name"; - L.DomUtil.create("th", null, hr).textContent = "Color"; - if (canWrite) L.DomUtil.create("th", null, hr).textContent = "Commands"; + L.DomUtil.create("th", null, hr).textContent = wX("dialog.zones.id"); + L.DomUtil.create("th", null, hr).textContent = wX("dialog.zones.name"); + L.DomUtil.create("th", null, hr).textContent = wX("dialog.zones.color"); + if (canWrite) + L.DomUtil.create("th", null, hr).textContent = wX( + "dialog.zones.commands" + ); for (const z of op.zones) { const tr = L.DomUtil.create("tr", null, tbody); diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index c24497452..7f523d23d 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -1150,9 +1150,8 @@ export default class WasabeeOp extends Evented implements IOperation { } zoneName(zoneID: ZoneID) { - if (zoneID == 0) - // All zone - return "All"; + if (zoneID === 0) + return 0; for (const z of this.zones) { if (z.id == zoneID) return z.name; } diff --git a/src/code/toolbox.ts b/src/code/toolbox.ts index 23f3e44fc..d37b71ebf 100644 --- a/src/code/toolbox.ts +++ b/src/code/toolbox.ts @@ -51,7 +51,7 @@ export function setupToolbox() { }); const onlineAgentLink = L.DomUtil.create("a", "wasabee", toolbox); - onlineAgentLink.textContent = "Teammates Online"; + onlineAgentLink.textContent = wX("toolbox.teammates"); L.DomEvent.on(onlineAgentLink, "click", (ev) => { L.DomEvent.stop(ev); const oll = new OnlineAgentList(); diff --git a/src/code/translations/English.json b/src/code/translations/English.json index f5609c7b2..2aeaf47e2 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -47,6 +47,8 @@ "AUTODRAW_PORTALS_SET": "Portals", "autodraw.common.draw_button": "Draw", "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.homogeneous.order": "Order", + "autodraw.madrid.auto_determined": "Auto-determined", "autodraw.onion.variant": "Option", "autodraw.onion.variant.equilateral": "~Equilateral", "autodraw.onion.variant.grow": "Let it grow", @@ -93,8 +95,17 @@ "DESCRIP_PLACEHOLD": "Description (optional)", "DestroyPortalAlert": "Destroy", "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.setcomment.portal_hardness": "Hardness", + "dialog.common.zone_all": "All", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", + "dialog.op_settings.zones": "Zones", + "dialog.setcomment.portal_hardness": "Hardness", + "dialog.team_manage.join_link": "Join Link", + "dialog.team_manage.join_link.create": "Create", + "dialog.team_manage.join_link.revoke": "Revoke", + "dialog.zones.color": "Color", + "dialog.zones.commands": "Commands", + "dialog.zones.id": "ID", + "dialog.zones.name": "Name", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplicate Operation", "END_PORT": "End Portal", @@ -247,6 +258,7 @@ "PERM DENIED SHORT": "Permission denied", "PERMS": "{opName} permissions", "PLEASE_SELECT_PORTAL": "Please select a portal", + "popup.anchor.keys": "Keys: {onHand} / {required}", "popup.marker.state_button": "Set State", "PORT_FAKE": "", "PORTAL KEY LIST": "Key list for portal {portalName}", @@ -359,6 +371,7 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Click first portal", "toolbar.quick_draw.tooltip.single_mode.next": "Click next portal", "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", + "toolbox.teammates": "Teammates Online", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", diff --git a/src/code/ui/anchor.js b/src/code/ui/anchor.js index 8e1ca3e99..e717d59dd 100644 --- a/src/code/ui/anchor.js +++ b/src/code/ui/anchor.js @@ -43,7 +43,7 @@ const WLAnchor = PortalUI.WLPortal.extend({ const requiredKeys = L.DomUtil.create("div", "desc", content); const onHand = operation.KeysOnHandForPortal(portal.id); const required = operation.KeysRequiredForPortal(portal.id); - requiredKeys.textContent = "Keys: " + onHand + " / " + required; + requiredKeys.textContent = wX("popup.anchor.keys", { onHand, required }); const buttonSet = L.DomUtil.create( "div", From 25d7470581e453c721212841324660b5f7374826 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 18 Jan 2022 22:30:39 +0100 Subject: [PATCH 223/275] wX: add (some) untranslated strings #2 --- src/code/dialogs/checklist.js | 2 +- src/code/dialogs/manageTeamDialog.js | 13 ++++++++----- src/code/dialogs/teamListDialog.js | 4 ++-- src/code/translations/English.json | 12 ++++++++++++ src/code/uiCommands.ts | 12 ++++++------ 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 019840145..9ae74cbcb 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -169,7 +169,7 @@ const OperationChecklistDialog = WDialog.extend({ }, }, { - name: "Zone", + name: wX("ZONE"), value: (thing) => thing.zone, sort: (a, b) => a - b, format: (cell, value, thing) => { diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 33ae5bfab..2137d1324 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -60,7 +60,7 @@ const ManageTeamDialog = WDialog.extend({ sort: (a, b) => a && !b, }, { - name: wX("SQUAD"), + name: wX("COMMENT"), value: (agent) => agent.comment, sort: (a, b) => a.localeCompare(b), format: (cell, value, obj) => { @@ -69,8 +69,8 @@ const ManageTeamDialog = WDialog.extend({ L.DomEvent.on(button, "click", (ev) => { L.DomEvent.stop(ev); const squadDialog = new PromptDialog({ - title: `Set Squad for ${obj.name}`, - label: "Squad", + title: wX("dialog.agent_comment.title", { agentName: obj.name }), + label: wX("dialog.agent_comment.text"), callback: async () => { if (squadDialog.inputField.value) { try { @@ -110,8 +110,11 @@ const ManageTeamDialog = WDialog.extend({ L.DomEvent.on(button, "click", (ev) => { L.DomEvent.stop(ev); const con = new ConfirmDialog({ - title: `${button.textContent}: ${obj.name}`, - label: `${button.textContent}: ${obj.name}?`, + title: wX("dialog.remove_agent.title", { agentName: obj.name }), + label: wX("dialog.remove_agent.text", { + agentName: obj.name, + teamName: this.options.team.Name, + }), type: "agent", callback: async () => { try { diff --git a/src/code/dialogs/teamListDialog.js b/src/code/dialogs/teamListDialog.js index e79aeec1d..14dea30bd 100644 --- a/src/code/dialogs/teamListDialog.js +++ b/src/code/dialogs/teamListDialog.js @@ -111,8 +111,8 @@ const TeamListDialog = WDialog.extend({ L.DomEvent.on(link, "click", (ev) => { L.DomEvent.stop(ev); const cd = new ConfirmDialog({ - title: `Leave ${obj.Name}?`, - label: `If you leave ${obj.Name} you cannot rejoin unless the owner re-adds you.`, + title: wX("dialog.leave_team.title", { teamName: obj.Name }), + label: wX("dialog.leave_team.text"), type: "team", callback: async () => { try { diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 2aeaf47e2..11902e1d7 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -95,9 +95,21 @@ "DESCRIP_PLACEHOLD": "Description (optional)", "DestroyPortalAlert": "Destroy", "dialog.about.download_mobile_app": "

Wasabee App:

", + "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.title": "Set comment for {agentName}", "dialog.common.zone_all": "All", + "dialog.clear_all.text": "Do you want to reset {opName}?", + "dialog.clear_all.title": "Clear: {opName}", + "dialog.clear_links.text": "Do you want to remove all links from {opName}?", + "dialog.clear_links.title": "Clear Links: {opName}", + "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", + "dialog.clear_markers.title": "Clear Links: {opName}", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", + "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", + "dialog.leave_team.title": "Leave: {teamName}", "dialog.op_settings.zones": "Zones", + "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", + "dialog.remove_agent.title": "Remove: {agentName}", "dialog.setcomment.portal_hardness": "Hardness", "dialog.team_manage.join_link": "Join Link", "dialog.team_manage.join_link.create": "Create", diff --git a/src/code/uiCommands.ts b/src/code/uiCommands.ts index 76fad4f56..ddf157cf6 100644 --- a/src/code/uiCommands.ts +++ b/src/code/uiCommands.ts @@ -102,8 +102,8 @@ export function deleteMarker( export function clearAllItems(operation: WasabeeOp) { const con = new ConfirmDialog({ - title: `Clear: ${operation.name}`, - label: `Do you want to reset ${operation.name}?`, + title: wX("dialog.clear_all.title", { opName: operation.name }), + label: wX("dialog.clear_all.text", { opName: operation.name }), type: "operation", callback: () => { operation.clearAllItems(); @@ -115,8 +115,8 @@ export function clearAllItems(operation: WasabeeOp) { export function clearAllLinks(operation: WasabeeOp) { const con = new ConfirmDialog({ - title: `Clear Links: ${operation.name}`, - label: `Do you want to remove all links from ${operation.name}?`, + title: wX("dialog.clear_links.title", { opName: operation.name }), + label: wX("dialog.clear_links.text", { opName: operation.name }), type: "operation", callback: () => { operation.clearAllLinks(); @@ -128,8 +128,8 @@ export function clearAllLinks(operation: WasabeeOp) { export function clearAllMarkers(operation: WasabeeOp) { const con = new ConfirmDialog({ - title: `Clear Markers: ${operation.name}`, - label: `Do you want to remove all markers from ${operation.name}?`, + title: wX("dialog.clear_markers.title", { opName: operation.name }), + label: wX("dialog.clear_markers.text", { opName: operation.name }), type: "operation", callback: () => { operation.clearAllMarkers(); From b59b57caf8e53d5153c8646b6e51ebf2612ea525 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 18 Jan 2022 23:17:45 +0100 Subject: [PATCH 224/275] wX: add (some) untranslated strings #3 --- src/code/dialogs/checklist.js | 20 ++++++++++++++++---- src/code/translations/English.json | 4 ++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 9ae74cbcb..5618f2cee 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -315,7 +315,11 @@ const OperationChecklistDialog = WDialog.extend({ const container = L.DomUtil.create("div", "field-count"); if (emptyFieldLinks.length) { const header = L.DomUtil.create("div", null, container); - header.textContent = `Found ${fieldCount} fields and ${emptyCount} empty field(s) on ${emptyFieldLinks.length} link(s)`; + header.textContent = wX("dialog.checklist.field_count_with_empty", { + fieldCount: fieldCount, + emptyCount: emptyCount, + linkCount: emptyFieldLinks, + }); const content = L.DomUtil.create("ul", null, container); for (const [link, c] of emptyFieldLinks) { const li = L.DomUtil.create("li", "empty-field-link", content); @@ -324,18 +328,26 @@ const OperationChecklistDialog = WDialog.extend({ } } else { const header = L.DomUtil.create("div", null, container); - header.textContent = `Found ${fieldCount} fields and no empty field`; + header.textContent = wX("dialog.checklist.field_count", { + fieldCount: fieldCount, + }); } if (linksFromInner.length) { const header = L.DomUtil.create("div", null, container); - header.textContent = `Found ${linksFromInner.length} links from covered portals`; + header.textContent = wX("dialog.checklist.link_from_inside", { + count: linksFromInner.length, + }); const content = L.DomUtil.create("ul", null, container); for (const link of linksFromInner) { const cl = coveredPortals.get(link.fromPortalId); const li = L.DomUtil.create("li", "inner-link", content); li.append(`${link.order}: `); li.appendChild(LinkUI.displayFormat(link, operation)); - li.append(` at ${cl.order} by link `); + li.append( + wX("dialog.checklist.link_from_inside.covered_at_order", { + order: cl.order, + }) + ); li.appendChild(LinkUI.displayFormat(cl, operation)); } } diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 11902e1d7..8b251ed1b 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -104,6 +104,10 @@ "dialog.clear_links.title": "Clear Links: {opName}", "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.checklist.field_count": "Found {fieldCount} fields and no empty field", + "dialog.checklist.field_count_with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", + "dialog.checklist.link_from_inside": "Found {count} links from covered portals", + "dialog.checklist.link_from_inside.covered_at_order": " at {order} by link ", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", "dialog.leave_team.title": "Leave: {teamName}", From dde8d0d0280c2f794bba8a5bc2737890e08cefe7 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 19 Jan 2022 22:08:50 +0100 Subject: [PATCH 225/275] wx: add (some) untranslatable strings #4 --- src/code/dialogs/autodraws/fanfield.js | 6 +++++- src/code/dialogs/autodraws/homogeneous.js | 11 ++++++----- src/code/dialogs/autodraws/madrid.js | 2 +- src/code/dialogs/autodraws/multimaxDialog.js | 15 ++++++++++++++- src/code/dialogs/manageTeamDialog.js | 5 ----- src/code/dialogs/opsDialog.js | 9 ++++++--- src/code/firebaseSupport.ts | 9 +++++++-- src/code/translations/English.json | 10 ++++++++++ 8 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/code/dialogs/autodraws/fanfield.js b/src/code/dialogs/autodraws/fanfield.js index 42b650d2d..6c2a3c8c6 100644 --- a/src/code/dialogs/autodraws/fanfield.js +++ b/src/code/dialogs/autodraws/fanfield.js @@ -185,7 +185,11 @@ const FanfieldDialog = AutoDraw.extend({ const ap = 313 * links.length + 1250 * fields; // too many parameters for wX(); displayInfo( - `Fanfield found ${links.length} links and ${fields} fields for ${ap} AP` + wX("autodraw.fanfield.result", { + links: links.length, + fields: fields, + ap: ap, + }) ); }, }); diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index a8744ed0e..57ad17007 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -368,9 +368,10 @@ const HomogeneousDialog = AutoDraw.extend({ this.depthMenu.value = 4; L.DomEvent.on(this.depthMenu, "change", () => { - this.spanPortalNeeded.textContent = `(${numInnerPortalsPerDepth( - +this.depthMenu.value - )} needed)`; + this.spanPortalNeeded.textContent = wX( + "autodraw.homogeneous.portals_required", + { count: numInnerPortalsPerDepth(+this.depthMenu.value) } + ); }); const orderLabel = L.DomUtil.create("label", null, container); @@ -466,7 +467,7 @@ const HomogeneousDialog = AutoDraw.extend({ if (this._failed > 0) { displayWarning( - `Unable to find ${this._failed} splits, try less depth or a different region` + wX("autodraw.homogeneous.missing_split", { count: this._failed }) ); } }, @@ -504,7 +505,7 @@ const HomogeneousDialog = AutoDraw.extend({ if (this._failed > 0) { displayWarning( - `Unable to find ${this._failed} splits, try less depth or a different region` + wX("autodraw.homogeneous.missing_split", { count: this._failed }) ); } diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index 1a6b439ea..79ffba5eb 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -126,7 +126,7 @@ const MadridDialog = AutoDraw.extend({ const total = this._balancedcheck ? this.doBalancedMadrid.call(this) : this.doMadrid.call(this); - displayInfo(`Madrid found ${total} layers`); + displayInfo(wX("autodraw.madrid.result", { count: total })); // this.closeDialog(); }); diff --git a/src/code/dialogs/autodraws/multimaxDialog.js b/src/code/dialogs/autodraws/multimaxDialog.js index d414e3a4f..ade0151ba 100644 --- a/src/code/dialogs/autodraws/multimaxDialog.js +++ b/src/code/dialogs/autodraws/multimaxDialog.js @@ -80,7 +80,20 @@ const MultimaxDialog = AutoDraw.extend({ button.textContent = wX("MULTI_M"); L.DomEvent.on(button, "click", () => { const total = this.doMultimax.call(this); - displayInfo(`Multimax found ${total.join(" and ")} layers`); + if (total.length === 2) { + displayInfo( + wX("autodraw.multimax.result_both_side", { + count1: total[0], + count2: total[1], + }) + ); + } else { + displayInfo( + wX("autodraw.multimax.result", { + count: total[0], + }) + ); + } // this.closeDialog(); }); diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 2137d1324..0d074ef0e 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -79,9 +79,6 @@ const ManageTeamDialog = WDialog.extend({ this.options.team.ID, squadDialog.inputField.value ); - displayInfo( - `squad updated to ${squadDialog.inputField.value} for ${obj.name}` - ); // refresh team data await WasabeeTeam.get(this.options.team.ID, 0); } catch (e) { @@ -203,7 +200,6 @@ const ManageTeamDialog = WDialog.extend({ await renameTeamPromise(team.id, renameField.value); // refresh team data await WasabeeTeam.get(this.options.team.ID, 0); - displayInfo(`renamed to ${renameField.value}`); window.map.fire("wasabee:team:update"); } catch (e) { console.error(e); @@ -281,7 +277,6 @@ const ManageTeamDialog = WDialog.extend({ callback: async () => { try { await deleteTeamPromise(team.id); - displayInfo(`${team.name} removed`); this.closeDialog(); await WasabeeMe.waitGet(true); } catch (e) { diff --git a/src/code/dialogs/opsDialog.js b/src/code/dialogs/opsDialog.js index 5cdfc4e38..bb8dc8232 100644 --- a/src/code/dialogs/opsDialog.js +++ b/src/code/dialogs/opsDialog.js @@ -106,9 +106,12 @@ const OpsDialog = WDialog.extend({ link.href = "#"; link.textContent = op.name; if (!op.local) { - link.title = `Last fetched: ${op.fetched}\n`; - if (op.localchanged) link.title += "Local has changed\n"; - if (op.remotechanged) link.title += "Remote has changed"; + link.title = + wX("dialog.ops_list.last_fetched", { date: op.fetched }) + "\n"; + if (op.localchanged) + link.title += wX("dialog.ops_list.local_change") + "\n"; + if (op.remotechanged) + link.title += wX("dialog.ops_list.remote_change") + "\n"; } if (op.id == getSelectedOperation().ID) link.classList.add("enl"); L.DomEvent.on(link, "click", async (ev) => { diff --git a/src/code/firebaseSupport.ts b/src/code/firebaseSupport.ts index 763041bac..b3341b8e6 100644 --- a/src/code/firebaseSupport.ts +++ b/src/code/firebaseSupport.ts @@ -29,6 +29,7 @@ import WasabeeMe from "./model/me"; import { constants } from "./static"; import WasabeeLink from "./model/link"; import WasabeeMarker from "./model/marker"; +import wX from "./wX"; // TODO: use a dedicated message channel: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API/Using_channel_messaging @@ -67,7 +68,9 @@ async function onMessage( ) { if (event.data === "permission-blocked") { displayWarning( - `Visit ${constants.FIREBASE_IFRAME} and press the button to authorize live updates. You will need to reload IITC afterward.`, + wX("dialog.firebase.setup", { + url: `${constants.FIREBASE_IFRAME}`, + }), true ); return; @@ -87,7 +90,9 @@ async function onMessage( case "Generic Message": const agent = await WasabeeAgent.get(data.sender); const name = agent ? agent.name : "[unknown sender]"; - displayInfo(`Team announcement: “${data.msg}” from ${name}`); + displayInfo( + wX("dialog.team_message", { message: data.msg, sender: name }) + ); break; case "Login": console.debug("server reported teammate login: ", data.gid); diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 8b251ed1b..1849b3270 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -46,9 +46,15 @@ "AUTODRAWS": "Wasabee Auto-draw Options", "AUTODRAW_PORTALS_SET": "Portals", "autodraw.common.draw_button": "Draw", + "autodraw.fanfield.result": "Fanfield found {links} links and {fields} fields for {ap} AP", "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.homogeneous.missing_split": "Unable to find {count} splits, try less depth or a different region", "autodraw.homogeneous.order": "Order", + "autodraw.homogeneous.portals_required": "{count} required", "autodraw.madrid.auto_determined": "Auto-determined", + "autodraw.madrid.result": "Madrid found {count} layers", + "autodraw.multimax.result": "Multimax found {count} layers", + "autodraw.multimax.result_both_side": "Multimax found {count1} and {count2} layers", "autodraw.onion.variant": "Option", "autodraw.onion.variant.equilateral": "~Equilateral", "autodraw.onion.variant.grow": "Let it grow", @@ -108,10 +114,14 @@ "dialog.checklist.field_count_with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", "dialog.checklist.link_from_inside": "Found {count} links from covered portals", "dialog.checklist.link_from_inside.covered_at_order": " at {order} by link ", + "dialog.firebase.setup": "Visit {url} and press the button to authorize live updates. You will need to reload IITC afterward.", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", "dialog.leave_team.title": "Leave: {teamName}", "dialog.op_settings.zones": "Zones", + "dialog.ops_list.last_fetched": "Last fetched: {date}", + "dialog.ops_list.local_change": "Local has changed", + "dialog.ops_list.remote_change": "Remote has changed", "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", "dialog.remove_agent.title": "Remove: {agentName}", "dialog.setcomment.portal_hardness": "Hardness", From 95b1284e9b14f5cebbd32acc4065a0c75d1f3932 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 19 Jan 2022 22:19:57 +0100 Subject: [PATCH 226/275] remove squads display --- src/code/dialogs/manageTeamDialog.js | 28 +++++++++++--------------- src/code/dialogs/teamMembershipList.js | 2 +- src/code/translations/English.json | 3 +-- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 0d074ef0e..951a44860 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -72,23 +72,19 @@ const ManageTeamDialog = WDialog.extend({ title: wX("dialog.agent_comment.title", { agentName: obj.name }), label: wX("dialog.agent_comment.text"), callback: async () => { - if (squadDialog.inputField.value) { - try { - await setAgentTeamSquadPromise( - obj.id, - this.options.team.ID, - squadDialog.inputField.value - ); - // refresh team data - await WasabeeTeam.get(this.options.team.ID, 0); - } catch (e) { - console.error(e); - displayError(e); - } - } else { - displayInfo(wX("INPUT_SQUAD_NAME")); + try { + await setAgentTeamSquadPromise( + obj.id, + this.options.team.ID, + squadDialog.inputField.value + ); + // refresh team data + await WasabeeTeam.get(this.options.team.ID, 0); + window.map.fire("wasabee:team:update"); + } catch (e) { + console.error(e); + displayError(e); } - window.map.fire("wasabee:team:update"); }, current: value, placeholder: "boots", diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index d8dc15de5..19a1ab485 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -68,7 +68,7 @@ const TeamMembershipList = WDialog.extend({ cell.appendChild(AgentUI.formatDisplay(agent)), }, { - name: wX("SQUAD"), + name: wX("COMMENT"), value: (agent) => agent.comment, sort: (a, b) => a.localeCompare(b), }, diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 1849b3270..6331ba988 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -128,6 +128,7 @@ "dialog.team_manage.join_link": "Join Link", "dialog.team_manage.join_link.create": "Create", "dialog.team_manage.join_link.revoke": "Revoke", + "dialog.team_message": "Team announcement: “{message}” from {sender}", "dialog.zones.color": "Color", "dialog.zones.commands": "Commands", "dialog.zones.id": "ID", @@ -172,7 +173,6 @@ "IMPOSSIBLE": "Impossible", "INGNAME_GID": "Ingress name or GoogleID", "INPUT_DT_KEY_COUNT": "Input Defensive Key Count", - "INPUT_SQUAD_NAME": "Input a Squad name", "INVALID REQUEST": "Invalid Request", "IOS NEED FAKE UA": "You must set a 'Custom UserAgent for Webviews' in the IITC-Mobile settings or login will fail", "KEY_LIST2": "Key List for Operation: {opName}", @@ -362,7 +362,6 @@ "SKIP_CONFIRM_NEVER": "Always ask", "SKIP_CONFIRM": "Skip confirmation", "SOURCE_PORT": "Source Portal", - "SQUAD": "Squad", "STARBURST TITLE": "Starburst", "STARBURST_DRAW": "Draw", "STARBURST": "Starburst", From 8909426f277ed840acb4b2e3d73559690a867852 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 20 Jan 2022 11:54:18 +0100 Subject: [PATCH 227/275] wx: add (some) untranslatable strings #5 --- src/code/dialogs/checklist.js | 4 +++- src/code/dialogs/opPerms.js | 2 +- src/code/dialogs/zoneDialog.js | 2 +- src/code/translations/English.json | 5 +++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 5618f2cee..d95614367 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -260,7 +260,9 @@ const OperationChecklistDialog = WDialog.extend({ ]; if (canWrite) columns.push({ - name: this._smallScreen ? "Cmds" : "Commands", + name: this._smallScreen + ? wX("dialog.common.commands_short") + : wX("dialog.common.commands"), value: (obj) => typeof obj, format: (cell, value, obj) => { if (obj instanceof WasabeeLink) { diff --git a/src/code/dialogs/opPerms.js b/src/code/dialogs/opPerms.js index b9282cfdd..958c9b8ba 100644 --- a/src/code/dialogs/opPerms.js +++ b/src/code/dialogs/opPerms.js @@ -139,7 +139,7 @@ const OpPermList = WDialog.extend({ for (const field of fields) delete field.foot; } else { fields.push({ - name: "Commands", + name: wX("dialog.common.commands"), value: () => wX("REMOVE"), format: (cell, value, obj) => { const link = L.DomUtil.create("a", null, cell); diff --git a/src/code/dialogs/zoneDialog.js b/src/code/dialogs/zoneDialog.js index 3070d5498..9be086293 100644 --- a/src/code/dialogs/zoneDialog.js +++ b/src/code/dialogs/zoneDialog.js @@ -83,7 +83,7 @@ const ZoneDialog = WDialog.extend({ L.DomUtil.create("th", null, hr).textContent = wX("dialog.zones.color"); if (canWrite) L.DomUtil.create("th", null, hr).textContent = wX( - "dialog.zones.commands" + "dialog.common.commands" ); for (const z of op.zones) { diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 6331ba988..800e78f94 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -103,7 +103,6 @@ "dialog.about.download_mobile_app": "

Wasabee App:

", "dialog.agent_comment.text": "Comment: ", "dialog.agent_comment.title": "Set comment for {agentName}", - "dialog.common.zone_all": "All", "dialog.clear_all.text": "Do you want to reset {opName}?", "dialog.clear_all.title": "Clear: {opName}", "dialog.clear_links.text": "Do you want to remove all links from {opName}?", @@ -114,6 +113,9 @@ "dialog.checklist.field_count_with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", "dialog.checklist.link_from_inside": "Found {count} links from covered portals", "dialog.checklist.link_from_inside.covered_at_order": " at {order} by link ", + "dialog.common.commands": "Commands", + "dialog.common.commands_short": "Cmds", + "dialog.common.zone_all": "All", "dialog.firebase.setup": "Visit {url} and press the button to authorize live updates. You will need to reload IITC afterward.", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", @@ -130,7 +132,6 @@ "dialog.team_manage.join_link.revoke": "Revoke", "dialog.team_message": "Team announcement: “{message}” from {sender}", "dialog.zones.color": "Color", - "dialog.zones.commands": "Commands", "dialog.zones.id": "ID", "dialog.zones.name": "Name", "DRAW TOOLS FORMAT": "Draw Tools Format", From 2314d19ed24448aaef993bd7fc7fa4696c182a99 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 20 Jan 2022 20:03:27 +0100 Subject: [PATCH 228/275] wx: add (some) untranslatable strings #6 --- src/code/buttons/uploadButton.js | 8 ++--- src/code/buttons/wasabeeButton.js | 2 +- src/code/dialogs/authDialog.js | 11 +++++-- src/code/dialogs/autodraws/homogeneous.js | 2 +- src/code/dialogs/autodraws/madrid.js | 2 +- src/code/dialogs/autodraws/onionfield.js | 2 +- src/code/dialogs/blockersList.js | 2 +- src/code/dialogs/checklist.js | 24 ++++++++------ src/code/dialogs/importDialog.js | 5 ++- src/code/dialogs/linkListDialog.js | 4 +-- src/code/dialogs/manageTeamDialog.js | 2 +- src/code/dialogs/onlineAgentList.js | 6 ++-- src/code/dialogs/opPerms.js | 2 +- src/code/dialogs/opsDialog.js | 29 ++++++++--------- src/code/dialogs/teamListDialog.js | 16 +++++++--- src/code/dialogs/teamMembershipList.js | 4 +-- src/code/dialogs/zoneDialog.js | 4 +-- src/code/dialogs/zoneSetColor.js | 8 +++-- src/code/translations/English.json | 39 +++++++++++++++++++---- 19 files changed, 108 insertions(+), 64 deletions(-) diff --git a/src/code/buttons/uploadButton.js b/src/code/buttons/uploadButton.js index cdb66be4c..51e77bb44 100644 --- a/src/code/buttons/uploadButton.js +++ b/src/code/buttons/uploadButton.js @@ -68,7 +68,7 @@ const UploadButton = WButton.extend({ update: function () { if (!WasabeeMe.isLoggedIn()) { this._invisible(); - this.title = wX("NOT LOGGED IN SHORT"); + this.title = ""; this.button.title = this.title; return; } @@ -83,21 +83,21 @@ const UploadButton = WButton.extend({ if (!operation.canWriteServer()) { this._invisible(); - this.title = wX("UPDATE PERM DENIED"); + this.title = ""; this.button.title = this.title; return; } if (!operation.localchanged) { this._invisible(); - this.title = wX("UPDATE HOVER NOT CHANGED", { opName: operation.name }); + this.title = ""; this.button.title = this.title; return; } if (operation.server && operation.server != GetWasabeeServer()) { this._invisible(); - this.title = wX("UPDATE HOVER WRONG SERVER", { opName: operation.name }); + this.title = ""; this.button.title = this.title; return; } diff --git a/src/code/buttons/wasabeeButton.js b/src/code/buttons/wasabeeButton.js index 4f9a54a12..1147ed4e7 100644 --- a/src/code/buttons/wasabeeButton.js +++ b/src/code/buttons/wasabeeButton.js @@ -159,7 +159,7 @@ const WasabeeButton = WButton.extend({ this._SettingsActions = [ { - title: "Settings", + title: wX("toolbar.wasabee.settings"), text: "⚙", callback: () => { this.disable(); diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index 25f965350..873e6fa0c 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -12,6 +12,7 @@ import { sendAccessToken, sendOneTimeToken, } from "../auth"; +import { constants } from "../static"; const AuthDialog = WDialog.extend({ statics: { @@ -124,12 +125,16 @@ const AuthDialog = WDialog.extend({ }); const oneTimeButton = L.DomUtil.create("button", "server", content); - oneTimeButton.textContent = "One Time Token Login"; + oneTimeButton.textContent = wX("dialog.auth.ott.button"); L.DomEvent.on(oneTimeButton, "click", (ev) => { L.DomEvent.stop(ev); + const text = L.DomUtil.create("span"); + text.innerHTML = wX("dialog.auth.ott.text", { + url: `${constants.WEBUI_DEFAULT}/#/settings`, + }); const ottDialog = new PromptDialog({ - title: "One Time Token", - label: "One Time Token", + title: wX("dialog.auth.ott.title"), + label: text, callback: async () => { if (ottDialog.inputField.value) { try { diff --git a/src/code/dialogs/autodraws/homogeneous.js b/src/code/dialogs/autodraws/homogeneous.js index 57ad17007..1d1340d3f 100644 --- a/src/code/dialogs/autodraws/homogeneous.js +++ b/src/code/dialogs/autodraws/homogeneous.js @@ -427,7 +427,7 @@ const HomogeneousDialog = AutoDraw.extend({ }; this.createDialog({ - title: "Homogeneous", + title: wX("HG"), html: container, width: "auto", dialogClass: "homogeneous", diff --git a/src/code/dialogs/autodraws/madrid.js b/src/code/dialogs/autodraws/madrid.js index 79ffba5eb..f7997c6ee 100644 --- a/src/code/dialogs/autodraws/madrid.js +++ b/src/code/dialogs/autodraws/madrid.js @@ -104,7 +104,7 @@ const MadridDialog = AutoDraw.extend({ container ); this._addCheckbox( - "Balanced", // wX + wX("autodraw.madrid.balanced"), "wasabee-madrid-balanced", "_balancedcheck", container diff --git a/src/code/dialogs/autodraws/onionfield.js b/src/code/dialogs/autodraws/onionfield.js index 286d97d29..8860e4112 100644 --- a/src/code/dialogs/autodraws/onionfield.js +++ b/src/code/dialogs/autodraws/onionfield.js @@ -182,7 +182,7 @@ const OnionfieldDialog = AutoDraw.extend({ }; this.createDialog({ - title: "Onion/Rose", + title: wX("ONION_WAS_TAKEN"), html: container, width: "auto", dialogClass: "onion", diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index f507da570..a60e3688a 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -73,7 +73,7 @@ const BlockerList = WDialog.extend({ td.enable(); }; if (operation.canWrite()) { - buttons["Clear Automark"] = () => { + buttons[wX("dialog.blockers.clear_automark")] = () => { const operation = getSelectedOperation(); operation.startBatchMode(); for (const m of operation.markers) { diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index d95614367..2e6e83b9a 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -65,7 +65,7 @@ const OperationChecklistDialog = WDialog.extend({ buttons[wX("LOAD PORTALS")] = () => { loadFaked(getSelectedOperation(), true); // force }; - buttons["Count fields"] = () => { + buttons[wX("dialog.checklist.count_fields")] = () => { this.countFields(getSelectedOperation(), true); }; buttons[wX("SET_MARKERS_ZONES")] = () => { @@ -317,7 +317,7 @@ const OperationChecklistDialog = WDialog.extend({ const container = L.DomUtil.create("div", "field-count"); if (emptyFieldLinks.length) { const header = L.DomUtil.create("div", null, container); - header.textContent = wX("dialog.checklist.field_count_with_empty", { + header.textContent = wX("dialog.checklist.count_fields.with_empty", { fieldCount: fieldCount, emptyCount: emptyCount, linkCount: emptyFieldLinks, @@ -330,15 +330,18 @@ const OperationChecklistDialog = WDialog.extend({ } } else { const header = L.DomUtil.create("div", null, container); - header.textContent = wX("dialog.checklist.field_count", { + header.textContent = wX("dialog.checklist.count_fields.no_empty", { fieldCount: fieldCount, }); } if (linksFromInner.length) { const header = L.DomUtil.create("div", null, container); - header.textContent = wX("dialog.checklist.link_from_inside", { - count: linksFromInner.length, - }); + header.textContent = wX( + "dialog.checklist.count_fields.link_from_inside", + { + count: linksFromInner.length, + } + ); const content = L.DomUtil.create("ul", null, container); for (const link of linksFromInner) { const cl = coveredPortals.get(link.fromPortalId); @@ -346,9 +349,12 @@ const OperationChecklistDialog = WDialog.extend({ li.append(`${link.order}: `); li.appendChild(LinkUI.displayFormat(link, operation)); li.append( - wX("dialog.checklist.link_from_inside.covered_at_order", { - order: cl.order, - }) + wX( + "dialog.checklist.count_fields.link_from_inside.covered_at_order", + { + order: cl.order, + } + ) ); li.appendChild(LinkUI.displayFormat(cl, operation)); } diff --git a/src/code/dialogs/importDialog.js b/src/code/dialogs/importDialog.js index a2287ecd2..f2efb9fcf 100644 --- a/src/code/dialogs/importDialog.js +++ b/src/code/dialogs/importDialog.js @@ -55,8 +55,7 @@ const ImportDialog = WDialog.extend({ buttons[wX("GET DT")] = () => { this.drawToolsFormat(); }; - // wX - buttons["Fill from URL"] = () => { + buttons[wX("dialog.import.url")] = () => { this.fillFromURL(); }; @@ -84,7 +83,7 @@ const ImportDialog = WDialog.extend({ fillFromURL() { // todo: wX const prompt = new PromptDialog({ - title: "Fill from URL", + title: wX("dialog.import.url"), label: "URL", callback: async () => { try { diff --git a/src/code/dialogs/linkListDialog.js b/src/code/dialogs/linkListDialog.js index 8ad4a9411..ce1f550fe 100644 --- a/src/code/dialogs/linkListDialog.js +++ b/src/code/dialogs/linkListDialog.js @@ -23,7 +23,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ ); const linkFields = [ { - name: "Length", + name: wX("dialog.link_list.length"), value: (link) => link.length(operation), format: (cell, data) => { cell.classList.add("length"); @@ -33,7 +33,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ smallScreenHide: true, }, { - name: "Min Lvl", + name: wX("dialog.link_list.level"), title: wX("MIN_SRC_PORT_LVL"), value: (link) => link.length(operation), format: (cell, data, link) => { diff --git a/src/code/dialogs/manageTeamDialog.js b/src/code/dialogs/manageTeamDialog.js index 951a44860..2783d2d24 100644 --- a/src/code/dialogs/manageTeamDialog.js +++ b/src/code/dialogs/manageTeamDialog.js @@ -247,7 +247,7 @@ const ManageTeamDialog = WDialog.extend({ this.update(); }); } else { - L.DomUtil.create("span", null, container).textContent = "not set"; + L.DomUtil.create("span", null, container).textContent = wX("NOT_SET"); const joinlinkadd = L.DomUtil.create("button", null, container); joinlinkadd.textContent = wX("dialog.team_manage.join_link.create"); L.DomEvent.on(joinlinkadd, "click", async (ev) => { diff --git a/src/code/dialogs/onlineAgentList.js b/src/code/dialogs/onlineAgentList.js index 10eb12295..e4a899fd2 100644 --- a/src/code/dialogs/onlineAgentList.js +++ b/src/code/dialogs/onlineAgentList.js @@ -32,7 +32,7 @@ const OnlineAgentList = WDialog.extend({ this.update(); this.createDialog({ - title: "Online Agents", + title: wX("dialog.online_agents.title"), html: this._table.table, width: "auto", dialogClass: "teamlist", @@ -51,7 +51,7 @@ const OnlineAgentList = WDialog.extend({ cell.appendChild(AgentUI.formatDisplay(agent)), }, { - name: "Last Seen", + name: wX("dialog.online_agents.last_seen"), value: (agent) => agent.date, sort: (a, b) => a.localeCompare(b), format: (cell, value, agent) => { @@ -59,7 +59,7 @@ const OnlineAgentList = WDialog.extend({ }, }, { - name: "Actions", + name: wX("dialog.online_agents.actions"), value: (agent) => agent.id, format: (cell, value, agent) => { if (value) { diff --git a/src/code/dialogs/opPerms.js b/src/code/dialogs/opPerms.js index 958c9b8ba..25ea40650 100644 --- a/src/code/dialogs/opPerms.js +++ b/src/code/dialogs/opPerms.js @@ -114,7 +114,7 @@ const OpPermList = WDialog.extend({ }, }, { - name: "Zone", + name: wX("ZONE"), value: (perm) => { if (perm.zone === 0) return wX("dialog.common.zone_all"); return operation.zoneName(perm.zone); diff --git a/src/code/dialogs/opsDialog.js b/src/code/dialogs/opsDialog.js index bb8dc8232..f2b3722a0 100644 --- a/src/code/dialogs/opsDialog.js +++ b/src/code/dialogs/opsDialog.js @@ -50,12 +50,11 @@ const OpsDialog = WDialog.extend({ await this.updateSortable(0, false); const buttons = {}; - // wX - buttons["Unhide all OPs"] = () => { + buttons[wX("dialog.ops_list.unhide_ops")] = () => { resetHiddenOps(); this.update(); }; - buttons["Toggle Show/Hide"] = () => { + buttons[wX("dialog.ops_list.toggle_hide")] = () => { const showHiddenOps = localStorage[ window.plugin.wasabee.static.constants.OPS_SHOW_HIDDEN_OPS @@ -98,7 +97,7 @@ const OpsDialog = WDialog.extend({ }, }, { - name: "Name", + name: wX("dialog.common.name"), value: (op) => op.name, sort: (a, b) => a.localeCompare(b), format: (cell, value, op) => { @@ -134,18 +133,18 @@ const OpsDialog = WDialog.extend({ if (op.localchanged) { status.textContent = "☀"; status.style.color = "green"; - status.title = "Local changes"; + status.title = wX("dialog.ops_list.local_change"); } if (op.remotechanged) { status.textContent = "⛅"; status.style.color = "red"; - status.title = "Local&remote changes"; + status.title = wX("dialog.ops_list.remote_change"); } } }, }, { - name: "Owner", + name: wX("dialog.common.owner"), value: (op) => op.owner, sort: (a, b) => a.localeCompare(b), format: (cell, value, op) => { @@ -184,23 +183,21 @@ const OpsDialog = WDialog.extend({ const background = L.DomUtil.create("input", null, cell); background.type = "checkbox"; background.checked = op.background; - // wX background.title = op.background - ? "Disable background" - : "Show in background"; + ? wX("dialog.ops_list.background_disable") + : wX("dialog.ops_list.background_enable"); L.DomEvent.on(background, "change", (ev) => { L.DomEvent.stop(ev); const background = ev.target; - // wX background.title = background.checked - ? "Disable background" - : "Show in background"; + ? wX("dialog.ops_list.background_disable") + : wX("dialog.ops_list.background_enable"); setOpBackground(op.id, background.checked); }); }, }, { - name: "Cmds", + name: wX("dialog.common.commands_short"), value: () => null, sort: null, className: "actions", @@ -220,7 +217,9 @@ const OpsDialog = WDialog.extend({ const download = L.DomUtil.create("a", "", cell); download.href = "#"; download.textContent = "↻"; - download.title = "Download " + op.name; + download.title = wX("dialog.ops_list.download", { + opName: op.name, + }); L.DomEvent.on(download, "click", (ev) => { L.DomEvent.stop(ev); syncOp(op.id); diff --git a/src/code/dialogs/teamListDialog.js b/src/code/dialogs/teamListDialog.js index 14dea30bd..55a3e388b 100644 --- a/src/code/dialogs/teamListDialog.js +++ b/src/code/dialogs/teamListDialog.js @@ -63,7 +63,9 @@ const TeamListDialog = WDialog.extend({ value: (team) => team.State, format: (row, value, obj) => { const link = L.DomUtil.create("a", null, row); - link.textContent = value ? "On" : "Off"; + link.textContent = value + ? wX("dialog.common.on") + : wX("dialog.common.off"); if (value) L.DomUtil.addClass(link, "enl"); link.onclick = async () => { await this.toggleTeam(obj.ID, value); @@ -72,11 +74,13 @@ const TeamListDialog = WDialog.extend({ }, }, { - name: "Share W-D Keys", + name: wX("dialog.team_list.share_wd_keys"), value: (team) => team.ShareWD, format: (row, value, obj) => { const link = L.DomUtil.create("a", null, row); - link.textContent = value ? "On" : "Off"; + link.textContent = value + ? wX("dialog.common.on") + : wX("dialog.common.off"); if (value) L.DomUtil.addClass(link, "enl"); link.onclick = async () => { await this.toggleShareWD(obj.ID, value); @@ -86,11 +90,13 @@ const TeamListDialog = WDialog.extend({ }, }, { - name: "Load W-D Keys", + name: wX("dialog.team_list.load_wd_keys"), value: (team) => team.LoadWD, format: (row, value, obj) => { const link = L.DomUtil.create("a", null, row); - link.textContent = value ? "On" : "Off"; + link.textContent = value + ? wX("dialog.common.on") + : wX("dialog.common.off"); if (value) L.DomUtil.addClass(link, "enl"); link.onclick = async () => { await this.toggleLoadWD(obj.ID, value); diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index 19a1ab485..e669b44b3 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -73,7 +73,7 @@ const TeamMembershipList = WDialog.extend({ sort: (a, b) => a.localeCompare(b), }, { - name: "Sharing Location", + name: wX("dialog.team_members.location"), value: (agent) => agent.shareLocation, sort: (a, b) => a.localeCompare(b), format: (cell, value) => { @@ -81,7 +81,7 @@ const TeamMembershipList = WDialog.extend({ }, }, { - name: "Sharing W-D Keys", + name: wX("dialog.team_members.wd_keys"), value: (agent) => agent.shareWDKeys, sort: (a, b) => a.localeCompare(b), format: (cell, value) => { diff --git a/src/code/dialogs/zoneDialog.js b/src/code/dialogs/zoneDialog.js index 9be086293..cb1fd5636 100644 --- a/src/code/dialogs/zoneDialog.js +++ b/src/code/dialogs/zoneDialog.js @@ -55,7 +55,7 @@ const ZoneDialog = WDialog.extend({ }; this.createDialog({ - title: "Zones", + title: wX("dialog.zones.title"), html: html, width: "auto", dialogClass: "zone", @@ -79,7 +79,7 @@ const ZoneDialog = WDialog.extend({ ); const hr = L.DomUtil.create("tr", null, tbody); L.DomUtil.create("th", null, hr).textContent = wX("dialog.zones.id"); - L.DomUtil.create("th", null, hr).textContent = wX("dialog.zones.name"); + L.DomUtil.create("th", null, hr).textContent = wX("dialog.common.name"); L.DomUtil.create("th", null, hr).textContent = wX("dialog.zones.color"); if (canWrite) L.DomUtil.create("th", null, hr).textContent = wX( diff --git a/src/code/dialogs/zoneSetColor.js b/src/code/dialogs/zoneSetColor.js index a6d092d19..12ecc3bc4 100644 --- a/src/code/dialogs/zoneSetColor.js +++ b/src/code/dialogs/zoneSetColor.js @@ -1,6 +1,7 @@ import { WDialog } from "../leafletClasses"; import { getSelectedOperation } from "../selectedOp"; import { addToColorList } from "../skin"; +import wX from "../wX"; const ZoneSetColorDialog = WDialog.extend({ statics: { @@ -20,7 +21,7 @@ const ZoneSetColorDialog = WDialog.extend({ _displayDialog: function () { this.createDialog({ - title: "Zone color", + title: wX("dialog.zone_color.title"), html: this._buildContent(), width: "auto", dialogClass: "zone-color", @@ -30,8 +31,9 @@ const ZoneSetColorDialog = WDialog.extend({ _buildContent: function () { const container = L.DomUtil.create("div", "container"); const desc = L.DomUtil.create("div", "desc", container); - desc.textContent = - "Set the color of all links in zone " + this.options.zone.name; + desc.textContent = wX("dialog.zone_color.text", { + zoneName: this.options.zone.name, + }); const picker = L.DomUtil.create("input", "picker", container); picker.type = "color"; diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 800e78f94..321c40cc4 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -52,6 +52,7 @@ "autodraw.homogeneous.order": "Order", "autodraw.homogeneous.portals_required": "{count} required", "autodraw.madrid.auto_determined": "Auto-determined", + "autodraw.madrid.balanced": "Balanced", "autodraw.madrid.result": "Madrid found {count} layers", "autodraw.multimax.result": "Multimax found {count} layers", "autodraw.multimax.result_both_side": "Multimax found {count1} and {count2} layers", @@ -103,37 +104,63 @@ "dialog.about.download_mobile_app": "

Wasabee App:

", "dialog.agent_comment.text": "Comment: ", "dialog.agent_comment.title": "Set comment for {agentName}", + "dialog.auth.ott.button": "One Time Token Login", + "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", + "dialog.auth.ott.title": "One Time Token", + "dialog.blockers.clear_automark": "Clear Automark", "dialog.clear_all.text": "Do you want to reset {opName}?", "dialog.clear_all.title": "Clear: {opName}", "dialog.clear_links.text": "Do you want to remove all links from {opName}?", "dialog.clear_links.title": "Clear Links: {opName}", "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", "dialog.clear_markers.title": "Clear Links: {opName}", - "dialog.checklist.field_count": "Found {fieldCount} fields and no empty field", - "dialog.checklist.field_count_with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", - "dialog.checklist.link_from_inside": "Found {count} links from covered portals", - "dialog.checklist.link_from_inside.covered_at_order": " at {order} by link ", + "dialog.checklist.count_fields": "Count fields", + "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", + "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", + "dialog.checklist.count_fields.link_from_inside": "Found {count} links from covered portals", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", "dialog.common.commands": "Commands", "dialog.common.commands_short": "Cmds", + "dialog.common.name": "Name", + "dialog.common.off": "Off", + "dialog.common.on": "On", + "dialog.common.owner": "Owner", "dialog.common.zone_all": "All", "dialog.firebase.setup": "Visit {url} and press the button to authorize live updates. You will need to reload IITC afterward.", + "dialog.import.url": "Fill from URL", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", "dialog.leave_team.title": "Leave: {teamName}", + "dialog.link_list.length": "Length", + "dialog.link_list.level": "Min Lvl", + "dialog.online_agents.actions": "Actions", + "dialog.online_agents.last_seen": "Last Seen", + "dialog.online_agents.title": "Online Agents", "dialog.op_settings.zones": "Zones", + "dialog.ops_list.background_disable": "Disable background", + "dialog.ops_list.background_enable": "Show in background", + "dialog.ops_list.download": "Download {opName}", "dialog.ops_list.last_fetched": "Last fetched: {date}", "dialog.ops_list.local_change": "Local has changed", "dialog.ops_list.remote_change": "Remote has changed", + "dialog.ops_list.toggle_hide": "Toggle Show/Hide", + "dialog.ops_list.unhide_ops": "Unhide all OPs", "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", "dialog.remove_agent.title": "Remove: {agentName}", "dialog.setcomment.portal_hardness": "Hardness", + "dialog.team_list.load_wd_keys": "Load W-D Keys", + "dialog.team_list.share_wd_keys": "Share W-D Keys", "dialog.team_manage.join_link": "Join Link", "dialog.team_manage.join_link.create": "Create", "dialog.team_manage.join_link.revoke": "Revoke", + "dialog.team_members.location": "Sharing Location", + "dialog.team_members.wd_keys": "Sharing W-D Keys", "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.zone_color.title": "Zone Color", + "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", "dialog.zones.id": "ID", - "dialog.zones.name": "Name", + "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplicate Operation", "END_PORT": "End Portal", @@ -397,6 +424,7 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Click first portal", "toolbar.quick_draw.tooltip.single_mode.next": "Click next portal", "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", + "toolbar.wasabee.settings": "Settings", "toolbox.teammates": "Teammates Online", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", @@ -411,7 +439,6 @@ "TYPE": "Type", "UNASSIGNED": "Unassigned", "UNKNOWN": "Unknown", - "UPDATE HOVER NOT CHANGED": "{opName} not changed locally", "UPDATE HOVER": "UPDATE {opName} on the server", "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "The OP has been modified on the server since last sync. Do you want to replace the server version with the current one?", From b032eb65e0337f685adfdc98ad43314430268652 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 20 Jan 2022 21:33:23 +0100 Subject: [PATCH 229/275] build: eslint rule for unknown wX keys --- .eslintrc.json | 4 +++- eslint-local-rules.js | 45 +++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 eslint-local-rules.js diff --git a/.eslintrc.json b/.eslintrc.json index 4d0645d1f..5866aa92b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,6 +4,7 @@ "sourceType": "module" }, "extends": ["eslint:recommended", "plugin:prettier/recommended"], + "plugins": ["eslint-plugin-local-rules"], "env": { "browser": true, "jest": false, @@ -45,7 +46,8 @@ "no-unused-expressions": 1, "no-void": 1, "no-sequences": 1, - "radix": 1 + "radix": 1, + "local-rules/wx-keys": 2 }, "globals": { "L": "readonly", diff --git a/eslint-local-rules.js b/eslint-local-rules.js new file mode 100644 index 000000000..daa69410d --- /dev/null +++ b/eslint-local-rules.js @@ -0,0 +1,45 @@ +"use strict"; + +const sourceLanguage = require("./src/code/translations/English.json"); + +module.exports = { + "wx-keys": { + meta: { + docs: { + description: "Check wX calls", + category: "Possible Errors", + recommended: false, + }, + schema: [], + }, + create: function (context) { + return { + CallExpression: function (node) { + const callee = node.callee; + if (callee.type !== "Identifier") return; + if (callee.name !== "wX") return; + const args = node.arguments; + if (args.length < 1 || args.length > 2) { + context.report({ + node: node, + message: "Invalid number of arguments for wX", + }); + } else { + if (args[0].type !== "Literal") return; + const key = args[0].value; + if (key in sourceLanguage) { + return; + } + context.report({ + node: node, + message: "Unknown wX key: {{ key }}", + data: { + key: args[0].raw + }, + }); + } + }, + }; + }, + }, +}; diff --git a/package.json b/package.json index 3bad346ae..015d9ae3c 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "del": "^6.0.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", + "eslint-plugin-local-rules": "^1.1.0", "eslint-plugin-prettier": "^3.4.0", "eslint-webpack-plugin": "^3.0.1", "fancy-log": "^1.3.3", From 58855d18eb4abd3700a09fe775e05229a83466cd Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 21 Jan 2022 00:05:26 +0100 Subject: [PATCH 230/275] fix: lint --- src/code/firebaseSupport.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/code/firebaseSupport.ts b/src/code/firebaseSupport.ts index b3341b8e6..7e3456f28 100644 --- a/src/code/firebaseSupport.ts +++ b/src/code/firebaseSupport.ts @@ -88,11 +88,13 @@ async function onMessage( await changeOpIfNeeded(); break; case "Generic Message": - const agent = await WasabeeAgent.get(data.sender); - const name = agent ? agent.name : "[unknown sender]"; - displayInfo( - wX("dialog.team_message", { message: data.msg, sender: name }) - ); + { + const agent = await WasabeeAgent.get(data.sender); + const name = agent ? agent.name : "[unknown sender]"; + displayInfo( + wX("dialog.team_message", { message: data.msg, sender: name }) + ); + } break; case "Login": console.debug("server reported teammate login: ", data.gid); From a24b4cfa182a816b4852d1d488ad8efc39bdd132 Mon Sep 17 00:00:00 2001 From: Bill Gillock Date: Tue, 25 Jan 2022 14:12:34 -0600 Subject: [PATCH 231/275] Bulk marker add (#324) --- src/code/css/wasabee.css | 4 ++++ src/code/dialogs/markerAddDialog.js | 23 +++++++++++++++++++++++ src/code/translations/Danish.json | 1 + src/code/translations/English.json | 1 + src/code/translations/Filipino.json | 1 + src/code/translations/French.json | 1 + src/code/translations/German.json | 1 + src/code/translations/Italian.json | 1 + src/code/translations/Portuguese.json | 1 + src/code/translations/Russian.json | 1 + src/code/translations/Spanish.json | 1 + 11 files changed, 36 insertions(+) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index 82ed0d76d..92c74a212 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -279,6 +279,10 @@ margin: 0px 25px; } +.wasabee-dialog-markeradd div.bulk { + grid-column: 2; +} + .wasabee-dialog-markeradd div.content input { grid-column: 1 / span 2; } diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index 9ac8af829..b54426dca 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -33,6 +33,24 @@ const MarkerAddDialog = WDialog.extend({ }, update: async function () { + // updating with a new portal selected and in bulk mode? + if ( + this._selectedPortal && + PortalUI.getSelected() && + this._selectedPortal.id != PortalUI.getSelected().id && + this._bulk.checked + ) { + this._selectedPortal = PortalUI.getSelected(); + if (WasabeeMarker.markerTypes.has(this._type.value)) + await this._addMarker( + this._type.value, + this._comment.value, + this._zones.value, + this._assign.value + ); + return; + } + this._type.textContent = ""; // zones can be populated even if portal not selected @@ -103,6 +121,11 @@ const MarkerAddDialog = WDialog.extend({ L.DomUtil.create("label", null, content).textContent = wX("AGENT"); this._assign = L.DomUtil.create("select", null, content); + L.DomUtil.create("label", null, content).textContent = wX("ADD_BULK"); + const bulk = L.DomUtil.create("div", "bulk", content); + this._bulk = L.DomUtil.create("input", "checkbox-input", bulk); + this._bulk.type = "checkbox"; + this._comment = L.DomUtil.create("input", null, content); this._comment.placeholder = wX("SET_COMMENT"); diff --git a/src/code/translations/Danish.json b/src/code/translations/Danish.json index 682f3b40b..faf3372fd 100644 --- a/src/code/translations/Danish.json +++ b/src/code/translations/Danish.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Tilføj Markører", "ADD_AGENT": "Tilføj Agent: ", "ADD_BL": "Tilføj baglinie: ", + "ADD_BULK": "Massetilføj", "ADD_BUTTON_LINKS": "Tilføj alle links med det samme.", "ADD_LINKS": "Tilføj Links", "ADD_MARKER": "+ Markør", diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 321c40cc4..e32d269ba 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Add Markers", "ADD_AGENT": "Add Agent: ", "ADD_BL": "Add Back Links: ", + "ADD_BULK": "Bulk add", "ADD_BUTTON_LINKS": "Add all links at once.", "ADD_LINKS": "Add Links", "ADD_MARKER": "+ Marker", diff --git a/src/code/translations/Filipino.json b/src/code/translations/Filipino.json index 781b8dd8f..98f1f37c9 100644 --- a/src/code/translations/Filipino.json +++ b/src/code/translations/Filipino.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Magdagdag ng Markers", "ADD_AGENT": "Magdagdag ng Agent: ", "ADD_BL": "Magdagdag ng Back Links: ", + "ADD_BULK": "Maramihang idagdag", "ADD_BUTTON_LINKS": "Sabay-sabay idagdag ang lahat ng link", "ADD_LINKS": "Magdagdag ng Link", "ADD_MARKER": "Magdagdag ng Marker", diff --git a/src/code/translations/French.json b/src/code/translations/French.json index 2eb1bc2cd..a27450f7a 100644 --- a/src/code/translations/French.json +++ b/src/code/translations/French.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Ajouter des marqueurs", "ADD_AGENT": "Ajouter l'agent : ", "ADD_BL": "Ajouter les backlinks : ", + "ADD_BULK": "Ajouter en masse", "ADD_BUTTON_LINKS": "Ajouter les liens", "ADD_LINKS": "Ajouter des liens", "ADD_MARKER": "+ Marqueur", diff --git a/src/code/translations/German.json b/src/code/translations/German.json index 354dbddcf..a79bb62b7 100644 --- a/src/code/translations/German.json +++ b/src/code/translations/German.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Dialog - Markierung hinzufügen", "ADD_AGENT": "Füge Agent hinzu: ", "ADD_BL": "Füge Portal zur Ankerkette hinzu: ", + "ADD_BULK": "Bulk hinzufügen", "ADD_BUTTON_LINKS": "Alle Links auf einmal hinzufügen.", "ADD_LINKS": "Füge Links hinzu", "ADD_MARKER": "Füge Markierung hinzu", diff --git a/src/code/translations/Italian.json b/src/code/translations/Italian.json index 47a786a65..a2fd40842 100644 --- a/src/code/translations/Italian.json +++ b/src/code/translations/Italian.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Aggiunta Marker", "ADD_AGENT": "Aggiungi Agente: ", "ADD_BL": "Aggiungi Link all'indietro: ", + "ADD_BULK": "Aggiungi in blocco", "ADD_BUTTON_LINKS": "Aggiungi tutti i link assieme.", "ADD_LINKS": "Aggiungi Link", "ADD_MARKER": "+ Marker", diff --git a/src/code/translations/Portuguese.json b/src/code/translations/Portuguese.json index 01adb3e68..e429f5efd 100644 --- a/src/code/translations/Portuguese.json +++ b/src/code/translations/Portuguese.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Adicionar Marcadores", "ADD_AGENT": "Adicionar Agente: ", "ADD_BL": "Adicionar links traseiros: ", + "ADD_BULK": "Adicionar em massa", "ADD_BUTTON_LINKS": "Adicionar todos os links de uma vez.", "ADD_LINKS": "Adicionar Links", "ADD_MARKER": "+ Marcador", diff --git a/src/code/translations/Russian.json b/src/code/translations/Russian.json index a585f7722..e1ef44bcf 100644 --- a/src/code/translations/Russian.json +++ b/src/code/translations/Russian.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Добавление маркеров", "ADD_AGENT": "Добавить агента: ", "ADD_BL": "Добавить перемычки: ", + "ADD_BULK": "Массовое добавление", "ADD_BUTTON_LINKS": "Добавить все линки сразу.", "ADD_LINKS": "Добавить линки", "ADD_MARKER": "+ маркер", diff --git a/src/code/translations/Spanish.json b/src/code/translations/Spanish.json index 003a68702..1bc06c792 100644 --- a/src/code/translations/Spanish.json +++ b/src/code/translations/Spanish.json @@ -5,6 +5,7 @@ "ADD MARKER TITLE": "Texto de Agregar Marcadores", "ADD_AGENT": "Agregar Agente", "ADD_BL": "Agregar Links Anidados", + "ADD_BULK": "Agregar en bloque", "ADD_BUTTON_LINKS": "Agregar todos los links a la vez.", "ADD_LINKS": "Agregar Links", "ADD_MARKER": "Agregar Marcador", From 8692995852d26b7895e809c2a2adb52ad4023e09 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 22 Jan 2022 18:51:14 +0100 Subject: [PATCH 232/275] fix: count field display [object] --- src/code/dialogs/checklist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 2e6e83b9a..34932eff4 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -320,7 +320,7 @@ const OperationChecklistDialog = WDialog.extend({ header.textContent = wX("dialog.checklist.count_fields.with_empty", { fieldCount: fieldCount, emptyCount: emptyCount, - linkCount: emptyFieldLinks, + linkCount: emptyFieldLinks.length, }); const content = L.DomUtil.create("ul", null, container); for (const [link, c] of emptyFieldLinks) { From f426ae5ef5d270daff826e125546ef72ff1345d1 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 22 Jan 2022 21:03:20 +0100 Subject: [PATCH 233/275] fix: dialog with grid layout and misalign content --- src/code/css/wasabee.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index 92c74a212..2e3e84cef 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -75,6 +75,10 @@ pointer-events: none; } +.wasabee-dialog .container { + align-items: center; +} + /* all dialogs get this class -- do global stuff with it */ /* .wasabee-dialog { background-color: rgba(250, 250, 250, 0.9); From 3d2378085d04c06082a90101e780fda46dd53c26 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 22 Jan 2022 21:04:13 +0100 Subject: [PATCH 234/275] settings: one column layout --- src/code/css/wasabee.css | 36 +++++++++++------------------- src/code/dialogs/settingsDialog.js | 23 +++++++++---------- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index 2e3e84cef..6a8c3515e 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -373,33 +373,23 @@ padding: 4px; width: 96%; } -.wasabee-dialog-settings { - max-width: min-content; + +.wasabee-dialog-settings div.container > * { + display: block; + width: 100%; + margin: 0.3em 0; } -.wasabee-dialog-settings div.container { - display: grid; - grid-template-columns: 1fr 1fr; +.wasabee-dialog-settings div.container > :first-child { + border: none; + margin: 0; } .wasabee-dialog-settings label { - grid-column-start: 1; - grid-column-end: 2; + border-top: solid 1px #fff5; + padding: 0.3em 0 0 0; } -.wasabee-dialog-settings select { - grid-column-start: 2; - grid-column-end: 3; -} -.wasabee-dialog-settings input { - grid-column-start: 2; - grid-column-end: 3; -} -.wasabee-dialog-settings div.desc { - grid-column-start: 1; - grid-column-end: 3; -} - -.wasabee-dialog-settings button { - grid-column-start: 1; - grid-column-end: 3; +.wasabee-dialog-settings label.checkbox input { + margin-right: .5rem; + vertical-align: middle; } .wasabee-dialog-trawl div.container { diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index 5269ad8d3..b0b7914af 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -30,12 +30,11 @@ const SettingsDialog = WDialog.extend({ }, _addCheckBox(container, label, id, storageKey, onChange, defValue) { - const title = L.DomUtil.create("label", null, container); - title.textContent = label; - title.htmlFor = id; - const check = L.DomUtil.create("input", null, container); + const title = L.DomUtil.create("label", "checkbox", container); + const check = L.DomUtil.create("input", "", title); check.type = "checkbox"; check.id = id; + L.DomUtil.create("span", "", title).textContent = label; const sl = localStorage[storageKey]; if (!defValue && sl === "true") check.checked = true; if (defValue && sl !== "false") check.checked = true; @@ -132,14 +131,6 @@ const SettingsDialog = WDialog.extend({ [1, 100, 250, 500, 750, 1000].map((v) => [v, v]) ); - const serverInfo = L.DomUtil.create("button", "server", container); - serverInfo.textContent = wX("WSERVER", { url: GetWasabeeServer() }); - serverInfo.href = "#"; - L.DomEvent.on(serverInfo, "click", (ev) => { - L.DomEvent.stop(ev); - this.setServer(); - }); - this._addSelect( container, wX("TRAWL SKIP TILES"), @@ -156,6 +147,14 @@ const SettingsDialog = WDialog.extend({ ); } + const serverInfo = L.DomUtil.create("button", "server", container); + serverInfo.textContent = wX("WSERVER", { url: GetWasabeeServer() }); + serverInfo.href = "#"; + L.DomEvent.on(serverInfo, "click", (ev) => { + L.DomEvent.stop(ev); + this.setServer(); + }); + const skinsButton = L.DomUtil.create("button", null, container); skinsButton.textContent = wX("SKINS_BUTTON"); L.DomEvent.on(skinsButton, "click", (ev) => { From 1e983b89b54419a0307940b9c0437f7995d6ac99 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 27 Jan 2022 21:09:58 +0100 Subject: [PATCH 235/275] crowdin: add update option --- crowdin.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crowdin.yml b/crowdin.yml index 7be7d6980..54c017dff 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,3 +1,5 @@ files: - source: /src/code/translations/English.json translation: /src/code/translations/%language%.json + skip_untranslated_strings: true + update_option: "update_as_unapproved" From b857c58ca48b7be0b8696af42bc247e30d5a5608 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 30 Jan 2022 00:20:03 +0100 Subject: [PATCH 236/275] agent: support community name (display) --- src/code/dialogs/agentDialog.js | 1 + src/code/model/agent.ts | 34 ++++++++++++--------------------- src/code/ui/agent.js | 5 +++++ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/code/dialogs/agentDialog.js b/src/code/dialogs/agentDialog.js index c6afdd01d..6ef9fe961 100644 --- a/src/code/dialogs/agentDialog.js +++ b/src/code/dialogs/agentDialog.js @@ -27,6 +27,7 @@ const AgentDialog = WDialog.extend({ const ul = L.DomUtil.create("ul", "", html); const rows = [ ["Server name: ", data.name], + ["Ingress name: ", data.communityname], ["V name: ", data.vname], ["V verified: ", data.Vverified], ["Rocks name: ", data.rocksname], diff --git a/src/code/model/agent.ts b/src/code/model/agent.ts index 9fa2e5831..a496a7d0d 100644 --- a/src/code/model/agent.ts +++ b/src/code/model/agent.ts @@ -7,6 +7,7 @@ interface BaseAgent { name: string; intelname?: string; intelfaction: "unset" | "ENLIGHTENED" | "RESISTANCE"; + communityname?: string; pic?: string; lat: number; lng: number; @@ -70,7 +71,10 @@ export default class WasabeeAgent implements Agent { lng: number; date: string; - // intel + // Community (strong) + communityname?: string; + + // intel (weak) intelname?: string; intelfaction: "unset" | "ENLIGHTENED" | "RESISTANCE"; @@ -107,6 +111,7 @@ export default class WasabeeAgent implements Agent { this.name = obj.name; this.intelname = obj.intelname !== "unset" ? obj.intelname : ""; this.intelfaction = obj.intelfaction; + this.communityname = obj.communityname || ''; this.pic = obj.pic ? obj.pic : null; this.lat = obj.lat ? obj.lat : 0; this.lng = obj.lng ? obj.lng : 0; @@ -121,9 +126,11 @@ export default class WasabeeAgent implements Agent { this.rocksname = obj.rocksname; this.rocks = !!obj.rocks; - if (this.Vverified) this.name = this.vname || this.name; + if (this.communityname) this.name = this.communityname; + else if (this.Vverified) this.name = this.vname || this.name; else if (this.rocks) this.name = this.rocksname || this.name; else if (this.intelname) this.name = this.intelname + " [!]"; + else this.name = this.name || '[unknown name]'; /* what did we decide to do with these? this.startlat = obj.startlat ? obj.startlat : 0; @@ -147,6 +154,7 @@ export default class WasabeeAgent implements Agent { } getName() { + if (this.communityname) return this.communityname; if (this.Vverified && this.vname) return this.vname; if (this.rocks && this.rocksname) return this.rocksname; if (this.intelname) return this.intelname; @@ -174,26 +182,8 @@ export default class WasabeeAgent implements Agent { // console.debug("incoming is older, not updating cache"); return; } - // note the new fetched time - cached.fetched = this.fetched; - // console.debug("updating cache"); - - // update location only if known - if (this.lat != 0 && this.lng != 0) { - cached.lat = this.lat; - cached.lng = this.lng; - cached.date = this.date; - } - - // these probably won't change, but just be sure - cached.name = this.name; - cached.level = this.level; - cached.enlid = this.enlid; - cached.pic = this.pic; - cached.Vverified = this.Vverified; - cached.blacklisted = this.blacklisted; - cached.rocks = this.rocks; - // cansendto is never true from a team pull, but might be true from a direct pull + // update data + Object.assign(cached, this); // remove things which make no sense in the global cache delete cached.shareWDKeys; diff --git a/src/code/ui/agent.js b/src/code/ui/agent.js index 32962887e..ef253b0ab 100644 --- a/src/code/ui/agent.js +++ b/src/code/ui/agent.js @@ -8,6 +8,10 @@ import wX from "../wX"; import WasabeeAgent from "../model/agent"; import { displayInfo, displayWarning } from "../error"; +/** + * @param {WasabeeAgent} agent + * @returns html anchor with agent name (and verification states) + */ function formatDisplay(agent) { const display = L.DomUtil.create("a", "wasabee-agent-label"); if (agent.Vverified || agent.rocks) { @@ -23,6 +27,7 @@ function formatDisplay(agent) { }); let prefix = ""; + if (agent.communityname) prefix += "C"; if (agent.Vverified) prefix += "V"; else if (agent.vname === agent.name) prefix += "v"; if (agent.rocks) prefix += "R"; From d0c8ba53c6716de63256873c9fc3bdc0e9d7f59e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 1 Feb 2022 22:48:17 +0100 Subject: [PATCH 237/275] new op: don't close the prompt without a name --- src/code/dialogs/newopDialog.js | 1 + src/code/dialogs/promptDialog.d.ts | 1 + src/code/dialogs/promptDialog.js | 3 +++ 3 files changed, 5 insertions(+) diff --git a/src/code/dialogs/newopDialog.js b/src/code/dialogs/newopDialog.js index 956dcc854..a7b240716 100644 --- a/src/code/dialogs/newopDialog.js +++ b/src/code/dialogs/newopDialog.js @@ -50,6 +50,7 @@ const NewopDialog = WDialog.extend({ } }, placeholder: wX("MUST_NOT_BE_EMPTY"), + nonEmpty: true, }); addDialog.enable(); }); diff --git a/src/code/dialogs/promptDialog.d.ts b/src/code/dialogs/promptDialog.d.ts index 9255f6d07..e5d331676 100644 --- a/src/code/dialogs/promptDialog.d.ts +++ b/src/code/dialogs/promptDialog.d.ts @@ -9,6 +9,7 @@ interface PromptDialogOptions extends WDialogOptions { text: string; value: string; }[]; + nonEmpty?: boolean; callback?: () => void; cancelCallback?: () => void; } diff --git a/src/code/dialogs/promptDialog.js b/src/code/dialogs/promptDialog.js index 9f6472683..f78c88f23 100644 --- a/src/code/dialogs/promptDialog.js +++ b/src/code/dialogs/promptDialog.js @@ -14,6 +14,7 @@ const PromptDialog = WDialog.extend({ placeholder: "", current: "", suggestions: [], + nonEmpty: false, // callback // cancelCallback }, @@ -30,6 +31,7 @@ const PromptDialog = WDialog.extend({ _displayDialog: function () { const buttons = {}; buttons[wX("OK")] = () => { + if (this.options.nonEmpty && !this.inputField.value) return; if (this.options.callback) this.options.callback(); // callback must fire appropriate ui update events this.closeDialog(); @@ -61,6 +63,7 @@ const PromptDialog = WDialog.extend({ this.inputField.id = "inputField"; this.inputField.placeholder = this.options.placeholder; this.inputField.value = this.options.current; + this.inputField.required = this.options.nonEmpty; if (this.options.suggestions) { const datalist = L.DomUtil.create("datalist", null, content); From 811116022bcf4d5447c21d7adddc220e5e1c8ecd Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 4 Feb 2022 00:29:07 +0100 Subject: [PATCH 238/275] fix: update setting title --- src/code/dialogs/settingsDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index b0b7914af..e1a06a19f 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -26,7 +26,7 @@ const SettingsDialog = WDialog.extend({ update: function () { this.setContent(this._getContent()); - // TODO also update the title + this.setTitle(wX("SETTINGS")); }, _addCheckBox(container, label, id, storageKey, onChange, defValue) { From 96271f84d807ada38ba0409892e31c5bc936a274 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 4 Feb 2022 21:01:56 +0100 Subject: [PATCH 239/275] fix: upload loading button --- src/code/buttons/uploadButton.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code/buttons/uploadButton.js b/src/code/buttons/uploadButton.js index 51e77bb44..395d90c3a 100644 --- a/src/code/buttons/uploadButton.js +++ b/src/code/buttons/uploadButton.js @@ -113,6 +113,7 @@ const UploadButton = WButton.extend({ _invisible: function () { this.button.style.display = "none"; + this.button.classList.remove("loading"); }, // update operation that is either From 05ad93b594df48cc913983372b339e80060919bf Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 20 Jan 2022 18:23:15 +0100 Subject: [PATCH 240/275] fix: toolbar subactions --- src/code/css/smallscreen.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/code/css/smallscreen.css b/src/code/css/smallscreen.css index 37f004550..d5e181057 100644 --- a/src/code/css/smallscreen.css +++ b/src/code/css/smallscreen.css @@ -45,3 +45,8 @@ white-space: nowrap; text-overflow: ellipsis; } + +/* tool-bar */ +.leaflet-touch li.wasabee-subactions a { + width: inherit; +} \ No newline at end of file From 6997d357c7f1055c030d51fdc0bc8d3487e69c54 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 20 Jan 2022 18:23:53 +0100 Subject: [PATCH 241/275] linkDialog: new layout to better support mobile --- src/code/css/autodraws.css | 21 ++++++++-- src/code/dialogs/linkDialog.js | 74 ++++++++++++++-------------------- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/code/css/autodraws.css b/src/code/css/autodraws.css index 61427428b..b9fefe748 100644 --- a/src/code/css/autodraws.css +++ b/src/code/css/autodraws.css @@ -13,7 +13,6 @@ .wasabee-dialog-fanfield .container, .wasabee-dialog-flipflop .container, .wasabee-dialog-homogeneous .container, -.wasabee-dialog-link .container, .wasabee-dialog-madrid .container, .wasabee-dialog-multimax .container, .wasabee-dialog-onion .container, @@ -26,6 +25,13 @@ max-width: 700px; } +.wasabee-dialog-link .container { + display: grid; + grid-gap: 0.2em 0.5em; + align-items: center; + max-width: 700px; +} + .wasabee-dialog-fanfield label, .wasabee-dialog-flipflop label, .wasabee-dialog-link label, @@ -35,6 +41,7 @@ .wasabee-dialog-starburst label, .wasabee-dialog-savelinks label { grid-column: 1; + text-decoration: dotted underline; } .wasabee-dialog-fanfield button, @@ -55,7 +62,10 @@ grid-column: 4; } -.wasabee-dialog-link .drawb, +.wasabee-dialog-link .drawb { + grid-column: 1/3; +} + .wasabee-dialog-fanfield .drawb, .wasabee-dialog-flipflop .drawb, .wasabee-dialog-onion .drawb, @@ -91,10 +101,13 @@ } .wasabee-dialog-link .portal { - grid-column: 3; + grid-column: 1/4; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .wasabee-dialog-link .add, .wasabee-dialog-link .desc { - grid-column: 4; + grid-column: 3; } diff --git a/src/code/dialogs/linkDialog.js b/src/code/dialogs/linkDialog.js index 72e3b1710..0a735cb5a 100644 --- a/src/code/dialogs/linkDialog.js +++ b/src/code/dialogs/linkDialog.js @@ -40,9 +40,7 @@ const LinkDialog = WDialog.extend({ sourceButton.textContent = wX("SET"); this._sourceDisplay = L.DomUtil.create("span", "portal", container); if (this._source) { - this._sourceDisplay.appendChild( - PortalUI.displayFormat(this._source, this._smallScreen) - ); + this._sourceDisplay.appendChild(PortalUI.displayFormat(this._source)); } else { this._sourceDisplay.textContent = wX("NOT_SET"); } @@ -53,9 +51,7 @@ const LinkDialog = WDialog.extend({ localStorage[window.plugin.wasabee.static.constants.LINK_SOURCE_KEY] = JSON.stringify(this._source); this._sourceDisplay.textContent = ""; - this._sourceDisplay.appendChild( - PortalUI.displayFormat(this._source, this._smallScreen) - ); + this._sourceDisplay.appendChild(PortalUI.displayFormat(this._source)); } else { displayError(wX("PLEASE_SELECT_PORTAL")); } @@ -65,11 +61,23 @@ const LinkDialog = WDialog.extend({ anchor1Label.textContent = wX("ANCHOR1"); const anchor1Button = L.DomUtil.create("button", "set", container); anchor1Button.textContent = wX("SET"); + const anchor1AddButton = L.DomUtil.create("button", "add", container); + anchor1AddButton.textContent = wX("ADD1"); + L.DomEvent.on(anchor1AddButton, "click", (ev) => { + L.DomEvent.stop(ev); + if (this._source && this._anchor1) { + const operation = getSelectedOperation(); + operation.addLink(this._source, this._anchor1, { + description: this._desc.value, + order: operation.nextOrder, + }); + } else { + displayError("Select both Source and Anchor 1"); + } + }); this._anchor1Display = L.DomUtil.create("span", "portal", container); if (this._anchor1) { - this._anchor1Display.appendChild( - PortalUI.displayFormat(this._anchor1, this._smallScreen) - ); + this._anchor1Display.appendChild(PortalUI.displayFormat(this._anchor1)); } else { this._anchor1Display.textContent = wX("NOT_SET"); } @@ -80,37 +88,33 @@ const LinkDialog = WDialog.extend({ localStorage[window.plugin.wasabee.static.constants.ANCHOR_ONE_KEY] = JSON.stringify(this._anchor1); this._anchor1Display.textContent = ""; - this._anchor1Display.appendChild( - PortalUI.displayFormat(this._anchor1, this._smallScreen) - ); + this._anchor1Display.appendChild(PortalUI.displayFormat(this._anchor1)); } else { displayError(wX("PLEASE_SELECT_PORTAL")); } }); - const anchor1AddButton = L.DomUtil.create("button", "add", container); - anchor1AddButton.textContent = wX("ADD1"); - L.DomEvent.on(anchor1AddButton, "click", (ev) => { + + const anchor2Label = L.DomUtil.create("label", null, container); + anchor2Label.textContent = wX("ANCHOR2"); + const anchor2Button = L.DomUtil.create("button", "set", container); + anchor2Button.textContent = wX("SET"); + const anchor2AddButton = L.DomUtil.create("button", "add", container); + anchor2AddButton.textContent = wX("ADD2"); + L.DomEvent.on(anchor2AddButton, "click", (ev) => { L.DomEvent.stop(ev); - if (this._source && this._anchor1) { + if (this._source && this._anchor2) { const operation = getSelectedOperation(); - operation.addLink(this._source, this._anchor1, { + operation.addLink(this._source, this._anchor2, { description: this._desc.value, order: operation.nextOrder, }); } else { - displayError("Select both Source and Anchor 1"); + displayError(wX("SEL_SRC_ANC2")); } }); - - const anchor2Label = L.DomUtil.create("label", null, container); - anchor2Label.textContent = wX("ANCHOR2"); - const anchor2Button = L.DomUtil.create("button", "set", container); - anchor2Button.textContent = wX("SET"); this._anchor2Display = L.DomUtil.create("span", "portal", container); if (this._anchor2) { - this._anchor2Display.appendChild( - PortalUI.displayFormat(this._anchor2, this._smallScreen) - ); + this._anchor2Display.appendChild(PortalUI.displayFormat(this._anchor2)); } else { this._anchor2Display.textContent = wX("NOT_SET"); } @@ -121,27 +125,11 @@ const LinkDialog = WDialog.extend({ localStorage[window.plugin.wasabee.static.constants.ANCHOR_TWO_KEY] = JSON.stringify(this._anchor2); this._anchor2Display.textContent = ""; - this._anchor2Display.appendChild( - PortalUI.displayFormat(this._anchor2, this._smallScreen) - ); + this._anchor2Display.appendChild(PortalUI.displayFormat(this._anchor2)); } else { displayError(wX("PLEASE_SELECT_PORTAL")); } }); - const anchor2AddButton = L.DomUtil.create("button", "add", container); - anchor2AddButton.textContent = wX("ADD2"); - L.DomEvent.on(anchor2AddButton, "click", (ev) => { - L.DomEvent.stop(ev); - if (this._source && this._anchor2) { - const operation = getSelectedOperation(); - operation.addLink(this._source, this._anchor2, { - description: this._desc.value, - order: operation.nextOrder, - }); - } else { - displayError(wX("SEL_SRC_ANC2")); - } - }); // Go button const button = L.DomUtil.create("button", "drawb", container); From d7108d7cb37bbecb8a0390e49fa78b2857adef27 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 20 Jan 2022 18:24:48 +0100 Subject: [PATCH 242/275] simplify smallscreen code --- src/code/dialogs/about.js | 14 +------------- src/code/dialogs/autodraws.js | 10 +--------- src/code/dialogs/checklist.js | 6 +++--- src/code/dialogs/settingsDialog.js | 12 +----------- src/code/dialogs/zoneDialog.js | 10 +--------- 5 files changed, 7 insertions(+), 45 deletions(-) diff --git a/src/code/dialogs/about.js b/src/code/dialogs/about.js index e9cdf3d3b..7f318d38c 100644 --- a/src/code/dialogs/about.js +++ b/src/code/dialogs/about.js @@ -12,13 +12,7 @@ const AboutDialog = WDialog.extend({ addHooks: function () { // this pulls in the addHooks from the parent class WDialog.prototype.addHooks.call(this); - // put any per-open setup here - // this is the call to actually do our work - if (this._smallScreen) { - this._displaySmallDialog(); - } else { - this._displayDialog(); - } + this._displayDialog(); }, // define our work in _displayDialog @@ -64,12 +58,6 @@ const AboutDialog = WDialog.extend({ buttons: buttons, }); }, - - // small-screen versions go in _displaySmallDialog - _displaySmallDialog: function () { - // for this dialog, the small screen is the same as the normal - this._displayDialog(); - }, }); // this line allows other files to import our dialog diff --git a/src/code/dialogs/autodraws.js b/src/code/dialogs/autodraws.js index 4403ba4e3..18180dba9 100644 --- a/src/code/dialogs/autodraws.js +++ b/src/code/dialogs/autodraws.js @@ -90,11 +90,7 @@ const AutodrawsDialog = WDialog.extend({ addHooks: function () { WDialog.prototype.addHooks.call(this); - if (this._smallScreen) { - this._displaySmallDialog(); - } else { - this._displayDialog(); - } + this._displayDialog(); }, _displayDialog: function () { @@ -124,10 +120,6 @@ const AutodrawsDialog = WDialog.extend({ id: window.plugin.wasabee.static.dialogNames.autodraws, }); }, - - _displaySmallDialog: function () { - this._displayDialog(); - }, }); export default AutodrawsDialog; diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 34932eff4..2c60f812e 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -133,7 +133,7 @@ const OperationChecklistDialog = WDialog.extend({ format: (cell, value, thing) => { if (thing instanceof WasabeeLink) { cell.appendChild(LinkUI.displayFormat(thing, operation)); - if (this._smallScreen) cell.colSpan = 2; + cell.colSpan = 2; } else { cell.appendChild( PortalUI.displayFormat(operation.getPortal(thing.portalId)) @@ -145,7 +145,7 @@ const OperationChecklistDialog = WDialog.extend({ name: wX("TYPE"), value: (thing) => { if (thing instanceof WasabeeLink) { - return "Link"; + return operation.getPortal(thing.toPortalId).name; } else { // push this shit into the marker class return wX(thing.type); @@ -158,7 +158,7 @@ const OperationChecklistDialog = WDialog.extend({ span.textContent = value; if (thing instanceof WasabeeLink) { - if (this._smallScreen) cell.style.display = "none"; + cell.style.display = "none"; } else if (thing instanceof WasabeeMarker && canWrite) { L.DomEvent.on(cell, "click", (ev) => { L.DomEvent.stop(ev); diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index e1a06a19f..dae7be00a 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -13,11 +13,7 @@ const SettingsDialog = WDialog.extend({ addHooks: function () { WDialog.prototype.addHooks.call(this); - if (this._smallScreen) { - this._displaySmallDialog(); - } else { - this._displayDialog(); - } + this._displayDialog(); }, removeHooks: function () { @@ -207,12 +203,6 @@ const SettingsDialog = WDialog.extend({ id: window.plugin.wasabee.static.dialogNames.settings, }); }, - - // small-screen versions go in _displaySmallDialog - _displaySmallDialog: function () { - // for this dialog, the small screen is the same as the normal - this._displayDialog(); - }, }); // this line allows other files to import our dialog diff --git a/src/code/dialogs/zoneDialog.js b/src/code/dialogs/zoneDialog.js index cb1fd5636..506b857be 100644 --- a/src/code/dialogs/zoneDialog.js +++ b/src/code/dialogs/zoneDialog.js @@ -16,11 +16,7 @@ const ZoneDialog = WDialog.extend({ WDialog.prototype.addHooks.call(this); window.map.on("wasabee:op:change wasabee:op:select", this.update, this); - if (this._smallScreen) { - this._displaySmallDialog(); - } else { - this._displayDialog(); - } + this._displayDialog(); }, removeHooks: function () { @@ -64,10 +60,6 @@ const ZoneDialog = WDialog.extend({ }); }, - _displaySmallDialog: function () { - this._displayDialog(); - }, - buildList: function () { const op = getSelectedOperation(); const canWrite = op.getPermission() === "write"; From 91f6728ee74668be996acd665ed7f54af071b164 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 4 Feb 2022 22:28:11 +0100 Subject: [PATCH 243/275] fix: link list on small screen --- src/code/css/smallscreen.css | 9 ++++++--- src/code/dialogs/linkListDialog.js | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/code/css/smallscreen.css b/src/code/css/smallscreen.css index d5e181057..65c2c3785 100644 --- a/src/code/css/smallscreen.css +++ b/src/code/css/smallscreen.css @@ -18,20 +18,23 @@ vertical-align: bottom; } -.wasabee-dialog-checklist.wasabee-small-screen .wasabee-table td:nth-child(2) > div { +.wasabee-dialog-checklist.wasabee-small-screen .wasabee-table td:nth-child(2) > div, +.wasabee-dialog-linklist.wasabee-small-screen .wasabee-table td:nth-child(2) > div { display: grid; grid-template-columns: auto auto auto; grid-column-gap: 2px; align-items: center; } -.wasabee-dialog-checklist.wasabee-small-screen .wasabee-table td:nth-child(2) a.wasabee-portal { +.wasabee-dialog-checklist.wasabee-small-screen .wasabee-table td:nth-child(2) a.wasabee-portal, +.wasabee-dialog-linklist.wasabee-small-screen .wasabee-table td:nth-child(2) a.wasabee-portal { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } -.wasabee-dialog-checklist.wasabee-small-screen .wasabee-table td:nth-child(2) > a.wasabee-portal { +.wasabee-dialog-checklist.wasabee-small-screen .wasabee-table td:nth-child(2) > a.wasabee-portal +.wasabee-dialog-linklist.wasabee-small-screen .wasabee-table td:nth-child(2) > a.wasabee-portal { display: inline-block; vertical-align: bottom; width: calc(100vw - 13em - 24px); diff --git a/src/code/dialogs/linkListDialog.js b/src/code/dialogs/linkListDialog.js index ce1f550fe..a45345108 100644 --- a/src/code/dialogs/linkListDialog.js +++ b/src/code/dialogs/linkListDialog.js @@ -21,6 +21,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ this, operation ); + fields[2].name = ""; const linkFields = [ { name: wX("dialog.link_list.length"), @@ -42,7 +43,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ smallScreenHide: true, }, ]; - return fields.slice(0, 2).concat(linkFields, fields.slice(3)); + return fields.slice(0, 3).concat(linkFields, fields.slice(3)); }, _displayDialog: async function () { From 94bc3836e53dde6574a332c8732f517e12ea0e8c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 4 Feb 2022 22:28:52 +0100 Subject: [PATCH 244/275] remove ellipsis portal names leave it to css or scrolling on some dialogs --- src/code/dialogs/assignDialog.js | 8 +++----- src/code/dialogs/autodraws/tools.js | 8 ++------ src/code/dialogs/defensiveKeysDialog.js | 4 +--- src/code/dialogs/markerAddDialog.js | 4 +--- src/code/dialogs/markerChangeDialog.js | 4 +--- src/code/dialogs/sendTargetDialog.js | 8 ++------ src/code/dialogs/setCommentDialog.js | 6 +----- src/code/dialogs/stateDialog.js | 4 ++-- src/code/dialogs/wasabeeDlist.js | 2 +- 9 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/code/dialogs/assignDialog.js b/src/code/dialogs/assignDialog.js index b532d3941..0d4738cc6 100644 --- a/src/code/dialogs/assignDialog.js +++ b/src/code/dialogs/assignDialog.js @@ -60,9 +60,7 @@ const AssignDialog = WDialog.extend({ this._name = wX("ASSIGN LINK PROMPT", { portalName: PortalUI.displayName(portal), }); - divtitle.appendChild( - LinkUI.displayFormat(target, operation, this._smallScreen) - ); + divtitle.appendChild(LinkUI.displayFormat(target, operation)); const t = L.DomUtil.create("label", null, menu); t.textContent = wX("LINK ASSIGNMENT"); } @@ -73,7 +71,7 @@ const AssignDialog = WDialog.extend({ this._name = wX("ASSIGN MARKER PROMPT", { portalName: PortalUI.displayName(portal), }); - divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); + divtitle.appendChild(PortalUI.displayFormat(portal)); const t = L.DomUtil.create("label", null, menu); t.textContent = wX("MARKER ASSIGNMENT"); } @@ -84,7 +82,7 @@ const AssignDialog = WDialog.extend({ this._name = wX("ASSIGN OUTBOUND PROMPT", { portalName: PortalUI.displayName(portal), }); - divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); + divtitle.appendChild(PortalUI.displayFormat(portal)); const t = L.DomUtil.create("label", null, menu); t.textContent = wX("ANCHOR ASSIGNMENT"); } diff --git a/src/code/dialogs/autodraws/tools.js b/src/code/dialogs/autodraws/tools.js index 2ac80dbf9..d859d2dc9 100644 --- a/src/code/dialogs/autodraws/tools.js +++ b/src/code/dialogs/autodraws/tools.js @@ -100,9 +100,7 @@ export const AutoDraw = WDialog.extend({ button.textContent = wX("SET"); const display = L.DomUtil.create("span", "set-portal-display", container); if (this[thisKey]) { - display.appendChild( - PortalUI.displayFormat(this[thisKey], this._smallScreen) - ); + display.appendChild(PortalUI.displayFormat(this[thisKey])); } else { display.textContent = wX("NOT_SET"); } @@ -112,9 +110,7 @@ export const AutoDraw = WDialog.extend({ if (storageKey) localStorage[storageKey] = JSON.stringify(this[thisKey]); display.textContent = ""; - display.appendChild( - PortalUI.displayFormat(this[thisKey], this._smallScreen) - ); + display.appendChild(PortalUI.displayFormat(this[thisKey])); } else { display.textContent = wX("NOT_SET"); displayError(wX("PLEASE_SELECT_PORTAL")); diff --git a/src/code/dialogs/defensiveKeysDialog.js b/src/code/dialogs/defensiveKeysDialog.js index 4da4b6c3c..229a150e9 100644 --- a/src/code/dialogs/defensiveKeysDialog.js +++ b/src/code/dialogs/defensiveKeysDialog.js @@ -33,9 +33,7 @@ const DefensiveKeysDialog = WDialog.extend({ this._selectedPortal = PortalUI.getSelected(); if (this._selectedPortal) { this._portal.textContent = ""; - this._portal.appendChild( - PortalUI.displayFormat(this._selectedPortal, this._smallScreen) - ); + this._portal.appendChild(PortalUI.displayFormat(this._selectedPortal)); const mine = await getAgentPortalWasabeeDkeys( this._me.id, this._selectedPortal.id diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index b54426dca..38d2609b0 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -75,9 +75,7 @@ const MarkerAddDialog = WDialog.extend({ if (this._selectedPortal) { this._portal.textContent = ""; this._portal.textContent = ""; - this._portal.appendChild( - PortalUI.displayFormat(this._selectedPortal, this._smallScreen) - ); + this._portal.appendChild(PortalUI.displayFormat(this._selectedPortal)); this._zones.value = getSelectedOperation().determineZone( this._selectedPortal.latLng diff --git a/src/code/dialogs/markerChangeDialog.js b/src/code/dialogs/markerChangeDialog.js index dc4d3d4cb..7f0145183 100644 --- a/src/code/dialogs/markerChangeDialog.js +++ b/src/code/dialogs/markerChangeDialog.js @@ -29,9 +29,7 @@ const MarkerChangeDialog = WDialog.extend({ const portal = operation.getPortal(this.options.marker.portalId); const portalDisplay = L.DomUtil.create("div", "portal", content); - portalDisplay.appendChild( - PortalUI.displayFormat(portal, this._smallScreen) - ); + portalDisplay.appendChild(PortalUI.displayFormat(portal)); this._type = L.DomUtil.create("select", null, content); diff --git a/src/code/dialogs/sendTargetDialog.js b/src/code/dialogs/sendTargetDialog.js index 1138ac1f8..2ee751706 100644 --- a/src/code/dialogs/sendTargetDialog.js +++ b/src/code/dialogs/sendTargetDialog.js @@ -53,9 +53,7 @@ const SendTargetDialog = WDialog.extend({ if (this.options.target instanceof WasabeeMarker) { this._portal = operation.getPortal(this.options.target.portalId); this._targettype = this.options.target.type; - divtitle.appendChild( - PortalUI.displayFormat(this._portal, this._smallScreen) - ); + divtitle.appendChild(PortalUI.displayFormat(this._portal)); const t = L.DomUtil.create("label", null); t.textContent = wX("SEND TARGET AGENT"); menu.prepend(t); @@ -64,9 +62,7 @@ const SendTargetDialog = WDialog.extend({ if (this.options.target instanceof WasabeePortal) { this._portal = this.options.target; this._targettype = "anchor"; - divtitle.appendChild( - PortalUI.displayFormat(this._portal, this._smallScreen) - ); + divtitle.appendChild(PortalUI.displayFormat(this._portal)); const t = L.DomUtil.create("label", null); t.textContent = wX("SEND TARGET AGENT"); menu.prepend(t); diff --git a/src/code/dialogs/setCommentDialog.js b/src/code/dialogs/setCommentDialog.js index 1d893c0d7..4aef2e7fd 100644 --- a/src/code/dialogs/setCommentDialog.js +++ b/src/code/dialogs/setCommentDialog.js @@ -84,11 +84,7 @@ export const SetCommentDialog = WDialog.extend({ if (this.commentType == "link") { desc.textContent = wX("SET_LINK_COMMENT"); desc.appendChild( - LinkUI.displayFormat( - this.options.target, - this.options.operation, - this._smallScreen - ) + LinkUI.displayFormat(this.options.target, this.options.operation) ); if (this.options.target.comment) input.value = this.options.target.comment; diff --git a/src/code/dialogs/stateDialog.js b/src/code/dialogs/stateDialog.js index 767cbf59f..63b86352a 100644 --- a/src/code/dialogs/stateDialog.js +++ b/src/code/dialogs/stateDialog.js @@ -60,7 +60,7 @@ const StateDialog = WDialog.extend({ this._type = "Link"; this._name = wX("LINK STATE PROMPT", portal.name); divtitle.appendChild( - LinkUI.displayFormat(this.options.target, operation, this._smallScreen) + LinkUI.displayFormat(this.options.target, operation) ); const t = L.DomUtil.create("label", null); t.textContent = wX("LINK STATE"); @@ -71,7 +71,7 @@ const StateDialog = WDialog.extend({ const portal = operation.getPortal(this.options.target.portalId); this._type = "Marker"; this._name = wX("MARKER STATE PROMPT", portal.name); - divtitle.appendChild(PortalUI.displayFormat(portal, this._smallScreen)); + divtitle.appendChild(PortalUI.displayFormat(portal)); const t = L.DomUtil.create("label", null); t.textContent = wX("MARKER STATE"); menu.prepend(t); diff --git a/src/code/dialogs/wasabeeDlist.js b/src/code/dialogs/wasabeeDlist.js index fd5969cc0..f9b419acd 100644 --- a/src/code/dialogs/wasabeeDlist.js +++ b/src/code/dialogs/wasabeeDlist.js @@ -68,7 +68,7 @@ const WasabeeDList = WDialog.extend({ lat: n.Lat, lng: n.Lng, }); - cell.appendChild(PortalUI.displayFormat(p, this._smallScreen)); + cell.appendChild(PortalUI.displayFormat(p)); }, }, { From a19fd083d3c07874449d6a4b345d4138c3a0788a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 4 Feb 2022 22:52:15 +0100 Subject: [PATCH 245/275] new translations --- src/code/translations/Danish.json | 75 ++++++++++++++++++++-- src/code/translations/Filipino.json | 75 ++++++++++++++++++++-- src/code/translations/French.json | 75 ++++++++++++++++++++-- src/code/translations/German.json | 74 +++++++++++++++++++++- src/code/translations/Italian.json | 77 +++++++++++++++++++++-- src/code/translations/Portuguese.json | 91 +++++++++++++++++++++++---- src/code/translations/Russian.json | 77 +++++++++++++++++++++-- src/code/translations/Spanish.json | 87 ++++++++++++++++++++++--- 8 files changed, 584 insertions(+), 47 deletions(-) diff --git a/src/code/translations/Danish.json b/src/code/translations/Danish.json index faf3372fd..9f8ee5a8e 100644 --- a/src/code/translations/Danish.json +++ b/src/code/translations/Danish.json @@ -47,7 +47,16 @@ "AUTODRAWS": "Wasabee Indstillinger for automatisk tegning", "AUTODRAW_PORTALS_SET": "Portaler", "autodraw.common.draw_button": "Tegn", + "autodraw.fanfield.result": "Fanfield found {links} links and {fields} fields for {ap} AP", "autodraw.flipflop.result": "Flip flop: fundet {count} links", + "autodraw.homogeneous.missing_split": "Unable to find {count} splits, try less depth or a different region", + "autodraw.homogeneous.order": "Order", + "autodraw.homogeneous.portals_required": "{count} required", + "autodraw.madrid.auto_determined": "Auto-determined", + "autodraw.madrid.balanced": "Balanced", + "autodraw.madrid.result": "Madrid found {count} layers", + "autodraw.multimax.result": "Multimax found {count} layers", + "autodraw.multimax.result_both_side": "Multimax found {count1} and {count2} layers", "autodraw.onion.variant": "Valg", "autodraw.onion.variant.equilateral": "~Ligesidet", "autodraw.onion.variant.grow": "Lad det vokse", @@ -94,8 +103,65 @@ "DESCRIP_PLACEHOLD": "Beskrivelse (valgfri)", "DestroyPortalAlert": "Ødelæg/Skyd", "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.setcomment.portal_hardness": "Sværhedsgrad", + "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.title": "Set comment for {agentName}", + "dialog.auth.ott.button": "One Time Token Login", + "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", + "dialog.auth.ott.title": "One Time Token", + "dialog.blockers.clear_automark": "Clear Automark", + "dialog.clear_all.text": "Do you want to reset {opName}?", + "dialog.clear_all.title": "Clear: {opName}", + "dialog.clear_links.text": "Do you want to remove all links from {opName}?", + "dialog.clear_links.title": "Clear Links: {opName}", + "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", + "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.checklist.count_fields": "Count fields", + "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", + "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", + "dialog.checklist.count_fields.link_from_inside": "Found {count} links from covered portals", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", + "dialog.common.commands": "Commands", + "dialog.common.commands_short": "Cmds", + "dialog.common.name": "Name", + "dialog.common.off": "Off", + "dialog.common.on": "On", + "dialog.common.owner": "Owner", + "dialog.common.zone_all": "All", + "dialog.firebase.setup": "Visit {url} and press the button to authorize live updates. You will need to reload IITC afterward.", + "dialog.import.url": "Fill from URL", "dialog.import.success_message": "Import fuldført. Fandt {count} portaler og brugte {faked} forfalskede. Brug venligst swap-funktionen til at flytte forfalskede portaler til de rigtige portaler på samme sted. Zoom ind på 'Indlæser' portaler i tjeklisten kan tvinge dem til at indlæse.", + "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", + "dialog.leave_team.title": "Leave: {teamName}", + "dialog.link_list.length": "Length", + "dialog.link_list.level": "Min Lvl", + "dialog.online_agents.actions": "Actions", + "dialog.online_agents.last_seen": "Last Seen", + "dialog.online_agents.title": "Online Agents", + "dialog.op_settings.zones": "Zones", + "dialog.ops_list.background_disable": "Disable background", + "dialog.ops_list.background_enable": "Show in background", + "dialog.ops_list.download": "Download {opName}", + "dialog.ops_list.last_fetched": "Last fetched: {date}", + "dialog.ops_list.local_change": "Local has changed", + "dialog.ops_list.remote_change": "Remote has changed", + "dialog.ops_list.toggle_hide": "Toggle Show/Hide", + "dialog.ops_list.unhide_ops": "Unhide all OPs", + "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", + "dialog.remove_agent.title": "Remove: {agentName}", + "dialog.setcomment.portal_hardness": "Sværhedsgrad", + "dialog.team_list.load_wd_keys": "Load W-D Keys", + "dialog.team_list.share_wd_keys": "Share W-D Keys", + "dialog.team_manage.join_link": "Join Link", + "dialog.team_manage.join_link.create": "Create", + "dialog.team_manage.join_link.revoke": "Revoke", + "dialog.team_members.location": "Sharing Location", + "dialog.team_members.wd_keys": "Sharing W-D Keys", + "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.zone_color.title": "Zone Color", + "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", + "dialog.zones.color": "Color", + "dialog.zones.id": "ID", + "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplikere Operation", "END_PORT": "Slut Portal ", @@ -136,7 +202,6 @@ "IMPOSSIBLE": "Umulig", "INGNAME_GID": "Ingress navn eller GoogleID", "INPUT_DT_KEY_COUNT": "Input antal defensiv nøgler", - "INPUT_SQUAD_NAME": "Indtast et holdnavn", "INVALID REQUEST": "Ugyldig forespørgsel", "IOS NEED FAKE UA": "Du skal indstille en 'Custom UserAgent for Webviews' i IITC-Mobile-indstillingerne, ellers mislykkes login", "KEY_LIST2": "Nøgleliste til Operationen: {opName}", @@ -248,6 +313,8 @@ "PERM DENIED SHORT": "Tilladelse nægtet", "PERMS": "{opName} tilladelser", "PLEASE_SELECT_PORTAL": "Vælg venligst en portal", + "popup.anchor.keys": "Keys: {onHand} / {required}", + "popup.marker.state_button": "Set State", "PORT_FAKE": "", "PORTAL KEY LIST": "Nøgleliste for portal {portalName}", "PORTAL_COUNT": "{count} portaler", @@ -324,7 +391,6 @@ "SKIP_CONFIRM_NEVER": "Spørg altid", "SKIP_CONFIRM": "Spring bekræftelse over", "SOURCE_PORT": "Kildeportal", - "SQUAD": "hold", "STARBURST TITLE": "Starburst", "STARBURST_DRAW": "Tegn", "STARBURST": "Starburst", @@ -359,6 +425,8 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Klik på den første portal", "toolbar.quick_draw.tooltip.single_mode.next": "Klik på den næste portal", "toolbar.quick_draw.tooltip.portal_fail": "Portaldata ikke indlæst, prøv venligst igen", + "toolbar.wasabee.settings": "Settings", + "toolbox.teammates": "Teammates Online", "TRAWL SKIP TILES": "Trawl Skip fliser", "TRAWL TITLE": "Trawl baner", "TRAWL WARNING": "Dette vil indlæse flisedataene under alle tegnede links. Dette er en langsom proces.", @@ -372,7 +440,6 @@ "TYPE": "Type", "UNASSIGNED": "Ikke tildelt", "UNKNOWN": "Ukendt", - "UPDATE HOVER NOT CHANGED": "{opName} ikke ændret lokalt", "UPDATE HOVER": "OPDATER {opName} på serveren", "UPDATE PERM DENIED": "Du har ikke rettigheder til at opdatere", "UPDATE_CONFLICT_DESC": "OP er blevet ændret på serveren siden sidste synkronisering. Ønsker du at erstatte serverversionen med den nuværende?", diff --git a/src/code/translations/Filipino.json b/src/code/translations/Filipino.json index 98f1f37c9..578382999 100644 --- a/src/code/translations/Filipino.json +++ b/src/code/translations/Filipino.json @@ -47,7 +47,16 @@ "AUTODRAWS": "Wasabee Auto-draw Options", "AUTODRAW_PORTALS_SET": "Portals", "autodraw.common.draw_button": "Draw", + "autodraw.fanfield.result": "Fanfield found {links} links and {fields} fields for {ap} AP", "autodraw.flipflop.result": "Flip flop: found {count} links", + "autodraw.homogeneous.missing_split": "Unable to find {count} splits, try less depth or a different region", + "autodraw.homogeneous.order": "Order", + "autodraw.homogeneous.portals_required": "{count} required", + "autodraw.madrid.auto_determined": "Auto-determined", + "autodraw.madrid.balanced": "Balanced", + "autodraw.madrid.result": "Madrid found {count} layers", + "autodraw.multimax.result": "Multimax found {count} layers", + "autodraw.multimax.result_both_side": "Multimax found {count1} and {count2} layers", "autodraw.onion.variant": "Option", "autodraw.onion.variant.equilateral": "~Equilateral", "autodraw.onion.variant.grow": "Let it grow", @@ -94,8 +103,65 @@ "DESCRIP_PLACEHOLD": "Description (opsyonal)", "DestroyPortalAlert": "Sirain", "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.setcomment.portal_hardness": "Hardness", + "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.title": "Set comment for {agentName}", + "dialog.auth.ott.button": "One Time Token Login", + "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", + "dialog.auth.ott.title": "One Time Token", + "dialog.blockers.clear_automark": "Clear Automark", + "dialog.clear_all.text": "Do you want to reset {opName}?", + "dialog.clear_all.title": "Clear: {opName}", + "dialog.clear_links.text": "Do you want to remove all links from {opName}?", + "dialog.clear_links.title": "Clear Links: {opName}", + "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", + "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.checklist.count_fields": "Count fields", + "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", + "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", + "dialog.checklist.count_fields.link_from_inside": "Found {count} links from covered portals", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", + "dialog.common.commands": "Commands", + "dialog.common.commands_short": "Cmds", + "dialog.common.name": "Name", + "dialog.common.off": "Off", + "dialog.common.on": "On", + "dialog.common.owner": "Owner", + "dialog.common.zone_all": "All", + "dialog.firebase.setup": "Visit {url} and press the button to authorize live updates. You will need to reload IITC afterward.", + "dialog.import.url": "Fill from URL", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", + "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", + "dialog.leave_team.title": "Leave: {teamName}", + "dialog.link_list.length": "Length", + "dialog.link_list.level": "Min Lvl", + "dialog.online_agents.actions": "Actions", + "dialog.online_agents.last_seen": "Last Seen", + "dialog.online_agents.title": "Online Agents", + "dialog.op_settings.zones": "Zones", + "dialog.ops_list.background_disable": "Disable background", + "dialog.ops_list.background_enable": "Show in background", + "dialog.ops_list.download": "Download {opName}", + "dialog.ops_list.last_fetched": "Last fetched: {date}", + "dialog.ops_list.local_change": "Local has changed", + "dialog.ops_list.remote_change": "Remote has changed", + "dialog.ops_list.toggle_hide": "Toggle Show/Hide", + "dialog.ops_list.unhide_ops": "Unhide all OPs", + "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", + "dialog.remove_agent.title": "Remove: {agentName}", + "dialog.setcomment.portal_hardness": "Hardness", + "dialog.team_list.load_wd_keys": "Load W-D Keys", + "dialog.team_list.share_wd_keys": "Share W-D Keys", + "dialog.team_manage.join_link": "Join Link", + "dialog.team_manage.join_link.create": "Create", + "dialog.team_manage.join_link.revoke": "Revoke", + "dialog.team_members.location": "Sharing Location", + "dialog.team_members.wd_keys": "Sharing W-D Keys", + "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.zone_color.title": "Zone Color", + "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", + "dialog.zones.color": "Color", + "dialog.zones.id": "ID", + "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Kopyahin ang Operasyon", "END_PORT": "End Portal ", @@ -136,7 +202,6 @@ "IMPOSSIBLE": "Imposible", "INGNAME_GID": "Pangalan sa Ingress o GoogleID", "INPUT_DT_KEY_COUNT": "Ilagay ang Bilang ng Pangharang na Keys", - "INPUT_SQUAD_NAME": "Maglagay ng pangalan ng Squad", "INVALID REQUEST": "Hindi wastong Request", "IOS NEED FAKE UA": "Kailangang pumili ng 'Custom UserAgent for Webviews' sa IITC-Mobile settings para makapag-login ng maayos", "KEY_LIST2": "Litahan ng Keys para sa Operation: {opName}", @@ -248,6 +313,8 @@ "PERM DENIED SHORT": "Walang pahintulot", "PERMS": "{opName} permisyo", "PLEASE_SELECT_PORTAL": "Pumili ng portal", + "popup.anchor.keys": "Keys: {onHand} / {required}", + "popup.marker.state_button": "Set State", "PORT_FAKE": "", "PORTAL KEY LIST": "Listahan ng Key para sa Portal {portalName}", "PORTAL_COUNT": "{count} portals", @@ -324,7 +391,6 @@ "SKIP_CONFIRM_NEVER": "Always ask", "SKIP_CONFIRM": "Skip confirmation", "SOURCE_PORT": "Source Portal", - "SQUAD": "Squad", "STARBURST TITLE": "Starburst ", "STARBURST_DRAW": "Iguhit", "STARBURST": "Starburst", @@ -359,6 +425,8 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Click first portal", "toolbar.quick_draw.tooltip.single_mode.next": "Click next portal", "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", + "toolbar.wasabee.settings": "Settings", + "toolbox.teammates": "Teammates Online", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", @@ -372,7 +440,6 @@ "TYPE": "Uri", "UNASSIGNED": "Hindi Nakatalaga", "UNKNOWN": "Nakatago", - "UPDATE HOVER NOT CHANGED": "{opName} hindi naipalit locally", "UPDATE HOVER": "UPDATE {opName} sa server", "UPDATE PERM DENIED": "Walang pahintulot para sa pag-update", "UPDATE_CONFLICT_DESC": "The OP has been modified on server since last sync. Do you want to replace the server version by the current one?", diff --git a/src/code/translations/French.json b/src/code/translations/French.json index a27450f7a..914d5b775 100644 --- a/src/code/translations/French.json +++ b/src/code/translations/French.json @@ -47,7 +47,16 @@ "AUTODRAWS": "Choix d'Auto-draw", "AUTODRAW_PORTALS_SET": "Portails", "autodraw.common.draw_button": "Tracer", + "autodraw.fanfield.result": "Fanfield a trouvé {links} liens et {fields} fields pour {ap} AP", "autodraw.flipflop.result": "Flip flop: {count} liens trouvés", + "autodraw.homogeneous.missing_split": "Il manque {count} portails pour une configuration complète", + "autodraw.homogeneous.order": "Order", + "autodraw.homogeneous.portals_required": "{count} requis", + "autodraw.madrid.auto_determined": "Auto-déterminée", + "autodraw.madrid.balanced": "Équilibré", + "autodraw.madrid.result": "Madrid a trouvé {count} couches", + "autodraw.multimax.result": "Multimax a trouvé {count} couches", + "autodraw.multimax.result_both_side": "Multimax a trouvé {count1} et {count2} couches", "autodraw.onion.variant": "Variante", "autodraw.onion.variant.equilateral": "~Équilatéral", "autodraw.onion.variant.grow": "Un plus grand", @@ -94,8 +103,65 @@ "DESCRIP_PLACEHOLD": "Description (optionnelle)", "DestroyPortalAlert": "Casse", "dialog.about.download_mobile_app": "

Application Wasabee :

", - "dialog.setcomment.portal_hardness": "Difficulté", + "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.title": "Définir le commentaire de {agentName}", + "dialog.auth.ott.button": "Connexion à jeton unique", + "dialog.auth.ott.text": "Récupérez un jeton (One time Token) depuis le server wasabee, puis collez-le ici", + "dialog.auth.ott.title": "Connexion à jeton unique", + "dialog.blockers.clear_automark": "Supprimer les Auto-Mark", + "dialog.clear_all.text": "Voulez-vous supprimer les liens et marqueurs de {opName} ?", + "dialog.clear_all.title": "Réinitialisation de {opName}", + "dialog.clear_links.text": "Voulez-vous supprimer tous les liens de {opName} ?", + "dialog.clear_links.title": "Effacer les liens : {opName}", + "dialog.clear_markers.text": "Voulez-vous supprimer tous les marqueurs de {opName} ?", + "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.checklist.count_fields": "Nombre de fields", + "dialog.checklist.count_fields.no_empty": "{fieldCount} fields trouvés et aucun champ vide", + "dialog.checklist.count_fields.with_empty": "{fieldCount} fields trouvés et {emptyCount} champ(s) vide(s) sur {linkCount} lien(s)", + "dialog.checklist.count_fields.link_from_inside": "{count} liens trouvés depuis des portails sous fields", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " à {order} par le lien ", + "dialog.common.commands": "Commandes", + "dialog.common.commands_short": "Cmds", + "dialog.common.name": "Nom", + "dialog.common.off": "Off", + "dialog.common.on": "On", + "dialog.common.owner": "Propriétaire", + "dialog.common.zone_all": "Toutes les zones", + "dialog.firebase.setup": "Visitez {url} et cliquez sur le bouton pour autoriser les mises à jour en direct. Vous devrez recharger l'IITC ensuite.", + "dialog.import.url": "Charger l’URL", "dialog.import.success_message": "Importation terminée. {count} portails trouvés et {faked} faux portails utilisés. Veuillez utiliser la fonction d'échange pour déplacer les faux portails vers les vrais portails au même endroit. Faire un zoom avant sur les portails 'Chargement' dans la liste de contrôle peut les forcer à charger.", + "dialog.leave_team.text": "Si vous quittez {teamName} vous ne pouvez pas rejoindre à moins que le propriétaire vous rajoute.", + "dialog.leave_team.title": "Quitter : {teamName}", + "dialog.link_list.length": "Longueur", + "dialog.link_list.level": "Niv Min", + "dialog.online_agents.actions": "Action", + "dialog.online_agents.last_seen": "Dernière activité", + "dialog.online_agents.title": "Agents en ligne", + "dialog.op_settings.zones": "Zones", + "dialog.ops_list.background_disable": "Cacher en arrière-plan", + "dialog.ops_list.background_enable": "Afficher en arrière-plan", + "dialog.ops_list.download": "Télécharger {opName}", + "dialog.ops_list.last_fetched": "Dernière récupération : {date}", + "dialog.ops_list.local_change": "La version locale a été modifiée", + "dialog.ops_list.remote_change": "Modifications sur le serveur", + "dialog.ops_list.toggle_hide": "Afficher/Masquer", + "dialog.ops_list.unhide_ops": "Démasquer tout", + "dialog.remove_agent.text": "Voulez-vous retirer {agentName} de {teamName}?", + "dialog.remove_agent.title": "Retirer : {agentName}", + "dialog.setcomment.portal_hardness": "Difficulté", + "dialog.team_list.load_wd_keys": "Charger les clés W-D", + "dialog.team_list.share_wd_keys": "Partager les clés W-D", + "dialog.team_manage.join_link": "Lien pour rejoindre", + "dialog.team_manage.join_link.create": "Créer", + "dialog.team_manage.join_link.revoke": "Révoquer", + "dialog.team_members.location": "Partage de position", + "dialog.team_members.wd_keys": "Partage de clés W-D", + "dialog.team_message": "Message d'équipe: « {message} » de {sender}", + "dialog.zone_color.title": "Colorier la zone", + "dialog.zone_color.text": "Colorier tous les liens dans la zone {zoneName}", + "dialog.zones.color": "Couleur ", + "dialog.zones.id": "ID", + "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Format DrawTools", "DUPE_OP": "Dupliquer l'opération", "END_PORT": "Portail de fin", @@ -136,7 +202,6 @@ "IMPOSSIBLE": "Impossible", "INGNAME_GID": "Pseudo Ingress ou Identifiants Google", "INPUT_DT_KEY_COUNT": "Entrer le nombre de clés défensive", - "INPUT_SQUAD_NAME": "Entrer le nom de l'équipe", "INVALID REQUEST": "Requête invalide", "IOS NEED FAKE UA": "Vous devez définir un 'Custom UserAgent for Webviews' dans les options de IITC-Mobile pour que la connexion à Wasabee fonctionne", "KEY_LIST2": "Liste des clées pour l'opération : {opName}", @@ -248,6 +313,8 @@ "PERM DENIED SHORT": "Permission refusée", "PERMS": "Permissions de {opName}", "PLEASE_SELECT_PORTAL": "Selectionner un portail", + "popup.anchor.keys": "Clés : {onHand} / {required}", + "popup.marker.state_button": "Définir l'état", "PORT_FAKE": "", "PORTAL KEY LIST": "Clés du portail {portalName}", "PORTAL_COUNT": "{count} portails", @@ -324,7 +391,6 @@ "SKIP_CONFIRM_NEVER": "Tout", "SKIP_CONFIRM": "Demander confirmation pour", "SOURCE_PORT": "Portail source", - "SQUAD": "Commentaire", "STARBURST TITLE": "Starburst", "STARBURST_DRAW": "Tracer", "STARBURST": "Starburst", @@ -359,6 +425,8 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Sélectionnez le premier portail", "toolbar.quick_draw.tooltip.single_mode.next": "Sélectionnez le portail suivant", "toolbar.quick_draw.tooltip.portal_fail": "Données de portail incomplètes, réessayez", + "toolbar.wasabee.settings": "Options", + "toolbox.teammates": "Coéquipiers en ligne", "TRAWL SKIP TILES": "Fouille: sauter des tuiles", "TRAWL TITLE": "Fouille des bloquants", "TRAWL WARNING": "Ceci va charger les tuiles de données sous les liens dessinés. C'est un processus lent.", @@ -372,7 +440,6 @@ "TYPE": "Type", "UNASSIGNED": "Non assigné", "UNKNOWN": "Inconnu", - "UPDATE HOVER NOT CHANGED": "{opName} n'a pas changé localement", "UPDATE HOVER": "Mettre à jour {opName} sur le serveur", "UPDATE PERM DENIED": "Vous n'avez pas la permission de mettre à jour", "UPDATE_CONFLICT_DESC": "L'opération a été modifié sur le serveur depuis la dernière synchronisation. Voulez-vous écraser la version du serveur par la votre ?", diff --git a/src/code/translations/German.json b/src/code/translations/German.json index a79bb62b7..3b425a2c7 100644 --- a/src/code/translations/German.json +++ b/src/code/translations/German.json @@ -47,7 +47,16 @@ "AUTODRAWS": "Wasabee Auto-draw Optionen", "AUTODRAW_PORTALS_SET": "Portale", "autodraw.common.draw_button": "Draw", + "autodraw.fanfield.result": "Fanfield found {links} links and {fields} fields for {ap} AP", "autodraw.flipflop.result": "Flip flop: hat {count} Links gefunden", + "autodraw.homogeneous.missing_split": "Unable to find {count} splits, try less depth or a different region", + "autodraw.homogeneous.order": "Order", + "autodraw.homogeneous.portals_required": "{count} required", + "autodraw.madrid.auto_determined": "Auto-determined", + "autodraw.madrid.balanced": "Balanced", + "autodraw.madrid.result": "Madrid found {count} layers", + "autodraw.multimax.result": "Multimax found {count} layers", + "autodraw.multimax.result_both_side": "Multimax found {count1} and {count2} layers", "autodraw.onion.variant": "Option", "autodraw.onion.variant.equilateral": "~Gleichseitig", "autodraw.onion.variant.grow": "Los!", @@ -94,8 +103,65 @@ "DESCRIP_PLACEHOLD": "Beschreibung (optional)", "DestroyPortalAlert": "Zerstören", "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.setcomment.portal_hardness": "Schwierigkeitsgrad", + "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.title": "Set comment for {agentName}", + "dialog.auth.ott.button": "One Time Token Login", + "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", + "dialog.auth.ott.title": "One Time Token", + "dialog.blockers.clear_automark": "Clear Automark", + "dialog.clear_all.text": "Do you want to reset {opName}?", + "dialog.clear_all.title": "Clear: {opName}", + "dialog.clear_links.text": "Do you want to remove all links from {opName}?", + "dialog.clear_links.title": "Clear Links: {opName}", + "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", + "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.checklist.count_fields": "Count fields", + "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", + "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", + "dialog.checklist.count_fields.link_from_inside": "Found {count} links from covered portals", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", + "dialog.common.commands": "Commands", + "dialog.common.commands_short": "Cmds", + "dialog.common.name": "Name", + "dialog.common.off": "Off", + "dialog.common.on": "On", + "dialog.common.owner": "Owner", + "dialog.common.zone_all": "All", + "dialog.firebase.setup": "Visit {url} and press the button to authorize live updates. You will need to reload IITC afterward.", + "dialog.import.url": "Fill from URL", "dialog.import.success_message": "Import abgeschlossen. {count} Portale gefunden und {faked} gefälscht verwendet. Bitte nutze die Swap-Funktion, um gefälschte Portale zu den echten Portalen am gleichen Ort zu bewegen. Das Einzoomen der 'Laden'-Portale in der Checkliste kann sie zum Laden zwingen.", + "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", + "dialog.leave_team.title": "Leave: {teamName}", + "dialog.link_list.length": "Length", + "dialog.link_list.level": "Min Lvl", + "dialog.online_agents.actions": "Actions", + "dialog.online_agents.last_seen": "Last Seen", + "dialog.online_agents.title": "Online Agents", + "dialog.op_settings.zones": "Zones", + "dialog.ops_list.background_disable": "Disable background", + "dialog.ops_list.background_enable": "Show in background", + "dialog.ops_list.download": "Download {opName}", + "dialog.ops_list.last_fetched": "Last fetched: {date}", + "dialog.ops_list.local_change": "Local has changed", + "dialog.ops_list.remote_change": "Remote has changed", + "dialog.ops_list.toggle_hide": "Toggle Show/Hide", + "dialog.ops_list.unhide_ops": "Unhide all OPs", + "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", + "dialog.remove_agent.title": "Remove: {agentName}", + "dialog.setcomment.portal_hardness": "Schwierigkeitsgrad", + "dialog.team_list.load_wd_keys": "Load W-D Keys", + "dialog.team_list.share_wd_keys": "Share W-D Keys", + "dialog.team_manage.join_link": "Join Link", + "dialog.team_manage.join_link.create": "Create", + "dialog.team_manage.join_link.revoke": "Revoke", + "dialog.team_members.location": "Sharing Location", + "dialog.team_members.wd_keys": "Sharing W-D Keys", + "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.zone_color.title": "Zone Color", + "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", + "dialog.zones.color": "Color", + "dialog.zones.id": "ID", + "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Dupliziere Operation", "END_PORT": "Endportal", @@ -136,7 +202,6 @@ "IMPOSSIBLE": "Unmöglich", "INGNAME_GID": "Ingress name oder GoogleID", "INPUT_DT_KEY_COUNT": "Eingabe defensiver Schlüssel", - "INPUT_SQUAD_NAME": "Name des Kaders", "INVALID REQUEST": "Ungültige Anfrage", "IOS NEED FAKE UA": "Du musst 'Custom UserAgent for Webviews' in den IITC-Mobile Einstellungen aktivieren der Login wird fehlgeschlagen", "KEY_LIST2": "Schlüsselliste: {opName}", @@ -248,6 +313,8 @@ "PERM DENIED SHORT": "Keine Berechtigung", "PERMS": "{opName} permissions", "PLEASE_SELECT_PORTAL": "Bitte wähle ein Portal", + "popup.anchor.keys": "Keys: {onHand} / {required}", + "popup.marker.state_button": "Set State", "PORT_FAKE": "", "PORTAL KEY LIST": "Key list for portal {portalName}", "PORTAL_COUNT": "{count} portals", @@ -324,7 +391,6 @@ "SKIP_CONFIRM_NEVER": "Always ask", "SKIP_CONFIRM": "Skip confirmation", "SOURCE_PORT": "Source Portal", - "SQUAD": "Kader", "STARBURST TITLE": "Starburst ", "STARBURST_DRAW": "Draw", "STARBURST": "Starburst", @@ -359,6 +425,8 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Click first portal", "toolbar.quick_draw.tooltip.single_mode.next": "Click next portal", "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", + "toolbar.wasabee.settings": "Settings", + "toolbox.teammates": "Teammates Online", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", diff --git a/src/code/translations/Italian.json b/src/code/translations/Italian.json index a2fd40842..4ac7eb7ef 100644 --- a/src/code/translations/Italian.json +++ b/src/code/translations/Italian.json @@ -47,7 +47,16 @@ "AUTODRAWS": "Opzioni Wasabee Auto-draw", "AUTODRAW_PORTALS_SET": "Portali", "autodraw.common.draw_button": "Disegna", + "autodraw.fanfield.result": "Fanfield ha trovato {links} link e {fields} field per {ap} AP", "autodraw.flipflop.result": "Flip flop: trovati {count} link", + "autodraw.homogeneous.missing_split": "Impossibile trovare {count} suddivisioni, prova meno profondità o una regione diversa", + "autodraw.homogeneous.order": "Ordina", + "autodraw.homogeneous.portals_required": "{count} richiesti", + "autodraw.madrid.auto_determined": "Auto-determinato", + "autodraw.madrid.balanced": "Bilanciato", + "autodraw.madrid.result": "Madrid ha trovato {count} strati", + "autodraw.multimax.result": "Multimax ha trovato {count} strati", + "autodraw.multimax.result_both_side": "Multimax ha trovato {count1} e {count2} strati", "autodraw.onion.variant": "Alternativo", "autodraw.onion.variant.equilateral": "~Equilatero", "autodraw.onion.variant.grow": "Lascia che cresca", @@ -93,9 +102,66 @@ "DELETE_OP": "Eliminare {opName}", "DESCRIP_PLACEHOLD": "Descrizione (facoltativo)", "DestroyPortalAlert": "Distruggere", - "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.setcomment.portal_hardness": "Durezza", + "dialog.about.download_mobile_app": "

App Wasabee:

", + "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.title": "Imposta commento per {agentName}", + "dialog.auth.ott.button": "Login con One Time Token", + "dialog.auth.ott.text": "Ottieni un token dal Server Wasabee, quindi incollalo qui", + "dialog.auth.ott.title": "One Time Token", + "dialog.blockers.clear_automark": "Pulisci Automark", + "dialog.clear_all.text": "Vuoi resettare {opName}?", + "dialog.clear_all.title": "Pulisci: {opName}", + "dialog.clear_links.text": "Vuoi rimuovere tutti i link da {opName}?", + "dialog.clear_links.title": "Pulisci link: {opName}", + "dialog.clear_markers.text": "Vuoi rimuovere tutti i marker da {opName}?", + "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.checklist.count_fields": "Conta field", + "dialog.checklist.count_fields.no_empty": "Trovati {fieldCount} field e nessun field vuoto", + "dialog.checklist.count_fields.with_empty": "Trovati {fieldCount} field e {emptyCount} field vuoti su {linkCount} link", + "dialog.checklist.count_fields.link_from_inside": "Trovati {count} link da portali coperti", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " a {order} tramite link ", + "dialog.common.commands": "Comandi", + "dialog.common.commands_short": "Cmd", + "dialog.common.name": "Nome", + "dialog.common.off": "Off", + "dialog.common.on": "On", + "dialog.common.owner": "Proprietario", + "dialog.common.zone_all": "Tutto", + "dialog.firebase.setup": "Visita {url} e premi il pulsante per autorizzare gli aggiornamenti live. Dovrai ricaricare IITC.", + "dialog.import.url": "Importa da URL", "dialog.import.success_message": "Importazione completata. Trovati {count} portali e usati {faked} finti. Si prega di utilizzare la funzione di scambio per spostare i portali finti sui portali reali alla stessa posizione. Zoomando sui portali 'Caricamento' nella checklist potrebbe forzarne il caricamento.", + "dialog.leave_team.text": "Se lasci {teamName} non potrai ricollegarti a meno che il proprietario non ti aggiunga nuovamente.", + "dialog.leave_team.title": "Lascia: {teamName}", + "dialog.link_list.length": "Lunghezza", + "dialog.link_list.level": "Livello minimo", + "dialog.online_agents.actions": "Azioni", + "dialog.online_agents.last_seen": "Ultimo accesso", + "dialog.online_agents.title": "Agenti Online", + "dialog.op_settings.zones": "Zone", + "dialog.ops_list.background_disable": "Disabilita background", + "dialog.ops_list.background_enable": "Mostra in background", + "dialog.ops_list.download": "Scarica {opName}", + "dialog.ops_list.last_fetched": "Ultimo scarico: {date}", + "dialog.ops_list.local_change": "Locale modificato", + "dialog.ops_list.remote_change": "Remoto modificato", + "dialog.ops_list.toggle_hide": "Toggle Show/Hide", + "dialog.ops_list.unhide_ops": "Unhide all OPs", + "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", + "dialog.remove_agent.title": "Remove: {agentName}", + "dialog.setcomment.portal_hardness": "Durezza", + "dialog.team_list.load_wd_keys": "Load W-D Keys", + "dialog.team_list.share_wd_keys": "Share W-D Keys", + "dialog.team_manage.join_link": "Join Link", + "dialog.team_manage.join_link.create": "Create", + "dialog.team_manage.join_link.revoke": "Revoke", + "dialog.team_members.location": "Sharing Location", + "dialog.team_members.wd_keys": "Sharing W-D Keys", + "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.zone_color.title": "Zone Color", + "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", + "dialog.zones.color": "Color", + "dialog.zones.id": "ID", + "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplica Operazione", "END_PORT": "Portale di fine ", @@ -136,7 +202,6 @@ "IMPOSSIBLE": "Impossibile", "INGNAME_GID": "Nome Ingress o GoogleID", "INPUT_DT_KEY_COUNT": "Inserisci numero Chiavi difensive", - "INPUT_SQUAD_NAME": "Inserisci un nome per la Squadra", "INVALID REQUEST": "Richiesta non valida", "IOS NEED FAKE UA": "Devi impostare un 'Custom UserAgent for Webviews' nelle impostazioni di IITC-Mobile o il login fallirà", "KEY_LIST2": "Lista Chiavi per Operazione: {opName}", @@ -248,6 +313,8 @@ "PERM DENIED SHORT": "Accesso negato", "PERMS": "{opName} permessi", "PLEASE_SELECT_PORTAL": "Seleziona un portale", + "popup.anchor.keys": "Keys: {onHand} / {required}", + "popup.marker.state_button": "Set State", "PORT_FAKE": "", "PORTAL KEY LIST": "Lista Chiavi per Portale: {portalName}", "PORTAL_COUNT": "{count} Portali", @@ -324,7 +391,6 @@ "SKIP_CONFIRM_NEVER": "Chiedi sempre", "SKIP_CONFIRM": "Salta conferma", "SOURCE_PORT": "Portale di Origine", - "SQUAD": "Squadra", "STARBURST TITLE": "Starburst ", "STARBURST_DRAW": "Disegna", "STARBURST": "Starburst", @@ -359,6 +425,8 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Clicca il primo portale", "toolbar.quick_draw.tooltip.single_mode.next": "Clicca il portale successivo", "toolbar.quick_draw.tooltip.portal_fail": "Dati portale non caricati, riprova", + "toolbar.wasabee.settings": "Settings", + "toolbox.teammates": "Teammates Online", "TRAWL SKIP TILES": "Salta tile durante controllo", "TRAWL TITLE": "Controllo corridoi", "TRAWL WARNING": "Verranno caricati i dati delle tile sotto i link disegnati. Sarà un processo lento.", @@ -372,7 +440,6 @@ "TYPE": "Tipo", "UNASSIGNED": "Non Assegnato", "UNKNOWN": "Sconosciuto", - "UPDATE HOVER NOT CHANGED": "{opName} non modificato localmente", "UPDATE HOVER": "AGGIORNA {opName} sul server", "UPDATE PERM DENIED": "Non hai il permesso di aggiornare", "UPDATE_CONFLICT_DESC": "L'OP è stata modificata sul server dopo la tua ultima sincronizzazione. Vuoi sostituire la versione sul server con la attuale?", diff --git a/src/code/translations/Portuguese.json b/src/code/translations/Portuguese.json index e429f5efd..f2f1e3543 100644 --- a/src/code/translations/Portuguese.json +++ b/src/code/translations/Portuguese.json @@ -4,13 +4,13 @@ "ADD LINK TITLE": "Adicionar Links", "ADD MARKER TITLE": "Adicionar Marcadores", "ADD_AGENT": "Adicionar Agente: ", - "ADD_BL": "Adicionar links traseiros: ", - "ADD_BULK": "Adicionar em massa", + "ADD_BL": "Adicionar links para trás: ", + "ADD_BULK": "Adição em massa ", "ADD_BUTTON_LINKS": "Adicionar todos os links de uma vez.", "ADD_LINKS": "Adicionar Links", "ADD_MARKER": "+ Marcador", "ADD_NEW_OP": "Adicionar Nova Op", - "ADD_SUCC_INSTR": "Adicionar agente, bem sucedido", + "ADD_SUCC_INSTR": "Agente adicionado com sucesso", "ADD_ZONE": "Adicionar zona", "ADD": "Adicionar", "ADD1": "Adicionar primeiro link", @@ -47,7 +47,16 @@ "AUTODRAWS": "Wasabee Auto-draw Opções", "AUTODRAW_PORTALS_SET": "Portais", "autodraw.common.draw_button": "Desenhar", + "autodraw.fanfield.result": "Fanfield encontrado {links} links e {fields} campos para {ap} AP", "autodraw.flipflop.result": "Flip flop: {count} links encontrados", + "autodraw.homogeneous.missing_split": "Não foi possível encontrar {count} divisões, tente menos profundidade ou uma região diferente", + "autodraw.homogeneous.order": "Pedido", + "autodraw.homogeneous.portals_required": "{count} necessário", + "autodraw.madrid.auto_determined": "Auto-determinado", + "autodraw.madrid.balanced": "Equilibrado", + "autodraw.madrid.result": "Madri encontrou {count} camadas", + "autodraw.multimax.result": "Multimax encontrou {count} camadas", + "autodraw.multimax.result_both_side": "Multimax encontrou {count1} e {count2} camadas", "autodraw.onion.variant": "Opção", "autodraw.onion.variant.equilateral": "~Equalizador", "autodraw.onion.variant.grow": "Deixe crescer", @@ -86,16 +95,73 @@ "DEFAULT OP NAME": "Nova Op: ${value}", "DELETE ANCHOR PROMPT": "Desejas excluir esta âncora e todos os links associados: ", "DELETE ANCHOR TITLE": "Apagar Âncora", - "DELETE MARKER PROMPT": "Desejas apagar esta âncora: ", + "DELETE MARKER PROMPT": "Você deseja excluir este marcador: ", "DELETE MARKER TITLE": "Apagar Marcador", "DELETE_ANCHOR": "Apagar", "DELETE_LINK": "Apagar", "DELETE_OP": "Apagar ${value}", "DESCRIP_PLACEHOLD": "Descrição (opcional)", "DestroyPortalAlert": "Destroir", - "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.setcomment.portal_hardness": "Difículdade", + "dialog.about.download_mobile_app": "

Aplicativo Wasabee:

", + "dialog.agent_comment.text": "Comentario: ", + "dialog.agent_comment.title": "Definir comentário para {agentName}", + "dialog.auth.ott.button": "Login único para o Token", + "dialog.auth.ott.text": "Obtenha um token do servidor Wasabee, e então cole-o aqui", + "dialog.auth.ott.title": "Usar Token Único", + "dialog.blockers.clear_automark": "Limpar Automark", + "dialog.clear_all.text": "Você quer resetar o {opName}?", + "dialog.clear_all.title": "Limpar: {opName}", + "dialog.clear_links.text": "Você quer remover todos os links de {opName}?", + "dialog.clear_links.title": "Limpar Links: {opName}", + "dialog.clear_markers.text": "Deseja remover todos os marcadores de {opName}?", + "dialog.clear_markers.title": "Limpar Links: {opName}", + "dialog.checklist.count_fields": "Contar campos", + "dialog.checklist.count_fields.no_empty": "Encontrados {fieldCount} campos e sem campo vazio", + "dialog.checklist.count_fields.with_empty": "Encontrados {fieldCount} campos e {emptyCount} campo(s) vazio(s) no link {linkCount}", + "dialog.checklist.count_fields.link_from_inside": "Encontrados {count} links dos portais cobertos", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " em {order} por link ", + "dialog.common.commands": "Comandos", + "dialog.common.commands_short": "Cmds", + "dialog.common.name": "Nome", + "dialog.common.off": "Desligar", + "dialog.common.on": "Ligar", + "dialog.common.owner": "Dono", + "dialog.common.zone_all": "Todos", + "dialog.firebase.setup": "Visite {url} e pressione o botão para autorizar atualizações ao vivo. Você precisará recarregar o IITC depois.", + "dialog.import.url": "Preencher do URL", "dialog.import.success_message": "Importação completa. Encontrados {count} portais e usados {faked} falsificados. Por favor, use o recurso de troca para mover portais falsos para os portais reais no mesmo local. Ampliar os portais de 'Carregamento' na lista de verificação pode forçá-los a carregar.", + "dialog.leave_team.text": "Se você sair do {teamName}, você não pode entrar novamente a menos que o dono adicione você novamente.", + "dialog.leave_team.title": "Deixar: {teamName}", + "dialog.link_list.length": "Comprimento", + "dialog.link_list.level": "Min Lvl", + "dialog.online_agents.actions": "Ações", + "dialog.online_agents.last_seen": "Visto pela última vez", + "dialog.online_agents.title": "Agentes Online", + "dialog.op_settings.zones": "Zonas", + "dialog.ops_list.background_disable": "Desat. dados seg. plano", + "dialog.ops_list.background_enable": "Mostrar plano de fundo", + "dialog.ops_list.download": "Descarregar {opName}", + "dialog.ops_list.last_fetched": "Última pesquisa: {date}", + "dialog.ops_list.local_change": "Local foi alterado", + "dialog.ops_list.remote_change": "Controle remoto foi alterado", + "dialog.ops_list.toggle_hide": "Alternar Mostrar/Ocultar", + "dialog.ops_list.unhide_ops": "Exibir todas as OPs", + "dialog.remove_agent.text": "Você deseja remover {agentName} de {teamName}?", + "dialog.remove_agent.title": "Remover: {agentName}", + "dialog.setcomment.portal_hardness": "Difículdade", + "dialog.team_list.load_wd_keys": "Carregar chaves W-D", + "dialog.team_list.share_wd_keys": "Partilhar chaves W-D", + "dialog.team_manage.join_link": "Link de entrada", + "dialog.team_manage.join_link.create": "Criar", + "dialog.team_manage.join_link.revoke": "Revogar", + "dialog.team_members.location": "A partilhar a localização", + "dialog.team_members.wd_keys": "Partilhar chaves W-D", + "dialog.team_message": "Anúncio de equipa: “{message}” de {sender}", + "dialog.zone_color.title": "Cor da zona", + "dialog.zone_color.text": "Definir a cor de todos os links na zona {zoneName}", + "dialog.zones.color": "Cor", + "dialog.zones.id": "ID", + "dialog.zones.title": "Zonas", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplicar Operação", "END_PORT": "Portal final ", @@ -136,7 +202,6 @@ "IMPOSSIBLE": "Impossível", "INGNAME_GID": "Nome de entrada ou GoogleID", "INPUT_DT_KEY_COUNT": "Contagem de chaves defensivas de entrada", - "INPUT_SQUAD_NAME": "Insere um nome de esquadrão", "INVALID REQUEST": "Pedido inválido", "IOS NEED FAKE UA": "Deves definir um 'Agente de usuário personalizado para visualizações da Web' nas configurações do IITC-Mobile ou o login falhará", "KEY_LIST2": "Lista de chaves para operação: ${value}", @@ -235,7 +300,7 @@ "OP_SETTINGS_BUTTON": "Op ⚙", "OP_SETTINGS_TITLE": "Configurações de operação", "OPEN_REQUEST": "[pedido aberto]", - "OPER_COLOR": "Cor de operação: ", + "OPER_COLOR": "Cor da operação: ", "OPER_NAME": "Nome da Operação: ", "OPERATIONS": "Operações", "OPS BUTTON TITLE": "Operações", @@ -248,6 +313,8 @@ "PERM DENIED SHORT": "Permissão negada", "PERMS": "${value} permissões", "PLEASE_SELECT_PORTAL": "Seleciona um portal", + "popup.anchor.keys": "Chaves: {onHand} / {required}", + "popup.marker.state_button": "Definir estado", "PORT_FAKE": "", "PORTAL KEY LIST": "Lista de chaves para portal ${value}", "PORTAL_COUNT": "${value} portais", @@ -270,14 +337,14 @@ "REM_LOC_CP": "Remover cópia local de ${value}", "REMOVE_TEAM_CONFIRM_LABEL": "Você deseja remover permanentemente ${value} do servidor Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipe ${value}", - "REMOVE_TEAM": "Remover Equipe: ", + "REMOVE_TEAM": "Remover Equipa: ", "REMOVE": "Remover", "RENAME_TEAM": "Renomear Equipe: ", "RENAME": "Renomear", "REQUIRED": "Requerido", "RESET": "Redefinir", "REVERSE": "Inverter", - "ROCKS_COM": "enl.rocks comunidade: ", + "ROCKS_COM": "comunidade enl.rocks: ", "ROLE": "Função", "SAVELINKS TITLE": "Salvar Links", "SAVELINKS_DRAW": "Salvar Links", @@ -324,7 +391,6 @@ "SKIP_CONFIRM_NEVER": "Perguntar sempre", "SKIP_CONFIRM": "Confirmação de salto", "SOURCE_PORT": "Portal Fonte", - "SQUAD": "Esquadrão", "STARBURST TITLE": "Starburst", "STARBURST_DRAW": "Desenhar", "STARBURST": "Starburst", @@ -359,6 +425,8 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Clique no primeiro portal", "toolbar.quick_draw.tooltip.single_mode.next": "Clique no próximo portal", "toolbar.quick_draw.tooltip.portal_fail": "Dados do portal não carregados, por favor, tente novamente", + "toolbar.wasabee.settings": "Configurações", + "toolbox.teammates": "Companheiros Online", "TRAWL SKIP TILES": "Pular blocos para armadilha", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "Isto carregará os dados do bloco em todos os links desenhados. Este é um processo lento.", @@ -372,7 +440,6 @@ "TYPE": "Tipo", "UNASSIGNED": "Não atribuído", "UNKNOWN": "Desconhecido", - "UPDATE HOVER NOT CHANGED": "${value} não mudou localmente", "UPDATE HOVER": "UPDATE ${value} no servidor", "UPDATE PERM DENIED": "Você não possui permissão para editar", "UPDATE_CONFLICT_DESC": "A OP foi modificada no servidor desde a última sincronização. Queres substituir a versão do servidor pela atual?", diff --git a/src/code/translations/Russian.json b/src/code/translations/Russian.json index e1ef44bcf..898090992 100644 --- a/src/code/translations/Russian.json +++ b/src/code/translations/Russian.json @@ -47,7 +47,16 @@ "AUTODRAWS": "Опции авто-рисовки Wasabee", "AUTODRAW_PORTALS_SET": "Порталы", "autodraw.common.draw_button": "Нарисовать", + "autodraw.fanfield.result": "Найдено fanfield с {links} линками и {fields} полями для {ap} AP", "autodraw.flipflop.result": "Flip flop: найдено {count} линков", + "autodraw.homogeneous.missing_split": "Невозможно найти поле {count} уровня, попробуй уровни нижеили в другом месте", + "autodraw.homogeneous.order": "Порядок", + "autodraw.homogeneous.portals_required": "Нужно {count}", + "autodraw.madrid.auto_determined": "Авто-определённый", + "autodraw.madrid.balanced": "Сбалансированный", + "autodraw.madrid.result": "Для Мадрида найдено {count} полей", + "autodraw.multimax.result": "Для multimax найдено {count} полей", + "autodraw.multimax.result_both_side": "Для multimax найлено {count1} и {count2} полей", "autodraw.onion.variant": "Опции", "autodraw.onion.variant.equilateral": "~Равносторонний", "autodraw.onion.variant.grow": "Пусть растет", @@ -94,8 +103,65 @@ "DESCRIP_PLACEHOLD": "Описание (опционально)", "DestroyPortalAlert": "Снести", "dialog.about.download_mobile_app": "

Приложение Wasabee:

", - "dialog.setcomment.portal_hardness": "Сложность", + "dialog.agent_comment.text": "Комментарий: ", + "dialog.agent_comment.title": "Задать комментарий для {agentName}", + "dialog.auth.ott.button": "Вход с одноразовым токеном", + "dialog.auth.ott.text": "Получи токен на сервере Wasabee, затем вставь его здесь", + "dialog.auth.ott.title": "Одноразовый токен", + "dialog.blockers.clear_automark": "Очистить автометки", + "dialog.clear_all.text": "Хочешь сбросить {opName}?", + "dialog.clear_all.title": "Очистить: {opName}", + "dialog.clear_links.text": "Хочешь удалить все линки в {opName}?", + "dialog.clear_links.title": "Очистить линки: {opName}", + "dialog.clear_markers.text": "Хочешь удалить все маркеры в {opName}?", + "dialog.clear_markers.title": "Очистить линки: {opName}", + "dialog.checklist.count_fields": "Почситать поля", + "dialog.checklist.count_fields.no_empty": "Найдено {fieldCount} полей и пустых полей нет", + "dialog.checklist.count_fields.with_empty": "Найдено {fieldCount} полей и {emptyCount} пустых полей на {linkCount} линках", + "dialog.checklist.count_fields.link_from_inside": "Найдено {count} линков с накрытых порталов", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " на шаге {order} линком ", + "dialog.common.commands": "Команды", + "dialog.common.commands_short": "Команды", + "dialog.common.name": "Название", + "dialog.common.off": "Выкл.", + "dialog.common.on": "Вкл.", + "dialog.common.owner": "Владелец", + "dialog.common.zone_all": "Все", + "dialog.firebase.setup": "Посети {url} и нажми кнопку, чтобы авторизовать обновления в реальном времени. После этого перезагрузи IITC.", + "dialog.import.url": "Заполнить из URL", "dialog.import.success_message": "Импорт завершён. Найдено {count} порталов и {faked} порталов было не подгружено. Используй функцию замены, чтобы заменить неподгруженные порталы на настоящие на тех же местах. Увеличение масштаба на порталах чек-листа с меткой 'загрузка' может заставить их загрузиться.", + "dialog.leave_team.text": "Если покинешь {teamName}, то не сможешь снова присоединиться пока владенец не добавит тебя.", + "dialog.leave_team.title": "Покинуть: {teamName}", + "dialog.link_list.length": "Длина", + "dialog.link_list.level": "Мин. уровень", + "dialog.online_agents.actions": "Действия", + "dialog.online_agents.last_seen": "Последняя активность", + "dialog.online_agents.title": "Агенты онлайн", + "dialog.op_settings.zones": "Зоны", + "dialog.ops_list.background_disable": "Отключить фон", + "dialog.ops_list.background_enable": "Показывать в фоне", + "dialog.ops_list.download": "Скачать {opName}", + "dialog.ops_list.last_fetched": "Получено: {date}", + "dialog.ops_list.local_change": "Локальная версия изменилась", + "dialog.ops_list.remote_change": "Версия на сервере изменилась", + "dialog.ops_list.toggle_hide": "Переключить Показать/Скрыть", + "dialog.ops_list.unhide_ops": "Показать все ОПРЦ", + "dialog.remove_agent.text": "Хочешь удалить {agentName} из {teamName}?", + "dialog.remove_agent.title": "Удалить: {agentName}", + "dialog.setcomment.portal_hardness": "Сложность", + "dialog.team_list.load_wd_keys": "Загрузить ключи на руках", + "dialog.team_list.share_wd_keys": "Поделиться ключами на руках", + "dialog.team_manage.join_link": "Ссылка для присоединения", + "dialog.team_manage.join_link.create": "Создать", + "dialog.team_manage.join_link.revoke": "Отозвать", + "dialog.team_members.location": "Делится местоположением", + "dialog.team_members.wd_keys": "Делится ключами на руках", + "dialog.team_message": "Объявление команде: \"{message}\" от {sender}", + "dialog.zone_color.title": "Цвет зоны", + "dialog.zone_color.text": "Задать цвет всем линкам в зоне {zoneName}", + "dialog.zones.color": "Цвет", + "dialog.zones.id": "ID", + "dialog.zones.title": "Зоны", "DRAW TOOLS FORMAT": "Формат ДТ", "DUPE_OP": "Дублировать операцию", "END_PORT": "Конечный портал ", @@ -136,7 +202,6 @@ "IMPOSSIBLE": "Невозможно", "INGNAME_GID": "Ник Ingress или GoogleID", "INPUT_DT_KEY_COUNT": "Введи количество ключей на руках", - "INPUT_SQUAD_NAME": "Введи имя отряда", "INVALID REQUEST": "Неверный запрос", "IOS NEED FAKE UA": "Нужно установить 'Custom UserAgent for Webviews' в настройках IITC-Mobile, чтобы вход удался", "KEY_LIST2": "Список ключей для операции: {opName}", @@ -248,6 +313,8 @@ "PERM DENIED SHORT": "Доступ запрещен", "PERMS": "Разрешения {opName}", "PLEASE_SELECT_PORTAL": "Выбери портал", + "popup.anchor.keys": "Ключи: {onHand} / {required}", + "popup.marker.state_button": "Задать статус", "PORT_FAKE": "", "PORTAL KEY LIST": "Список ключей для портала {portalName}", "PORTAL_COUNT": "{count} порталов", @@ -266,7 +333,7 @@ "READ_SHORT": "RO", "READ": "только чтение", "RechargePortalAlert": "Зарядить", - "REFERENCE_TIME": "Reference time: ", + "REFERENCE_TIME": "Референсное время: ", "REM_LOC_CP": "Удалить локальную копию {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Хочешь навсегда удалить {teamName} с сервера Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Удаление команды {teamName}", @@ -324,7 +391,6 @@ "SKIP_CONFIRM_NEVER": "Всегда спрашивать", "SKIP_CONFIRM": "Подтверждение пропуска", "SOURCE_PORT": "Начальный портал", - "SQUAD": "Отряд", "STARBURST TITLE": "Звезда", "STARBURST_DRAW": "Рисовка", "STARBURST": "Звезда", @@ -359,6 +425,8 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Нажми на первый портал", "toolbar.quick_draw.tooltip.single_mode.next": "Нажми на следующий портал", "toolbar.quick_draw.tooltip.portal_fail": "Данные о портале не загружены, попробуй еще раз", + "toolbar.wasabee.settings": "Настройки", + "toolbox.teammates": "Сокомандники онлайн", "TRAWL SKIP TILES": "Шаг тайлов для выверки", "TRAWL TITLE": "Выверка трасс", "TRAWL WARNING": "Этот метод загрузит данные тайлов под всеми нарисованными линками. Это медленный процесс.", @@ -372,7 +440,6 @@ "TYPE": "Тип", "UNASSIGNED": "Не назначен", "UNKNOWN": "Неизвестен", - "UPDATE HOVER NOT CHANGED": "{opName} не изменилась локально", "UPDATE HOVER": "ОБНОВИТЬ {opName} на сервере", "UPDATE PERM DENIED": "У тебя недостаточно прав для обновления", "UPDATE_CONFLICT_DESC": "ОПРЦ изменилась на сервере с момента последней синхронизации. Хочешь заменить версию на сервере текущей?", diff --git a/src/code/translations/Spanish.json b/src/code/translations/Spanish.json index 1bc06c792..1896b6bca 100644 --- a/src/code/translations/Spanish.json +++ b/src/code/translations/Spanish.json @@ -22,12 +22,12 @@ "AMAZ_TEAM_NAME": "Excelente nombre de equipo", "ANCHOR ASSIGNMENT": "Assign all outbound links to: ", "ANCHOR_GMAP": "Google Map", - "ANCHOR_PORTAL": "Anchor Portal", + "ANCHOR_PORTAL": "Portal Ancla", "ANCHOR_PORTAL2": "Portal Ancla 2", "ANCHOR_PORTAL3": "Portal Ancla 3", - "ANCHOR1": "Anchor 1", - "ANCHOR2": "Anchor 2", - "ANCHOR3": "Anchor 3", + "ANCHOR1": "Ancla 1", + "ANCHOR2": "Ancla 2", + "ANCHOR3": "Ancla 3", "ANCHORS_AS_BOOKMARKS": "Anclas a Marcadores", "API_KEY": "Rocks API key: ", "ASS_TO": "Asignado A", @@ -47,7 +47,16 @@ "AUTODRAWS": "Opciones de dibujo automático de Wasabee", "AUTODRAW_PORTALS_SET": "Portales", "autodraw.common.draw_button": "Dibujar", + "autodraw.fanfield.result": "Fanfield ha encontrado {links} enlaces y {fields} campos para {ap} AP", "autodraw.flipflop.result": "Flip flop: encontró {count} enlaces", + "autodraw.homogeneous.missing_split": "Unable to find {count} splits, try less depth or a different region", + "autodraw.homogeneous.order": "Orden", + "autodraw.homogeneous.portals_required": "{count} requeridos", + "autodraw.madrid.auto_determined": "Auto-determinado", + "autodraw.madrid.balanced": "Equilibrado", + "autodraw.madrid.result": "Madrid ha encontrado {count} capas", + "autodraw.multimax.result": "Multimax ha encontrado {count} capas", + "autodraw.multimax.result_both_side": "Multimax found {count1} and {count2} layers", "autodraw.onion.variant": "Opción", "autodraw.onion.variant.equilateral": "~Equilátero", "autodraw.onion.variant.grow": "Permitir que crezca", @@ -94,8 +103,65 @@ "DESCRIP_PLACEHOLD": "Descripción (opcional)", "DestroyPortalAlert": "Destruir", "dialog.about.download_mobile_app": "

Aplicación Wasabee:

", - "dialog.setcomment.portal_hardness": "Dificultad", + "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.title": "Establecer comentario para {agentName}", + "dialog.auth.ott.button": "Inicio de sesión con token de un único uso", + "dialog.auth.ott.text": "Obtén un token en el Servidor Wasabee y pégalo aquí después", + "dialog.auth.ott.title": "Token de un sólo uso", + "dialog.blockers.clear_automark": "Clear Automark", + "dialog.clear_all.text": "Do you want to reset {opName}?", + "dialog.clear_all.title": "Clear: {opName}", + "dialog.clear_links.text": "Do you want to remove all links from {opName}?", + "dialog.clear_links.title": "Clear Links: {opName}", + "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", + "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.checklist.count_fields": "Count fields", + "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", + "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", + "dialog.checklist.count_fields.link_from_inside": "Found {count} links from covered portals", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", + "dialog.common.commands": "Commands", + "dialog.common.commands_short": "Cmds", + "dialog.common.name": "Nombre", + "dialog.common.off": "Desactivado", + "dialog.common.on": "Activado", + "dialog.common.owner": "Propietario", + "dialog.common.zone_all": "All", + "dialog.firebase.setup": "Visit {url} and press the button to authorize live updates. You will need to reload IITC afterward.", + "dialog.import.url": "Fill from URL", "dialog.import.success_message": "Import Complete. Found {count} portals and used {faked} faked. Please use the swap feature to move faked portals to the real portals at the same location. Zooming in on the 'Loading' portals in the checklist might force them to load.", + "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", + "dialog.leave_team.title": "Leave: {teamName}", + "dialog.link_list.length": "Longitud", + "dialog.link_list.level": "Nivel min.", + "dialog.online_agents.actions": "Acciones", + "dialog.online_agents.last_seen": "Visto por última vez", + "dialog.online_agents.title": "Agentes activos", + "dialog.op_settings.zones": "Zonas", + "dialog.ops_list.background_disable": "Disable background", + "dialog.ops_list.background_enable": "Show in background", + "dialog.ops_list.download": "Descargar {opName}", + "dialog.ops_list.last_fetched": "Last fetched: {date}", + "dialog.ops_list.local_change": "OP local ha cambiado", + "dialog.ops_list.remote_change": "OP remota ha cambiado", + "dialog.ops_list.toggle_hide": "Mostrar / Ocultar", + "dialog.ops_list.unhide_ops": "Mostrar todas las OPs", + "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", + "dialog.remove_agent.title": "Remove: {agentName}", + "dialog.setcomment.portal_hardness": "Dificultad", + "dialog.team_list.load_wd_keys": "Load W-D Keys", + "dialog.team_list.share_wd_keys": "Share W-D Keys", + "dialog.team_manage.join_link": "Enlace de unión", + "dialog.team_manage.join_link.create": "Crear", + "dialog.team_manage.join_link.revoke": "Anular", + "dialog.team_members.location": "Sharing Location", + "dialog.team_members.wd_keys": "Sharing W-D Keys", + "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.zone_color.title": "Zone Color", + "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", + "dialog.zones.color": "Color", + "dialog.zones.id": "ID", + "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplicar Operación", "END_PORT": "Portal de Fin", @@ -136,7 +202,6 @@ "IMPOSSIBLE": "Imposible", "INGNAME_GID": "Nombre de Ingress o GoogleID", "INPUT_DT_KEY_COUNT": "Ingresa el Conteo de Llaves Defensivas", - "INPUT_SQUAD_NAME": "Ingresa un nombre de Escuadrón", "INVALID REQUEST": "Solicitud No Válida", "IOS NEED FAKE UA": "Debes configurar un 'UsuarioAgente Personalizado para Vista Web' en las opciones de configuración de IITC-Mobile o el inicio de sesión fallará", "KEY_LIST2": "Lista de Llaves {opName}", @@ -248,6 +313,8 @@ "PERM DENIED SHORT": "Permiso denegado", "PERMS": "{opName} permisos", "PLEASE_SELECT_PORTAL": "Por favor, seleccionar un portal", + "popup.anchor.keys": "Keys: {onHand} / {required}", + "popup.marker.state_button": "Set State", "PORT_FAKE": "", "PORTAL KEY LIST": "Lista de Llaves del Portal {portalName}", "PORTAL_COUNT": "{count} portales", @@ -323,8 +390,7 @@ "SKIP_CONFIRM_ENTITY": "Sólo pedir equipo/op", "SKIP_CONFIRM_NEVER": "Preguntar siempre", "SKIP_CONFIRM": "Omitir confirmación", - "SOURCE_PORT": "Source Portal", - "SQUAD": "Escuadrón", + "SOURCE_PORT": "Portal de origen", "STARBURST TITLE": "Supernova", "STARBURST_DRAW": "Dibujar", "STARBURST": "Supernova", @@ -359,6 +425,8 @@ "toolbar.quick_draw.tooltip.single_mode.first": "Haz clic en el primer portal", "toolbar.quick_draw.tooltip.single_mode.next": "Haz clic en el siguiente portal", "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", + "toolbar.wasabee.settings": "Ajustes", + "toolbox.teammates": "Teammates Online", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", @@ -372,7 +440,6 @@ "TYPE": "Tipo", "UNASSIGNED": "No Asignado", "UNKNOWN": "Desconocido", - "UPDATE HOVER NOT CHANGED": "{opName} no ha sido cambiada localmente", "UPDATE HOVER": "{opName} en el servidor", "UPDATE PERM DENIED": "Permiso para acutalizar denegado", "UPDATE_CONFLICT_DESC": "The OP has been modified on server since last sync. Do you want to replace the server version by the current one?", @@ -420,7 +487,7 @@ "OPS BUTTON": "Ops", "QD END": "Fin", "STARBURST_DRAW": "Dibujar", - "STARBURST": "Star", + "STARBURST": "Estrella", "TEAMS BUTTON": "Equipos", "WD BUTTON": "Llaves W-D" } From c1955b35550994ccafe2920fa577e305c99d8ff6 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 4 Feb 2022 22:58:24 +0100 Subject: [PATCH 246/275] drop trailing space after : --- src/code/translations/Danish.json | 46 ++++++++++++------------- src/code/translations/English.json | 46 ++++++++++++------------- src/code/translations/Filipino.json | 46 ++++++++++++------------- src/code/translations/French.json | 32 +++++++++--------- src/code/translations/German.json | 48 +++++++++++++-------------- src/code/translations/Italian.json | 46 ++++++++++++------------- src/code/translations/Portuguese.json | 46 ++++++++++++------------- src/code/translations/Russian.json | 46 ++++++++++++------------- src/code/translations/Spanish.json | 16 ++++----- 9 files changed, 186 insertions(+), 186 deletions(-) diff --git a/src/code/translations/Danish.json b/src/code/translations/Danish.json index 9f8ee5a8e..0f89fae54 100644 --- a/src/code/translations/Danish.json +++ b/src/code/translations/Danish.json @@ -3,8 +3,8 @@ "acknowledged": "Anerkendt", "ADD LINK TITLE": "Tilføj Links", "ADD MARKER TITLE": "Tilføj Markører", - "ADD_AGENT": "Tilføj Agent: ", - "ADD_BL": "Tilføj baglinie: ", + "ADD_AGENT": "Tilføj Agent:", + "ADD_BL": "Tilføj baglinie:", "ADD_BULK": "Massetilføj", "ADD_BUTTON_LINKS": "Tilføj alle links med det samme.", "ADD_LINKS": "Tilføj Links", @@ -20,7 +20,7 @@ "AGES": " (for længe siden)", "ALREADY_HAS_MARKER": "Denne portal har allerede en markør, vælg en anden Portal.", "AMAZ_TEAM_NAME": "Fantastisk holdnavn.", - "ANCHOR ASSIGNMENT": "Tilknyt alle udgående links til: ", + "ANCHOR ASSIGNMENT": "Tilknyt alle udgående links til:", "ANCHOR_GMAP": "Google Maps", "ANCHOR_PORTAL": "Anker Portal", "ANCHOR_PORTAL2": "Anker Portal 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Anker 2", "ANCHOR3": "Anker 3", "ANCHORS_AS_BOOKMARKS": "Ankere som bookmarks", - "API_KEY": "Rocks API-nøgle: ", + "API_KEY": "Rocks API-nøgle:", "ASS_TO": "Tildelt", "ASSIGN LINK PROMPT": "Tilføj link fra: {portalName}", "ASSIGN MARKER PROMPT": "Tildel markør fra: {portalName}", @@ -93,9 +93,9 @@ "CUR_USER_INFO": "Aktuelle brugeroplysninger", "D_SHOW_LIST": "Input defensive nøgler", "DEFAULT OP NAME": "Ny Op: {date}", - "DELETE ANCHOR PROMPT": "Ønsker du at slette dette anker og alle tilhørende links: ", + "DELETE ANCHOR PROMPT": "Ønsker du at slette dette anker og alle tilhørende links:", "DELETE ANCHOR TITLE": "Slet anker", - "DELETE MARKER PROMPT": "Vil du slette denne markør: ", + "DELETE MARKER PROMPT": "Vil du slette denne markør:", "DELETE MARKER TITLE": "Slet markør", "DELETE_ANCHOR": "Slet", "DELETE_LINK": "Slet", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Beskrivelse (valgfri)", "DestroyPortalAlert": "Ødelæg/Skyd", "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.text": "Comment:", "dialog.agent_comment.title": "Set comment for {agentName}", "dialog.auth.ott.button": "One Time Token Login", "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", @@ -168,7 +168,7 @@ "ExcludeMarker": "Udelad fra Auto-Tegn/Marker", "EXPORT OP TITLE": "Eksporter aktuel Op", "EXPORT OP": "Eksporter Op", - "EXPORT": "Eksporter: ", + "EXPORT": "Eksporter:", "FAKED": "forfalsket: [{portalId}]", "FANFIELD": "Tegn", "FANFIELD2": "Tegn Fan Field", @@ -212,9 +212,9 @@ "LANG": "Sprog", "LEAVE": "Forlad", "LetDecayPortalAlert": "Lad forfalde", - "LINK ASSIGNMENT": "Tildel link til: ", + "LINK ASSIGNMENT": "Tildel link til:", "LINK STATE PROMPT": "Link tilstand", - "LINK STATE": "Angiv link-status: ", + "LINK STATE": "Angiv link-status:", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", @@ -234,11 +234,11 @@ "MADRID": "Tegn", "MANAGE_TEAM": "Administrer {teamName}", "MANAGE": "Administrer", - "MARKER ASSIGNMENT": "Tildel markør til: ", + "MARKER ASSIGNMENT": "Tildel markør til:", "MARKER LIST TITLE": "Markør Liste", "MARKER LIST": "Markører", "MARKER STATE PROMPT": "Markør Status", - "MARKER STATE": "Angiv markørtilstand: ", + "MARKER STATE": "Angiv markørtilstand:", "MARKER_LIST": "Markør Liste: {opName}", "MARKERS BUTTON TITLE": "Markører", "MAX_SPLITS": "Max Delinger", @@ -268,7 +268,7 @@ "MY_CAP_ID": "Mit kapsel ID", "MY_COUNT": "Mit Antal", "NAME_REQ": "Navn påkrævet", - "NAME": "Navn: ", + "NAME": "Navn:", "NEW_OP": "Ny operation", "NEW_TEAM_NAME": "Nyt holdnavn", "NEW_TEAM": "Nyt hold", @@ -300,8 +300,8 @@ "OP_SETTINGS_BUTTON": "Op Indstillinger ⚙", "OP_SETTINGS_TITLE": "Op Indstillinger", "OPEN_REQUEST": "[åbn anmodning]", - "OPER_COLOR": "Operation Farve: ", - "OPER_NAME": "Operation Navn: ", + "OPER_COLOR": "Operation Farve:", + "OPER_NAME": "Operation Navn:", "OPERATIONS": "Operationer", "OPS BUTTON TITLE": "Operations Liste", "OPS BUTTON": "Vælg OP", @@ -333,18 +333,18 @@ "READ_SHORT": "L", "READ": "Læs", "RechargePortalAlert": "Genoplad", - "REFERENCE_TIME": "Referencetid: ", + "REFERENCE_TIME": "Referencetid:", "REM_LOC_CP": "Fjern lokal kopi af {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Vil du permanent fjerne {team Name} fra Wasabi-serveren?", "REMOVE_TEAM_CONFIRM_TITLE": "Fjern hold {teamName}", - "REMOVE_TEAM": "Fjern hold: ", + "REMOVE_TEAM": "Fjern hold:", "REMOVE": "Fjern", - "RENAME_TEAM": "Omdøb hold: ", + "RENAME_TEAM": "Omdøb hold:", "RENAME": "Omdøb", "REQUIRED": "Påkrævet", "RESET": "Nulstil", "REVERSE": "Endevend", - "ROCKS_COM": "enl.rocks fællesskab: ", + "ROCKS_COM": "enl.rocks fællesskab:", "ROLE": "Rolle", "SAVELINKS TITLE": "Gem Links", "SAVELINKS_DRAW": "Gem Links", @@ -370,15 +370,15 @@ "SET_3_PORT": "Indstil venligst de tre portaler først!", "SET_COMMENT": "Indstil kommentar", "SET_LCOMMENT": "Indstil linkkommentar", - "SET_LINK_COMMENT": "Indstil kommentar til link: ", + "SET_LINK_COMMENT": "Indstil kommentar til link:", "SET_LINKS_ZONES": "Sæt links til zoner", - "SET_MARKER_COMMENT": "Sæt kommentar til markør på: ", + "SET_MARKER_COMMENT": "Sæt kommentar til markør på:", "SET_MARKER_TYPE_TITLE": "Skift markørtype", "SET_MARKERS_ZONES": "Indstil markører til zoner", "SET_MCOMMENT": "Indstil markørkommentar: {portalName}", "SET_NEW_OP": "Indstil venligst det nye operationsnavn", "SET_PCOMMENT": "Indstil portalkommentar: {portalName}", - "SET_PORT_COMMENT": "Indstil kommentar til portal: ", + "SET_PORT_COMMENT": "Indstil kommentar til portal:", "SET_PORTAL_COMMENT": "Indstil portalkommentar", "SET": "indstil", "SETTINGS": "Wasabee Indstillinger", @@ -397,7 +397,7 @@ "START_PORT": "Start Portal ", "STATE": "Status", "SUPPORT_INSTRUCT": "For at få support, tilmeld dig Wasabee bruger Telegram kanal", - "SWAP PROMPT": "Vil du bytte: ", + "SWAP PROMPT": "Vil du bytte:", "SWAP TITLE": "Byt portaler", "SWAP WITH": " med ", "SWAP": "Byt", diff --git a/src/code/translations/English.json b/src/code/translations/English.json index e32d269ba..683fad7bc 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -3,8 +3,8 @@ "acknowledged": "Acknowledged", "ADD LINK TITLE": "Add Links", "ADD MARKER TITLE": "Add Markers", - "ADD_AGENT": "Add Agent: ", - "ADD_BL": "Add Back Links: ", + "ADD_AGENT": "Add Agent:", + "ADD_BL": "Add Back Links:", "ADD_BULK": "Bulk add", "ADD_BUTTON_LINKS": "Add all links at once.", "ADD_LINKS": "Add Links", @@ -20,7 +20,7 @@ "AGES": " (ages ago)", "ALREADY_HAS_MARKER": "This portal already has a marker. Choose a different portal.", "AMAZ_TEAM_NAME": "Amazing Team Name.", - "ANCHOR ASSIGNMENT": "Assign all outbound links to: ", + "ANCHOR ASSIGNMENT": "Assign all outbound links to:", "ANCHOR_GMAP": "Google Map", "ANCHOR_PORTAL": "Anchor Portal", "ANCHOR_PORTAL2": "Anchor Portal 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Anchor 2", "ANCHOR3": "Anchor 3", "ANCHORS_AS_BOOKMARKS": "Anchors as bookmarks", - "API_KEY": "Rocks API key: ", + "API_KEY": "Rocks API key:", "ASS_TO": "Assigned To", "ASSIGN LINK PROMPT": "Assign link from: {portalName}", "ASSIGN MARKER PROMPT": "Assign marker from: {portalName}", @@ -93,9 +93,9 @@ "CUR_USER_INFO": "Current User Information", "D_SHOW_LIST": "Input Defensive Keys", "DEFAULT OP NAME": "New Op: {date}", - "DELETE ANCHOR PROMPT": "Do you want to delete this anchor and all associated links: ", + "DELETE ANCHOR PROMPT": "Do you want to delete this anchor and all associated links:", "DELETE ANCHOR TITLE": "Delete Anchor", - "DELETE MARKER PROMPT": "Do you want to delete this marker: ", + "DELETE MARKER PROMPT": "Do you want to delete this marker:", "DELETE MARKER TITLE": "Delete Marker", "DELETE_ANCHOR": "Delete", "DELETE_LINK": "Delete", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Description (optional)", "DestroyPortalAlert": "Destroy", "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.text": "Comment:", "dialog.agent_comment.title": "Set comment for {agentName}", "dialog.auth.ott.button": "One Time Token Login", "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", @@ -168,7 +168,7 @@ "ExcludeMarker": "Exclude from Auto-Draw/Mark", "EXPORT OP TITLE": "Export current Op", "EXPORT OP": "Export Op", - "EXPORT": "Export: ", + "EXPORT": "Export:", "FAKED": "Faked: [{portalId}]", "FANFIELD": "Draw", "FANFIELD2": "Draw Fan Field", @@ -212,9 +212,9 @@ "LANG": "Language", "LEAVE": "Leave", "LetDecayPortalAlert": "Let Decay", - "LINK ASSIGNMENT": "Assign link to: ", + "LINK ASSIGNMENT": "Assign link to:", "LINK STATE PROMPT": "Link State", - "LINK STATE": "Set link status: ", + "LINK STATE": "Set link status:", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", @@ -234,11 +234,11 @@ "MADRID": "Draw", "MANAGE_TEAM": "Manage {teamName}", "MANAGE": "Manage", - "MARKER ASSIGNMENT": "Assign marker to: ", + "MARKER ASSIGNMENT": "Assign marker to:", "MARKER LIST TITLE": "Marker List", "MARKER LIST": "Markers", "MARKER STATE PROMPT": "Marker Status", - "MARKER STATE": "Set marker state: ", + "MARKER STATE": "Set marker state:", "MARKER_LIST": "Marker List: {opName}", "MARKERS BUTTON TITLE": "Markers", "MAX_SPLITS": "Max Splits", @@ -268,7 +268,7 @@ "MY_CAP_ID": "My Capsule ID", "MY_COUNT": "My Count", "NAME_REQ": "Name Required", - "NAME": "Name: ", + "NAME": "Name:", "NEW_OP": "New Operation", "NEW_TEAM_NAME": "New Team Name", "NEW_TEAM": "New Team", @@ -300,8 +300,8 @@ "OP_SETTINGS_BUTTON": "Op ⚙", "OP_SETTINGS_TITLE": "Operation Settings", "OPEN_REQUEST": "[open request]", - "OPER_COLOR": "Operation Color: ", - "OPER_NAME": "Operation Name: ", + "OPER_COLOR": "Operation Color:", + "OPER_NAME": "Operation Name:", "OPERATIONS": "Operations", "OPS BUTTON TITLE": "Operations List", "OPS BUTTON": "Select OP", @@ -333,18 +333,18 @@ "READ_SHORT": "RO", "READ": "Read", "RechargePortalAlert": "Recharge", - "REFERENCE_TIME": "Reference Time: ", + "REFERENCE_TIME": "Reference Time:", "REM_LOC_CP": "Remove local copy of {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Do you want to permenantly remove {teamName} from the Wasabee Server?", "REMOVE_TEAM_CONFIRM_TITLE": "Remove Team {teamName}", - "REMOVE_TEAM": "Remove Team: ", + "REMOVE_TEAM": "Remove Team:", "REMOVE": "Remove", - "RENAME_TEAM": "Rename Team: ", + "RENAME_TEAM": "Rename Team:", "RENAME": "Rename", "REQUIRED": "Required", "RESET": "Reset", "REVERSE": "Reverse", - "ROCKS_COM": "enl.rocks community: ", + "ROCKS_COM": "enl.rocks community:", "ROLE": "Role", "SAVELINKS TITLE": "Save Links", "SAVELINKS_DRAW": "Save Links", @@ -370,15 +370,15 @@ "SET_3_PORT": "Please set the three portals first!", "SET_COMMENT": "Set Comment", "SET_LCOMMENT": "Set Link Comment", - "SET_LINK_COMMENT": "Set comment for link: ", + "SET_LINK_COMMENT": "Set comment for link:", "SET_LINKS_ZONES": "Set Links to Zones", - "SET_MARKER_COMMENT": "Set comment for marker on: ", + "SET_MARKER_COMMENT": "Set comment for marker on:", "SET_MARKER_TYPE_TITLE": "Change marker type", "SET_MARKERS_ZONES": "Set Markers to Zones", "SET_MCOMMENT": "Set Marker Comment: {portalName}", "SET_NEW_OP": "Please Set the New Operation Name", "SET_PCOMMENT": "Set Portal Comment: {portalName}", - "SET_PORT_COMMENT": "Set comment for portal: ", + "SET_PORT_COMMENT": "Set comment for portal:", "SET_PORTAL_COMMENT": "Set Portal Comment", "SET": "set", "SETTINGS": "Wasabee Settings", @@ -397,7 +397,7 @@ "START_PORT": "Start Portal", "STATE": "State", "SUPPORT_INSTRUCT": "For support, please join the Wasabee User Telegram Channel", - "SWAP PROMPT": "Do you want to swap: ", + "SWAP PROMPT": "Do you want to swap:", "SWAP TITLE": "Swap Portals", "SWAP WITH": " with ", "SWAP": "Swap", diff --git a/src/code/translations/Filipino.json b/src/code/translations/Filipino.json index 578382999..f6880a845 100644 --- a/src/code/translations/Filipino.json +++ b/src/code/translations/Filipino.json @@ -3,8 +3,8 @@ "acknowledged": "Natanggap", "ADD LINK TITLE": "Magdagdag ng Links", "ADD MARKER TITLE": "Magdagdag ng Markers", - "ADD_AGENT": "Magdagdag ng Agent: ", - "ADD_BL": "Magdagdag ng Back Links: ", + "ADD_AGENT": "Magdagdag ng Agent:", + "ADD_BL": "Magdagdag ng Back Links:", "ADD_BULK": "Maramihang idagdag", "ADD_BUTTON_LINKS": "Sabay-sabay idagdag ang lahat ng link", "ADD_LINKS": "Magdagdag ng Link", @@ -20,7 +20,7 @@ "AGES": " (matagal na panahon)", "ALREADY_HAS_MARKER": "May Marker ang portal na ito. Pumili ng ibang portal.", "AMAZ_TEAM_NAME": "Malupet na Pangalan ng Pangkat", - "ANCHOR ASSIGNMENT": "Assign all outbound links to: ", + "ANCHOR ASSIGNMENT": "Assign all outbound links to:", "ANCHOR_GMAP": "Google Map", "ANCHOR_PORTAL": "Anchor Portal", "ANCHOR_PORTAL2": "Anchor Portal 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Anchor 2", "ANCHOR3": "Anchor 3", "ANCHORS_AS_BOOKMARKS": "Anchors as bookmarks", - "API_KEY": "Rocks API key: ", + "API_KEY": "Rocks API key:", "ASS_TO": "Nakatalaga kay", "ASSIGN LINK PROMPT": "Magatalaga ng link mula: {portalName}", "ASSIGN MARKER PROMPT": "Magtalaga ng marker mula: {portalName}", @@ -93,9 +93,9 @@ "CUR_USER_INFO": "Kasalukuyang Impormasyon ng User", "D_SHOW_LIST": "Ipasok ang Defensive Keys", "DEFAULT OP NAME": "Bagong Op {date}", - "DELETE ANCHOR PROMPT": "Gusto mo bang tangalin ang anchor na ito at ang lahat ng links na nakakabit: ", + "DELETE ANCHOR PROMPT": "Gusto mo bang tangalin ang anchor na ito at ang lahat ng links na nakakabit:", "DELETE ANCHOR TITLE": "Tanggalin ang Anchor", - "DELETE MARKER PROMPT": "Gusto mo bang tangalin ang marker na ito: ", + "DELETE MARKER PROMPT": "Gusto mo bang tangalin ang marker na ito:", "DELETE MARKER TITLE": "Tanggalin ang Marker", "DELETE_ANCHOR": "Tangalin", "DELETE_LINK": "Tangalin", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Description (opsyonal)", "DestroyPortalAlert": "Sirain", "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.text": "Comment:", "dialog.agent_comment.title": "Set comment for {agentName}", "dialog.auth.ott.button": "One Time Token Login", "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", @@ -168,7 +168,7 @@ "ExcludeMarker": "Ibukod sa Auto-Draw/Pag-marka", "EXPORT OP TITLE": "I-Export ang kasalukuyang op", "EXPORT OP": "I-Export ang Op", - "EXPORT": "Export: ", + "EXPORT": "Export:", "FAKED": "Faked: [{portalId}]", "FANFIELD": "Guhit", "FANFIELD2": "Iguhit ang Fanfield", @@ -212,9 +212,9 @@ "LANG": "Wika", "LEAVE": "Ialis", "LetDecayPortalAlert": "Ipa-decay", - "LINK ASSIGNMENT": "Assign link to: ", + "LINK ASSIGNMENT": "Assign link to:", "LINK STATE PROMPT": "estado ng Link", - "LINK STATE": "Set link status: ", + "LINK STATE": "Set link status:", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", @@ -234,11 +234,11 @@ "MADRID": "Draw", "MANAGE_TEAM": "Ipamahala {teamName}", "MANAGE": "Ipamahala", - "MARKER ASSIGNMENT": "Assign marker to: ", + "MARKER ASSIGNMENT": "Assign marker to:", "MARKER LIST TITLE": "Listahan ng Marker", "MARKER LIST": "Markers", "MARKER STATE PROMPT": "Estado ng Marker", - "MARKER STATE": "Set marker state: ", + "MARKER STATE": "Set marker state:", "MARKER_LIST": "Listahan ng Marker: {opName}", "MARKERS BUTTON TITLE": "Markers", "MAX_SPLITS": "Max Splits", @@ -268,7 +268,7 @@ "MY_CAP_ID": "Aking Capsule ID", "MY_COUNT": "Aking Bilang", "NAME_REQ": "Kilanakailangan ng Pangalan", - "NAME": "Pangalan: ", + "NAME": "Pangalan:", "NEW_OP": "Bagong Operasyon", "NEW_TEAM_NAME": "Bagong Pangalan ng Pangkat", "NEW_TEAM": "New Team", @@ -300,8 +300,8 @@ "OP_SETTINGS_BUTTON": "Op ⚙", "OP_SETTINGS_TITLE": "Operation Settings", "OPEN_REQUEST": "[open request]", - "OPER_COLOR": "Kulay ng Operasyon: ", - "OPER_NAME": "Pangalan ng Operasyon: ", + "OPER_COLOR": "Kulay ng Operasyon:", + "OPER_NAME": "Pangalan ng Operasyon:", "OPERATIONS": "Mga Operasyon", "OPS BUTTON TITLE": "Operasyon", "OPS BUTTON": "Ops", @@ -333,18 +333,18 @@ "READ_SHORT": "RO", "READ": "basahin", "RechargePortalAlert": "Recharge", - "REFERENCE_TIME": "Reference Time: ", + "REFERENCE_TIME": "Reference Time:", "REM_LOC_CP": "Tangalin ang local copy ng {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Gusto mong permanenteng tanggalin {teamName} sa Wasabee Server?", "REMOVE_TEAM_CONFIRM_TITLE": "Tanggalin Pangkat {teamName}", - "REMOVE_TEAM": "Tanggalin Pangkat: ", + "REMOVE_TEAM": "Tanggalin Pangkat:", "REMOVE": "Tangalin", - "RENAME_TEAM": "Palitan ang Pangalan ng Pangkat: ", + "RENAME_TEAM": "Palitan ang Pangalan ng Pangkat:", "RENAME": "Palitan ang Pangalan", "REQUIRED": "Kinakailangan", "RESET": "Reset", "REVERSE": "Reverse", - "ROCKS_COM": "enl.rocks community: ", + "ROCKS_COM": "enl.rocks community:", "ROLE": "Papel", "SAVELINKS TITLE": "Save Links", "SAVELINKS_DRAW": "Save Links", @@ -370,15 +370,15 @@ "SET_3_PORT": "Pumili muna ng tatlong portals!", "SET_COMMENT": "Magatalaga ng Komentayro", "SET_LCOMMENT": "Italaga ang commento sa Link", - "SET_LINK_COMMENT": "Komento para sa link: ", + "SET_LINK_COMMENT": "Komento para sa link:", "SET_LINKS_ZONES": "Set Links to Zones", - "SET_MARKER_COMMENT": "Komento para sa marker: ", + "SET_MARKER_COMMENT": "Komento para sa marker:", "SET_MARKER_TYPE_TITLE": "Change marker type", "SET_MARKERS_ZONES": "Set Markers to Zones", "SET_MCOMMENT": "Italaga ang commento sa Marker: {portalName}", "SET_NEW_OP": "Bigyan ng pangalan ang bagong operasyon", "SET_PCOMMENT": "Italaga ang commento sa Portal: {portalName}", - "SET_PORT_COMMENT": "Komento para sa portal: ", + "SET_PORT_COMMENT": "Komento para sa portal:", "SET_PORTAL_COMMENT": "Magtalaga komento sa portal", "SET": "italaga", "SETTINGS": "Settings ng Wasabee", @@ -397,7 +397,7 @@ "START_PORT": "Panimulang Portal", "STATE": "Estado", "SUPPORT_INSTRUCT": "Para sa karagdagang tulong, sumali sa Ang Wasabee User Telegram Channel", - "SWAP PROMPT": "Gusto mo ba ipagpalit: ", + "SWAP PROMPT": "Gusto mo ba ipagpalit:", "SWAP TITLE": "Ipagpalit ang Portals", "SWAP WITH": " sa ", "SWAP": "Ipagpalit", diff --git a/src/code/translations/French.json b/src/code/translations/French.json index 914d5b775..70738e9f7 100644 --- a/src/code/translations/French.json +++ b/src/code/translations/French.json @@ -3,8 +3,8 @@ "acknowledged": "Noté", "ADD LINK TITLE": "Ajouter des liens", "ADD MARKER TITLE": "Ajouter des marqueurs", - "ADD_AGENT": "Ajouter l'agent : ", - "ADD_BL": "Ajouter les backlinks : ", + "ADD_AGENT": "Ajouter l'agent :", + "ADD_BL": "Ajouter les backlinks :", "ADD_BULK": "Ajouter en masse", "ADD_BUTTON_LINKS": "Ajouter les liens", "ADD_LINKS": "Ajouter des liens", @@ -20,7 +20,7 @@ "AGES": " (il y a longtemps)", "ALREADY_HAS_MARKER": "Ce portail porte déjà un marqueur. Choisissez un autre portail.", "AMAZ_TEAM_NAME": "Nom de l'équipe", - "ANCHOR ASSIGNMENT": "Affecter tous les liens sortants à : ", + "ANCHOR ASSIGNMENT": "Affecter tous les liens sortants à :", "ANCHOR_GMAP": "Google Maps", "ANCHOR_PORTAL": "Ancre", "ANCHOR_PORTAL2": "Portail Ancre 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Ancre 2", "ANCHOR3": "Ancre 3", "ANCHORS_AS_BOOKMARKS": "Ancres vers Bookmarks", - "API_KEY": "Clé API Rocks : ", + "API_KEY": "Clé API Rocks :", "ASS_TO": "Assigné à", "ASSIGN LINK PROMPT": "Assigner le lien de {portalName}", "ASSIGN MARKER PROMPT": "Assigner le marqueur sur {portalName}", @@ -93,9 +93,9 @@ "CUR_USER_INFO": "Information sur l'utilisateur courant", "D_SHOW_LIST": "Entrer les clés défensive", "DEFAULT OP NAME": "Opération {date}", - "DELETE ANCHOR PROMPT": "Voulez vous supprimer cette ancre et tous les liens associés : ", + "DELETE ANCHOR PROMPT": "Voulez vous supprimer cette ancre et tous les liens associés :", "DELETE ANCHOR TITLE": "Supprimer une ancre", - "DELETE MARKER PROMPT": "Voulez vous supprimer le marqueur : ", + "DELETE MARKER PROMPT": "Voulez vous supprimer le marqueur :", "DELETE MARKER TITLE": "Supprimer un marqueur", "DELETE_ANCHOR": "Supprimer", "DELETE_LINK": "Supprimer", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Description (optionnelle)", "DestroyPortalAlert": "Casse", "dialog.about.download_mobile_app": "

Application Wasabee :

", - "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.text": "Comment:", "dialog.agent_comment.title": "Définir le commentaire de {agentName}", "dialog.auth.ott.button": "Connexion à jeton unique", "dialog.auth.ott.text": "Récupérez un jeton (One time Token) depuis le server wasabee, puis collez-le ici", @@ -168,7 +168,7 @@ "ExcludeMarker": "Exclure d'Auto-Draw/Mark", "EXPORT OP TITLE": "Exporter l'opération", "EXPORT OP": "Exporter", - "EXPORT": "Exporter : ", + "EXPORT": "Exporter :", "FAKED": "Faux [{portalId}]", "FANFIELD": "Tracer", "FANFIELD2": "Fan Field", @@ -212,9 +212,9 @@ "LANG": "Langue", "LEAVE": "Quitter", "LetDecayPortalAlert": "À decay", - "LINK ASSIGNMENT": "Affecter le lien à : ", + "LINK ASSIGNMENT": "Affecter le lien à :", "LINK STATE PROMPT": "Statut du lien", - "LINK STATE": "Définir l'état du lien : ", + "LINK STATE": "Définir l'état du lien :", "LINKS BUTTON TITLE": "Liens", "LINKS": "Liens", "LINKS2": "{portalName} : Liens ({outgoing}↑/{incoming}↓)", @@ -234,11 +234,11 @@ "MADRID": "Tracer", "MANAGE_TEAM": "Gérer {teamName}", "MANAGE": "Gérer", - "MARKER ASSIGNMENT": "Affecter le marqueur à : ", + "MARKER ASSIGNMENT": "Affecter le marqueur à :", "MARKER LIST TITLE": "Liste des marqueurs", "MARKER LIST": "Marqueurs", "MARKER STATE PROMPT": "Statut du marqueur", - "MARKER STATE": "Définir l'état du marqueur : ", + "MARKER STATE": "Définir l'état du marqueur :", "MARKER_LIST": "Liste des marqueurs : {opName}", "MARKERS BUTTON TITLE": "Marqueurs", "MAX_SPLITS": "Nb Couches", @@ -268,7 +268,7 @@ "MY_CAP_ID": "ID de ma capsule", "MY_COUNT": "Mon nombre de clés", "NAME_REQ": "Nom requis", - "NAME": "Nom : ", + "NAME": "Nom :", "NEW_OP": "Nouvelle opération", "NEW_TEAM_NAME": "Nouveau nom d'équipe", "NEW_TEAM": "Nouvelle équipe", @@ -333,7 +333,7 @@ "READ_SHORT": "RO", "READ": "lire", "RechargePortalAlert": "Recharge", - "REFERENCE_TIME": "Temps de référence : ", + "REFERENCE_TIME": "Temps de référence :", "REM_LOC_CP": "Supprimer la copie locale de {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Voulez vous vraiment supprimer {teamName} du serveur Wasabee ?", "REMOVE_TEAM_CONFIRM_TITLE": "supprimer l'équipe {teamName}", @@ -370,9 +370,9 @@ "SET_3_PORT": "Sélectionner d'abord trois portails", "SET_COMMENT": "Entrer un commentaire", "SET_LCOMMENT": "Commentaires du liens", - "SET_LINK_COMMENT": "Entrer un commentaire pour le lien : ", + "SET_LINK_COMMENT": "Entrer un commentaire pour le lien :", "SET_LINKS_ZONES": "Affecter les liens aux zones", - "SET_MARKER_COMMENT": "Entrer un commentaire pour le marqueur : ", + "SET_MARKER_COMMENT": "Entrer un commentaire pour le marqueur :", "SET_MARKER_TYPE_TITLE": "Changer le type de marqueur", "SET_MARKERS_ZONES": "Affecter les marqueurs aux zones", "SET_MCOMMENT": "Commentaire pour ce marqueur : {portalName}", diff --git a/src/code/translations/German.json b/src/code/translations/German.json index 3b425a2c7..73bc0e376 100644 --- a/src/code/translations/German.json +++ b/src/code/translations/German.json @@ -3,8 +3,8 @@ "acknowledged": "Bestätigt", "ADD LINK TITLE": "Dialog - Links hinzufügen", "ADD MARKER TITLE": "Dialog - Markierung hinzufügen", - "ADD_AGENT": "Füge Agent hinzu: ", - "ADD_BL": "Füge Portal zur Ankerkette hinzu: ", + "ADD_AGENT": "Füge Agent hinzu:", + "ADD_BL": "Füge Portal zur Ankerkette hinzu:", "ADD_BULK": "Bulk hinzufügen", "ADD_BUTTON_LINKS": "Alle Links auf einmal hinzufügen.", "ADD_LINKS": "Füge Links hinzu", @@ -20,7 +20,7 @@ "AGES": "vor langer Zeit", "ALREADY_HAS_MARKER": "Dieses Portal hat bereits eine Markierung. Bitte wähle ein anderes Portal.", "AMAZ_TEAM_NAME": "Toller Teamname", - "ANCHOR ASSIGNMENT": "Alle ausgehenden Links zuweisen an: ", + "ANCHOR ASSIGNMENT": "Alle ausgehenden Links zuweisen an:", "ANCHOR_GMAP": "Google Map", "ANCHOR_PORTAL": "Anker Portal", "ANCHOR_PORTAL2": "Anker Portal 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Anker 2", "ANCHOR3": "Anker 3", "ANCHORS_AS_BOOKMARKS": "Anker als Lesezeichen", - "API_KEY": "Rocks API-Schlüssel: ", + "API_KEY": "Rocks API-Schlüssel:", "ASS_TO": "Zugewiesen an", "ASSIGN LINK PROMPT": "Link zugewiesenen von: {portalName}", "ASSIGN MARKER PROMPT": "Markierung zugewiesenen von: {portalName}", @@ -93,9 +93,9 @@ "CUR_USER_INFO": "Aktuelle Nutzer Informationen", "D_SHOW_LIST": "Defensive Schlüssel eingeben", "DEFAULT OP NAME": "Neue Operation: {date}", - "DELETE ANCHOR PROMPT": "Möchtest du den Anker mit allen zugewiesenen Links löschen? : ", + "DELETE ANCHOR PROMPT": "Möchtest du den Anker mit allen zugewiesenen Links löschen? :", "DELETE ANCHOR TITLE": "Anker löschen", - "DELETE MARKER PROMPT": "Möchtest du die Markierung löschen? : ", + "DELETE MARKER PROMPT": "Möchtest du die Markierung löschen? :", "DELETE MARKER TITLE": "Markierung löschen", "DELETE_ANCHOR": "Löschen", "DELETE_LINK": "Löschen", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Beschreibung (optional)", "DestroyPortalAlert": "Zerstören", "dialog.about.download_mobile_app": "

Wasabee App:

", - "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.text": "Comment:", "dialog.agent_comment.title": "Set comment for {agentName}", "dialog.auth.ott.button": "One Time Token Login", "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", @@ -168,7 +168,7 @@ "ExcludeMarker": "Von Auto-Draw/Markieren ausschließen", "EXPORT OP TITLE": "Exportiere aktuelle Operation ", "EXPORT OP": "Exportiere Op", - "EXPORT": "Exportieren: ", + "EXPORT": "Exportieren:", "FAKED": "Gefaked: [{portalId}]", "FANFIELD": "Fächerfeld!", "FANFIELD2": "Fächerfeld", @@ -212,9 +212,9 @@ "LANG": "Sprache", "LEAVE": "Verlassen", "LetDecayPortalAlert": "Decayen lassen", - "LINK ASSIGNMENT": "Link zuweisen an: ", + "LINK ASSIGNMENT": "Link zuweisen an:", "LINK STATE PROMPT": "Linkstatus", - "LINK STATE": "Linkstatus festlegen: ", + "LINK STATE": "Linkstatus festlegen:", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", @@ -234,11 +234,11 @@ "MADRID": "Zeichnen", "MANAGE_TEAM": "Verwalten {teamName}", "MANAGE": "Verwalten", - "MARKER ASSIGNMENT": "Marker zuweisen an: ", + "MARKER ASSIGNMENT": "Marker zuweisen an:", "MARKER LIST TITLE": "Liste der Markierungen", "MARKER LIST": "Markierungen", "MARKER STATE PROMPT": "Marker Status", - "MARKER STATE": "Marker-Status setzen: ", + "MARKER STATE": "Marker-Status setzen:", "MARKER_LIST": "Liste Makerierungen: {opName}", "MARKERS BUTTON TITLE": "Markierungen", "MAX_SPLITS": "Max. Aufteilungen", @@ -268,7 +268,7 @@ "MY_CAP_ID": "Kapsel ID", "MY_COUNT": "Meine Anzahl", "NAME_REQ": "Name benötigt", - "NAME": "Name: ", + "NAME": "Name:", "NEW_OP": "Neue Operation", "NEW_TEAM_NAME": "Neuer Teamname", "NEW_TEAM": "New Team", @@ -300,8 +300,8 @@ "OP_SETTINGS_BUTTON": "Op ⚙", "OP_SETTINGS_TITLE": "Operation Settings", "OPEN_REQUEST": "[öffne Anfrage]", - "OPER_COLOR": "Operation Color: ", - "OPER_NAME": "Operation Name: ", + "OPER_COLOR": "Operation Color:", + "OPER_NAME": "Operation Name:", "OPERATIONS": "Operationen", "OPS BUTTON TITLE": "Operationen", "OPS BUTTON": "Ops", @@ -333,18 +333,18 @@ "READ_SHORT": "RO", "READ": "lesen", "RechargePortalAlert": "Recharge", - "REFERENCE_TIME": "Reference Time: ", + "REFERENCE_TIME": "Reference Time:", "REM_LOC_CP": "Remove local copy of {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Möchtest du {teamName} permanent vom Server entfernen?", "REMOVE_TEAM_CONFIRM_TITLE": "Entferne Team {teamName}", - "REMOVE_TEAM": "Team entfernen: ", + "REMOVE_TEAM": "Team entfernen:", "REMOVE": "Entfernen", - "RENAME_TEAM": "Team umbenennen: ", + "RENAME_TEAM": "Team umbenennen:", "RENAME": "Umbenennen", "REQUIRED": "Benötigt", "RESET": "Reset", "REVERSE": "Reverse", - "ROCKS_COM": "enl.rocks community: ", + "ROCKS_COM": "enl.rocks community:", "ROLE": "Rolle", "SAVELINKS TITLE": "Save Links", "SAVELINKS_DRAW": "Save Links", @@ -369,16 +369,16 @@ "SEND_LOC": "Sende Standort", "SET_3_PORT": "Bitte wähle zuerst drei Portale!", "SET_COMMENT": "Füge Kommentar hinzu", - "SET_LCOMMENT": "Setze Kommentar für Link: ", - "SET_LINK_COMMENT": "Set comment for link: ", + "SET_LCOMMENT": "Setze Kommentar für Link:", + "SET_LINK_COMMENT": "Set comment for link:", "SET_LINKS_ZONES": "Set Links to Zones", - "SET_MARKER_COMMENT": "Set comment for marker on: ", + "SET_MARKER_COMMENT": "Set comment for marker on:", "SET_MARKER_TYPE_TITLE": "Change marker type", "SET_MARKERS_ZONES": "Set Markers to Zones", "SET_MCOMMENT": "Setze Kommentar für Markierung: {portalName}", "SET_NEW_OP": "Bitte gebe einen neuen Operationnamen ein", "SET_PCOMMENT": "Setze Kommentar für Portal: {portalName}", - "SET_PORT_COMMENT": "Set comment for portal: ", + "SET_PORT_COMMENT": "Set comment for portal:", "SET_PORTAL_COMMENT": "Set Portal Comment", "SET": "setzen", "SETTINGS": "Wasabee Settings", @@ -397,7 +397,7 @@ "START_PORT": "Startportal", "STATE": "Status", "SUPPORT_INSTRUCT": "Für Hilfe trete bitte der Telegram Gruppe bei The Wasabee User Telegram Channel ", - "SWAP PROMPT": "Möchtest du tauschen?: ", + "SWAP PROMPT": "Möchtest du tauschen?:", "SWAP TITLE": "Portale tauschen", "SWAP WITH": " mit ", "SWAP": "Wechseln", diff --git a/src/code/translations/Italian.json b/src/code/translations/Italian.json index 4ac7eb7ef..66dc15061 100644 --- a/src/code/translations/Italian.json +++ b/src/code/translations/Italian.json @@ -3,8 +3,8 @@ "acknowledged": "Ricevuto", "ADD LINK TITLE": "Aggiunta Link", "ADD MARKER TITLE": "Aggiunta Marker", - "ADD_AGENT": "Aggiungi Agente: ", - "ADD_BL": "Aggiungi Link all'indietro: ", + "ADD_AGENT": "Aggiungi Agente:", + "ADD_BL": "Aggiungi Link all'indietro:", "ADD_BULK": "Aggiungi in blocco", "ADD_BUTTON_LINKS": "Aggiungi tutti i link assieme.", "ADD_LINKS": "Aggiungi Link", @@ -20,7 +20,7 @@ "AGES": " (epoche fa)", "ALREADY_HAS_MARKER": "Questo portale ha già un marker. Scegli un altro portale.", "AMAZ_TEAM_NAME": "Fantastico Nome del Team.", - "ANCHOR ASSIGNMENT": "Assegna tutti i link in uscita a: ", + "ANCHOR ASSIGNMENT": "Assegna tutti i link in uscita a:", "ANCHOR_GMAP": "Mappa Google", "ANCHOR_PORTAL": "Portale Ancora", "ANCHOR_PORTAL2": "Portale Ancora 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Ancora 2", "ANCHOR3": "Ancora 3", "ANCHORS_AS_BOOKMARKS": "Ancore come bookmark", - "API_KEY": "Chiave API Rocks: ", + "API_KEY": "Chiave API Rocks:", "ASS_TO": "Assegnato a", "ASSIGN LINK PROMPT": "Assegna link da: {portalName}", "ASSIGN MARKER PROMPT": "Assegna marker da: {portalName}", @@ -93,9 +93,9 @@ "CUR_USER_INFO": "Informazioni utente attuale", "D_SHOW_LIST": "Inserisci chiavi difensive", "DEFAULT OP NAME": "Nuova Op: {date}", - "DELETE ANCHOR PROMPT": "Vuoi eliminare quest'ancora e tutti i link associati: ", + "DELETE ANCHOR PROMPT": "Vuoi eliminare quest'ancora e tutti i link associati:", "DELETE ANCHOR TITLE": "Elimina Ancora", - "DELETE MARKER PROMPT": "Vuoi eliminare questo Marker: ", + "DELETE MARKER PROMPT": "Vuoi eliminare questo Marker:", "DELETE MARKER TITLE": "Elimina Marker", "DELETE_ANCHOR": "Elimina", "DELETE_LINK": "Elimina", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Descrizione (facoltativo)", "DestroyPortalAlert": "Distruggere", "dialog.about.download_mobile_app": "

App Wasabee:

", - "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.text": "Comment:", "dialog.agent_comment.title": "Imposta commento per {agentName}", "dialog.auth.ott.button": "Login con One Time Token", "dialog.auth.ott.text": "Ottieni un token dal Server Wasabee, quindi incollalo qui", @@ -168,7 +168,7 @@ "ExcludeMarker": "Escludi da Auto-Draw/Mark", "EXPORT OP TITLE": "Esporta Op attuale", "EXPORT OP": "Esporta Op", - "EXPORT": "Esporta: ", + "EXPORT": "Esporta:", "FAKED": "Simulato: [{portalId}]", "FANFIELD": "Fanfield!", "FANFIELD2": "Fanfield", @@ -212,9 +212,9 @@ "LANG": "Lingua", "LEAVE": "Esci", "LetDecayPortalAlert": "Lasciare Decadere", - "LINK ASSIGNMENT": "Assegna link a: ", + "LINK ASSIGNMENT": "Assegna link a:", "LINK STATE PROMPT": "Stato Link", - "LINK STATE": "Imposta stato link: ", + "LINK STATE": "Imposta stato link:", "LINKS BUTTON TITLE": "Link", "LINKS": "Link", "LINKS2": "{portalName} : Link ({outgoing}↑/{incoming}↓)", @@ -234,11 +234,11 @@ "MADRID": "Disegna", "MANAGE_TEAM": "Gestisci {teamName}", "MANAGE": "Gestisci", - "MARKER ASSIGNMENT": "Assegna marker a: ", + "MARKER ASSIGNMENT": "Assegna marker a:", "MARKER LIST TITLE": "Lista Marker", "MARKER LIST": "Marker", "MARKER STATE PROMPT": "Stato Marker", - "MARKER STATE": "Imposta stato marker: ", + "MARKER STATE": "Imposta stato marker:", "MARKER_LIST": "Lista Marker: {opName}", "MARKERS BUTTON TITLE": "Marker", "MAX_SPLITS": "Più Split possibili", @@ -268,7 +268,7 @@ "MY_CAP_ID": "ID Capsula", "MY_COUNT": "Conteggio", "NAME_REQ": "Nome Richiesto", - "NAME": "Nome: ", + "NAME": "Nome:", "NEW_OP": "Nuova Operazione", "NEW_TEAM_NAME": "Nuovo nome Team", "NEW_TEAM": "Clicca per creare un nuovo Team", @@ -300,8 +300,8 @@ "OP_SETTINGS_BUTTON": "Op ⚙", "OP_SETTINGS_TITLE": "Impostazioni Operazione", "OPEN_REQUEST": "[apri richiesta]", - "OPER_COLOR": "Colore Operazione: ", - "OPER_NAME": "Nome Operazione: ", + "OPER_COLOR": "Colore Operazione:", + "OPER_NAME": "Nome Operazione:", "OPERATIONS": "Operationi", "OPS BUTTON TITLE": "Operazioni", "OPS BUTTON": "Ops", @@ -333,18 +333,18 @@ "READ_SHORT": "SL", "READ": "Lettura", "RechargePortalAlert": "Ricaricare", - "REFERENCE_TIME": "Ora riferimento: ", + "REFERENCE_TIME": "Ora riferimento:", "REM_LOC_CP": "Elimina copia locale di {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Vuoi eliominare definitivamente {teamName} dal Server Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Elimina team {teamName}", - "REMOVE_TEAM": "Elimina Team: ", + "REMOVE_TEAM": "Elimina Team:", "REMOVE": "Elimina", - "RENAME_TEAM": "Rinomina Team: ", + "RENAME_TEAM": "Rinomina Team:", "RENAME": "Rinomina", "REQUIRED": "Richieste", "RESET": "Reset", "REVERSE": "Inverti", - "ROCKS_COM": "community enl.rocks: ", + "ROCKS_COM": "community enl.rocks:", "ROLE": "Ruolo", "SAVELINKS TITLE": "Salva Link", "SAVELINKS_DRAW": "Salva Link", @@ -370,15 +370,15 @@ "SET_3_PORT": "Imposta prima i tre portali", "SET_COMMENT": "Imposta Commento", "SET_LCOMMENT": "Imposta commento Link", - "SET_LINK_COMMENT": "Imposta commento per il link: ", + "SET_LINK_COMMENT": "Imposta commento per il link:", "SET_LINKS_ZONES": "Imposta Link alle Zone", - "SET_MARKER_COMMENT": "Imposta commento per il marker su: ", + "SET_MARKER_COMMENT": "Imposta commento per il marker su:", "SET_MARKER_TYPE_TITLE": "Cambia tipo marker", "SET_MARKERS_ZONES": "Imposta Marker alle Zone", "SET_MCOMMENT": "Imposta commento Marker: {portalName}", "SET_NEW_OP": "Impostare il nuovo Nome Operazione", "SET_PCOMMENT": "Imposta commento Portale: {portalName}", - "SET_PORT_COMMENT": "Imposta il commento per il Portale: ", + "SET_PORT_COMMENT": "Imposta il commento per il Portale:", "SET_PORTAL_COMMENT": "Imposta commento Portale", "SET": "impostato", "SETTINGS": "Impostazioni Wasabee", @@ -397,7 +397,7 @@ "START_PORT": "Portale di Partenza ", "STATE": "Stato", "SUPPORT_INSTRUCT": "Per assistenza, entrate nel Canale Telegram per Utenti di Wasabee", - "SWAP PROMPT": "Vuoi scambiare: ", + "SWAP PROMPT": "Vuoi scambiare:", "SWAP TITLE": "Scambia portali", "SWAP WITH": " con ", "SWAP": "Scambia", diff --git a/src/code/translations/Portuguese.json b/src/code/translations/Portuguese.json index f2f1e3543..760b082ff 100644 --- a/src/code/translations/Portuguese.json +++ b/src/code/translations/Portuguese.json @@ -3,8 +3,8 @@ "acknowledged": "Reconhecido", "ADD LINK TITLE": "Adicionar Links", "ADD MARKER TITLE": "Adicionar Marcadores", - "ADD_AGENT": "Adicionar Agente: ", - "ADD_BL": "Adicionar links para trás: ", + "ADD_AGENT": "Adicionar Agente:", + "ADD_BL": "Adicionar links para trás:", "ADD_BULK": "Adição em massa ", "ADD_BUTTON_LINKS": "Adicionar todos os links de uma vez.", "ADD_LINKS": "Adicionar Links", @@ -20,7 +20,7 @@ "AGES": " (há muito tempo)", "ALREADY_HAS_MARKER": "Este portal já tem um marcador. Escolha um portal diferente.", "AMAZ_TEAM_NAME": "Nome incrível da equipe.", - "ANCHOR ASSIGNMENT": "Atribuir todos os links de saída para: ", + "ANCHOR ASSIGNMENT": "Atribuir todos os links de saída para:", "ANCHOR_GMAP": "Mapa Google", "ANCHOR_PORTAL": "Portal Âncora", "ANCHOR_PORTAL2": "Âncora Portal 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Âncora 2", "ANCHOR3": "Âncora 3", "ANCHORS_AS_BOOKMARKS": "Âncora como bookmarks", - "API_KEY": "Chave API do Rocks: ", + "API_KEY": "Chave API do Rocks:", "ASS_TO": "Atrubuir a:", "ASSIGN LINK PROMPT": "Atribuir link para: ${value}", "ASSIGN MARKER PROMPT": "Atrubuir marcador para: ${value}", @@ -93,9 +93,9 @@ "CUR_USER_INFO": "Informações do usuário atual", "D_SHOW_LIST": "Chaves de defesa de entrada", "DEFAULT OP NAME": "Nova Op: ${value}", - "DELETE ANCHOR PROMPT": "Desejas excluir esta âncora e todos os links associados: ", + "DELETE ANCHOR PROMPT": "Desejas excluir esta âncora e todos os links associados:", "DELETE ANCHOR TITLE": "Apagar Âncora", - "DELETE MARKER PROMPT": "Você deseja excluir este marcador: ", + "DELETE MARKER PROMPT": "Você deseja excluir este marcador:", "DELETE MARKER TITLE": "Apagar Marcador", "DELETE_ANCHOR": "Apagar", "DELETE_LINK": "Apagar", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Descrição (opcional)", "DestroyPortalAlert": "Destroir", "dialog.about.download_mobile_app": "

Aplicativo Wasabee:

", - "dialog.agent_comment.text": "Comentario: ", + "dialog.agent_comment.text": "Comentario:", "dialog.agent_comment.title": "Definir comentário para {agentName}", "dialog.auth.ott.button": "Login único para o Token", "dialog.auth.ott.text": "Obtenha um token do servidor Wasabee, e então cole-o aqui", @@ -168,7 +168,7 @@ "ExcludeMarker": "Excluir de Auto-Desenhar / Marcar", "EXPORT OP TITLE": "Exportar Op Actual", "EXPORT OP": "Exportar Op", - "EXPORT": "Exportar: ", + "EXPORT": "Exportar:", "FAKED": "Falsificado: [${value}]", "FANFIELD": "Desenhar", "FANFIELD2": "Desenhar Fan Field", @@ -212,9 +212,9 @@ "LANG": "Língua", "LEAVE": "Deixar", "LetDecayPortalAlert": "Deixar caír", - "LINK ASSIGNMENT": "Atribuir link a: ", + "LINK ASSIGNMENT": "Atribuir link a:", "LINK STATE PROMPT": "Estado do link", - "LINK STATE": "Definir status do link: ", + "LINK STATE": "Definir status do link:", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", "LINKS2": ": Links", @@ -234,11 +234,11 @@ "MADRID": "Desenhar", "MANAGE_TEAM": "Gerenciar ${value}", "MANAGE": "Gerenciar", - "MARKER ASSIGNMENT": "Atribuir marcador a: ", + "MARKER ASSIGNMENT": "Atribuir marcador a:", "MARKER LIST TITLE": "Lista de Marcadores", "MARKER LIST": "Marcadores", "MARKER STATE PROMPT": "Status do marcador", - "MARKER STATE": "Definir estado do marcador: ", + "MARKER STATE": "Definir estado do marcador:", "MARKER_LIST": "Lista de Marcadores: ${value}", "MARKERS BUTTON TITLE": "Marcadores", "MAX_SPLITS": "Divisões máximas", @@ -268,7 +268,7 @@ "MY_CAP_ID": "Minha Capsula ID", "MY_COUNT": "Minha Conta", "NAME_REQ": "Nome Requerido", - "NAME": "Nome: ", + "NAME": "Nome:", "NEW_OP": "Nova Operação", "NEW_TEAM_NAME": "Novo nome de Equipa", "NEW_TEAM": "Nova Equipa", @@ -300,8 +300,8 @@ "OP_SETTINGS_BUTTON": "Op ⚙", "OP_SETTINGS_TITLE": "Configurações de operação", "OPEN_REQUEST": "[pedido aberto]", - "OPER_COLOR": "Cor da operação: ", - "OPER_NAME": "Nome da Operação: ", + "OPER_COLOR": "Cor da operação:", + "OPER_NAME": "Nome da Operação:", "OPERATIONS": "Operações", "OPS BUTTON TITLE": "Operações", "OPS BUTTON": "Ops", @@ -333,18 +333,18 @@ "READ_SHORT": "Ler Abreviado", "READ": "Ler", "RechargePortalAlert": "Recarregar", - "REFERENCE_TIME": "Tempo de Referência: ", + "REFERENCE_TIME": "Tempo de Referência:", "REM_LOC_CP": "Remover cópia local de ${value}", "REMOVE_TEAM_CONFIRM_LABEL": "Você deseja remover permanentemente ${value} do servidor Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipe ${value}", - "REMOVE_TEAM": "Remover Equipa: ", + "REMOVE_TEAM": "Remover Equipa:", "REMOVE": "Remover", - "RENAME_TEAM": "Renomear Equipe: ", + "RENAME_TEAM": "Renomear Equipe:", "RENAME": "Renomear", "REQUIRED": "Requerido", "RESET": "Redefinir", "REVERSE": "Inverter", - "ROCKS_COM": "comunidade enl.rocks: ", + "ROCKS_COM": "comunidade enl.rocks:", "ROLE": "Função", "SAVELINKS TITLE": "Salvar Links", "SAVELINKS_DRAW": "Salvar Links", @@ -370,15 +370,15 @@ "SET_3_PORT": "Defina os três portais primeiro!", "SET_COMMENT": "Definir Comentário", "SET_LCOMMENT": "Definir comentário do link", - "SET_LINK_COMMENT": "Definir comentário para o link: ", + "SET_LINK_COMMENT": "Definir comentário para o link:", "SET_LINKS_ZONES": "Definir links para zonas", - "SET_MARKER_COMMENT": "Definir comentário para marcador em: ", + "SET_MARKER_COMMENT": "Definir comentário para marcador em:", "SET_MARKER_TYPE_TITLE": "Alterar o tipo de marcador", "SET_MARKERS_ZONES": "Definir Marcadores para Zonas", "SET_MCOMMENT": "Definir comentário do marcador: ${value}", "SET_NEW_OP": "Define o novo nome da operação", "SET_PCOMMENT": "Definir comentário do portal: ${value}", - "SET_PORT_COMMENT": "Definir comentário para portal: ", + "SET_PORT_COMMENT": "Definir comentário para portal:", "SET_PORTAL_COMMENT": "Definir comentário do portal", "SET": "definir", "SETTINGS": "Configurações do Wasabee", @@ -397,7 +397,7 @@ "START_PORT": "Portal inicial", "STATE": "Estado", "SUPPORT_INSTRUCT": "Para obter suporte, por favor, junte-se ao The Wasabee User Telegram Channel", - "SWAP PROMPT": "Queres trocar: ", + "SWAP PROMPT": "Queres trocar:", "SWAP TITLE": "Trocar Portais", "SWAP WITH": " com ", "SWAP": "Troca", diff --git a/src/code/translations/Russian.json b/src/code/translations/Russian.json index 898090992..8372c0efb 100644 --- a/src/code/translations/Russian.json +++ b/src/code/translations/Russian.json @@ -3,8 +3,8 @@ "acknowledged": "цель получена", "ADD LINK TITLE": "Добавление линков", "ADD MARKER TITLE": "Добавление маркеров", - "ADD_AGENT": "Добавить агента: ", - "ADD_BL": "Добавить перемычки: ", + "ADD_AGENT": "Добавить агента:", + "ADD_BL": "Добавить перемычки:", "ADD_BULK": "Массовое добавление", "ADD_BUTTON_LINKS": "Добавить все линки сразу.", "ADD_LINKS": "Добавить линки", @@ -20,7 +20,7 @@ "AGES": " (давно)", "ALREADY_HAS_MARKER": "У этого портала уже есть маркер. Выбери другой портал.", "AMAZ_TEAM_NAME": "Отличное название.", - "ANCHOR ASSIGNMENT": "Назначить все исходящие линки: ", + "ANCHOR ASSIGNMENT": "Назначить все исходящие линки:", "ANCHOR_GMAP": "Google-карты", "ANCHOR_PORTAL": "Опорный портал", "ANCHOR_PORTAL2": "Опорный портал 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Опорник 2", "ANCHOR3": "Опорник 3", "ANCHORS_AS_BOOKMARKS": "Опорники в закладки", - "API_KEY": "API ключ Rocks: ", + "API_KEY": "API ключ Rocks:", "ASS_TO": "Назначено агенту", "ASSIGN LINK PROMPT": "Назначить линк с портала: {portalName}", "ASSIGN MARKER PROMPT": "Назначить маркер с {portalName}", @@ -93,9 +93,9 @@ "CUR_USER_INFO": "Информация о пользователе", "D_SHOW_LIST": "Ввести ключи на руках", "DEFAULT OP NAME": "Новая ОПРЦ: {date}", - "DELETE ANCHOR PROMPT": "Хочешь удалить этот портал и все связанные линки: ", + "DELETE ANCHOR PROMPT": "Хочешь удалить этот портал и все связанные линки:", "DELETE ANCHOR TITLE": "Удалить портал", - "DELETE MARKER PROMPT": "Хочешь удалить этот маркер: ", + "DELETE MARKER PROMPT": "Хочешь удалить этот маркер:", "DELETE MARKER TITLE": "Удалить маркер", "DELETE_ANCHOR": "Удалить", "DELETE_LINK": "Удалить", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Описание (опционально)", "DestroyPortalAlert": "Снести", "dialog.about.download_mobile_app": "

Приложение Wasabee:

", - "dialog.agent_comment.text": "Комментарий: ", + "dialog.agent_comment.text": "Комментарий:", "dialog.agent_comment.title": "Задать комментарий для {agentName}", "dialog.auth.ott.button": "Вход с одноразовым токеном", "dialog.auth.ott.text": "Получи токен на сервере Wasabee, затем вставь его здесь", @@ -168,7 +168,7 @@ "ExcludeMarker": "Исключить из авто-рисовки/маркировки", "EXPORT OP TITLE": "Экспортировать текущую ОПРЦ", "EXPORT OP": "Экспортировать ОПРЦ", - "EXPORT": "Экспортировать: ", + "EXPORT": "Экспортировать:", "FAKED": "Неподгружен: [{portalId}]", "FANFIELD": "Нарисовать", "FANFIELD2": "Нарисовать Fan Field", @@ -212,9 +212,9 @@ "LANG": "Язык", "LEAVE": "Выйти", "LetDecayPortalAlert": "Просадить", - "LINK ASSIGNMENT": "Назначить линк: ", + "LINK ASSIGNMENT": "Назначить линк:", "LINK STATE PROMPT": "Статус линка", - "LINK STATE": "Установить статус линка: ", + "LINK STATE": "Установить статус линка:", "LINKS BUTTON TITLE": "Линки", "LINKS": "Линки", "LINKS2": "{portalName} : Линки ({outgoing}↑/{incoming}↓)", @@ -234,11 +234,11 @@ "MADRID": "Нарисовать", "MANAGE_TEAM": "Редактировать {teamName}", "MANAGE": "Редактировать", - "MARKER ASSIGNMENT": "Назначить маркер: ", + "MARKER ASSIGNMENT": "Назначить маркер:", "MARKER LIST TITLE": "Список маркеров", "MARKER LIST": "Маркеры", "MARKER STATE PROMPT": "Статус маркера", - "MARKER STATE": "Установить статус маркера: ", + "MARKER STATE": "Установить статус маркера:", "MARKER_LIST": "Список маркеров: {opName}", "MARKERS BUTTON TITLE": "Маркеры", "MAX_SPLITS": "Максимальный уровень", @@ -268,7 +268,7 @@ "MY_CAP_ID": "ID моей капсулы", "MY_COUNT": "Моё количество", "NAME_REQ": "Требуется имя", - "NAME": "Название: ", + "NAME": "Название:", "NEW_OP": "Новая операция", "NEW_TEAM_NAME": "Новое имя команды", "NEW_TEAM": "Новая команда", @@ -300,8 +300,8 @@ "OP_SETTINGS_BUTTON": "ОПРЦ ⚙", "OP_SETTINGS_TITLE": "Настройки операции", "OPEN_REQUEST": "[открытый запрос]", - "OPER_COLOR": "Цвет операции: ", - "OPER_NAME": "Название операции: ", + "OPER_COLOR": "Цвет операции:", + "OPER_NAME": "Название операции:", "OPERATIONS": "Операции", "OPS BUTTON TITLE": "Список операций", "OPS BUTTON": "Выбери ОПРЦ", @@ -333,18 +333,18 @@ "READ_SHORT": "RO", "READ": "только чтение", "RechargePortalAlert": "Зарядить", - "REFERENCE_TIME": "Референсное время: ", + "REFERENCE_TIME": "Референсное время:", "REM_LOC_CP": "Удалить локальную копию {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "Хочешь навсегда удалить {teamName} с сервера Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Удаление команды {teamName}", - "REMOVE_TEAM": "Удалить команду: ", + "REMOVE_TEAM": "Удалить команду:", "REMOVE": "Удалить", - "RENAME_TEAM": "Переименовать команду: ", + "RENAME_TEAM": "Переименовать команду:", "RENAME": "Переименовать", "REQUIRED": "Требуется", "RESET": "Сброс", "REVERSE": "Обратить", - "ROCKS_COM": "Сообщество enl.rocks: ", + "ROCKS_COM": "Сообщество enl.rocks:", "ROLE": "Роль", "SAVELINKS TITLE": "Сохранить линки", "SAVELINKS_DRAW": "Сохранить линки", @@ -370,15 +370,15 @@ "SET_3_PORT": "Сначала задай три портала!", "SET_COMMENT": "Задать комментарий", "SET_LCOMMENT": "Задать комментарий к линку", - "SET_LINK_COMMENT": "Задать комментарий для линка: ", + "SET_LINK_COMMENT": "Задать комментарий для линка:", "SET_LINKS_ZONES": "Задать линкам зоны", - "SET_MARKER_COMMENT": "Задать комментарий для маркера на: ", + "SET_MARKER_COMMENT": "Задать комментарий для маркера на:", "SET_MARKER_TYPE_TITLE": "Изменить тип маркера", "SET_MARKERS_ZONES": "Задать маркеры в зоны", "SET_MCOMMENT": "Задать комментария маркеру: {portalName}", "SET_NEW_OP": "Задай имя для новой операции", "SET_PCOMMENT": "Задать комментарий порталу: {portalName}", - "SET_PORT_COMMENT": "Задать комментарий порталу: ", + "SET_PORT_COMMENT": "Задать комментарий порталу:", "SET_PORTAL_COMMENT": "Задать комментарий порталу", "SET": "задать", "SETTINGS": "Настройки Wasabee", @@ -397,7 +397,7 @@ "START_PORT": "Стартовый портал ", "STATE": "Статус", "SUPPORT_INSTRUCT": "Для поддержки, присоединяйся к The Wasabee User Telegram Channel", - "SWAP PROMPT": "Хочешь заменить: ", + "SWAP PROMPT": "Хочешь заменить:", "SWAP TITLE": "Замена порталов", "SWAP WITH": " на ", "SWAP": "Замена", diff --git a/src/code/translations/Spanish.json b/src/code/translations/Spanish.json index 1896b6bca..700a310d0 100644 --- a/src/code/translations/Spanish.json +++ b/src/code/translations/Spanish.json @@ -20,7 +20,7 @@ "AGES": "(Hace demasiado tiempo)", "ALREADY_HAS_MARKER": "Este portal ya tiene un marcador. Elige un portal diferente.", "AMAZ_TEAM_NAME": "Excelente nombre de equipo", - "ANCHOR ASSIGNMENT": "Assign all outbound links to: ", + "ANCHOR ASSIGNMENT": "Assign all outbound links to:", "ANCHOR_GMAP": "Google Map", "ANCHOR_PORTAL": "Portal Ancla", "ANCHOR_PORTAL2": "Portal Ancla 2", @@ -29,7 +29,7 @@ "ANCHOR2": "Ancla 2", "ANCHOR3": "Ancla 3", "ANCHORS_AS_BOOKMARKS": "Anclas a Marcadores", - "API_KEY": "Rocks API key: ", + "API_KEY": "Rocks API key:", "ASS_TO": "Asignado A", "ASSIGN LINK PROMPT": "Asignar link de {portalName}", "ASSIGN MARKER PROMPT": "Asignar marcador de {portalName}", @@ -103,7 +103,7 @@ "DESCRIP_PLACEHOLD": "Descripción (opcional)", "DestroyPortalAlert": "Destruir", "dialog.about.download_mobile_app": "

Aplicación Wasabee:

", - "dialog.agent_comment.text": "Comment: ", + "dialog.agent_comment.text": "Comment:", "dialog.agent_comment.title": "Establecer comentario para {agentName}", "dialog.auth.ott.button": "Inicio de sesión con token de un único uso", "dialog.auth.ott.text": "Obtén un token en el Servidor Wasabee y pégalo aquí después", @@ -212,9 +212,9 @@ "LANG": "Idioma", "LEAVE": "Salir", "LetDecayPortalAlert": "Dejar Decaer", - "LINK ASSIGNMENT": "Assign link to: ", + "LINK ASSIGNMENT": "Assign link to:", "LINK STATE PROMPT": "Estado del Link", - "LINK STATE": "Set link status: ", + "LINK STATE": "Set link status:", "LINKS BUTTON TITLE": "Enlaces", "LINKS": "Enlaces", "LINKS2": "{portalName}: Enlaces ({outgoing}↑/{incoming}↓)", @@ -234,11 +234,11 @@ "MADRID": "Dibujar", "MANAGE_TEAM": "Gestionar {teamName}", "MANAGE": "Gestionar", - "MARKER ASSIGNMENT": "Assign marker to: ", + "MARKER ASSIGNMENT": "Assign marker to:", "MARKER LIST TITLE": "Lista de Marcadores", "MARKER LIST": "Marcadores", "MARKER STATE PROMPT": "Estado Del Marcador", - "MARKER STATE": "Set marker state: ", + "MARKER STATE": "Set marker state:", "MARKER_LIST": "Listad de Marcadores {opName}", "MARKERS BUTTON TITLE": "Marcadores", "MAX_SPLITS": "Divisiones máximas", @@ -333,7 +333,7 @@ "READ_SHORT": "SL", "READ": "Leer", "RechargePortalAlert": "Recargar", - "REFERENCE_TIME": "Hora de referencia: ", + "REFERENCE_TIME": "Hora de referencia:", "REM_LOC_CP": "Borrar copia local de {opName}", "REMOVE_TEAM_CONFIRM_LABEL": "¿Deseas remover {teamName} permanentemente del Servidor Wasabee?", "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipo {teamName}", From e292974638c8a7244e74aee91bc025e15e076aad Mon Sep 17 00:00:00 2001 From: Bill Gillock Date: Mon, 7 Feb 2022 13:22:08 -0600 Subject: [PATCH 247/275] Rename Wasabee settings to Advance settings (#332) --- src/code/dialogs/settingsDialog.js | 2 +- src/code/toolbox.ts | 2 +- src/code/translations/Danish.json | 3 ++- src/code/translations/English.json | 3 ++- src/code/translations/Filipino.json | 3 ++- src/code/translations/French.json | 3 ++- src/code/translations/German.json | 3 ++- src/code/translations/Italian.json | 3 ++- src/code/translations/Portuguese.json | 3 ++- src/code/translations/Russian.json | 3 ++- src/code/translations/Spanish.json | 3 ++- 11 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index dae7be00a..ff54cb217 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -195,7 +195,7 @@ const SettingsDialog = WDialog.extend({ }; this.createDialog({ - title: wX("SETTINGS"), + title: wX("SETTINGS_TITLE"), html: container, width: "auto", dialogClass: "settings", diff --git a/src/code/toolbox.ts b/src/code/toolbox.ts index d37b71ebf..1c4481d3b 100644 --- a/src/code/toolbox.ts +++ b/src/code/toolbox.ts @@ -20,7 +20,7 @@ export function setupToolbox() { const settingsLink = L.DomUtil.create("a", "wasabee", toolbox); settingsLink.href = "#"; - settingsLink.textContent = wX("SETTINGS"); + settingsLink.textContent = wX("SETTINGS_TOOLBOX"); L.DomEvent.on(settingsLink, "click", (ev) => { L.DomEvent.stop(ev); diff --git a/src/code/translations/Danish.json b/src/code/translations/Danish.json index 0f89fae54..3cde8d6dc 100644 --- a/src/code/translations/Danish.json +++ b/src/code/translations/Danish.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Indstil kommentar til portal:", "SET_PORTAL_COMMENT": "Indstil portalkommentar", "SET": "indstil", - "SETTINGS": "Wasabee Indstillinger", + "SETTINGS_TOOLBOX": "Wasabee Indstillinger", + "SETTINGS_TITLE": "Fremskreden Indstillinger", "SKINS_AVAILABLE": "Der er {count} tilgængelige skins.", "SKINS_BUTTON": "Konfigurer skins", "SKINS_DESCRIPTION": "Tilgængelige skin packs er placeret i højre kolonner. Flyt skins, du ønsker at bruge, til venstre kolonne.", diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 683fad7bc..1bb3c18a1 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Set comment for portal:", "SET_PORTAL_COMMENT": "Set Portal Comment", "SET": "set", - "SETTINGS": "Wasabee Settings", + "SETTINGS_TOOLBOX": "Wasabee Settings", + "SETTINGS_TITLE": "Advanced Settings", "SKINS_AVAILABLE": "There are {count} available skins.", "SKINS_BUTTON": "Configure Skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", diff --git a/src/code/translations/Filipino.json b/src/code/translations/Filipino.json index f6880a845..acd1b93a3 100644 --- a/src/code/translations/Filipino.json +++ b/src/code/translations/Filipino.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Komento para sa portal:", "SET_PORTAL_COMMENT": "Magtalaga komento sa portal", "SET": "italaga", - "SETTINGS": "Settings ng Wasabee", + "SETTINGS_TOOLBOX": "Settings ng Wasabee", + "SETTINGS_TITLE": "Mga advanced na setting", "SKINS_AVAILABLE": "There are {count} available skins.", "SKINS_BUTTON": "Configure Skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", diff --git a/src/code/translations/French.json b/src/code/translations/French.json index 70738e9f7..4839e45f2 100644 --- a/src/code/translations/French.json +++ b/src/code/translations/French.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Entrer un commentaire pour ce portail", "SET_PORTAL_COMMENT": "Entrer un commentaire", "SET": "Définir", - "SETTINGS": "Parametres Wasabee", + "SETTINGS_TOOLBOX": "Parametres Wasabee", + "SETTINGS_TITLE": "Réglages avancés", "SKINS_AVAILABLE": "Il y a {count} thèmes disponibles.", "SKINS_BUTTON": "Choisir les thèmes", "SKINS_DESCRIPTION": "Déplacer les thèmes de la colonne de droite vers la colonne de gauche pour les activer. L'ordre permet de les combiner. Le thème le plus bas est le dernier appliqué.", diff --git a/src/code/translations/German.json b/src/code/translations/German.json index 73bc0e376..685b345a3 100644 --- a/src/code/translations/German.json +++ b/src/code/translations/German.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Set comment for portal:", "SET_PORTAL_COMMENT": "Set Portal Comment", "SET": "setzen", - "SETTINGS": "Wasabee Settings", + "SETTINGS_TOOLBOX": "Wasabee Settings", + "SETTINGS_TITLE": "Erweiterte Einstellungen", "SKINS_AVAILABLE": "There are {count} available skins.", "SKINS_BUTTON": "Configure Skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", diff --git a/src/code/translations/Italian.json b/src/code/translations/Italian.json index 66dc15061..dd9ab76cc 100644 --- a/src/code/translations/Italian.json +++ b/src/code/translations/Italian.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Imposta il commento per il Portale:", "SET_PORTAL_COMMENT": "Imposta commento Portale", "SET": "impostato", - "SETTINGS": "Impostazioni Wasabee", + "SETTINGS_TOOLBOX": "Impostazioni Wasabee", + "SETTINGS_TITLE": "Impostazioni avanzate", "SKINS_AVAILABLE": "Sono disponibili {count} skin.", "SKINS_BUTTON": "Configura Skin", "SKINS_DESCRIPTION": "Gestisci le skin disponibili spostandole nella colonna di sinistra. Le skin più in basso hanno priorità più alta sulla UI.", diff --git a/src/code/translations/Portuguese.json b/src/code/translations/Portuguese.json index 760b082ff..85a874b45 100644 --- a/src/code/translations/Portuguese.json +++ b/src/code/translations/Portuguese.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Definir comentário para portal:", "SET_PORTAL_COMMENT": "Definir comentário do portal", "SET": "definir", - "SETTINGS": "Configurações do Wasabee", + "SETTINGS_TOOLBOX": "Configurações do Wasabee", + "SETTINGS_TITLE": "Configurações avançadas", "SKINS_AVAILABLE": "Existem ${value} skins disponíveis.", "SKINS_BUTTON": "Configurar Skins", "SKINS_DESCRIPTION": "Gerenciar as skins disponíveis movendo o tema para a coluna da esquerda. Quanto mais baixo na coluna, maior será a prioridade para o UI.", diff --git a/src/code/translations/Russian.json b/src/code/translations/Russian.json index 8372c0efb..655f69003 100644 --- a/src/code/translations/Russian.json +++ b/src/code/translations/Russian.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Задать комментарий порталу:", "SET_PORTAL_COMMENT": "Задать комментарий порталу", "SET": "задать", - "SETTINGS": "Настройки Wasabee", + "SETTINGS_TOOLBOX": "Настройки Wasabee", + "SETTINGS_TITLE": "Расширенные настройки", "SKINS_AVAILABLE": "Есть {count} доступных скинов.", "SKINS_BUTTON": "Настроить скины", "SKINS_DESCRIPTION": "Пакеты доступных скинов размещены в правой колонке. Перемести в левую колонку те, которые хочешь использовать.", diff --git a/src/code/translations/Spanish.json b/src/code/translations/Spanish.json index 700a310d0..aa3e6740a 100644 --- a/src/code/translations/Spanish.json +++ b/src/code/translations/Spanish.json @@ -381,7 +381,8 @@ "SET_PORT_COMMENT": "Definir comentario para el portal", "SET_PORTAL_COMMENT": "Definir comentarios del portal", "SET": "definir", - "SETTINGS": "Configuración de Wasabee", + "SETTINGS_TOOLBOX": "Configuración de Wasabee", + "SETTINGS_TITLE": "Ajustes avanzados", "SKINS_AVAILABLE": "Hay {count} skins disponibles.", "SKINS_BUTTON": "Configurar skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", From b9360db5ead12a6cb8e3e178e82128a12d6298fa Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 7 Feb 2022 21:44:09 +0100 Subject: [PATCH 248/275] fix: setting title --- src/code/dialogs/settingsDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index ff54cb217..d2341ac5a 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -22,7 +22,7 @@ const SettingsDialog = WDialog.extend({ update: function () { this.setContent(this._getContent()); - this.setTitle(wX("SETTINGS")); + this.setTitle(wX("SETTINGS_TITLE")); }, _addCheckBox(container, label, id, storageKey, onChange, defValue) { From 6177dca81df1ac02979840bc287b3969a35e1eaa Mon Sep 17 00:00:00 2001 From: Bill Gillock Date: Mon, 7 Feb 2022 15:17:28 -0600 Subject: [PATCH 249/275] Persist sortBy and sortAsc in local storage for ops, checklist, links and markers (#341) --- src/code/dialogs/checklist.js | 26 ++++++++++++++------ src/code/dialogs/keysList.js | 4 +-- src/code/dialogs/linkListDialog.js | 14 ++++++++--- src/code/dialogs/markerList.js | 14 +++++++---- src/code/dialogs/opsDialog.js | 18 ++++++++++---- src/code/sortable.ts | 39 ++++++++++++++++++++++++------ 6 files changed, 85 insertions(+), 30 deletions(-) diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 2c60f812e..9b4904ce5 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -26,6 +26,9 @@ const OperationChecklistDialog = WDialog.extend({ TYPE: "operationChecklist", }, + SORTBY_KEY: "wasabee-checklist-sortby", + SORTASC_KEY: "wasabee-checklist-sortasc", + options: { usePane: true, }, @@ -51,12 +54,13 @@ const OperationChecklistDialog = WDialog.extend({ _displayDialog: async function () { const operation = getSelectedOperation(); loadFaked(operation); + this.sortable = this.getListDialogContent( operation, operation.links.concat(operation.markers), - 0, - false - ); // defaults to sorting by op order + this.SORTBY_KEY, + this.SORTASC_KEY + ); const buttons = {}; buttons[wX("OK")] = () => { @@ -94,9 +98,10 @@ const OperationChecklistDialog = WDialog.extend({ this.sortable = this.getListDialogContent( operation, operation.links.concat(operation.markers), - this.sortable.sortBy, - this.sortable.sortAsc + this.SORTBY_KEY, + this.SORTASC_KEY ); + await this.sortable.done; this.setContent(this.sortable.table); }, @@ -295,11 +300,16 @@ const OperationChecklistDialog = WDialog.extend({ return columns; }, - getListDialogContent: function (operation, items, sortBy, sortAsc) { + getListDialogContent: function ( + operation, + items, + sortByStoreKey, + sortAscStoreKey + ) { const content = new Sortable(); content.fields = this.getFields(operation); - content.sortBy = sortBy; - content.sortAsc = sortAsc; + content.sortByStoreKey = sortByStoreKey; + content.sortAscStoreKey = sortAscStoreKey; content.items = items; return content; }, diff --git a/src/code/dialogs/keysList.js b/src/code/dialogs/keysList.js index 343022222..e4243601a 100644 --- a/src/code/dialogs/keysList.js +++ b/src/code/dialogs/keysList.js @@ -45,7 +45,7 @@ const KeysList = WDialog.extend({ this.createDialog({ title: wX("KEY_LIST2", { opName: operation.name }), - html: this.getListDialogContent(operation, 0, false).table, + html: this.getListDialogContent(operation, 0, true).table, width: "auto", dialogClass: "keyslist", buttons: buttons, @@ -153,7 +153,7 @@ const KeysList = WDialog.extend({ }, ]); } else { - this.sortable.fields = always; + this.sortable.fields = always; } const keys = new Array(); diff --git a/src/code/dialogs/linkListDialog.js b/src/code/dialogs/linkListDialog.js index a45345108..303994b67 100644 --- a/src/code/dialogs/linkListDialog.js +++ b/src/code/dialogs/linkListDialog.js @@ -11,6 +11,9 @@ const LinkListDialog = OperationChecklistDialog.extend({ TYPE: "linkListDialog", }, + SORTBY_KEY: "wasabee-linklist-sortby", + SORTASC_KEY: "wasabee-linklist-sortasc", + options: { usePane: true, // portal @@ -55,7 +58,12 @@ const LinkListDialog = OperationChecklistDialog.extend({ ).length; const toCount = links.length - fromCount; - this.sortable = this.getListDialogContent(operation, links, 0, false); // defaults to sorting by op order + this.sortable = this.getListDialogContent( + operation, + links, + this.SORTBY_KEY, + this.SORTASC_KEY + ); const buttons = {}; buttons[wX("OK")] = () => { @@ -89,8 +97,8 @@ const LinkListDialog = OperationChecklistDialog.extend({ this.sortable = this.getListDialogContent( operation, links, - this.sortable.sortBy, - this.sortable.sortAsc + this.SORTBY_KEY, + this.SORTASC_KEY ); await this.sortable.done; this.setContent(this.sortable.table); diff --git a/src/code/dialogs/markerList.js b/src/code/dialogs/markerList.js index 3090f1d87..db2443807 100644 --- a/src/code/dialogs/markerList.js +++ b/src/code/dialogs/markerList.js @@ -8,15 +8,19 @@ const MarkerList = OperationChecklistDialog.extend({ TYPE: "markerList", }, + SORTBY_KEY: "wasabee-markerlist-sortby", + SORTASC_KEY: "wasabee-markerlist-sortasc", + _displayDialog: async function () { const operation = getSelectedOperation(); loadFaked(operation); + this.sortable = this.getListDialogContent( operation, operation.markers, - 0, - false - ); // defaults to sorting by op order + this.SORTBY_KEY, + this.SORTASC_KEY + ); const buttons = {}; buttons[wX("CLEAR MARKERS")] = () => { @@ -46,8 +50,8 @@ const MarkerList = OperationChecklistDialog.extend({ this.sortable = this.getListDialogContent( operation, operation.markers, - this.sortable.sortBy, - this.sortable.sortAsc + this.SORTBY_KEY, + this.SORTASC_KEY ); await this.sortable.done; this.setContent(this.sortable.table); diff --git a/src/code/dialogs/opsDialog.js b/src/code/dialogs/opsDialog.js index f2b3722a0..c38bff64d 100644 --- a/src/code/dialogs/opsDialog.js +++ b/src/code/dialogs/opsDialog.js @@ -24,6 +24,9 @@ const OpsDialog = WDialog.extend({ TYPE: "opsDialog", }, + SORTBY_KEY: "wasabee-opslist-sortby", + SORTASC_KEY: "wasabee-opslist-sortasc", + options: { usePane: true, }, @@ -47,9 +50,11 @@ const OpsDialog = WDialog.extend({ _displayDialog: async function () { this.initSortable(); - await this.updateSortable(0, false); + + await this.updateSortable(); const buttons = {}; + // wX buttons[wX("dialog.ops_list.unhide_ops")] = () => { resetHiddenOps(); this.update(); @@ -80,7 +85,7 @@ const OpsDialog = WDialog.extend({ update: async function () { if (this._enabled) { - await this.updateSortable(this.sortable.sortBy, this.sortable.sortAsc); + await this.updateSortable(); // this.setContent(this.sortable.table); } }, @@ -183,12 +188,14 @@ const OpsDialog = WDialog.extend({ const background = L.DomUtil.create("input", null, cell); background.type = "checkbox"; background.checked = op.background; + background.title = op.background ? wX("dialog.ops_list.background_disable") : wX("dialog.ops_list.background_enable"); L.DomEvent.on(background, "change", (ev) => { L.DomEvent.stop(ev); const background = ev.target; + // wX background.title = background.checked ? wX("dialog.ops_list.background_disable") : wX("dialog.ops_list.background_enable"); @@ -245,10 +252,12 @@ const OpsDialog = WDialog.extend({ }, }, ]; + content.sortByStoreKey = this.SORTBY_KEY; + content.sortAscStoreKey = this.SORTASC_KEY; this.sortable = content; }, - updateSortable: async function (sortBy, sortAsc) { + updateSortable: async function () { if (!this.sortable) return; // collapse markers and links into one array. const showHiddenOps = @@ -294,8 +303,7 @@ const OpsDialog = WDialog.extend({ } ops.push(sum); } - this.sortable.sortBy = sortBy; - this.sortable.sortAsc = sortAsc; + this.sortable.items = ops; await this.sortable.done; diff --git a/src/code/sortable.ts b/src/code/sortable.ts index ed6b15e76..d85b8a8ea 100644 --- a/src/code/sortable.ts +++ b/src/code/sortable.ts @@ -28,14 +28,16 @@ export default class Sortable { _foot: HTMLTableSectionElement; _smallScreen: boolean; _done: Promise | boolean; + _sortByStoreKey: string; + _sortAscStoreKey: string; constructor() { this._items = []; this._fields = []; this._sortBy = 0; // which field/column number to sort by - this._sortAsc = false; // ascending or descending + this._sortAsc = true; // ascending or descending this._table = L.DomUtil.create("table", "wasabee-table"); - + // create this once for all this._head = L.DomUtil.create("thead", null, this._table); this._body = L.DomUtil.create("tbody", null, this._table); @@ -43,7 +45,8 @@ export default class Sortable { // if IITC-Mobile is detected... this is a kludge this._smallScreen = window.plugin.userLocation ? true : false; - + this._sortByStoreKey = ""; + this._sortAscStoreKey = ""; this._done = true; } @@ -68,6 +71,7 @@ export default class Sortable { set sortBy(property) { this._sortBy = Number(property); + this.renderHead(); this.sort(); } @@ -78,9 +82,26 @@ export default class Sortable { set sortAsc(b) { if (b !== true) b = false; this._sortAsc = b; + this.renderHead(); this.sort(); } + set sortByStoreKey(b) { + this._sortByStoreKey = b; + if (localStorage[this._sortByStoreKey] == null) { + localStorage[this._sortByStoreKey] = 0; + } + this.sortBy = localStorage[this._sortByStoreKey]; + } + + set sortAscStoreKey(b) { + this._sortAscStoreKey = b; + if (localStorage[this._sortAscStoreKey] == null) { + localStorage[this._sortAscStoreKey] = "true"; + } + this.sortAsc = localStorage[this._sortAscStoreKey] == "true"; + } + get table() { return this._table; } @@ -189,22 +210,26 @@ export default class Sortable { cell.style.display = "none"; if (field.sort !== null) { L.DomUtil.addClass(cell, "sortable"); + if (index == this._sortBy) { + L.DomUtil.addClass(cell, this._sortAsc ? "asc" : "desc"); + } L.DomEvent.on( cell, "click", (ev) => { L.DomEvent.stop(ev); for (const element of titleRow.children) { - L.DomUtil.removeClass(element as HTMLElement, "sorted"); L.DomUtil.removeClass(element as HTMLElement, "asc"); L.DomUtil.removeClass(element as HTMLElement, "desc"); } if (index == this._sortBy) { this._sortAsc = !this._sortAsc; - L.DomUtil.addClass(cell, "sorted"); - L.DomUtil.addClass(cell, this._sortAsc ? "asc" : "desc"); } + L.DomUtil.addClass(cell, this._sortAsc ? "asc" : "desc"); + this._sortBy = index; + if (this._sortByStoreKey != null) localStorage[this._sortByStoreKey] = this._sortBy; + if (this._sortAscStoreKey != null) localStorage[this._sortAscStoreKey] = this._sortAsc.toString(); this.sort(); }, false @@ -246,7 +271,7 @@ export default class Sortable { } // if two values are the same, preserve previous order if (l == 0) l = a.index - b.index; - return this._sortAsc ? -l : l; + return this._sortAsc ? l : -l; }); for (const [index, item] of this._items.entries()) { From fc8663b4efd3445d738c0157ea2cb4267d9a87be Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 5 Feb 2022 17:29:49 +0100 Subject: [PATCH 250/275] fix [OK] to [Close] in some dialogs --- src/code/dialogs/about.js | 2 +- src/code/dialogs/agentDialog.js | 2 +- src/code/dialogs/authDialog.js | 2 +- src/code/dialogs/autodraws.js | 2 +- src/code/dialogs/blockersList.js | 2 +- src/code/dialogs/checklist.js | 2 +- src/code/dialogs/defensiveKeysDialog.js | 2 +- src/code/dialogs/exportDialog.js | 2 +- src/code/dialogs/keyListPortal.js | 2 +- src/code/dialogs/keysList.js | 2 +- src/code/dialogs/linkListDialog.js | 2 +- src/code/dialogs/markerAddDialog.js | 2 +- src/code/dialogs/markerList.js | 2 +- src/code/dialogs/newopDialog.js | 2 +- src/code/dialogs/onlineAgentList.js | 2 +- src/code/dialogs/opPerms.js | 2 +- src/code/dialogs/teamListDialog.js | 2 +- src/code/dialogs/teamMembershipList.js | 2 +- src/code/dialogs/trawl.js | 4 ++-- src/code/dialogs/wasabeeDlist.js | 2 +- src/code/dialogs/zoneDialog.js | 2 +- 21 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/code/dialogs/about.js b/src/code/dialogs/about.js index 7f318d38c..1e08f8359 100644 --- a/src/code/dialogs/about.js +++ b/src/code/dialogs/about.js @@ -42,7 +42,7 @@ const AboutDialog = WDialog.extend({ // Since the JqueryUI dialog buttons are hard-coded, we have to override them to translate them const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/agentDialog.js b/src/code/dialogs/agentDialog.js index 6ef9fe961..890d70a55 100644 --- a/src/code/dialogs/agentDialog.js +++ b/src/code/dialogs/agentDialog.js @@ -47,7 +47,7 @@ const AgentDialog = WDialog.extend({ } const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/authDialog.js b/src/code/dialogs/authDialog.js index 873e6fa0c..790ddc72d 100644 --- a/src/code/dialogs/authDialog.js +++ b/src/code/dialogs/authDialog.js @@ -154,7 +154,7 @@ const AuthDialog = WDialog.extend({ }); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/autodraws.js b/src/code/dialogs/autodraws.js index 18180dba9..75e8233ea 100644 --- a/src/code/dialogs/autodraws.js +++ b/src/code/dialogs/autodraws.js @@ -107,7 +107,7 @@ const AutodrawsDialog = WDialog.extend({ } const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/blockersList.js b/src/code/dialogs/blockersList.js index a60e3688a..3fc03cc70 100644 --- a/src/code/dialogs/blockersList.js +++ b/src/code/dialogs/blockersList.js @@ -48,7 +48,7 @@ const BlockerList = WDialog.extend({ this.sortable = await this._getListDialogContent(0, false); // defaults to sorting by op order loadBlockerFaked(operation); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; // doesn't support op select event diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 9b4904ce5..734eb0bca 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -63,7 +63,7 @@ const OperationChecklistDialog = WDialog.extend({ ); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; buttons[wX("LOAD PORTALS")] = () => { diff --git a/src/code/dialogs/defensiveKeysDialog.js b/src/code/dialogs/defensiveKeysDialog.js index 229a150e9..aa9392b41 100644 --- a/src/code/dialogs/defensiveKeysDialog.js +++ b/src/code/dialogs/defensiveKeysDialog.js @@ -83,7 +83,7 @@ const DefensiveKeysDialog = WDialog.extend({ const content = this._buildContent(); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/exportDialog.js b/src/code/dialogs/exportDialog.js index f1f383ec6..e6e39f479 100644 --- a/src/code/dialogs/exportDialog.js +++ b/src/code/dialogs/exportDialog.js @@ -17,7 +17,7 @@ const ExportDialog = WDialog.extend({ _displayDialog: function () { const operation = getSelectedOperation(); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; buttons[wX("DRAW TOOLS FORMAT")] = () => { diff --git a/src/code/dialogs/keyListPortal.js b/src/code/dialogs/keyListPortal.js index f32c9ec2d..57fa8cb09 100644 --- a/src/code/dialogs/keyListPortal.js +++ b/src/code/dialogs/keyListPortal.js @@ -35,7 +35,7 @@ const KeyListPortal = WDialog.extend({ this._sortable = this.getSortable(); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/keysList.js b/src/code/dialogs/keysList.js index e4243601a..d784fe101 100644 --- a/src/code/dialogs/keysList.js +++ b/src/code/dialogs/keysList.js @@ -39,7 +39,7 @@ const KeysList = WDialog.extend({ _displayDialog: function () { const operation = getSelectedOperation(); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/linkListDialog.js b/src/code/dialogs/linkListDialog.js index 303994b67..a21214afc 100644 --- a/src/code/dialogs/linkListDialog.js +++ b/src/code/dialogs/linkListDialog.js @@ -66,7 +66,7 @@ const LinkListDialog = OperationChecklistDialog.extend({ ); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/markerAddDialog.js b/src/code/dialogs/markerAddDialog.js index 38d2609b0..a088076f0 100644 --- a/src/code/dialogs/markerAddDialog.js +++ b/src/code/dialogs/markerAddDialog.js @@ -144,7 +144,7 @@ const MarkerAddDialog = WDialog.extend({ }); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/markerList.js b/src/code/dialogs/markerList.js index db2443807..0da9cd4a2 100644 --- a/src/code/dialogs/markerList.js +++ b/src/code/dialogs/markerList.js @@ -27,7 +27,7 @@ const MarkerList = OperationChecklistDialog.extend({ clearAllMarkers(getSelectedOperation()); }; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/newopDialog.js b/src/code/dialogs/newopDialog.js index a7b240716..30e3d4d48 100644 --- a/src/code/dialogs/newopDialog.js +++ b/src/code/dialogs/newopDialog.js @@ -56,7 +56,7 @@ const NewopDialog = WDialog.extend({ }); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/onlineAgentList.js b/src/code/dialogs/onlineAgentList.js index e4a899fd2..b820ba8cf 100644 --- a/src/code/dialogs/onlineAgentList.js +++ b/src/code/dialogs/onlineAgentList.js @@ -25,7 +25,7 @@ const OnlineAgentList = WDialog.extend({ _displayDialog: function () { const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/opPerms.js b/src/code/dialogs/opPerms.js index 25ea40650..47413efa2 100644 --- a/src/code/dialogs/opPerms.js +++ b/src/code/dialogs/opPerms.js @@ -48,7 +48,7 @@ const OpPermList = WDialog.extend({ const html = this.buildHTML(operation); const buttons = {}; - buttons[wX("CLOSE")] = () => { + buttons[wX("OK")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/teamListDialog.js b/src/code/dialogs/teamListDialog.js index 55a3e388b..9c7d4823d 100644 --- a/src/code/dialogs/teamListDialog.js +++ b/src/code/dialogs/teamListDialog.js @@ -160,7 +160,7 @@ const TeamListDialog = WDialog.extend({ } const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; buttons[wX("NEW_TEAM")] = () => { diff --git a/src/code/dialogs/teamMembershipList.js b/src/code/dialogs/teamMembershipList.js index e669b44b3..de39c565f 100644 --- a/src/code/dialogs/teamMembershipList.js +++ b/src/code/dialogs/teamMembershipList.js @@ -38,7 +38,7 @@ const TeamMembershipList = WDialog.extend({ this._table.items = team.agents; const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/trawl.js b/src/code/dialogs/trawl.js index 93d0032dc..12b08729b 100644 --- a/src/code/dialogs/trawl.js +++ b/src/code/dialogs/trawl.js @@ -79,7 +79,7 @@ const TrawlerDialog = WDialog.extend({ const content = this._buildContent(); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog("close"); }; @@ -263,7 +263,7 @@ const TrawlDialog = WDialog.extend({ }); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/wasabeeDlist.js b/src/code/dialogs/wasabeeDlist.js index f9b419acd..042736ac1 100644 --- a/src/code/dialogs/wasabeeDlist.js +++ b/src/code/dialogs/wasabeeDlist.js @@ -37,7 +37,7 @@ const WasabeeDList = WDialog.extend({ const sortable = await this.getListDialogContent(); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; diff --git a/src/code/dialogs/zoneDialog.js b/src/code/dialogs/zoneDialog.js index 506b857be..155b48d17 100644 --- a/src/code/dialogs/zoneDialog.js +++ b/src/code/dialogs/zoneDialog.js @@ -34,7 +34,7 @@ const ZoneDialog = WDialog.extend({ const html = this.buildList(); const buttons = {}; - buttons[wX("OK")] = () => { + buttons[wX("CLOSE")] = () => { this.closeDialog(); }; From 838fc3f5fed10a843774eb98391299cde23efd1f Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 7 Feb 2022 22:22:30 +0100 Subject: [PATCH 251/275] fix: color picker in link setcomment is oversized --- src/code/css/wasabee.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index 6a8c3515e..8a906504c 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -540,7 +540,7 @@ a.wasabee-portal.res { color: rgb(0, 135, 255) !important; } } /* color pickers */ -.hidden-color-picker { +input[type=color].hidden-color-picker { visibility: hidden; width: 0; height: 0; From a699b59f2ef6635ab6e1848516e22caa0c14f751 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 7 Feb 2022 22:26:53 +0100 Subject: [PATCH 252/275] fix some code style --- src/code/crosslinks.ts | 6 +----- src/code/dialogs/autodraws/tools.d.ts | 2 +- src/code/dialogs/keysList.js | 2 +- src/code/model/agent.ts | 4 ++-- src/code/model/operation.ts | 4 +--- src/code/sortable.ts | 12 +++++++----- src/code/wX.ts | 2 +- 7 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/code/crosslinks.ts b/src/code/crosslinks.ts index 3cfa18ea4..8d3d65846 100644 --- a/src/code/crosslinks.ts +++ b/src/code/crosslinks.ts @@ -64,11 +64,7 @@ export function normalize(a: Vec3): Vec3 { } export function dist2(a: Vec3, b: Vec3) { - return norm2([ - a[0] - b[0], - a[1] - b[1], - a[2] - b[2], - ]) + return norm2([a[0] - b[0], a[1] - b[1], a[2] - b[2]]); } function equals(a: L.LatLng, b: L.LatLng) { diff --git a/src/code/dialogs/autodraws/tools.d.ts b/src/code/dialogs/autodraws/tools.d.ts index 1a651e9b4..31be0a3d4 100644 --- a/src/code/dialogs/autodraws/tools.d.ts +++ b/src/code/dialogs/autodraws/tools.d.ts @@ -26,7 +26,7 @@ export class AutoDraw extends WDialog { thisKey: string, container: HTMLDivElement, storageKey: string, - callback?: () => void, + callback?: () => void ): void; _addCheckbox( text: string, diff --git a/src/code/dialogs/keysList.js b/src/code/dialogs/keysList.js index d784fe101..a8a270094 100644 --- a/src/code/dialogs/keysList.js +++ b/src/code/dialogs/keysList.js @@ -153,7 +153,7 @@ const KeysList = WDialog.extend({ }, ]); } else { - this.sortable.fields = always; + this.sortable.fields = always; } const keys = new Array(); diff --git a/src/code/model/agent.ts b/src/code/model/agent.ts index a496a7d0d..97ba33248 100644 --- a/src/code/model/agent.ts +++ b/src/code/model/agent.ts @@ -111,7 +111,7 @@ export default class WasabeeAgent implements Agent { this.name = obj.name; this.intelname = obj.intelname !== "unset" ? obj.intelname : ""; this.intelfaction = obj.intelfaction; - this.communityname = obj.communityname || ''; + this.communityname = obj.communityname || ""; this.pic = obj.pic ? obj.pic : null; this.lat = obj.lat ? obj.lat : 0; this.lng = obj.lng ? obj.lng : 0; @@ -130,7 +130,7 @@ export default class WasabeeAgent implements Agent { else if (this.Vverified) this.name = this.vname || this.name; else if (this.rocks) this.name = this.rocksname || this.name; else if (this.intelname) this.name = this.intelname + " [!]"; - else this.name = this.name || '[unknown name]'; + else this.name = this.name || "[unknown name]"; /* what did we decide to do with these? this.startlat = obj.startlat ? obj.startlat : 0; diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 7f523d23d..65a5fafe7 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -525,7 +525,6 @@ export default class WasabeeOp extends Evented implements IOperation { } } - removeLinkByID(linkID: LinkID) { this.links = this.links.filter((l) => l.ID != linkID); this.cleanAnchorList(); @@ -1150,8 +1149,7 @@ export default class WasabeeOp extends Evented implements IOperation { } zoneName(zoneID: ZoneID) { - if (zoneID === 0) - return 0; + if (zoneID === 0) return 0; for (const z of this.zones) { if (z.id == zoneID) return z.name; } diff --git a/src/code/sortable.ts b/src/code/sortable.ts index d85b8a8ea..0ec5269e1 100644 --- a/src/code/sortable.ts +++ b/src/code/sortable.ts @@ -14,7 +14,7 @@ export interface SortableField { sort?: (a: unknown, b: unknown, aobj?: T, bobj?: T) => number; format?: (cell: HTMLTableCellElement, value: unknown, thing?: T) => void; smallScreenHide?: boolean; - foot?: (cell: HTMLTableCellElement) => void, + foot?: (cell: HTMLTableCellElement) => void; } export default class Sortable { @@ -37,7 +37,7 @@ export default class Sortable { this._sortBy = 0; // which field/column number to sort by this._sortAsc = true; // ascending or descending this._table = L.DomUtil.create("table", "wasabee-table"); - + // create this once for all this._head = L.DomUtil.create("thead", null, this._table); this._body = L.DomUtil.create("tbody", null, this._table); @@ -226,10 +226,12 @@ export default class Sortable { this._sortAsc = !this._sortAsc; } L.DomUtil.addClass(cell, this._sortAsc ? "asc" : "desc"); - + this._sortBy = index; - if (this._sortByStoreKey != null) localStorage[this._sortByStoreKey] = this._sortBy; - if (this._sortAscStoreKey != null) localStorage[this._sortAscStoreKey] = this._sortAsc.toString(); + if (this._sortByStoreKey != null) + localStorage[this._sortByStoreKey] = this._sortBy; + if (this._sortAscStoreKey != null) + localStorage[this._sortAscStoreKey] = this._sortAsc.toString(); this.sort(); }, false diff --git a/src/code/wX.ts b/src/code/wX.ts index 1aea8ac57..835409c2d 100644 --- a/src/code/wX.ts +++ b/src/code/wX.ts @@ -61,4 +61,4 @@ export function getLanguage() { return lang; } -export default wX; \ No newline at end of file +export default wX; From a7e1445311e0e8ffe67d9d9ec572cca1f19af495 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 7 Feb 2022 22:34:05 +0100 Subject: [PATCH 253/275] Use font awesome icons instead of unicode glyphs (#326) * use fa-icons instead of unicode glyph * fix: icon padding * fix: reduce dev build size * fa: don't use dom.watch conflict with plugins using css only icons * fa: remove library * fa: add title to icons * fix: sudden type issue --- package.json | 2 + src/code/auxiliar.ts | 35 +++++++++++++++++ src/code/css/wasabee.css | 13 ++++++- src/code/dialogs/agentDialog.js | 7 +++- src/code/dialogs/checklist.js | 11 ++++-- src/code/dialogs/opsDialog.js | 22 +++++------ src/code/dialogs/zoneDialog.js | 60 +++++++++++++++++------------- src/code/translations/English.json | 5 +++ 8 files changed, 112 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 015d9ae3c..7caf34670 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,8 @@ }, "homepage": "https://github.com/wasabee-project/Wasabee-IITC/blob/master/README.md", "dependencies": { + "@fortawesome/fontawesome-svg-core": "^1.2.36", + "@fortawesome/free-solid-svg-icons": "^5.15.4", "arc": "^0.1.1", "color-string": "^1.5.5", "geodesy": "^2.2.1", diff --git a/src/code/auxiliar.ts b/src/code/auxiliar.ts index 1055b2555..4f38dd13f 100644 --- a/src/code/auxiliar.ts +++ b/src/code/auxiliar.ts @@ -1,5 +1,19 @@ import colorString from "color-string"; +import { icon, IconLookup, IconName } from "@fortawesome/fontawesome-svg-core"; +// avoid import from "@fortawesome/free-solid-svg-icons" to reduce *dev* build size +import { faCheck } from "@fortawesome/free-solid-svg-icons/faCheck"; +import { faTrash } from "@fortawesome/free-solid-svg-icons/faTrash"; +import { faServer } from "@fortawesome/free-solid-svg-icons/faServer"; +import { faSync } from "@fortawesome/free-solid-svg-icons/faSync"; +import { faArrowsAltH } from "@fortawesome/free-solid-svg-icons/faArrowsAltH"; +import { faPen } from "@fortawesome/free-solid-svg-icons/faPen"; +import { faEraser } from "@fortawesome/free-solid-svg-icons/faEraser"; +import { faBan } from "@fortawesome/free-solid-svg-icons/faBan"; +import { faPalette } from "@fortawesome/free-solid-svg-icons/faPalette"; +import { faAsterisk } from "@fortawesome/free-solid-svg-icons/faAsterisk"; +import { faDesktop } from "@fortawesome/free-solid-svg-icons/faDesktop"; + //** This function generates a unique ID for an object */ export function generateId(len = 40) { const arr = new Uint8Array(len / 2); @@ -37,3 +51,24 @@ export function convertColorToHex(color: string, on_error = "#000000") { return on_error; } } + +const icons = [ + faCheck, + faTrash, + faServer, + faSync, + faArrowsAltH, + faPen, + faEraser, + faBan, + faPalette, + faAsterisk, + faDesktop, +]; + +export function appendFAIcon(iconName: IconName, container: Element) { + const iconDef = icons.find((i) => i.iconName === iconName); + if (!iconDef) return; + const iconNode = icon(iconDef as IconLookup).node[0]; + container.appendChild(iconNode); +} \ No newline at end of file diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index 8a906504c..2940c5ea2 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -341,7 +341,11 @@ .wasabee-dialog-ops .wasabee-table.hideOps .visibility { display: none; } -.wasabee-dialog-checklist { +.wasabee-dialog-checklist .wasabee-table .actions { + white-space: nowrap; +} +.wasabee-dialog-checklist .wasabee-table .actions a { + padding: .25em } .wasabee-dialog-perms .add-perm { display: grid; @@ -447,6 +451,13 @@ list-style-position:inside; } +.wasabee-dialog-zone .wasabee-table .actions { + white-space: nowrap; +} +.wasabee-dialog-zone .wasabee-table .actions a { + padding: .25em +} + .wasabee-link-seperator:before { content: " ➾ "; } diff --git a/src/code/dialogs/agentDialog.js b/src/code/dialogs/agentDialog.js index 890d70a55..8cf8ac20a 100644 --- a/src/code/dialogs/agentDialog.js +++ b/src/code/dialogs/agentDialog.js @@ -1,6 +1,7 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; import WasabeeAgent from "../model/agent"; +import { appendFAIcon } from "../auxiliar"; const AgentDialog = WDialog.extend({ statics: { @@ -36,7 +37,11 @@ const AgentDialog = WDialog.extend({ for (const [label, value] of rows) { const li = L.DomUtil.create("li", "", ul); L.DomUtil.create("label", null, li).textContent = label; - L.DomUtil.create("span", null, li).textContent = value; + if (value === true) { + appendFAIcon("check", li); + } else { + L.DomUtil.create("span", null, li).textContent = value; + } } const img = L.DomUtil.create("img", null, html); diff --git a/src/code/dialogs/checklist.js b/src/code/dialogs/checklist.js index 734eb0bca..94d95cec9 100644 --- a/src/code/dialogs/checklist.js +++ b/src/code/dialogs/checklist.js @@ -20,6 +20,7 @@ import wX from "../wX"; import PortalUI from "../ui/portal"; import LinkUI from "../ui/link"; import { displayInfo, displayWarning } from "../error"; +import { appendFAIcon } from "../auxiliar"; const OperationChecklistDialog = WDialog.extend({ statics: { @@ -268,12 +269,14 @@ const OperationChecklistDialog = WDialog.extend({ name: this._smallScreen ? wX("dialog.common.commands_short") : wX("dialog.common.commands"), + className: "actions", value: (obj) => typeof obj, format: (cell, value, obj) => { if (obj instanceof WasabeeLink) { const rev = L.DomUtil.create("a", null, cell); rev.href = "#"; - rev.textContent = "🔄"; + rev.title = wX("REVERSE"); + appendFAIcon("arrows-alt-h", rev); L.DomEvent.on(rev, "click", (ev) => { L.DomEvent.stop(ev); operation.reverseLink(obj.fromPortalId, obj.toPortalId); @@ -281,7 +284,8 @@ const OperationChecklistDialog = WDialog.extend({ const del = L.DomUtil.create("a", null, cell); del.href = "#"; - del.textContent = "🗑"; + del.title = wX("dialog.common.delete"); + appendFAIcon("trash", del); L.DomEvent.on(del, "click", (ev) => { L.DomEvent.stop(ev); operation.removeLink(obj.fromPortalId, obj.toPortalId); @@ -289,7 +293,8 @@ const OperationChecklistDialog = WDialog.extend({ } else { const del = L.DomUtil.create("a", null, cell); del.href = "#"; - del.textContent = "🗑"; + del.title = wX("dialog.common.delete"); + appendFAIcon("trash", del); L.DomEvent.on(del, "click", (ev) => { L.DomEvent.stop(ev); operation.removeMarker(obj); diff --git a/src/code/dialogs/opsDialog.js b/src/code/dialogs/opsDialog.js index c38bff64d..1e35c09c4 100644 --- a/src/code/dialogs/opsDialog.js +++ b/src/code/dialogs/opsDialog.js @@ -18,6 +18,7 @@ import { syncOp, deleteLocalOp, zoomToOperation } from "../uiCommands"; import Sortable from "../sortable"; import AgentUI from "../ui/agent"; +import { appendFAIcon } from "../auxiliar"; const OpsDialog = WDialog.extend({ statics: { @@ -132,18 +133,13 @@ const OpsDialog = WDialog.extend({ 1 * op.local + 2 * op.localchanged + 4 * op.remotechanged, // sort: (a, b) => a - b, format: (cell, value, op) => { - const status = L.DomUtil.create("span", "", cell); - status.textContent = ""; if (!op.local) { - if (op.localchanged) { - status.textContent = "☀"; - status.style.color = "green"; - status.title = wX("dialog.ops_list.local_change"); - } - if (op.remotechanged) { - status.textContent = "⛅"; - status.style.color = "red"; - status.title = wX("dialog.ops_list.remote_change"); + if (op.localchanged && !op.remotechanged) { + appendFAIcon("desktop", cell); + cell.title = wX("dialog.ops_list.local_change"); + } else if (op.remotechanged) { + appendFAIcon("server", cell); + cell.title = wX("dialog.ops_list.remote_change"); } } }, @@ -212,7 +208,7 @@ const OpsDialog = WDialog.extend({ // delete locally const deleteLocaly = L.DomUtil.create("a", "", cell); deleteLocaly.href = "#"; - deleteLocaly.textContent = "🗑️"; + appendFAIcon("trash", deleteLocaly); deleteLocaly.title = wX("REM_LOC_CP", { opName: op.name }); L.DomEvent.on(deleteLocaly, "click", (ev) => { L.DomEvent.stop(ev); @@ -223,7 +219,7 @@ const OpsDialog = WDialog.extend({ // download op const download = L.DomUtil.create("a", "", cell); download.href = "#"; - download.textContent = "↻"; + appendFAIcon("sync", download); download.title = wX("dialog.ops_list.download", { opName: op.name, }); diff --git a/src/code/dialogs/zoneDialog.js b/src/code/dialogs/zoneDialog.js index 155b48d17..a954a1b0b 100644 --- a/src/code/dialogs/zoneDialog.js +++ b/src/code/dialogs/zoneDialog.js @@ -3,7 +3,7 @@ import wX from "../wX"; import { getSelectedOperation } from "../selectedOp"; import { addToColorList } from "../skin"; import ZoneSetColorDialog from "./zoneSetColor"; -import { convertColorToHex } from "../auxiliar"; +import { appendFAIcon, convertColorToHex } from "../auxiliar"; import { setMarkersToZones, setLinksToZones } from "../uiCommands"; const ZoneDialog = WDialog.extend({ @@ -107,11 +107,11 @@ const ZoneDialog = WDialog.extend({ }); if (canWrite) { - const commandcell = L.DomUtil.create("td", null, tr); - + const commandcell = L.DomUtil.create("td", "actions", tr); const color = L.DomUtil.create("a", null, commandcell); - color.textContent = "🖌"; color.href = "#"; + color.title = wX("dialog.zones.color_links"); + appendFAIcon("palette", color); L.DomEvent.on(color, "click", (ev) => { L.DomEvent.stop(ev); const zoneSetColorDialog = new ZoneSetColorDialog({ @@ -121,40 +121,50 @@ const ZoneDialog = WDialog.extend({ }); if (z.id != 1) { const del = L.DomUtil.create("a", null, commandcell); - del.textContent = "🗑"; del.href = "#"; + del.title = wX("dialog.common.delete"); + appendFAIcon("trash", del); L.DomEvent.on(del, "click", (ev) => { L.DomEvent.stop(ev); getSelectedOperation().removeZone(z.id); }); } - if (z.points.length == 0) { - const addPoints = L.DomUtil.create("a", null, commandcell); - addPoints.textContent = " 🖍"; - addPoints.href = "#"; - L.DomEvent.on(addPoints, "click", (ev) => { - L.DomEvent.stop(ev); - this.ZonedrawHandler.zoneID = z.id; - this.ZonedrawHandler.enable(); - }); - } else { - const delPoints = L.DomUtil.create("a", null, commandcell); - delPoints.textContent = " 🧽"; - delPoints.href = "#"; - L.DomEvent.on(delPoints, "click", (ev) => { - L.DomEvent.stop(ev); - getSelectedOperation().removeZonePoints(z.id); - }); - } - if (this.ZonedrawHandler && this.ZonedrawHandler.enabled()) { + if ( + this.ZonedrawHandler && + this.ZonedrawHandler.zoneID === z.id && + this.ZonedrawHandler.enabled() + ) { const stopDrawing = L.DomUtil.create("a", null, commandcell); stopDrawing.href = "#"; - stopDrawing.textContent = " 🛑"; + stopDrawing.title = wX("dialog.zones.stop_drawing"); + appendFAIcon("ban", stopDrawing); L.DomEvent.on(stopDrawing, "click", (ev) => { L.DomEvent.stop(ev); this.ZonedrawHandler.disable(); this.update(); }); + } else { + if (z.points.length == 0) { + const addPoints = L.DomUtil.create("a", null, commandcell); + addPoints.title = wX("dialog.zones.draw_zone_shape"); + appendFAIcon("pen", addPoints); + addPoints.href = "#"; + L.DomEvent.on(addPoints, "click", (ev) => { + L.DomEvent.stop(ev); + this.ZonedrawHandler.zoneID = z.id; + this.ZonedrawHandler.enable(); + this.update(); + }); + } else { + const delPoints = L.DomUtil.create("a", null, commandcell); + delPoints.title = wX("dialog.zones.delete_zone_shape"); + appendFAIcon("eraser", delPoints); + delPoints.href = "#"; + L.DomEvent.on(delPoints, "click", (ev) => { + L.DomEvent.stop(ev); + getSelectedOperation().removeZonePoints(z.id); + }); + } } } } diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 1bb3c18a1..4bd28c359 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", "dialog.common.commands": "Commands", "dialog.common.commands_short": "Cmds", + "dialog.common.delete": "Delete", "dialog.common.name": "Name", "dialog.common.off": "Off", "dialog.common.on": "On", @@ -160,7 +161,11 @@ "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", + "dialog.zones.color_links": "Color links", + "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.draw_zone_shape": "Draw the boundaries", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Stop drawing", "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplicate Operation", From c43c0b68bda697d3370801ea24d7e51d560223fd Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 6 Feb 2022 02:26:27 +0100 Subject: [PATCH 254/275] support new task fields don't use them but don't erase them either --- src/code/model/link.ts | 8 ++------ src/code/model/marker.ts | 13 ++++++------- src/code/model/task.ts | 26 +++++++++++++++++++------- src/code/ui/marker.js | 10 ---------- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/code/model/link.ts b/src/code/model/link.ts index 492fdae23..0f9c25f9c 100644 --- a/src/code/model/link.ts +++ b/src/code/model/link.ts @@ -32,15 +32,11 @@ export default class WasabeeLink extends Task { // build object to serialize toJSON() { return { - ID: this.ID, - throwOrderPos: this.order, - zone: this.zone, - assignedTo: this.assignedTo, - completed: !!this.completedID, // !! forces a boolean value + ...super.toJSON(), + fromPortalId: this.fromPortalId, toPortalId: this.toPortalId, color: this.color, - description: this.comment, }; } diff --git a/src/code/model/marker.ts b/src/code/model/marker.ts index 2c1a6a230..898dd25c0 100644 --- a/src/code/model/marker.ts +++ b/src/code/model/marker.ts @@ -43,6 +43,8 @@ const iconTypes = { export default class WasabeeMarker extends Task { portalId: PortalID; type: string; + // future compatibility + attributes?: any[]; // static properties is not supported by eslint yet static get markerTypes() { @@ -57,20 +59,17 @@ export default class WasabeeMarker extends Task { super(obj); this.portalId = obj.portalId; this.type = obj.type; + this.attributes = obj.attributes || []; } toJSON(): any { return { - ID: this.ID, - zone: Number(this.zone), - order: Number(this.order), - completedID: this.completedID, - assignedTo: this.assignedTo, - state: this._state, + ...super.toJSON(), portalId: this.portalId, type: this.type, - comment: this.comment, + // preserve data + attributes: this.attributes, }; } diff --git a/src/code/model/task.ts b/src/code/model/task.ts index 52cb94548..a80371cea 100644 --- a/src/code/model/task.ts +++ b/src/code/model/task.ts @@ -7,8 +7,9 @@ export default class Task { order: number; zone: ZoneID; assignedTo?: GoogleID; - completedID?: GoogleID; comment?: string; + dependsOn?: TaskID[]; + deltaminutes?: number; _state: TaskState; @@ -16,10 +17,19 @@ export default class Task { this.ID = obj.ID || generateId(); this.zone = +obj.zone || 1; this.order = +obj.order || 0; + // to be replaced by .assignments this.assignedTo = obj.assignedTo ? obj.assignedTo : null; - this.completedID = obj.completedID ? obj.completedID : null; this.comment = obj.comment ? obj.comment : ""; this.state = obj._state || obj.state; + // need UI + this.deltaminutes = obj.deltaminutes; + + // future compatibility + this.dependsOn = obj.dependsOn || []; + + // for raw task + if (!this.assignedTo && obj.assignments && obj.assignments.length > 0) + this.assignedTo = obj.assignments[0]; } toServer() { @@ -31,9 +41,12 @@ export default class Task { ID: this.ID, zone: Number(this.zone), order: Number(this.order), - completedID: this.completedID, assignedTo: this.assignedTo, state: this._state, + comment: this.comment, + // preserve data + deltaminutes: this.deltaminutes, + dependsOn: this.dependsOn, }; } @@ -67,13 +80,13 @@ export default class Task { } assign(gid?: GoogleID) { - if (gid !== this.assignedTo) this._state = gid ? "assigned" : "pending"; + if (gid !== this.assignedTo) { + this._state = gid ? "assigned" : "pending"; + } this.assignedTo = gid ? gid : null; } complete(gid?: GoogleID) { - if (!this.completedID || gid) - this.completedID = gid ? gid : this.assignedTo; this._state = "completed"; } @@ -84,7 +97,6 @@ export default class Task { set completed(v) { if (v) this.complete(); else { - delete this.completedID; this.state = "assigned"; } } diff --git a/src/code/ui/marker.js b/src/code/ui/marker.js index 4398c8dea..5289f4595 100644 --- a/src/code/ui/marker.js +++ b/src/code/ui/marker.js @@ -111,16 +111,6 @@ const WLMarker = PortalUI.WLPortal.extend({ console.error(err); } } - if (marker.state == "completed" && marker.completedID) { - try { - const a = await WasabeeAgent.get(marker.completedID); - assignment.innerHTML = wX("COMPLETED BY", { - agentName: a ? a.getName() : marker.completedID, - }); - } catch (e) { - console.error(e); - } - } }, _stateButton: function (container, marker) { From a3899ebaae1eabc68fb10e704c0969fdd6335f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20-=20fisher01?= Date: Tue, 8 Feb 2022 00:24:50 +0100 Subject: [PATCH 255/275] New Crowdin updates (#342) fix: Portuguese variables... remove trailing spaces --- src/code/translations/Danish.json | 11 +++- src/code/translations/English.json | 2 +- src/code/translations/Filipino.json | 11 +++- src/code/translations/French.json | 13 ++-- src/code/translations/German.json | 10 ++- src/code/translations/Italian.json | 11 +++- src/code/translations/Portuguese.json | 93 ++++++++++++++------------- src/code/translations/Russian.json | 9 ++- src/code/translations/Spanish.json | 11 +++- 9 files changed, 105 insertions(+), 66 deletions(-) diff --git a/src/code/translations/Danish.json b/src/code/translations/Danish.json index 3cde8d6dc..d090d00a9 100644 --- a/src/code/translations/Danish.json +++ b/src/code/translations/Danish.json @@ -114,7 +114,7 @@ "dialog.clear_links.text": "Do you want to remove all links from {opName}?", "dialog.clear_links.title": "Clear Links: {opName}", "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", - "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.clear_markers.title": "Clear Markers: {opName}", "dialog.checklist.count_fields": "Count fields", "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", "dialog.common.commands": "Commands", "dialog.common.commands_short": "Cmds", + "dialog.common.delete": "Delete", "dialog.common.name": "Name", "dialog.common.off": "Off", "dialog.common.on": "On", @@ -160,7 +161,11 @@ "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", + "dialog.zones.color_links": "Color links", + "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.draw_zone_shape": "Draw the boundaries", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Stop drawing", "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Duplikere Operation", @@ -381,8 +386,8 @@ "SET_PORT_COMMENT": "Indstil kommentar til portal:", "SET_PORTAL_COMMENT": "Indstil portalkommentar", "SET": "indstil", - "SETTINGS_TOOLBOX": "Wasabee Indstillinger", - "SETTINGS_TITLE": "Fremskreden Indstillinger", + "SETTINGS_TOOLBOX": "Wasabee Settings", + "SETTINGS_TITLE": "Advanced Settings", "SKINS_AVAILABLE": "Der er {count} tilgængelige skins.", "SKINS_BUTTON": "Konfigurer skins", "SKINS_DESCRIPTION": "Tilgængelige skin packs er placeret i højre kolonner. Flyt skins, du ønsker at bruge, til venstre kolonne.", diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 4bd28c359..3bcd5aefa 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -114,7 +114,7 @@ "dialog.clear_links.text": "Do you want to remove all links from {opName}?", "dialog.clear_links.title": "Clear Links: {opName}", "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", - "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.clear_markers.title": "Clear Markers: {opName}", "dialog.checklist.count_fields": "Count fields", "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", diff --git a/src/code/translations/Filipino.json b/src/code/translations/Filipino.json index acd1b93a3..26d6b5cb8 100644 --- a/src/code/translations/Filipino.json +++ b/src/code/translations/Filipino.json @@ -114,7 +114,7 @@ "dialog.clear_links.text": "Do you want to remove all links from {opName}?", "dialog.clear_links.title": "Clear Links: {opName}", "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", - "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.clear_markers.title": "Clear Markers: {opName}", "dialog.checklist.count_fields": "Count fields", "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", "dialog.common.commands": "Commands", "dialog.common.commands_short": "Cmds", + "dialog.common.delete": "Delete", "dialog.common.name": "Name", "dialog.common.off": "Off", "dialog.common.on": "On", @@ -160,7 +161,11 @@ "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", + "dialog.zones.color_links": "Color links", + "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.draw_zone_shape": "Draw the boundaries", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Stop drawing", "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Kopyahin ang Operasyon", @@ -381,8 +386,8 @@ "SET_PORT_COMMENT": "Komento para sa portal:", "SET_PORTAL_COMMENT": "Magtalaga komento sa portal", "SET": "italaga", - "SETTINGS_TOOLBOX": "Settings ng Wasabee", - "SETTINGS_TITLE": "Mga advanced na setting", + "SETTINGS_TOOLBOX": "Wasabee Settings", + "SETTINGS_TITLE": "Advanced Settings", "SKINS_AVAILABLE": "There are {count} available skins.", "SKINS_BUTTON": "Configure Skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", diff --git a/src/code/translations/French.json b/src/code/translations/French.json index 4839e45f2..9bfa43239 100644 --- a/src/code/translations/French.json +++ b/src/code/translations/French.json @@ -114,7 +114,7 @@ "dialog.clear_links.text": "Voulez-vous supprimer tous les liens de {opName} ?", "dialog.clear_links.title": "Effacer les liens : {opName}", "dialog.clear_markers.text": "Voulez-vous supprimer tous les marqueurs de {opName} ?", - "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.clear_markers.title": "Effacer les marqueurs : {opName}", "dialog.checklist.count_fields": "Nombre de fields", "dialog.checklist.count_fields.no_empty": "{fieldCount} fields trouvés et aucun champ vide", "dialog.checklist.count_fields.with_empty": "{fieldCount} fields trouvés et {emptyCount} champ(s) vide(s) sur {linkCount} lien(s)", @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " à {order} par le lien ", "dialog.common.commands": "Commandes", "dialog.common.commands_short": "Cmds", + "dialog.common.delete": "Supprimer", "dialog.common.name": "Nom", "dialog.common.off": "Off", "dialog.common.on": "On", @@ -159,8 +160,12 @@ "dialog.team_message": "Message d'équipe: « {message} » de {sender}", "dialog.zone_color.title": "Colorier la zone", "dialog.zone_color.text": "Colorier tous les liens dans la zone {zoneName}", - "dialog.zones.color": "Couleur ", + "dialog.zones.color": "Couleur", + "dialog.zones.color_links": "Colorier les liens", + "dialog.zones.delete_zone_shape": "Réinitialiser la forme", + "dialog.zones.draw_zone_shape": "Dessiner la zone", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Terminer le dessin", "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Format DrawTools", "DUPE_OP": "Dupliquer l'opération", @@ -381,8 +386,8 @@ "SET_PORT_COMMENT": "Entrer un commentaire pour ce portail", "SET_PORTAL_COMMENT": "Entrer un commentaire", "SET": "Définir", - "SETTINGS_TOOLBOX": "Parametres Wasabee", - "SETTINGS_TITLE": "Réglages avancés", + "SETTINGS_TOOLBOX": "Paramètres Wasabee", + "SETTINGS_TITLE": "Paramètres avancés", "SKINS_AVAILABLE": "Il y a {count} thèmes disponibles.", "SKINS_BUTTON": "Choisir les thèmes", "SKINS_DESCRIPTION": "Déplacer les thèmes de la colonne de droite vers la colonne de gauche pour les activer. L'ordre permet de les combiner. Le thème le plus bas est le dernier appliqué.", diff --git a/src/code/translations/German.json b/src/code/translations/German.json index 685b345a3..38ca21896 100644 --- a/src/code/translations/German.json +++ b/src/code/translations/German.json @@ -114,7 +114,7 @@ "dialog.clear_links.text": "Do you want to remove all links from {opName}?", "dialog.clear_links.title": "Clear Links: {opName}", "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", - "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.clear_markers.title": "Clear Markers: {opName}", "dialog.checklist.count_fields": "Count fields", "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", "dialog.common.commands": "Commands", "dialog.common.commands_short": "Cmds", + "dialog.common.delete": "Delete", "dialog.common.name": "Name", "dialog.common.off": "Off", "dialog.common.on": "On", @@ -160,7 +161,11 @@ "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", + "dialog.zones.color_links": "Color links", + "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.draw_zone_shape": "Draw the boundaries", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Stop drawing", "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Dupliziere Operation", @@ -382,7 +387,7 @@ "SET_PORTAL_COMMENT": "Set Portal Comment", "SET": "setzen", "SETTINGS_TOOLBOX": "Wasabee Settings", - "SETTINGS_TITLE": "Erweiterte Einstellungen", + "SETTINGS_TITLE": "Advanced Settings", "SKINS_AVAILABLE": "There are {count} available skins.", "SKINS_BUTTON": "Configure Skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", @@ -441,7 +446,6 @@ "TYPE": "Typ", "UNASSIGNED": "Nicht zugewiesenen", "UNKNOWN": "Unbekannt", - "UPDATE HOVER NOT CHANGED": "{opName} lokal nicht verändert", "UPDATE HOVER": "UPDATE {opName} auf dem Server", "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "The OP has been modified on server since last sync. Do you want to replace the server version by the current one?", diff --git a/src/code/translations/Italian.json b/src/code/translations/Italian.json index dd9ab76cc..f7ad1219d 100644 --- a/src/code/translations/Italian.json +++ b/src/code/translations/Italian.json @@ -114,7 +114,7 @@ "dialog.clear_links.text": "Vuoi rimuovere tutti i link da {opName}?", "dialog.clear_links.title": "Pulisci link: {opName}", "dialog.clear_markers.text": "Vuoi rimuovere tutti i marker da {opName}?", - "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.clear_markers.title": "Clear Markers: {opName}", "dialog.checklist.count_fields": "Conta field", "dialog.checklist.count_fields.no_empty": "Trovati {fieldCount} field e nessun field vuoto", "dialog.checklist.count_fields.with_empty": "Trovati {fieldCount} field e {emptyCount} field vuoti su {linkCount} link", @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " a {order} tramite link ", "dialog.common.commands": "Comandi", "dialog.common.commands_short": "Cmd", + "dialog.common.delete": "Delete", "dialog.common.name": "Nome", "dialog.common.off": "Off", "dialog.common.on": "On", @@ -160,7 +161,11 @@ "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", + "dialog.zones.color_links": "Color links", + "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.draw_zone_shape": "Draw the boundaries", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Stop drawing", "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplica Operazione", @@ -381,8 +386,8 @@ "SET_PORT_COMMENT": "Imposta il commento per il Portale:", "SET_PORTAL_COMMENT": "Imposta commento Portale", "SET": "impostato", - "SETTINGS_TOOLBOX": "Impostazioni Wasabee", - "SETTINGS_TITLE": "Impostazioni avanzate", + "SETTINGS_TOOLBOX": "Wasabee Settings", + "SETTINGS_TITLE": "Advanced Settings", "SKINS_AVAILABLE": "Sono disponibili {count} skin.", "SKINS_BUTTON": "Configura Skin", "SKINS_DESCRIPTION": "Gestisci le skin disponibili spostandole nella colonna di sinistra. Le skin più in basso hanno priorità più alta sulla UI.", diff --git a/src/code/translations/Portuguese.json b/src/code/translations/Portuguese.json index 85a874b45..c0bc8028c 100644 --- a/src/code/translations/Portuguese.json +++ b/src/code/translations/Portuguese.json @@ -5,7 +5,7 @@ "ADD MARKER TITLE": "Adicionar Marcadores", "ADD_AGENT": "Adicionar Agente:", "ADD_BL": "Adicionar links para trás:", - "ADD_BULK": "Adição em massa ", + "ADD_BULK": "Adição em massa", "ADD_BUTTON_LINKS": "Adicionar todos os links de uma vez.", "ADD_LINKS": "Adicionar Links", "ADD_MARKER": "+ Marcador", @@ -31,9 +31,9 @@ "ANCHORS_AS_BOOKMARKS": "Âncora como bookmarks", "API_KEY": "Chave API do Rocks:", "ASS_TO": "Atrubuir a:", - "ASSIGN LINK PROMPT": "Atribuir link para: ${value}", - "ASSIGN MARKER PROMPT": "Atrubuir marcador para: ${value}", - "ASSIGN OUTBOUND PROMPT": "Atribuir todos os links externos de: ${value}", + "ASSIGN LINK PROMPT": "Atribuir link para: {portalName}", + "ASSIGN MARKER PROMPT": "Atrubuir marcador para: {portalName}", + "ASSIGN OUTBOUND PROMPT": "Atribuir todos os links externos de: {portalName}", "ASSIGN OUTBOUND": "Atribuir links externos", "ASSIGN": "Atribuir", "ASSIGNED_ONLY_SHORT": "A", @@ -41,7 +41,7 @@ "assigned": "Atribuído", "AUTH INCOMPAT": "Você ativou um plugin no TamperMonkey que é incompatível com o Wasabee", "AUTH REQUIRED": "Autentificação Requerida", - "AUTH TOKEN REJECTED": "Envio de token de autenticação rejeitado pelo servidor: ${value}", + "AUTH TOKEN REJECTED": "Envio de token de autenticação rejeitado pelo servidor: {error}", "AUTH_SELECT_ACCOUNT": "Selecionar conta", "AUTO_DRAWS": "Auto-desenhar", "AUTODRAWS": "Wasabee Auto-draw Opções", @@ -84,22 +84,22 @@ "CLEAROPS PROMPT": "Isto limpará todas as OPS e dados relacionados a Wasabee. Tudo será restaurado apartir do servidor na próxima sincronização.", "CLOSE": "Perto", "COMMENT": "Comentario", - "COMPLETED BY": "Completo por ${value}", + "COMPLETED BY": "Completo por {agentName}", "completed": "Completo", - "CON_DEL": "Confirmar Apagar: ${value}", + "CON_DEL": "Confirmar Apagar: {opName}", "COUNT": "Contar", "CREATE_NEW_TEAM": "Criar Nova Equipa", "CreateLinkAlert": "Link", "CUR_USER_INFO": "Informações do usuário atual", "D_SHOW_LIST": "Chaves de defesa de entrada", - "DEFAULT OP NAME": "Nova Op: ${value}", + "DEFAULT OP NAME": "Nova Op: {date}", "DELETE ANCHOR PROMPT": "Desejas excluir esta âncora e todos os links associados:", "DELETE ANCHOR TITLE": "Apagar Âncora", "DELETE MARKER PROMPT": "Você deseja excluir este marcador:", "DELETE MARKER TITLE": "Apagar Marcador", "DELETE_ANCHOR": "Apagar", "DELETE_LINK": "Apagar", - "DELETE_OP": "Apagar ${value}", + "DELETE_OP": "Apagar {opName}", "DESCRIP_PLACEHOLD": "Descrição (opcional)", "DestroyPortalAlert": "Destroir", "dialog.about.download_mobile_app": "

Aplicativo Wasabee:

", @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " em {order} por link ", "dialog.common.commands": "Comandos", "dialog.common.commands_short": "Cmds", + "dialog.common.delete": "Delete", "dialog.common.name": "Nome", "dialog.common.off": "Desligar", "dialog.common.on": "Ligar", @@ -160,16 +161,20 @@ "dialog.zone_color.title": "Cor da zona", "dialog.zone_color.text": "Definir a cor de todos os links na zona {zoneName}", "dialog.zones.color": "Cor", + "dialog.zones.color_links": "Color links", + "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.draw_zone_shape": "Draw the boundaries", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Stop drawing", "dialog.zones.title": "Zonas", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplicar Operação", - "END_PORT": "Portal final ", + "END_PORT": "Portal final", "ExcludeMarker": "Excluir de Auto-Desenhar / Marcar", "EXPORT OP TITLE": "Exportar Op Actual", "EXPORT OP": "Exportar Op", "EXPORT": "Exportar:", - "FAKED": "Falsificado: [${value}]", + "FAKED": "Falsificado: [{portalId}]", "FANFIELD": "Desenhar", "FANFIELD2": "Desenhar Fan Field", "FarmPortalMarker": "Farmar", @@ -191,22 +196,22 @@ "HF_DRAW_BUTTON": "Desenhar", "HF_REDRAW_BUTTON": "Redesenhar", "HG": "Campo Homogêneo", - "HOURS": " (${value} horas atrás)", + "HOURS": " ({hours} horas atrás)", "HOW_TO_VIDS": "

Vídeos de instruções:

", "IMP_COMP": "", "IMP_NOPE": "A Importação Falhou: {error}", "IMP_WAS_OP": "Importar Operação Wasabee", - "IMPORT_OP_SUCCESS": "OP Importada: ${value} successfuly.", - "IMPORT_OP_TITLE": "Importar Op: ${value}", + "IMPORT_OP_SUCCESS": "OP Importada: {opName} successfuly.", + "IMPORT_OP_TITLE": "Importar Op: {date}", "IMPORT_OP": "Importar Operação", "IMPOSSIBLE": "Impossível", "INGNAME_GID": "Nome de entrada ou GoogleID", "INPUT_DT_KEY_COUNT": "Contagem de chaves defensivas de entrada", "INVALID REQUEST": "Pedido inválido", "IOS NEED FAKE UA": "Deves definir um 'Agente de usuário personalizado para visualizações da Web' nas configurações do IITC-Mobile ou o login falhará", - "KEY_LIST2": "Lista de chaves para operação: ${value}", + "KEY_LIST2": "Lista de chaves para operação: {opName}", "KEYS": "Chaves", - "KNOWN_BLOCK": "Blockers conhecidos: ${value}", + "KNOWN_BLOCK": "Blockers conhecidos: {opName}", "LA DESC": "Dependendo do número e tipo de Link Amps usados, um nível de portal de origem inferior pode ser suficiente.", "LA": "L8+ alguns LA", "LANG": "Língua", @@ -217,10 +222,10 @@ "LINK STATE": "Definir status do link:", "LINKS BUTTON TITLE": "Links", "LINKS": "Links", - "LINKS2": ": Links", + "LINKS2": "{portalName} : Links ({outgoing}↑/{incoming}↓)", "LOAD PORTALS": "Carregar Portais", "LOADING": "[a carregar]", - "LOADING1": "a carregar: [${value}]", + "LOADING1": "a carregar: [{portalGuid}]", "LOC_PROC": "localização processada", "LOCATION SUB": "Localização registrada", "LOCFRMSER": " (localmente e do servidor)", @@ -232,14 +237,14 @@ "MADRID_TITLE": "Madrid Protocol", "MADRID_WAS_TAKEN": "Madrid Protocol", "MADRID": "Desenhar", - "MANAGE_TEAM": "Gerenciar ${value}", + "MANAGE_TEAM": "Gerenciar {teamName}", "MANAGE": "Gerenciar", "MARKER ASSIGNMENT": "Atribuir marcador a:", "MARKER LIST TITLE": "Lista de Marcadores", "MARKER LIST": "Marcadores", "MARKER STATE PROMPT": "Status do marcador", "MARKER STATE": "Definir estado do marcador:", - "MARKER_LIST": "Lista de Marcadores: ${value}", + "MARKER_LIST": "Lista de Marcadores: {opName}", "MARKERS BUTTON TITLE": "Marcadores", "MAX_SPLITS": "Divisões máximas", "MAX": "Fan Field", @@ -254,7 +259,7 @@ "MERGE_REPLACE": "Usar servidor", "MERGE_TITLE": "Combinar OP local&remoto", "MIN_SRC_PORT_LVL": "Nível mínimo exigido no portal de origem", - "MINUTES": " (${value} minutos atrás)", + "MINUTES": " ({minutes} minutos atrás)", "MM": "Multimáx", "MM_BOTH_SIDE": "Usar ambos os lados base", "MM_INSERT_ORDER": "Inserir no final", @@ -282,7 +287,7 @@ "NO LONGER AVAILABLE": "Recurso removido do servidor: {error}", "NO LONGER AVAILABLE SHORT": "Recurso removido do servidor", "NOT LOGGED IN SHORT": "Não logado", - "NOT LOGGED IN": "Não logado: ${value}", + "NOT LOGGED IN": "Não logado: {error}", "NOT_LOADED": "Não totalmente carregado, tente novamente.", "NOT_SET": "não configurado", "NTNAME": "Nome", @@ -291,10 +296,10 @@ "ONION_WAS_TAKEN": "Cebola", "ONION": "Desenhar", "ONLY_DT_IMP": " (apenas para importações do DrawTools)", - "OP DELETED": "Operação removida do servidor: ${value}", - "OP PERM DENIED": "Permissão negada para operação: ${value}", + "OP DELETED": "Operação removida do servidor: {opID}", + "OP PERM DENIED": "Permissão negada para operação: {opID}", "OP_BUTTON": "Operação", - "OP_CHECKLIST": "Lista de verificação de operação: ${value}", + "OP_CHECKLIST": "Lista de verificação de operação: {opName}", "OP_NAME_UNSET": "O nome da operação não estava definido", "OP_PERMS": "Permissões de operação", "OP_SETTINGS_BUTTON": "Op ⚙", @@ -311,13 +316,13 @@ "pending": "Pendente", "PERM DENIED": "Permissão negada: {error}", "PERM DENIED SHORT": "Permissão negada", - "PERMS": "${value} permissões", + "PERMS": "{opName} permissões", "PLEASE_SELECT_PORTAL": "Seleciona um portal", "popup.anchor.keys": "Chaves: {onHand} / {required}", "popup.marker.state_button": "Definir estado", "PORT_FAKE": "", - "PORTAL KEY LIST": "Lista de chaves para portal ${value}", - "PORTAL_COUNT": "${value} portais", + "PORTAL KEY LIST": "Lista de chaves para portal {portalName}", + "PORTAL_COUNT": "{count} portais", "PORTAL": "Portal", "QD BUTTON CHANGE COLOR": "Clique para alterar a cor dos próximos links", "QD BUTTON END": "Clique para parar de desenhar campos", @@ -334,9 +339,9 @@ "READ": "Ler", "RechargePortalAlert": "Recarregar", "REFERENCE_TIME": "Tempo de Referência:", - "REM_LOC_CP": "Remover cópia local de ${value}", - "REMOVE_TEAM_CONFIRM_LABEL": "Você deseja remover permanentemente ${value} do servidor Wasabee?", - "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipe ${value}", + "REM_LOC_CP": "Remover cópia local de {opName}", + "REMOVE_TEAM_CONFIRM_LABEL": "Você deseja remover permanentemente {teamName} do servidor Wasabee?", + "REMOVE_TEAM_CONFIRM_TITLE": "Remover Equipe {teamName}", "REMOVE_TEAM": "Remover Equipa:", "REMOVE": "Remover", "RENAME_TEAM": "Renomear Equipe:", @@ -349,7 +354,7 @@ "SAVELINKS TITLE": "Salvar Links", "SAVELINKS_DRAW": "Salvar Links", "SAVELINKS": "Salvar Links", - "SECONDS": " (${value} segundos atrás)", + "SECONDS": " ({seconds} segundos atrás)", "SEL_SB_ANCHOR": "Seleciona a âncora.", "SEL_SB_ANCHOR2": "Reduzir o zoom. Verifica se todos os portais foram carregados e clica em desenhar.", "SEL_SL_ANCHOR": "Selecione o portal para salvar os links de. Clique no botão salvar links e veja a lista de seleção.", @@ -364,7 +369,7 @@ "SEND ANALYTICS": "Enviar análises anônimas", "SEND LOCATION": "Enviar localização", "SEND TARGET AGENT": "Selecionar o destinatário alvo", - "SEND TARGET CONFIRM": "Queres enviar ${value} alvo para ${option}?", + "SEND TARGET CONFIRM": "Queres enviar {portalName} alvo para {agent}?", "SEND TARGET": "Enviar alvo", "SEND_LOC": "Enviar localização", "SET_3_PORT": "Defina os três portais primeiro!", @@ -375,15 +380,15 @@ "SET_MARKER_COMMENT": "Definir comentário para marcador em:", "SET_MARKER_TYPE_TITLE": "Alterar o tipo de marcador", "SET_MARKERS_ZONES": "Definir Marcadores para Zonas", - "SET_MCOMMENT": "Definir comentário do marcador: ${value}", + "SET_MCOMMENT": "Definir comentário do marcador: {portalName}", "SET_NEW_OP": "Define o novo nome da operação", - "SET_PCOMMENT": "Definir comentário do portal: ${value}", + "SET_PCOMMENT": "Definir comentário do portal: {portalName}", "SET_PORT_COMMENT": "Definir comentário para portal:", "SET_PORTAL_COMMENT": "Definir comentário do portal", "SET": "definir", - "SETTINGS_TOOLBOX": "Configurações do Wasabee", - "SETTINGS_TITLE": "Configurações avançadas", - "SKINS_AVAILABLE": "Existem ${value} skins disponíveis.", + "SETTINGS_TOOLBOX": "Wasabee Settings", + "SETTINGS_TITLE": "Advanced Settings", + "SKINS_AVAILABLE": "Existem {count} skins disponíveis.", "SKINS_BUTTON": "Configurar Skins", "SKINS_DESCRIPTION": "Gerenciar as skins disponíveis movendo o tema para a coluna da esquerda. Quanto mais baixo na coluna, maior será a prioridade para o UI.", "SKINS_MANAGE_TITLE": "Gerenciar skins", @@ -406,7 +411,7 @@ "SYNC": "Download operações disponíveis", "TARGET SENT": "Alvo Enviado", "TEAM STATE": "Partilhar localização", - "TEAM_CREATED": "Equipa ${value} created", + "TEAM_CREATED": "Equipa {teamName} created", "TEAM_NAME": "Nome Equipa", "TEAM": "Equipa", "TEAMS BUTTON TITLE": "Listar equipas Wasabee", @@ -435,20 +440,20 @@ "TRAWL_BULK_LOAD_WARNING": "Este método carrega os dados do bloco o mais rápido possível. Usa por sua conta e risco.", "TRAWL_BULK_LOAD": "Carregar rapidamente Dados do Bloco", "TRAWL_CLEAR_MARKERS": "Limpa vírus / destroi marcadores antes da procura", - "TRAWL_REMAINING": "${value} Restantes", + "TRAWL_REMAINING": "{count} Restantes", "TRAWL": "Procurar por Blockers", "TRAWLING": "A Varrer os links a procura de blockers, fecha esta caixa de diálogo para parar", "TYPE": "Tipo", "UNASSIGNED": "Não atribuído", "UNKNOWN": "Desconhecido", - "UPDATE HOVER": "UPDATE ${value} no servidor", + "UPDATE HOVER": "UPDATE {opName} no servidor", "UPDATE PERM DENIED": "Você não possui permissão para editar", "UPDATE_CONFLICT_DESC": "A OP foi modificada no servidor desde a última sincronização. Queres substituir a versão do servidor pela atual?", "UPDATE_CONFLICT_TITLE": "Conflito detectado com o servidor", "UPDATE_COUNT": "Contagem de atualização", "UPDATED": "Atualizado com sucesso", "UpgradePortalAlert": "Atualizar", - "UPLOAD BUTTON HOVER": "UPLOAD ${value} (atualmente não está no servidor)", + "UPLOAD BUTTON HOVER": "UPLOAD {opName} (atualmente não está no servidor)", "UPLOADED": "Carregado com sucesso", "USE PANES ON MOBILE": "Usar painéis (precisa recarregar)", "USE_SWAP_INSTRUCT": "", @@ -462,8 +467,8 @@ "WD BUTTON": "W-D Chaves", "WRITE_SHORT": "RW", "WRITE": "escrita", - "WSERVER": "Servidor: ${value}", - "YESNO_DEL": "Tem certeza de que deseja excluir ${value}?", + "WSERVER": "Servidor: {url}", + "YESNO_DEL": "Tem certeza de que deseja excluir {opName}?", "ZONE_DRAW": "Clique para definir os limites da zona", "ZONE": "Zona", "smallScreen": { diff --git a/src/code/translations/Russian.json b/src/code/translations/Russian.json index 655f69003..70ba15aea 100644 --- a/src/code/translations/Russian.json +++ b/src/code/translations/Russian.json @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " на шаге {order} линком ", "dialog.common.commands": "Команды", "dialog.common.commands_short": "Команды", + "dialog.common.delete": "Удалить", "dialog.common.name": "Название", "dialog.common.off": "Выкл.", "dialog.common.on": "Вкл.", @@ -160,11 +161,15 @@ "dialog.zone_color.title": "Цвет зоны", "dialog.zone_color.text": "Задать цвет всем линкам в зоне {zoneName}", "dialog.zones.color": "Цвет", + "dialog.zones.color_links": "Задать цвет линкам", + "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.draw_zone_shape": "Нарисовать границы", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Закончить рисовать", "dialog.zones.title": "Зоны", "DRAW TOOLS FORMAT": "Формат ДТ", "DUPE_OP": "Дублировать операцию", - "END_PORT": "Конечный портал ", + "END_PORT": "Конечный портал", "ExcludeMarker": "Исключить из авто-рисовки/маркировки", "EXPORT OP TITLE": "Экспортировать текущую ОПРЦ", "EXPORT OP": "Экспортировать ОПРЦ", @@ -395,7 +400,7 @@ "STARBURST TITLE": "Звезда", "STARBURST_DRAW": "Рисовка", "STARBURST": "Звезда", - "START_PORT": "Стартовый портал ", + "START_PORT": "Стартовый портал", "STATE": "Статус", "SUPPORT_INSTRUCT": "Для поддержки, присоединяйся к The Wasabee User Telegram Channel", "SWAP PROMPT": "Хочешь заменить:", diff --git a/src/code/translations/Spanish.json b/src/code/translations/Spanish.json index aa3e6740a..ca044a027 100644 --- a/src/code/translations/Spanish.json +++ b/src/code/translations/Spanish.json @@ -114,7 +114,7 @@ "dialog.clear_links.text": "Do you want to remove all links from {opName}?", "dialog.clear_links.title": "Clear Links: {opName}", "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", - "dialog.clear_markers.title": "Clear Links: {opName}", + "dialog.clear_markers.title": "Clear Markers: {opName}", "dialog.checklist.count_fields": "Count fields", "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", @@ -122,6 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", "dialog.common.commands": "Commands", "dialog.common.commands_short": "Cmds", + "dialog.common.delete": "Delete", "dialog.common.name": "Nombre", "dialog.common.off": "Desactivado", "dialog.common.on": "Activado", @@ -160,7 +161,11 @@ "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", + "dialog.zones.color_links": "Color links", + "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.draw_zone_shape": "Draw the boundaries", "dialog.zones.id": "ID", + "dialog.zones.stop_drawing": "Stop drawing", "dialog.zones.title": "Zones", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplicar Operación", @@ -381,8 +386,8 @@ "SET_PORT_COMMENT": "Definir comentario para el portal", "SET_PORTAL_COMMENT": "Definir comentarios del portal", "SET": "definir", - "SETTINGS_TOOLBOX": "Configuración de Wasabee", - "SETTINGS_TITLE": "Ajustes avanzados", + "SETTINGS_TOOLBOX": "Wasabee Settings", + "SETTINGS_TITLE": "Advanced Settings", "SKINS_AVAILABLE": "Hay {count} skins disponibles.", "SKINS_BUTTON": "Configurar skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", From 69eebaf50bf5f22623ddcf278a136dac75140754 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 9 Feb 2022 21:29:46 +0100 Subject: [PATCH 256/275] fib: remove warning on op delete --- src/code/firebaseSupport.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/code/firebaseSupport.ts b/src/code/firebaseSupport.ts index 7e3456f28..60cc31e75 100644 --- a/src/code/firebaseSupport.ts +++ b/src/code/firebaseSupport.ts @@ -82,7 +82,6 @@ async function onMessage( drawSingleTeam(data.msg); break; case "Delete": - displayWarning("server requested op delete: " + data.opID); console.warn("server requested op delete: ", data.opID); await removeOperation(data.opID); await changeOpIfNeeded(); From 886148aa950665722f53fbce0d85407212c29a9a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 11 Feb 2022 22:24:19 +0100 Subject: [PATCH 257/275] check last version --- src/code/init.ts | 10 +++++++++- src/code/translations/English.json | 1 + src/code/version.ts | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/code/version.ts diff --git a/src/code/init.ts b/src/code/init.ts index 2139bffc4..cbd11a867 100644 --- a/src/code/init.ts +++ b/src/code/init.ts @@ -24,7 +24,7 @@ import WasabeeMe from "./model/me"; import WasabeeOp from "./model/operation"; import db from "./db"; import polyfill from "./polyfill"; -import { displayError } from "./error"; +import { displayError, displayWarning } from "./error"; import { deleteJWT } from "./auth"; import type { FeatureGroup, LayerEvent, LayerGroup } from "leaflet"; @@ -34,6 +34,8 @@ import type { WLMarker } from "./ui/marker"; import type { WLAgent } from "./ui/agent"; import type { WLZone } from "./ui/zone"; import type { ButtonsControl } from "./leafletClasses"; +import { checkVersion } from "./version"; +import wX from "./wX"; type Awaited = T extends PromiseLike ? U : T; export interface Wasabee { @@ -258,6 +260,12 @@ window.plugin.wasabee.init = async () => { window.map.on("wdialog", (event) => { postToFirebase({ id: "analytics", action: event.dialogType }); }); + + checkVersion().then((v) => { + if (v) { + displayWarning(wX("dialog.update_warning")); + } + }); }; // this can be moved to auth dialog, no need to init it for people who never log in diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 3bcd5aefa..b47b47a1c 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -158,6 +158,7 @@ "dialog.team_members.location": "Sharing Location", "dialog.team_members.wd_keys": "Sharing W-D Keys", "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.update_warning": "Wasabee is out of date. Please update using your plugin manager or by going to https://wasabee.rocks", "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", diff --git a/src/code/version.ts b/src/code/version.ts new file mode 100644 index 000000000..80f0e921c --- /dev/null +++ b/src/code/version.ts @@ -0,0 +1,23 @@ +const metaURL = "https://cdn2.wasabee.rocks/iitcplugin/prod/wasabee.meta.js"; + +function getCurrentVersion() { + return window.plugin.wasabee.info.version; +} + +function simpleSemVer(a: string, b: string) { + const av = a.split(".", 3); + const bv = b.split(".", 3); + return +av[0] < +bv[0] || (+av[0] == +bv[0] && +av[1] < +bv[1]); +} + +export async function checkVersion() { + const data = await (await fetch(metaURL)).text(); + for (const line of data.split("\n")) { + if (line.startsWith("// @version")) { + const version = line.slice(11).trim(); + const curVer = getCurrentVersion(); + return simpleSemVer(curVer, version); + } + } + return false; +} From 9d932024b31c1bb74c928aa6476b054da7c71b2c Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 27 Nov 2021 19:05:44 +0100 Subject: [PATCH 258/275] merge: use server zone on conflict --- src/code/model/operation.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 65a5fafe7..b38449034 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -1336,16 +1336,25 @@ export default class WasabeeOp extends Evented implements IOperation { return this.localchanged; } + // currently overwrite zones instead of ignoring conflict mergeZones(op: WasabeeOp) { - const ids = new Set(); + const ids = new Map(); let count = 0; for (const z of this.zones) { - ids.add(z.id); + ids.set(z.id, z); } for (const z of op.zones) { if (!ids.has(z.id)) { this.zones.push(z); count += 1; + } else { + const lz = ids.get(z.id); + if (JSON.stringify(z) !== JSON.stringify(lz)) { + lz.color = z.color; + lz.name = z.name; + lz.points = z.points; + count += 1; + } } } return count; From 01689d444fb05d3cd1e381663693cd225cf8a121 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 27 Nov 2021 19:30:22 +0100 Subject: [PATCH 259/275] merge: type changes structure --- src/code/model/operation.ts | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index b38449034..115615bd4 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -1231,7 +1231,29 @@ export default class WasabeeOp extends Evented implements IOperation { } changes(origin?: WasabeeOp) { - const changes = { + interface PortalType { + type: "portal"; + portal: WasabeePortal; + } + interface LinkType { + type: "link"; + link: WasabeeLink; + } + interface MarkerType { + type: "marker"; + marker: WasabeeMarker; + } + interface OpChanges { + addition: (PortalType | LinkType | MarkerType)[]; + edition: ((PortalType | LinkType | MarkerType) & { + diff: [string, any][]; + })[]; + deletion: ((LinkType | MarkerType) & { id: TaskID })[]; + name: string; + color: string; + comment: string; + } + const changes: OpChanges = { addition: [], edition: [], deletion: [], @@ -1259,7 +1281,7 @@ export default class WasabeeOp extends Evented implements IOperation { const fields = ["comment", "hardness"]; const diff = fields .filter((k) => oldPortal[k] != p[k]) - .map((k) => [k, oldPortal[k]]); + .map((k) => [k, oldPortal[k]] as [string, any]); if (diff.length > 0) changes.edition.push({ type: "portal", portal: p, diff: diff }); } @@ -1287,7 +1309,7 @@ export default class WasabeeOp extends Evented implements IOperation { ]; const diff = fields .filter((k) => oldLink[k] != l[k]) - .map((k) => [k, oldLink[k]]); + .map((k) => [k, oldLink[k]] as [string, any]); if (diff.length > 0) changes.edition.push({ type: "link", link: l, diff: diff }); } @@ -1313,7 +1335,7 @@ export default class WasabeeOp extends Evented implements IOperation { ]; const diff = fields .filter((k) => oldMarker[k] != m[k]) - .map((k) => [k, oldMarker[k]]); + .map((k) => [k, oldMarker[k]] as [string, any]); if (diff.length > 0) changes.edition.push({ type: "marker", marker: m, diff: diff }); } @@ -1338,7 +1360,7 @@ export default class WasabeeOp extends Evented implements IOperation { // currently overwrite zones instead of ignoring conflict mergeZones(op: WasabeeOp) { - const ids = new Map(); + const ids = new Map(); let count = 0; for (const z of this.zones) { ids.set(z.id, z); @@ -1361,7 +1383,7 @@ export default class WasabeeOp extends Evented implements IOperation { } // assume that `this` is a server OP (teams/keys are correct) - applyChanges(changes, op: WasabeeOp) { + applyChanges(changes: ReturnType, op: WasabeeOp) { const summary = { compatibility: { ok: true, From ef22498ed5eaffc7a481d804a5f5b4dfb96dc570 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sat, 27 Nov 2021 20:14:30 +0100 Subject: [PATCH 260/275] merge: fix task field rename --- src/code/model/operation.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 115615bd4..9081f2b6b 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -1300,12 +1300,13 @@ export default class WasabeeOp extends Evented implements IOperation { const fields = [ "fromPortalId", "toPortalId", - "assignedTo", - "description", - "throwOrderPos", "color", - "completed", "zone", + "order", + "assignedTo", + "completedID", + "comment", + "state", ]; const diff = fields .filter((k) => oldLink[k] != l[k]) @@ -1326,12 +1327,14 @@ export default class WasabeeOp extends Evented implements IOperation { } else { const oldMarker = oldMarkers.get(m.ID); const fields = [ + /* "portalId", */ // unlikely because we don't swap marker yet "type", - "comment", + "zone", + "order", "assignedTo", + "completedID", + "comment", "state", - "order", - "zone", ]; const diff = fields .filter((k) => oldMarker[k] != m[k]) From 1e6dda2ebed9699d2a1bd0c5702b305d2ee8bd3e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 30 Nov 2021 00:00:02 +0100 Subject: [PATCH 261/275] merge: rewrite mechanism --- src/code/dialogs/mergeDialog.js | 356 ++++++++++------------ src/code/model/changes.ts | 522 ++++++++++++++++++++++++++++++++ src/code/model/operation.ts | 205 ++----------- src/code/model/zone.ts | 6 +- 4 files changed, 701 insertions(+), 388 deletions(-) create mode 100644 src/code/model/changes.ts diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index 3f027807d..020ce4d57 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -1,13 +1,14 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; -import WasabeeAgent from "../model/agent"; +// import WasabeeAgent from "../model/agent"; import WasabeeOp from "../model/operation"; -import Sortable from "../sortable"; +// import Sortable from "../sortable"; import { getSelectedOperation, makeSelectedOperation } from "../selectedOp"; -import { drawBackgroundOp } from "../mapDrawing"; -import PortalUI from "../ui/portal"; -import LinkUI from "../ui/link"; +import { computeRebaseChanges, applyRebaseChanges } from "../model/changes"; + +// import PortalUI from "../ui/portal"; +// import LinkUI from "../ui/link"; const MergeDialog = WDialog.extend({ statics: { @@ -33,7 +34,8 @@ const MergeDialog = WDialog.extend({ this._layer.remove(); }, - rebase: async function () { + rebase: async function (changes) { + applyRebaseChanges(this._opRebase, this.options.opOwn, changes); await this._opRebase.store(); if (getSelectedOperation().ID == this._opRebase.ID) await makeSelectedOperation(this._opRebase.ID); @@ -58,70 +60,167 @@ const MergeDialog = WDialog.extend({ _displayDialog: function () { this._opRebase = new WasabeeOp(this.options.opRemote); - const origin = new WasabeeOp( - // while merge should only occurs with server ops, it appears users succeed to merge - // with local ops. This is a failsafe for those edge-cases - this.options.opOwn.getFetchedOp() || this.options.opOwn.toExport() + const origin = this.options.opOwn.getFetchedOp() + ? new WasabeeOp(this.options.opOwn.getFetchedOp()) + : new WasabeeOp({ + // dummy op + ID: this.options.opOwn.ID, + name: this.options.opOwn.name, + comment: this.options.opOwn.comment, + color: this.options.opOwn.color, + referencetime: this.options.opOwn.referencetime, + }); + const changes = computeRebaseChanges( + origin, + this._opRebase, + this.options.opOwn ); - const changes = this.options.opOwn.changes(origin); - const summary = this._opRebase.applyChanges(changes, this.options.opOwn); - this._opRebase.cleanAll(); - this._opRebase.remoteChanged = this.options.opOwn.remoteChanged; - this._opRebase.localchanged = this.options.opOwn.localchanged; - - const remoteChanges = this.options.opRemote.changes(origin); - const rebaseChanges = this._opRebase.changes(origin); + console.debug(changes); + const conflicts = []; + + for (const pc of changes.portals.conflict) { + if (pc.type === "edition/edition") { + conflicts.push({ + conflict: pc, + masterValue: this._opRebase.getPortal(pc.id), + followerValue: this.options.opOwn.getPortal(pc.id), + }); + } + } + for (const zc of changes.zones.conflict) { + if (zc.type === "edition/edition") { + conflicts.push({ + conflict: zc, + masterValue: this._opRebase.getZone(zc.id), + followerValue: this.options.opOwn.getZone(zc.id), + }); + } + } + // don't show double addition, caused by old export + for (const mc of changes.markers.conflict) { + if (mc.type !== "addition/addition") { + conflicts.push({ + conflict: mc, + masterValue: this._opRebase.getMarker(mc.id), + followerValue: this.options.opOwn.getMarker(mc.id), + }); + } + } + for (const lc of changes.links.conflict) { + if (lc.type !== "addition/addition") { + conflicts.push({ + conflict: lc, + masterValue: this._opRebase.getLinkById(lc.id), + followerValue: this.options.opOwn.getLinkById(lc.id), + }); + } + } - // if nothing was deleted on the server, - // and if portal swaps do not end up to 1-portal link - // auto merge - if ( - remoteChanges.deletion.length === 0 && - summary.edition.singlePortalLink === 0 - ) { - this.rebase(); + if (conflicts.length === 0) { + this.rebase(changes); return; } - const style = { - dashArray: [2, 8], - opacity: 0.86, - weight: 4, - color: "blue", - interactive: false, - }; - drawBackgroundOp(this._opRebase, this._layer, style); - const content = L.DomUtil.create("div", "container"); const desc = L.DomUtil.create("div", "desc", content); desc.textContent = wX("MERGE_MESSAGE", { opName: this.options.opOwn.name }); - content.appendChild(this.formatSummary(summary)); - const details = L.DomUtil.create("div", "details", content); - { - const div = L.DomUtil.create("div", "local", details); - div.innerHTML = "" + wX("MERGE_CHANGES_LOCAL") + ""; - div.appendChild(this.formatChanges(changes, origin, this.options.opOwn)); - } - { - const div = L.DomUtil.create("div", "merge", details); - div.innerHTML = "" + wX("MERGE_CHANGES_MERGE") + ""; - div.appendChild( - this.formatChanges(rebaseChanges, origin, this._opRebase) + L.DomUtil.create("h3", "", content).textContent = "Conflicts:"; + + const details = L.DomUtil.create("table", "conflicts", content); + const head = L.DomUtil.create("tr", "", details); + // master head + const masterHead = L.DomUtil.create("th", "master", head); + masterHead.colSpan = 2; + masterHead.textContent = "Master copy"; + const masterRadioHead = L.DomUtil.create( + "input", + "", + L.DomUtil.create("th", "master", head) + ); + masterRadioHead.type = "radio"; + masterRadioHead.name = this.options.opOwn.ID; + // follower head + const followerRadioHead = L.DomUtil.create( + "input", + "", + L.DomUtil.create("th", "follower", head) + ); + followerRadioHead.type = "radio"; + followerRadioHead.name = this.options.opOwn.ID; + const followerHead = L.DomUtil.create("th", "follower", head); + followerHead.colSpan = 2; + followerHead.textContent = "Local copy"; + + L.DomEvent.on(masterRadioHead, "change", () => { + if (masterRadioHead.checked) { + details + .querySelectorAll("td.master input") + .forEach((el) => (el.checked = true)); + for (const c of conflicts) c.conflict.value = c.masterValue; + } + }); + L.DomEvent.on(followerRadioHead, "change", () => { + if (followerRadioHead.checked) { + details + .querySelectorAll("td.follower input") + .forEach((el) => (el.checked = true)); + for (const c of conflicts) c.conflict.value = c.followerValue; + } + }); + + for (const c of conflicts) { + const row = L.DomUtil.create("tr", "", details); + // master props + const masterTD = L.DomUtil.create("td", "master", row); + masterTD.textContent = JSON.stringify(c.conflict.master.props); + // master type + L.DomUtil.create("td", "master", row).textContent = + c.conflict.master.type === "edition" ? "~" : "-"; + // master radio + const masterRadio = L.DomUtil.create( + "input", + "", + L.DomUtil.create("td", "master", row) ); - } - { - const div = L.DomUtil.create("div", "server", details); - div.innerHTML = "" + wX("MERGE_CHANGES_REMOTE") + ""; - div.appendChild( - this.formatChanges(remoteChanges, origin, this.options.opRemote) + masterRadio.type = "radio"; + masterRadio.name = c.conflict.id; + masterRadio.value = "master"; + masterRadio.checked = true; + // follower radio + const followerRadio = L.DomUtil.create( + "input", + "", + L.DomUtil.create("td", "follower", row) ); + followerRadio.type = "radio"; + followerRadio.name = c.conflict.id; + followerRadio.value = "master"; + // follower type + L.DomUtil.create("td", "follower", row).textContent = + c.conflict.follower.type === "edition" ? "~" : "-"; + // follower props + const followerTD = L.DomUtil.create("td", "follower", row); + followerTD.textContent = JSON.stringify(c.conflict.follower.props); + + L.DomEvent.on(masterRadio, "change", () => { + if (masterRadio.checked) { + c.conflict.value = c.masterValue; + followerRadioHead.checked = false; + } + }); + L.DomEvent.on(followerRadio, "change", () => { + if (followerRadio.checked) { + c.conflict.value = c.followerValue; + masterRadioHead.checked = false; + } + }); } const buttons = []; buttons.push({ text: wX("MERGE_REBASE"), - click: () => this.rebase(), + click: () => this.rebase(changes), }); buttons.push({ text: wX("MERGE_REPLACE"), @@ -143,155 +242,6 @@ const MergeDialog = WDialog.extend({ buttons: buttons, }); }, - - formatSummary: function (summary) { - // wX - const list = []; - if (!summary.compatibility.ok) - list.push( - `old OP detected, merge ${summary.compatibility.rewrite.link} links and ${summary.compatibility.rewrite.marker} markers` - ); - if ( - summary.addition.link + summary.addition.marker + summary.addition.zone > - 0 - ) - list.push( - `add ${summary.addition.link} links, ${summary.addition.marker} markers and ${summary.addition.zone} zones` - ); - if (summary.addition.ignored > 0) - list.push( - `ignore ${summary.addition.ignored} new portals/links/markers already present on remote` - ); - if (summary.deletion.link + summary.deletion.marker > 0) - list.push( - `delete ${summary.deletion.link} links and ${summary.deletion.marker} markers` - ); - if ( - summary.edition.portal + summary.edition.link + summary.edition.marker > - 0 - ) - list.push( - `edit ${summary.edition.portal} portals, ${summary.edition.link} links and ${summary.edition.marker} markers` - ); - if (summary.edition.duplicate > 0) - list.push(`ignore ${summary.edition.duplicate} new duplicates`); - if (summary.edition.removed > 0) - list.push( - `ignore ${summary.edition.removed} links and markers removed from remote` - ); - if (summary.edition.singlePortalLink > 0) - list.push( - `delete ${summary.edition.singlePortalLink} single portal links` - ); - if (summary.edition.assignment > 0) - list.push(`change ${summary.edition.assignment} assignments`); - - const rebaseMessage = L.DomUtil.create("div"); - rebaseMessage.append("Rebase summary:"); - - if (list.length > 0) { - const rebaseList = L.DomUtil.create("ul", null, rebaseMessage); - for (const item of list) - L.DomUtil.create("li", null, rebaseList).textContent = item; - } else { - rebaseMessage.textContent = - "The local changes don't alter the server version."; - } - - return rebaseMessage; - }, - - formatChanges: function (changes, origin, operation) { - const sortable = new Sortable(); - sortable.fields = [ - { - name: " ", - value: (e) => e.type, - format: (cell, value) => { - cell.textContent = value; - }, - }, - { - name: " ", - value: (e) => { - let v = ""; - if (e.data.type === "link") { - v = e.data.link.ID; - } else if (e.data.type === "portal") { - v = e.data.portal.id; - } else if (e.data.type === "marker") { - v = e.data.marker.ID; - } - return v.slice(0, 4); - }, - format: (cell, value) => { - cell.innerHTML = `${value}`; - }, - }, - { - name: "Entry", - value: (e) => e.data.type, - format: (cell, value, e) => { - const op = e.type === "-" ? origin : operation; - if (e.data.type === "link") { - cell.appendChild(LinkUI.displayFormat(e.data.link, op)); - } else if (e.data.type === "portal") { - cell.appendChild(PortalUI.displayFormat(e.data.portal)); - } else if (e.data.type === "marker") { - const portal = op.getPortal(e.data.marker.portalId); - cell.appendChild(PortalUI.displayFormat(portal)); - } else { - cell.textContent = value; - } - if (e.type === "~") { - const pre = L.DomUtil.create("code", null, cell); - (async () => { - const diff = []; - for (const [k, v] of e.data.diff) { - let item = e.data.link || e.data.portal || e.data.marker; - let prev = v; - let cur = item[k]; - if (k.endsWith("ortalId")) { - prev = origin.getPortal(prev).name; - cur = operation.getPortal(cur).name; - } else if (k === "assignedTo") { - if (prev !== "") prev = await WasabeeAgent.get(prev); - if (cur !== "") cur = await WasabeeAgent.get(cur); - if (prev) prev = prev.name; - if (cur) cur = cur.name; - } - diff.push([k, prev, cur]); - } - pre.textContent = JSON.stringify(diff); - })(); - } - }, - }, - ]; - - const items = []; - for (const a of changes.addition) { - items.push({ - type: "+", - data: a, - }); - } - for (const e of changes.edition) { - items.push({ - type: "~", - data: e, - }); - } - for (const d of changes.deletion) { - items.push({ - type: "-", - data: d, - }); - } - - sortable.items = items; - return sortable.table; - }, }); export default MergeDialog; diff --git a/src/code/model/changes.ts b/src/code/model/changes.ts new file mode 100644 index 000000000..478c8ba43 --- /dev/null +++ b/src/code/model/changes.ts @@ -0,0 +1,522 @@ +import WasabeeLink from "./link"; +import WasabeePortal from "./portal"; +import type WasabeeOp from "./operation"; +import WasabeeMarker from "./marker"; +import WasabeeZone from "./zone"; + +type Change = { + id: string | number; + props?: Partial>; + value?: T; + type: "addition" | "edition" | "deletion"; +}; + +type MarkerChange = Change< + WasabeeMarker, + "type" | "zone" | "order" | "completedID" | "assignedTo" | "state" +>; +type LinkChange = Change< + WasabeeLink, + | "fromPortalId" + | "toPortalId" + | "color" + | "zone" + | "order" + | "completedID" + | "assignedTo" + | "state" +>; + +type PortalChange = Change; + +type ZoneChange = Change; + +type OperationChange = Change< + WasabeeOp, + "name" | "comment" | "referencetime" | "color" +> & { + type: "edition"; + portals: PortalChange[]; + links: LinkChange[]; + markers: MarkerChange[]; + zones: ZoneChange[]; +}; + +function computeDiff(origin: T, current: T, keys: K[]) { + const props: Partial = {}; + let once = false; + for (const key of keys) { + if (JSON.stringify(origin[key]) !== JSON.stringify(current[key])) { + props[key] = current[key]; + once = true; + } + } + if (once) return props; + return null; +} + +function linkChanges(origin: WasabeeLink, current: WasabeeLink) { + const changes: LinkChange = { + id: origin.ID, + type: "edition", + props: computeDiff(origin, current, [ + "fromPortalId", + "toPortalId", + "color", + "zone", + "order", + "completedID", + "assignedTo", + "state", + ]), + }; + return changes; +} + +function markerChanges(origin: WasabeeMarker, current: WasabeeMarker) { + const changes: MarkerChange = { + id: origin.ID, + type: "edition", + props: computeDiff(origin, current, [ + "type", + /*"portalId",*/ // unlikely because we don't swap marker yet + "zone", + "order", + "completedID", + "assignedTo", + "state", + ]), + }; + return changes; +} + +function portalChanges(origin: WasabeePortal, current: WasabeePortal) { + const changes: PortalChange = { + id: origin.id, + type: "edition", + props: computeDiff(origin, current, ["comment", "hardness"]), + }; + return changes; +} + +function zoneChanges(origin: WasabeeZone, current: WasabeeZone) { + const changes: ZoneChange = { + id: origin.id, + type: "edition", + props: computeDiff(origin, current, ["name", "color", "points"]), + }; + return changes; +} + +function compareList< + T extends { id?: string | number; ID?: string }, + K extends keyof T +>( + origin: T[], + current: T[], + keyID: keyof T & ("id" | "ID"), + cmp: (o: T, c: T) => Change +) { + const olist = origin.slice(); + const clist = current.slice(); + olist.sort((a, b) => + a[keyID] < b[keyID] ? -1 : a[keyID] > b[keyID] ? 1 : 0 + ); + clist.sort((a, b) => + a[keyID] < b[keyID] ? -1 : a[keyID] > b[keyID] ? 1 : 0 + ); + + const result: Change[] = []; + + let i = 0; + let j = 0; + while (i < olist.length && j < clist.length) { + const oTop = olist[i]; + const cTop = clist[j]; + if (oTop[keyID] < cTop[keyID]) { + result.push({ + id: oTop[keyID], + type: "deletion", + }); + i += 1; + } else if (oTop[keyID] > cTop[keyID]) { + result.push({ + id: cTop[keyID], + type: "addition", + value: cTop, + }); + j += 1; + } else { + const diff = cmp(oTop, cTop); + if (diff.props) result.push(diff); + i += 1; + j += 1; + } + } + + while (i < olist.length) { + result.push({ + id: olist[i][keyID], + type: "deletion", + }); + i += 1; + } + + while (j < clist.length) { + result.push({ + id: clist[j][keyID], + type: "addition", + value: clist[j], + }); + j += 1; + } + + return result; +} + +export function operationChanges(origin: WasabeeOp, current: WasabeeOp) { + const changes: OperationChange = { + id: origin.ID, + type: "edition", // always + props: computeDiff(origin, current, [ + "name", + "comment", + "referencetime", + "color", + ]), + portals: compareList( + origin.opportals, + current.opportals, + "id", + portalChanges + ), + links: compareList(origin.links, current.links, "ID", linkChanges), + markers: compareList(origin.markers, current.markers, "ID", markerChanges), + zones: compareList(origin.zones, current.zones, "id", zoneChanges), + }; + return changes; +} + +function rebaseDiff(master: Partial, follower: Partial) { + const props: Partial = {}; + let once = false; + for (const k in follower) { + if (JSON.stringify(master[k]) !== JSON.stringify(follower[k])) { + props[k] = follower[k]; + once = true; + } + } + if (once) return props; + return null; +} + +// asume changes sorted by id +function rebaseChanges( + master: Change[], + follower: Change[], + conflictOnDoubleEditOnly = false, // portal and zone + concurrentEditKeys: K[] = [] +) { + const result: Change[] = []; + const conflict: { + id: string | number; + type: + | "addition/addition" + | "edition/edition" + | "edition/deletion" + | "deletion/edition"; + value?: T; + master?: Change; + follower?: Change; + }[] = []; + + let i = 0; + let j = 0; + while (i < master.length && j < follower.length) { + const masterTop = master[i]; + const followerTop = follower[j]; + if (masterTop.id < followerTop.id) { + i += 1; + } else if (masterTop.id > followerTop.id) { + result.push(followerTop); + j += 1; + } else { + if (masterTop.type === "addition" || followerTop.type === "addition") { + // id cannot be created on both end except for portals (what about zones?) + if (conflictOnDoubleEditOnly) { + const p = rebaseDiff(masterTop.props, followerTop.props); + if (p) { + result.push({ + id: followerTop.id, + type: "edition", + props: p, + }); + } + } else { + conflict.push({ + id: followerTop.id, + type: "addition/addition", + }); + } + } else if ( + masterTop.type === "deletion" && + followerTop.type === "deletion" + ) { + // this is easy, both agree + } else if ( + masterTop.type === "edition" && + followerTop.type === "edition" + ) { + const p = rebaseDiff(masterTop.props, followerTop.props); + if (p) { + let ok = true; + // if edit same fields + for (const k in p) { + if (k in masterTop.props) { + ok = false; + break; + } + } + // or touch a field to be cautious about + for (const k in masterTop.props) { + if (!ok || concurrentEditKeys.includes(k)) { + ok = false; + break; + } + } + for (const k in followerTop.props) { + if (!ok || concurrentEditKeys.includes(k)) { + ok = false; + break; + } + } + // then don't solve + if (!ok) { + // concurrent edition on the same field + // of triggered on specific field + conflict.push({ + id: followerTop.id, + type: "edition/edition", + master: masterTop, + follower: followerTop, + }); + } else { + // looks good so far + result.push({ + id: followerTop.id, + type: "edition", + props: p, + }); + } + } + } else { + // edition/deletion conflict + if (conflictOnDoubleEditOnly) { + if (followerTop.type === "edition") { + result.push(followerTop); + } + } else { + conflict.push({ + id: followerTop.id, + type: (masterTop.type + + "/" + + followerTop.type) as typeof conflict[number]["type"], + master: masterTop, + follower: followerTop, + }); + } + } + i += 1; + j += 1; + } + } + + while (j < follower.length) { + result.push(follower[j]); + j += 1; + } + + return { + result, + conflict, + }; +} + +// change follower additions id to match master if equals +function unifyAdditions>( + master: C[], + follower: C[], + eq: (a: C["value"], b: C["value"]) => boolean +) { + const masterAdd = master.filter((c) => c.type === "addition"); + const followerAdd = follower.filter((c) => c.type === "addition"); + for (const a of followerAdd) { + for (const b of masterAdd) { + if (eq(a.value, b.value)) { + a.id = b.id; + break; + } + } + } +} + +export function computeRebaseChanges( + origin: WasabeeOp, + master: WasabeeOp, + follower: WasabeeOp +) { + // add "deleted" portal + for (const p of origin.opportals) { + master._addPortal(p); + follower._addPortal(p); + } + const masterChanges = operationChanges(origin, master); + const followerChanges = operationChanges(origin, follower); + + // use master ID if links are added at both ends + unifyAdditions( + masterChanges.links, + followerChanges.links, + (a, b) => + (a.fromPortalId === b.fromPortalId && a.toPortalId === b.toPortalId) || + (a.fromPortalId === b.toPortalId && a.toPortalId === b.fromPortalId) + ); + // use master ID if markers are added at both ends + // note: assume we shouldn't have multiple markers with same type on a portal + unifyAdditions( + masterChanges.markers, + followerChanges.markers, + (a, b) => a.portalId === b.portalId && a.type === b.type + ); + + const changes = { + props: rebaseDiff(masterChanges.props, followerChanges.props), + portals: rebaseChanges( + masterChanges.portals, + followerChanges.portals, + true + ), + links: rebaseChanges(masterChanges.links, followerChanges.links, false, [ + "fromPortalId", + "toPortalId", + ]), + markers: rebaseChanges( + masterChanges.markers, + followerChanges.markers, + false + ), + zones: rebaseChanges(masterChanges.zones, followerChanges.zones, true), + }; + + // define conflict default resolution value + defaultChangeChoice(master, changes); + + return changes; +} + +function applyChanges(obj: T, props: Partial) { + for (const k in props) { + obj[k] = props[k]; + } +} + +export function defaultChangeChoice( + masterOrCurrent: WasabeeOp, + changes: ReturnType +) { + for (const pc of changes.portals.conflict) { + pc.value = masterOrCurrent.getPortal(pc.id as string); + } + for (const zc of changes.zones.conflict) { + zc.value = masterOrCurrent.getZone(zc.id as number); + } + for (const mc of changes.markers.conflict) { + mc.value = masterOrCurrent.getMarker(mc.id as string); + } + for (const lc of changes.links.conflict) { + lc.value = masterOrCurrent.getLinkById(lc.id as string); + } +} + +export function applyRebaseChanges( + master: WasabeeOp, + current: WasabeeOp, + changes: ReturnType +) { + applyChanges(master, changes.props); + // add possible missing portals + for (const p of current.opportals) { + master._addPortal(new WasabeePortal(p)); + } + // add missing zone (deleted) + for (const z of current.zones) { + const mz = master.getZone(z.id); + if (!mz) master.zones.push(new WasabeeZone(z)); + } + // edit portals + for (const pc of changes.portals.result) { + if (pc.type === "addition") { + // already done, be safe + master._addPortal(pc.value); + } else if (pc.type === "edition") { + const p = master.getPortal(pc.id as string); + if (p) applyChanges(p, pc.props); + } + } + // edit zones + for (const zc of changes.zones.result) { + if (zc.type === "addition") { + // already done, be safe + const mz = master.getZone(zc.id as number); + if (!mz) master.zones.push(new WasabeeZone(zc.value)); + } else if (zc.type === "edition") { + const mz = master.getZone(zc.id as number); + if (mz) applyChanges(mz, zc.props); + } + } + // apply marker changes + for (const mc of changes.markers.result) { + if (mc.type === "deletion") { + master.markers = master.markers.filter((m) => m.ID === mc.id); + } else if (mc.type === "addition") { + master.markers.push(new WasabeeMarker(mc.value)); + } else { + const m = master.getMarker(mc.id as string); + if (m) applyChanges(m, mc.props); + } + } + // apply link changes + for (const lc of changes.links.result) { + if (lc.type === "deletion") { + master.links = master.links.filter((l) => l.ID === lc.id); + } else if (lc.type === "addition") { + master.links.push(new WasabeeLink(lc.value)); + } else { + const l = master.getLinkById(lc.id as string); + if (l) applyChanges(l, lc.props); + } + } + // Conflicts + for (const pc of changes.portals.conflict) { + // no deletion + if (pc.value) master._updatePortal(pc.value); + } + for (const zc of changes.zones.conflict) { + // no deletion + if (zc.value) { + master.zones = master.zones.filter((z) => z.id !== zc.id); + master.zones.push(zc.value); + } + } + for (const mc of changes.markers.conflict) { + master.markers = master.markers.filter((m) => m.ID !== mc.id); + if (mc.value) master.markers.push(mc.value); + } + for (const lc of changes.links.conflict) { + master.links = master.links.filter((l) => l.ID !== lc.id); + if (lc.value) master.links.push(lc.value); + } + + master.cleanAnchorList(); + master.cleanPortalList(); +} diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 9081f2b6b..641eeacbf 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -394,6 +394,15 @@ export default class WasabeeOp extends Evented implements IOperation { return this.getLinkByPortalIDs(portal1.id, portal2.id); } + getLinkById(linkID: LinkID) { + for (const l of this.links) { + if (l.ID == linkID) { + return l; + } + } + return null; + } + getLinkListFromPortal(portal: WasabeePortal) { const links = this.links.filter(function (listLink) { return ( @@ -1231,36 +1240,6 @@ export default class WasabeeOp extends Evented implements IOperation { } changes(origin?: WasabeeOp) { - interface PortalType { - type: "portal"; - portal: WasabeePortal; - } - interface LinkType { - type: "link"; - link: WasabeeLink; - } - interface MarkerType { - type: "marker"; - marker: WasabeeMarker; - } - interface OpChanges { - addition: (PortalType | LinkType | MarkerType)[]; - edition: ((PortalType | LinkType | MarkerType) & { - diff: [string, any][]; - })[]; - deletion: ((LinkType | MarkerType) & { id: TaskID })[]; - name: string; - color: string; - comment: string; - } - const changes: OpChanges = { - addition: [], - edition: [], - deletion: [], - name: null, - color: null, - comment: null, - }; // empty op if old OP (or local OP) const oldOp = new WasabeeOp(origin ? origin : this.getFetchedOp() || {}); const oldLinks = new Map(oldOp.links.map((l) => [l.ID, l])); @@ -1270,9 +1249,9 @@ export default class WasabeeOp extends Evented implements IOperation { const newMarkers = new Map(this.markers.map((m) => [m.ID, m])); // Note: teams/keyonhand are atomic - if (oldOp.name != this.name) changes.name = this.name; - if (oldOp.color != this.color) changes.color = this.color; - if (oldOp.comment != this.comment) changes.comment = this.comment; + if (oldOp.name != this.name) return true; + if (oldOp.color != this.color) return true; + if (oldOp.comment != this.comment) return true; // zones: handle them later for (const [id, p] of this._idToOpportals) { @@ -1282,19 +1261,18 @@ export default class WasabeeOp extends Evented implements IOperation { const diff = fields .filter((k) => oldPortal[k] != p[k]) .map((k) => [k, oldPortal[k]] as [string, any]); - if (diff.length > 0) - changes.edition.push({ type: "portal", portal: p, diff: diff }); + if (diff.length > 0) return true; } } - for (const [id, l] of oldLinks) { + for (const id of oldLinks.keys()) { if (!newLinks.has(id)) { - changes.deletion.push({ type: "link", link: l, id: id }); + return true; } } for (const l of this.links) { if (!oldLinks.has(l.ID)) { - changes.addition.push({ type: "link", link: l }); + return true; } else { const oldLink = oldLinks.get(l.ID); const fields = [ @@ -1311,19 +1289,18 @@ export default class WasabeeOp extends Evented implements IOperation { const diff = fields .filter((k) => oldLink[k] != l[k]) .map((k) => [k, oldLink[k]] as [string, any]); - if (diff.length > 0) - changes.edition.push({ type: "link", link: l, diff: diff }); + if (diff.length > 0) return true; } } - for (const [id, m] of oldMarkers) { + for (const id of oldMarkers.keys()) { if (!newMarkers.has(id)) { - changes.deletion.push({ type: "marker", marker: m, id: id }); + return true; } } for (const m of this.markers) { if (!oldMarkers.has(m.ID)) { - changes.addition.push({ type: "marker", marker: m }); + return true; } else { const oldMarker = oldMarkers.get(m.ID); const fields = [ @@ -1339,29 +1316,20 @@ export default class WasabeeOp extends Evented implements IOperation { const diff = fields .filter((k) => oldMarker[k] != m[k]) .map((k) => [k, oldMarker[k]] as [string, any]); - if (diff.length > 0) - changes.edition.push({ type: "marker", marker: m, diff: diff }); + if (diff.length > 0) return true; } } - return changes; + return false; } checkChanges() { if (this.localchanged) { - const changes = this.changes(); - if ( - changes.addition.length + - changes.edition.length + - changes.deletion.length == - 0 - ) - this.localchanged = false; + this.localchanged = this.changes(); } return this.localchanged; } - // currently overwrite zones instead of ignoring conflict mergeZones(op: WasabeeOp) { const ids = new Map(); let count = 0; @@ -1372,138 +1340,11 @@ export default class WasabeeOp extends Evented implements IOperation { if (!ids.has(z.id)) { this.zones.push(z); count += 1; - } else { - const lz = ids.get(z.id); - if (JSON.stringify(z) !== JSON.stringify(lz)) { - lz.color = z.color; - lz.name = z.name; - lz.points = z.points; - count += 1; - } } } return count; } - // assume that `this` is a server OP (teams/keys are correct) - applyChanges(changes: ReturnType, op: WasabeeOp) { - const summary = { - compatibility: { - ok: true, - rewrite: { - link: 0, - marker: 0, - }, - }, - addition: { - link: 0, - marker: 0, - zone: 0, - ignored: 0, - }, - deletion: { - link: 0, - marker: 0, - }, - edition: { - portal: 0, - link: 0, - marker: 0, - assignment: 0, - duplicate: 0, - singlePortalLink: 0, - removed: 0, - }, - }; - - // merge *portals* - for (const p of op.opportals) { - this._addPortal(p); - } - - // add missing zones - summary.addition.zone = this.mergeZones(op); - - for (const d of changes.deletion) { - if (d.type == "link") { - const links = this.links.filter((l) => l.ID != d.id); - summary.deletion.link += this.links.length - links.length; - this.links = links; - } else if (d.type == "marker") { - const markers = this.markers.filter((m) => m.ID != d.id); - summary.deletion.marker += this.markers.length - markers.length; - this.markers = markers; - } - } - // links/markers absent from `this` are not added back - for (const e of changes.edition) { - if (e.type == "portal") { - const portal = this.getPortal(e.portal.id); - for (const kv of e.diff) portal[kv[0]] = e.portal[kv[0]]; - summary.edition.portal += 1; - } else if (e.type == "link") { - let found = false; - for (const l of this.links) { - if (l.ID == e.link.ID) { - const link = this.getLinkByPortalIDs( - e.link.fromPortalId, - e.link.toPortalId - ); - if (link && link != l) { - // remove the link if leading to a duplicate - // note: in some unexpected situation, this could lead to link loses (when user swap portal a LOT on the same spines) - this.links = this.links.filter((l) => l.ID != e.link.ID); - summary.edition.duplicate += 1; - } else { - for (const kv of e.diff) l[kv[0]] = e.link[kv[0]]; - if (l.fromPortalId == l.toPortalId) { - this.links = this.links.filter((link) => link.ID != l.ID); - summary.edition.singlePortalLink += 1; - } else { - summary.edition.link += 1; - if (e.diff.some((kv) => kv[0] == "assignedTo")) - summary.edition.assignment += 1; - } - } - found = true; - break; - } - } - if (!found) summary.edition.removed += 1; - } else if (e.type == "marker") { - let found = false; - for (const m of this.markers) { - if (m.ID == e.marker.ID) { - for (const kv of e.diff) m[kv[0]] = e.marker[kv[0]]; - summary.edition.marker += 1; - if (e.diff.some((kv) => kv[0] == "assignedTo")) - summary.edition.assignment += 1; - found = true; - break; - } - } - if (!found) summary.edition.removed += 1; - } - } - // `this` takes over `changes` for additions - for (const a of changes.addition) { - if (a.type == "portal") { - // already done - } else if (a.type == "link") { - if (!this.getLinkByPortalIDs(a.link.fromPortalId, a.link.toPortalId)) { - this.links.push(a.link); - summary.addition.link += 1; - } else summary.addition.ignored += 1; - } else if (a.type == "marker") { - if (!this.containsMarkerByID(a.marker.portalId, a.marker.type)) { - this.markers.push(a.marker); - summary.addition.marker += 1; - } else summary.addition.ignored += 1; - } - } - return summary; - } - determineZone(latlng: { lat: number; lng: number }) { // sort first, lowest ID wins if a marker is in 2 overlapping zones this.zones.sort((a, b) => { diff --git a/src/code/model/zone.ts b/src/code/model/zone.ts index 18a52c6b9..3d4b35b69 100644 --- a/src/code/model/zone.ts +++ b/src/code/model/zone.ts @@ -2,7 +2,7 @@ export default class WasabeeZone { id: ZoneID; name: string; color: string; - points: zonePoint[]; + points: ZonePoint[]; constructor(obj) { this.id = Number(obj.id); @@ -12,7 +12,7 @@ export default class WasabeeZone { if (obj.points) { for (const p of obj.points) { - this.points.push(new zonePoint(p)); + this.points.push(new ZonePoint(p)); } } } @@ -55,7 +55,7 @@ export default class WasabeeZone { } } -class zonePoint { +export class ZonePoint { position: number; lat: number; lng: number; From cedcc6fccc362f9d8705a774b8361932788f7016 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 30 Nov 2021 21:02:35 +0100 Subject: [PATCH 262/275] merge: friendly display --- src/code/css/wasabee.css | 41 ++++++---- src/code/dialogs/mergeDialog.js | 140 +++++++++++++++++++++++++++++--- src/code/model/changes.ts | 15 +++- src/code/ui/marker.d.ts | 3 + src/code/ui/marker.js | 16 ++++ 5 files changed, 188 insertions(+), 27 deletions(-) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index 2940c5ea2..a37f188ff 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -50,7 +50,7 @@ .wasabee-table > thead .sortable.desc:before { content: "\25bc"; } -// .wasabee-table td.menu { position: relative; min-height: 20px; min-width: 24px; } +/* .wasabee-table td.menu { position: relative; min-height: 20px; min-width: 24px; } */ .wasabee-dialog-agent ul { padding-left: 0; @@ -531,23 +531,36 @@ a.wasabee-portal.res { color: rgb(0, 135, 255) !important; } padding-left: 1em; } -/* merge dialog */ -@media (min-width: 700px) { - .wasabee-dialog-merge .details { - display: grid; - grid-template-columns: auto auto auto; - } +.wasabee-dialog-merge .conflicts { + border-collapse: collapse; + empty-cells: show; + width: 100%; + clear: both; + background: #0004; } -.wasabee-dialog-merge .details .wasabee-table { - margin-bottom: auto; - border: 1px solid white; - margin-right: 2px; - margin-left: 2px; +.wasabee-dialog-merge .conflicts tr:nth-child(2n + 1) { + background: #0004; } -.wasabee-dialog-merge .details .wasabee-table code { - display: block; +.wasabee-dialog-merge .conflicts td, +.wasabee-dialog-merge .conflicts th { + border-width: 0 1px; + border-style: solid; + padding: 3px 4px; + text-align: left; + vertical-align: baseline; +} +.wasabee-dialog-merge .conflicts td:first-child, +.wasabee-dialog-merge .conflicts th:first-child { + border-left-width: 0; +} +.wasabee-dialog-merge .conflicts td:last-child, +.wasabee-dialog-merge .conflicts th:last-child { + border-right-width: 0; +} +.wasabee-dialog-merge .strike { + text-decoration: line-through; } /* color pickers */ diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index 020ce4d57..93e6ae725 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -1,14 +1,14 @@ import { WDialog } from "../leafletClasses"; import wX from "../wX"; -// import WasabeeAgent from "../model/agent"; +import WasabeeAgent from "../model/agent"; import WasabeeOp from "../model/operation"; -// import Sortable from "../sortable"; import { getSelectedOperation, makeSelectedOperation } from "../selectedOp"; import { computeRebaseChanges, applyRebaseChanges } from "../model/changes"; -// import PortalUI from "../ui/portal"; -// import LinkUI from "../ui/link"; +import PortalUI from "../ui/portal"; +import LinkUI from "../ui/link"; +import MarkerUI from "../ui/marker"; const MergeDialog = WDialog.extend({ statics: { @@ -60,7 +60,7 @@ const MergeDialog = WDialog.extend({ _displayDialog: function () { this._opRebase = new WasabeeOp(this.options.opRemote); - const origin = this.options.opOwn.getFetchedOp() + this._origin = this.options.opOwn.getFetchedOp() ? new WasabeeOp(this.options.opOwn.getFetchedOp()) : new WasabeeOp({ // dummy op @@ -71,7 +71,7 @@ const MergeDialog = WDialog.extend({ referencetime: this.options.opOwn.referencetime, }); const changes = computeRebaseChanges( - origin, + this._origin, this._opRebase, this.options.opOwn ); @@ -81,6 +81,7 @@ const MergeDialog = WDialog.extend({ for (const pc of changes.portals.conflict) { if (pc.type === "edition/edition") { conflicts.push({ + kind: "portal", conflict: pc, masterValue: this._opRebase.getPortal(pc.id), followerValue: this.options.opOwn.getPortal(pc.id), @@ -90,6 +91,7 @@ const MergeDialog = WDialog.extend({ for (const zc of changes.zones.conflict) { if (zc.type === "edition/edition") { conflicts.push({ + kind: "zone", conflict: zc, masterValue: this._opRebase.getZone(zc.id), followerValue: this.options.opOwn.getZone(zc.id), @@ -100,6 +102,7 @@ const MergeDialog = WDialog.extend({ for (const mc of changes.markers.conflict) { if (mc.type !== "addition/addition") { conflicts.push({ + kind: "marker", conflict: mc, masterValue: this._opRebase.getMarker(mc.id), followerValue: this.options.opOwn.getMarker(mc.id), @@ -109,6 +112,7 @@ const MergeDialog = WDialog.extend({ for (const lc of changes.links.conflict) { if (lc.type !== "addition/addition") { conflicts.push({ + kind: "link", conflict: lc, masterValue: this._opRebase.getLinkById(lc.id), followerValue: this.options.opOwn.getLinkById(lc.id), @@ -172,8 +176,12 @@ const MergeDialog = WDialog.extend({ for (const c of conflicts) { const row = L.DomUtil.create("tr", "", details); // master props - const masterTD = L.DomUtil.create("td", "master", row); - masterTD.textContent = JSON.stringify(c.conflict.master.props); + this.formatConflict( + c, + c.conflict.master, + this._opRebase, + L.DomUtil.create("td", "master", row) + ); // master type L.DomUtil.create("td", "master", row).textContent = c.conflict.master.type === "edition" ? "~" : "-"; @@ -200,8 +208,12 @@ const MergeDialog = WDialog.extend({ L.DomUtil.create("td", "follower", row).textContent = c.conflict.follower.type === "edition" ? "~" : "-"; // follower props - const followerTD = L.DomUtil.create("td", "follower", row); - followerTD.textContent = JSON.stringify(c.conflict.follower.props); + this.formatConflict( + c, + c.conflict.follower, + this.options.opOwn, + L.DomUtil.create("td", "follower", row) + ); L.DomEvent.on(masterRadio, "change", () => { if (masterRadio.checked) { @@ -242,6 +254,114 @@ const MergeDialog = WDialog.extend({ buttons: buttons, }); }, + + formatConflict(conflict, change, op, container) { + // fail safe for now + try { + if (conflict.kind === "link") { + const link = this._origin.getLinkById(change.id); + const linkDisplay = LinkUI.displayFormat(link, this._origin); + container.appendChild(linkDisplay); + if (change.type === "deletion") linkDisplay.classList.add("strike"); + else { + const list = L.DomUtil.create("ul", "", container); + for (const k in change.props) { + this.formatProp(k, link, change.props, op, list); + } + } + } else if (conflict.kind === "marker") { + const marker = this._origin.getMarker(change.id); + const markerDisplay = MarkerUI.displayFormat(marker, this._origin); + container.appendChild(markerDisplay); + if (change.type === "deletion") markerDisplay.classList.add("strike"); + else { + const list = L.DomUtil.create("ul", "", container); + for (const k in change.props) { + this.formatProp(k, marker, change.props, op, list); + } + } + } else if (conflict.kind === "portal") { + const portal = this._origin.getPortal(change.id); + const portalDisplay = PortalUI.displayFormat(portal); + container.appendChild(portalDisplay); + // only edition/edition + const list = L.DomUtil.create("ul", "", container); + for (const k in change.props) { + this.formatProp(k, portal, change.props, op, list); + } + } else if (conflict.kind === "zone") { + const zone = this._origin.getZone(change.id); + const zoneDisplay = L.DomUtil.create("span"); + zoneDisplay.textContent = "Zone: " + zone.name; + container.appendChild(zoneDisplay); + // only edition/edition + const list = L.DomUtil.create("ul", "", container); + for (const k in change.props) { + this.formatProp(k, zone, change.props, op, list); + } + } + } catch (e) { + console.error(e); + container.append(JSON.stringify(change.props)); + } + }, + + formatProp(key, old, next, op, container) { + const li = L.DomUtil.create("li", "", container); + // content with default value + const keySpan = L.DomUtil.create("span", "", li); + keySpan.textContent = key + ": "; + const oldSpan = L.DomUtil.create("span", "strike", li); + oldSpan.textContent = old[key]; + const newSpan = L.DomUtil.create("span", "", li); + newSpan.textContent = next[key]; + + if (key === "hardness") { + keySpan.textContent = "Hard: "; + } else if (key === "comment") { + keySpan.textContent = "Comment: "; + } else if (key === "assignedTo") { + keySpan.textContent = "Assign: "; + } else if (key === "completedID") { + keySpan.textContent = "Completed by: "; + } else if (key === "state") { + keySpan.textContent = "State: "; + } else if (key === "color") { + keySpan.textContent = "Color: "; + } else if (key === "order") { + keySpan.textContent = "Order: "; + } else if (key === "zone") { + keySpan.textContent = "Zone: "; + } else if (key === "points") { + keySpan.textContent = "Shape has changed"; + oldSpan.textContent = ""; + newSpan.textContent = ""; + } else if (key === "fromPortalId") { + keySpan.textContent = "From: "; + } else if (key === "toPortalId") { + keySpan.textContent = "To: "; + } + + if (key === "assignedTo" || key === "completedID") { + if (old[key]) + WasabeeAgent.get(old[key]).then( + (a) => (oldSpan.textContent = a.getName()) + ); + if (next[key]) + WasabeeAgent.get(next[key]).then( + (a) => (newSpan.textContent = a.getName()) + ); + } + + if (key === "fromPortalId" || key === "toPortalId") { + oldSpan.textContent = ""; + oldSpan.appendChild( + PortalUI.displayFormat(this._origin.getPortal(old[key])) + ); + newSpan.textContent = ""; + newSpan.appendChild(PortalUI.displayFormat(op.getPortal(next[key]))); + } + }, }); export default MergeDialog; diff --git a/src/code/model/changes.ts b/src/code/model/changes.ts index 478c8ba43..03a7b67d3 100644 --- a/src/code/model/changes.ts +++ b/src/code/model/changes.ts @@ -13,7 +13,7 @@ type Change = { type MarkerChange = Change< WasabeeMarker, - "type" | "zone" | "order" | "completedID" | "assignedTo" | "state" + "type" | "zone" | "order" | "completedID" | "assignedTo" | "state" | "comment" >; type LinkChange = Change< WasabeeLink, @@ -25,6 +25,7 @@ type LinkChange = Change< | "completedID" | "assignedTo" | "state" + | "comment" >; type PortalChange = Change; @@ -67,6 +68,7 @@ function linkChanges(origin: WasabeeLink, current: WasabeeLink) { "order", "completedID", "assignedTo", + "comment", "state", ]), }; @@ -84,6 +86,7 @@ function markerChanges(origin: WasabeeMarker, current: WasabeeMarker) { "order", "completedID", "assignedTo", + "comment", "state", ]), }; @@ -201,7 +204,7 @@ function rebaseDiff(master: Partial, follower: Partial) { const props: Partial = {}; let once = false; for (const k in follower) { - if (JSON.stringify(master[k]) !== JSON.stringify(follower[k])) { + if (!master || JSON.stringify(master[k]) !== JSON.stringify(follower[k])) { props[k] = follower[k]; once = true; } @@ -210,13 +213,14 @@ function rebaseDiff(master: Partial, follower: Partial) { return null; } -// asume changes sorted by id function rebaseChanges( master: Change[], follower: Change[], conflictOnDoubleEditOnly = false, // portal and zone concurrentEditKeys: K[] = [] ) { + master.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)); + follower.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)); const result: Change[] = []; const conflict: { id: string | number; @@ -517,6 +521,11 @@ export function applyRebaseChanges( if (lc.value) master.links.push(lc.value); } + // remove duplicates + master.links = master.links.filter( + (l) => master.getLinkByPortalIDs(l.fromPortalId, l.toPortalId) === l + ); + master.cleanAnchorList(); master.cleanPortalList(); } diff --git a/src/code/ui/marker.d.ts b/src/code/ui/marker.d.ts index fbc4b7edc..6844f7365 100644 --- a/src/code/ui/marker.d.ts +++ b/src/code/ui/marker.d.ts @@ -1,5 +1,6 @@ import type { WLPortal } from "./portal"; import type WasabeeMarker from "../model/marker"; +import type WasabeeOp from "../model/operation"; export class WLMarker extends WLPortal { state: string; @@ -13,3 +14,5 @@ export class WLMarker extends WLPortal { _setComment(ev: any): void; _setMarkerType(ev: any): void; } + +export function displayFormat(marker: WasabeeMarker, operation: WasabeeOp): HTMLSpanElement; diff --git a/src/code/ui/marker.js b/src/code/ui/marker.js index 5289f4595..bee205f1b 100644 --- a/src/code/ui/marker.js +++ b/src/code/ui/marker.js @@ -11,6 +11,21 @@ import PortalUI from "./portal"; import wX from "../wX"; +function displayFormat(marker, operation) { + const portal = operation.getPortal(marker.portalId); + + if (portal == null) { + console.log("null portal getting marker popup"); + return (L.DomUtil.create("div", "").textContent = "invalid portal"); + } + + const desc = L.DomUtil.create("span"); + const kind = L.DomUtil.create("span", `${marker.type}`, desc); + kind.textContent = wX(marker.type); + desc.appendChild(PortalUI.displayFormat(portal)); + return desc; +} + const WLMarker = PortalUI.WLPortal.extend({ type: "marker", @@ -156,4 +171,5 @@ const WLMarker = PortalUI.WLPortal.extend({ export default { WLMarker, + displayFormat, }; From d5318ab6fdb3540479bbfee076c9b62b744c5bfb Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Thu, 13 Jan 2022 19:03:29 +0100 Subject: [PATCH 263/275] changes: allow multiple markers with same type --- src/code/model/changes.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/code/model/changes.ts b/src/code/model/changes.ts index 03a7b67d3..1e88b3838 100644 --- a/src/code/model/changes.ts +++ b/src/code/model/changes.ts @@ -385,13 +385,6 @@ export function computeRebaseChanges( (a.fromPortalId === b.fromPortalId && a.toPortalId === b.toPortalId) || (a.fromPortalId === b.toPortalId && a.toPortalId === b.fromPortalId) ); - // use master ID if markers are added at both ends - // note: assume we shouldn't have multiple markers with same type on a portal - unifyAdditions( - masterChanges.markers, - followerChanges.markers, - (a, b) => a.portalId === b.portalId && a.type === b.type - ); const changes = { props: rebaseDiff(masterChanges.props, followerChanges.props), From d9c9fd350afd93834f9d5018e47408eb12c934bc Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 16 Jan 2022 22:05:36 +0100 Subject: [PATCH 264/275] fix: merged marked as unchanged --- src/code/model/changes.ts | 1 + src/code/model/operation.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/code/model/changes.ts b/src/code/model/changes.ts index 1e88b3838..5f2070c48 100644 --- a/src/code/model/changes.ts +++ b/src/code/model/changes.ts @@ -186,6 +186,7 @@ export function operationChanges(origin: WasabeeOp, current: WasabeeOp) { "comment", "referencetime", "color", + "localchanged", ]), portals: compareList( origin.opportals, diff --git a/src/code/model/operation.ts b/src/code/model/operation.ts index 641eeacbf..34f0cde48 100644 --- a/src/code/model/operation.ts +++ b/src/code/model/operation.ts @@ -112,7 +112,7 @@ export default class WasabeeOp extends Evented implements IOperation { this.teamlist = obj.teamlist ? obj.teamlist : []; this.fetched = obj.fetched ? obj.fetched : null; this.stored = obj.stored ? obj.stored : null; - this.localchanged = obj.localchanged === false ? obj.localchanged : true; + this.localchanged = !!obj.localchanged; this.keysonhand = obj.keysonhand ? obj.keysonhand : []; this.zones = this.convertZonesToObjs(obj.zones); // this.modified = obj.modified ? obj.modified : null; From 4b5ddc3b7115b034a7f180140732e96e2c6093f7 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Mon, 7 Feb 2022 22:52:54 +0100 Subject: [PATCH 265/275] drop completedID --- src/code/dialogs/mergeDialog.js | 5 +++-- src/code/model/changes.ts | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index 93e6ae725..ae287cc6a 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -316,14 +316,13 @@ const MergeDialog = WDialog.extend({ const newSpan = L.DomUtil.create("span", "", li); newSpan.textContent = next[key]; + // TODO wX if (key === "hardness") { keySpan.textContent = "Hard: "; } else if (key === "comment") { keySpan.textContent = "Comment: "; } else if (key === "assignedTo") { keySpan.textContent = "Assign: "; - } else if (key === "completedID") { - keySpan.textContent = "Completed by: "; } else if (key === "state") { keySpan.textContent = "State: "; } else if (key === "color") { @@ -340,6 +339,8 @@ const MergeDialog = WDialog.extend({ keySpan.textContent = "From: "; } else if (key === "toPortalId") { keySpan.textContent = "To: "; + } else if (key === "deltaminutes") { + keySpan.textContent = "Delta: "; } if (key === "assignedTo" || key === "completedID") { diff --git a/src/code/model/changes.ts b/src/code/model/changes.ts index 5f2070c48..7862a19e9 100644 --- a/src/code/model/changes.ts +++ b/src/code/model/changes.ts @@ -13,7 +13,13 @@ type Change = { type MarkerChange = Change< WasabeeMarker, - "type" | "zone" | "order" | "completedID" | "assignedTo" | "state" | "comment" + | "type" + | "zone" + | "order" + | "assignedTo" + | "state" + | "comment" + | "deltaminutes" >; type LinkChange = Change< WasabeeLink, @@ -22,10 +28,10 @@ type LinkChange = Change< | "color" | "zone" | "order" - | "completedID" | "assignedTo" | "state" | "comment" + | "deltaminutes" >; type PortalChange = Change; @@ -66,10 +72,10 @@ function linkChanges(origin: WasabeeLink, current: WasabeeLink) { "color", "zone", "order", - "completedID", "assignedTo", "comment", "state", + "deltaminutes", ]), }; return changes; @@ -84,10 +90,10 @@ function markerChanges(origin: WasabeeMarker, current: WasabeeMarker) { /*"portalId",*/ // unlikely because we don't swap marker yet "zone", "order", - "completedID", "assignedTo", "comment", "state", + "deltaminutes", ]), }; return changes; @@ -436,6 +442,12 @@ export function defaultChangeChoice( } } +/* + current properties that are preserved on master: + - Task.dependsOn + - Marker.attributes +*/ + export function applyRebaseChanges( master: WasabeeOp, current: WasabeeOp, From 57b148278bbbc419db51f7ff26e7df2fc9ee4ae8 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 8 Feb 2022 21:48:02 +0100 Subject: [PATCH 266/275] merge: add wX --- src/code/css/wasabee.css | 3 ++ src/code/dialogs/mergeDialog.js | 47 ++++++++++++++---------------- src/code/model/task.ts | 6 ++++ src/code/translations/English.json | 17 ++++++++++- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index a37f188ff..187e40e5f 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -562,6 +562,9 @@ a.wasabee-portal.res { color: rgb(0, 135, 255) !important; } .wasabee-dialog-merge .strike { text-decoration: line-through; } +.wasabee-dialog-merge .diff-label { + padding-right: .5em; +} /* color pickers */ input[type=color].hidden-color-picker { diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index ae287cc6a..bde7c8b57 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -9,6 +9,7 @@ import { computeRebaseChanges, applyRebaseChanges } from "../model/changes"; import PortalUI from "../ui/portal"; import LinkUI from "../ui/link"; import MarkerUI from "../ui/marker"; +import { sanitizeState } from "../model/task"; const MergeDialog = WDialog.extend({ statics: { @@ -129,14 +130,15 @@ const MergeDialog = WDialog.extend({ const desc = L.DomUtil.create("div", "desc", content); desc.textContent = wX("MERGE_MESSAGE", { opName: this.options.opOwn.name }); - L.DomUtil.create("h3", "", content).textContent = "Conflicts:"; + L.DomUtil.create("h3", "", content).textContent = wX( + "dialog.merge.conflicts" + ); const details = L.DomUtil.create("table", "conflicts", content); const head = L.DomUtil.create("tr", "", details); // master head const masterHead = L.DomUtil.create("th", "master", head); - masterHead.colSpan = 2; - masterHead.textContent = "Master copy"; + masterHead.textContent = wX("dialog.merge.server"); const masterRadioHead = L.DomUtil.create( "input", "", @@ -153,8 +155,7 @@ const MergeDialog = WDialog.extend({ followerRadioHead.type = "radio"; followerRadioHead.name = this.options.opOwn.ID; const followerHead = L.DomUtil.create("th", "follower", head); - followerHead.colSpan = 2; - followerHead.textContent = "Local copy"; + followerHead.textContent = wX("dialog.merge.local"); L.DomEvent.on(masterRadioHead, "change", () => { if (masterRadioHead.checked) { @@ -182,9 +183,6 @@ const MergeDialog = WDialog.extend({ this._opRebase, L.DomUtil.create("td", "master", row) ); - // master type - L.DomUtil.create("td", "master", row).textContent = - c.conflict.master.type === "edition" ? "~" : "-"; // master radio const masterRadio = L.DomUtil.create( "input", @@ -204,9 +202,6 @@ const MergeDialog = WDialog.extend({ followerRadio.type = "radio"; followerRadio.name = c.conflict.id; followerRadio.value = "master"; - // follower type - L.DomUtil.create("td", "follower", row).textContent = - c.conflict.follower.type === "edition" ? "~" : "-"; // follower props this.formatConflict( c, @@ -292,7 +287,7 @@ const MergeDialog = WDialog.extend({ } else if (conflict.kind === "zone") { const zone = this._origin.getZone(change.id); const zoneDisplay = L.DomUtil.create("span"); - zoneDisplay.textContent = "Zone: " + zone.name; + zoneDisplay.textContent = wX("dialog.merge.zone", { name: zone.name }); container.appendChild(zoneDisplay); // only edition/edition const list = L.DomUtil.create("ul", "", container); @@ -309,8 +304,8 @@ const MergeDialog = WDialog.extend({ formatProp(key, old, next, op, container) { const li = L.DomUtil.create("li", "", container); // content with default value - const keySpan = L.DomUtil.create("span", "", li); - keySpan.textContent = key + ": "; + const keySpan = L.DomUtil.create("span", "diff-label", li); + keySpan.textContent = key + ":"; const oldSpan = L.DomUtil.create("span", "strike", li); oldSpan.textContent = old[key]; const newSpan = L.DomUtil.create("span", "", li); @@ -318,29 +313,31 @@ const MergeDialog = WDialog.extend({ // TODO wX if (key === "hardness") { - keySpan.textContent = "Hard: "; + keySpan.textContent = wX("dialog.merge.prop.hardness"); } else if (key === "comment") { - keySpan.textContent = "Comment: "; + keySpan.textContent = wX("dialog.merge.prop.comment"); } else if (key === "assignedTo") { - keySpan.textContent = "Assign: "; + keySpan.textContent = wX("dialog.merge.prop.assignedTo"); } else if (key === "state") { - keySpan.textContent = "State: "; + keySpan.textContent = wX("dialog.merge.prop.state"); + oldSpan.textContent = wX(sanitizeState(old[key])); + newSpan.textContent = wX(sanitizeState(next[key])); } else if (key === "color") { - keySpan.textContent = "Color: "; + keySpan.textContent = wX("dialog.merge.prop.color"); } else if (key === "order") { - keySpan.textContent = "Order: "; + keySpan.textContent = wX("dialog.merge.prop.order"); } else if (key === "zone") { - keySpan.textContent = "Zone: "; + keySpan.textContent = wX("dialog.merge.prop.zone"); } else if (key === "points") { - keySpan.textContent = "Shape has changed"; + keySpan.textContent = wX("dialog.merge.prop.zone_points"); oldSpan.textContent = ""; newSpan.textContent = ""; } else if (key === "fromPortalId") { - keySpan.textContent = "From: "; + keySpan.textContent = wX("dialog.merge.prop.fromPortal"); } else if (key === "toPortalId") { - keySpan.textContent = "To: "; + keySpan.textContent = wX("dialog.merge.prop.toPortal"); } else if (key === "deltaminutes") { - keySpan.textContent = "Delta: "; + keySpan.textContent = wX("dialog.merge.prop.deltaminutes"); } if (key === "assignedTo" || key === "completedID") { diff --git a/src/code/model/task.ts b/src/code/model/task.ts index a80371cea..53476bd88 100644 --- a/src/code/model/task.ts +++ b/src/code/model/task.ts @@ -2,6 +2,12 @@ import { generateId } from "../auxiliar"; export type TaskState = "pending" | "assigned" | "acknowledged" | "completed"; +const States: TaskState[] = ["pending" , "assigned" , "acknowledged" , "completed"]; + +export function sanitizeState(v: string): TaskState { + return States.find((s) => s === v) || "pending" +} + export default class Task { ID: TaskID; order: number; diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 3bcd5aefa..63434a005 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -135,6 +135,21 @@ "dialog.leave_team.title": "Leave: {teamName}", "dialog.link_list.length": "Length", "dialog.link_list.level": "Min Lvl", + "dialog.merge.conflicts": "Conflicts:", + "dialog.merge.local": "Local copy", + "dialog.merge.server": "Server copy", + "dialog.merge.zone": "Zone: {name}", + "dialog.merge.prop.assignedTo": "Assign:", + "dialog.merge.prop.comment": "Comment:", + "dialog.merge.prop.color": "Color:", + "dialog.merge.prop.deltaminutes": "Delta:", + "dialog.merge.prop.fromPortal": "From:", + "dialog.merge.prop.hardness": "Hard:", + "dialog.merge.prop.order": "Order:", + "dialog.merge.prop.state": "State:", + "dialog.merge.prop.toPortal": "To:", + "dialog.merge.prop.zone": "Zone:", + "dialog.merge.prop.zone_points": "Shape has changed", "dialog.online_agents.actions": "Actions", "dialog.online_agents.last_seen": "Last Seen", "dialog.online_agents.title": "Online Agents", @@ -254,7 +269,7 @@ "MERGE_CHANGES_MERGE": "Merge result", "MERGE_CHANGES_REMOTE": "Remote changes", "MERGE_LOCAL": "Keep local", - "MERGE_MESSAGE": "It seems that {opName} has local changes. Do you want to merge your modifications with the server, use the server version, or keep the local version?", + "MERGE_MESSAGE": "Local and server modifications are clashing. You need to resolve the conflicts that Wasabee failed to resolve itself. Select which version in the following list to keep for every unresolved conflicts. You can also ignore all conflicts and use the server copy, or you can just keep the local copy intact.", "MERGE_REBASE": "Merge", "MERGE_REPLACE": "Use server", "MERGE_TITLE": "Merge local&remote OP", From 2fe5a6095ab4d35e60316c93590a18617fd11faf Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 8 Feb 2022 22:11:01 +0100 Subject: [PATCH 267/275] merge: space between old/new --- src/code/css/wasabee.css | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/code/css/wasabee.css b/src/code/css/wasabee.css index 187e40e5f..9ee0dde06 100644 --- a/src/code/css/wasabee.css +++ b/src/code/css/wasabee.css @@ -559,8 +559,15 @@ a.wasabee-portal.res { color: rgb(0, 135, 255) !important; } .wasabee-dialog-merge .conflicts th:last-child { border-right-width: 0; } + +.wasabee-dialog-merge .conflicts th:nth-child(2), +.wasabee-dialog-merge .conflicts th:nth-child(3) { + width: 2em; +} + .wasabee-dialog-merge .strike { - text-decoration: line-through; + text-decoration: line-through red; + padding-right: .5em; } .wasabee-dialog-merge .diff-label { padding-right: .5em; From b0e41e61f0932c752438c98edd9db6f65e7e1651 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Tue, 8 Feb 2022 23:33:09 +0100 Subject: [PATCH 268/275] merge: cancel on upload only --- src/code/buttons/uploadButton.js | 1 + src/code/dialogs/mergeDialog.d.ts | 1 + src/code/dialogs/mergeDialog.js | 13 ++++++++----- src/code/translations/English.json | 1 + 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/code/buttons/uploadButton.js b/src/code/buttons/uploadButton.js index 395d90c3a..715d6db97 100644 --- a/src/code/buttons/uploadButton.js +++ b/src/code/buttons/uploadButton.js @@ -155,6 +155,7 @@ const UploadButton = WButton.extend({ opOwn: getSelectedOperation(), opRemote: lastOp, updateCallback: (op) => this.doUpdate(op, true), + cancelText: wX("dialog.merge.cancel_upload"), }); md.enable(); } diff --git a/src/code/dialogs/mergeDialog.d.ts b/src/code/dialogs/mergeDialog.d.ts index 1f786d89a..ad6ec167e 100644 --- a/src/code/dialogs/mergeDialog.d.ts +++ b/src/code/dialogs/mergeDialog.d.ts @@ -5,6 +5,7 @@ interface MergeDialogOptions extends WDialogOptions { opOwn: WasabeeOp; opRemote: WasabeeOp; updateCallback?: (op: WasabeeOp) => void; + cancelText?: string; } declare class MergeDialog extends WDialog { options: MergeDialogOptions; diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index bde7c8b57..3d3cd70eb 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -20,7 +20,8 @@ const MergeDialog = WDialog.extend({ // title // opOwn // opRemote - // updateCallback + // updateCallback? + // cancelText? }, addHooks: function () { @@ -237,10 +238,12 @@ const MergeDialog = WDialog.extend({ text: wX("MERGE_LOCAL"), click: () => this.useLocal(), }); - buttons.push({ - text: wX("CANCEL"), - click: () => this.closeDialog(), - }); + if (this.options.updateCallback || this.options.cancelText) { + buttons.push({ + text: this.options.cancelText || wX("CANCEL"), + click: () => this.closeDialog(), + }); + } this.createDialog({ title: this.options.title || wX("MERGE_TITLE"), html: content, diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 63434a005..430a36511 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -135,6 +135,7 @@ "dialog.leave_team.title": "Leave: {teamName}", "dialog.link_list.length": "Length", "dialog.link_list.level": "Min Lvl", + "dialog.merge.cancel_upload": "Cancel upload", "dialog.merge.conflicts": "Conflicts:", "dialog.merge.local": "Local copy", "dialog.merge.server": "Server copy", From 93b1896ecbc1cda57673bda36f85817abef84877 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 20 Feb 2022 22:25:25 +0100 Subject: [PATCH 269/275] merge: comments --- src/code/model/changes.ts | 76 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/src/code/model/changes.ts b/src/code/model/changes.ts index 7862a19e9..415bf3a80 100644 --- a/src/code/model/changes.ts +++ b/src/code/model/changes.ts @@ -49,6 +49,12 @@ type OperationChange = Change< zones: ZoneChange[]; }; +/** + * @param origin Origin object + * @param current Object to compare with `origin` + * @param keys Keys of the object to compare the content + * @returns subset of `current` that differs from `origin` + */ function computeDiff(origin: T, current: T, keys: K[]) { const props: Partial = {}; let once = false; @@ -62,6 +68,9 @@ function computeDiff(origin: T, current: T, keys: K[]) { return null; } +/** + * @returns summary of link differences, including the link ID + */ function linkChanges(origin: WasabeeLink, current: WasabeeLink) { const changes: LinkChange = { id: origin.ID, @@ -81,6 +90,9 @@ function linkChanges(origin: WasabeeLink, current: WasabeeLink) { return changes; } +/** + * @returns summary of marker differences, including the marker ID + */ function markerChanges(origin: WasabeeMarker, current: WasabeeMarker) { const changes: MarkerChange = { id: origin.ID, @@ -99,6 +111,9 @@ function markerChanges(origin: WasabeeMarker, current: WasabeeMarker) { return changes; } +/** + * @returns summary of portal differences, including the portal ID + */ function portalChanges(origin: WasabeePortal, current: WasabeePortal) { const changes: PortalChange = { id: origin.id, @@ -108,6 +123,9 @@ function portalChanges(origin: WasabeePortal, current: WasabeePortal) { return changes; } +/** + * @returns summary of zone differences, including the zone ID + */ function zoneChanges(origin: WasabeeZone, current: WasabeeZone) { const changes: ZoneChange = { id: origin.id, @@ -117,6 +135,14 @@ function zoneChanges(origin: WasabeeZone, current: WasabeeZone) { return changes; } +/** + * Compare two lists of object identified by their ID/id. + * Either an object is: + * - in both lists, then compute the object difference and records an `"edition"` + * - in `origin` only, then records a `"deletion"` + * - in `current` only, then records a `"addition"` + * @returns list of addition/deletion and edition (drop object without difference). + */ function compareList< T extends { id?: string | number; ID?: string }, K extends keyof T @@ -183,6 +209,9 @@ function compareList< return result; } +/** + * @returns operation difference from `origin` to `current` + */ export function operationChanges(origin: WasabeeOp, current: WasabeeOp) { const changes: OperationChange = { id: origin.ID, @@ -207,6 +236,11 @@ export function operationChanges(origin: WasabeeOp, current: WasabeeOp) { return changes; } +/** + * Given two changes `master` and `follower`, compute the subset of `follower` + * that is not already in `master` + * @returns `follower` minus `master` + */ function rebaseDiff(master: Partial, follower: Partial) { const props: Partial = {}; let once = false; @@ -220,6 +254,23 @@ function rebaseDiff(master: Partial, follower: Partial) { return null; } +/** + * Given two lists of changes `master` and `follower`, compute the subset of + * `follower` that is not already in `master` and the list of conflicts, where + * a conflict occurs if: + * - double addition (ex: two markers with same IDs) + * - edition/deletion or deletion/edition + * - double editions where both editions have common fields (ex: comment + * changed both on remote and local) + * + * @param conflictOnDoubleEditOnly + * if true, double additions are degraded at double editions (if differ) + * and deletion/edition are kept as edition (for portal and zone) + * @param concurrentEditKeys + * set of keys that raises a conflict on double editions even if + * differences don't conflict + * @returns pair of `follower` minus `master` and conflicts + */ function rebaseChanges( master: Change[], follower: Change[], @@ -321,9 +372,10 @@ function rebaseChanges( } } } else { - // edition/deletion conflict + // edition/deletion or deletion/edition conflict if (conflictOnDoubleEditOnly) { if (followerTop.type === "edition") { + // should this be promoted to "addition" instead ? result.push(followerTop); } } else { @@ -353,7 +405,10 @@ function rebaseChanges( }; } -// change follower additions id to match master if equals +/** + * Change `follower` additions id to match `master` if equals. + * This is used for links if portals are the same while IDs differ + */ function unifyAdditions>( master: C[], follower: C[], @@ -371,6 +426,13 @@ function unifyAdditions>( } } +/** + * + * @param origin Common ancestor + * @param master Master copy that will be used to apply `follower` changes on + * @param follower Our copy + * @returns (`follower` - `origin`) - (`master` - `origin`) and conflicts + */ export function computeRebaseChanges( origin: WasabeeOp, master: WasabeeOp, @@ -418,12 +480,18 @@ export function computeRebaseChanges( return changes; } +/** + * Merge `props` on `obj` + */ function applyChanges(obj: T, props: Partial) { for (const k in props) { obj[k] = props[k]; } } +/** + * Add a value to all conflicts that matches the given op content + */ export function defaultChangeChoice( masterOrCurrent: WasabeeOp, changes: ReturnType @@ -448,6 +516,10 @@ export function defaultChangeChoice( - Marker.attributes */ +/** + * Apply the given changes on `master`. Use `current` to add missing portals + * and missing zones. + */ export function applyRebaseChanges( master: WasabeeOp, current: WasabeeOp, From b66f0dec69adb0ba54850bb7ef37630c6c437d47 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 4 Feb 2022 00:26:40 +0100 Subject: [PATCH 270/275] location share update while iitc is open --- src/code/dialogs/settingsDialog.js | 47 ++++++++++++++++-------------- src/code/init.ts | 23 ++++++++++++++- src/code/translations/English.json | 2 +- src/types/iitc/core/hooks.d.ts | 14 +++++++++ 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/code/dialogs/settingsDialog.js b/src/code/dialogs/settingsDialog.js index d2341ac5a..7ee0f8e97 100644 --- a/src/code/dialogs/settingsDialog.js +++ b/src/code/dialogs/settingsDialog.js @@ -79,13 +79,6 @@ const SettingsDialog = WDialog.extend({ } ); - this._addCheckBox( - container, - wX("SEND LOCATION"), - "wasabee-setting-sendloc", - window.plugin.wasabee.static.constants.SEND_LOCATION_KEY - ); - this._addSelect( container, wX("SKIP_CONFIRM"), @@ -97,12 +90,15 @@ const SettingsDialog = WDialog.extend({ ] ); - this._addCheckBox( - container, - wX("SEND ANALYTICS"), - "wasabee-setting-analytics", - window.plugin.wasabee.static.constants.SEND_ANALYTICS_KEY - ); + // send location on mobile + if (window.plugin.userLocation) { + this._addCheckBox( + container, + wX("SEND LOCATION"), + "wasabee-setting-sendloc", + window.plugin.wasabee.static.constants.SEND_LOCATION_KEY + ); + } this._addCheckBox( container, @@ -120,6 +116,22 @@ const SettingsDialog = WDialog.extend({ window.plugin.wasabee.static.constants.AUTO_LOAD_FAKED ); + if (window.isSmartphone()) { + this._addCheckBox( + container, + wX("USE PANES ON MOBILE"), + "wasabee-setting-usepanes", + window.plugin.wasabee.static.constants.USE_PANES + ); + } + + this._addCheckBox( + container, + wX("SEND ANALYTICS"), + "wasabee-setting-analytics", + window.plugin.wasabee.static.constants.SEND_ANALYTICS_KEY + ); + this._addSelect( container, wX("AUTOLOAD_RATE"), @@ -134,15 +146,6 @@ const SettingsDialog = WDialog.extend({ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map((v) => [v, v]) ); - if (window.isSmartphone()) { - this._addCheckBox( - container, - wX("USE PANES ON MOBILE"), - "wasabee-setting-usepanes", - window.plugin.wasabee.static.constants.USE_PANES - ); - } - const serverInfo = L.DomUtil.create("button", "server", container); serverInfo.textContent = wX("WSERVER", { url: GetWasabeeServer() }); serverInfo.href = "#"; diff --git a/src/code/init.ts b/src/code/init.ts index cbd11a867..dfe37a28b 100644 --- a/src/code/init.ts +++ b/src/code/init.ts @@ -1,6 +1,6 @@ import statics from "./static"; import { initCrossLinks } from "./crosslinks"; -import initServer from "./server"; +import initServer, { locationPromise } from "./server"; import { setupLocalStorage, initSelectedOperation, @@ -196,6 +196,11 @@ window.plugin.wasabee.init = async () => { }); } + // location update on mobile + if (window.plugin.userLocation) { + window.addHook("pluginUserLocation", onLocationChange); + } + // hooks called when layers are enabled/disabled window.map.on("layeradd", (obj: LayerEvent) => { if ( @@ -268,6 +273,22 @@ window.plugin.wasabee.init = async () => { }); }; +let lastUpdate = 0; +function onLocationChange(e: EventUserLocation) { + const { event, data } = e; + if (event !== "onLocationChange" || !data.latlng) return; + + const sl = localStorage[Wasabee.static.constants.SEND_LOCATION_KEY]; + if (sl !== "true") return; + + // do not update more than once per 5s + if (Date.now() - lastUpdate < 5000) return; + + if (!WasabeeMe.isLoggedIn()) return; + locationPromise(data.latlng.lat, data.latlng.lng); + lastUpdate = Date.now(); +} + // this can be moved to auth dialog, no need to init it for people who never log in // and use webpack, rather than importing it ourself function initGoogleAPI() { diff --git a/src/code/translations/English.json b/src/code/translations/English.json index f67618bd9..9fd517e00 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -384,7 +384,7 @@ "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", "SELF SWAP": "Cannot swap a portal with itself! Select a different portal.", "SEND ANALYTICS": "Send Anonymous Analytics", - "SEND LOCATION": "Send Location", + "SEND LOCATION": "Share Location (only when IITC is in foreground)", "SEND TARGET AGENT": "Select target recipient", "SEND TARGET CONFIRM": "Do you want to send {portalName} target to {agent}?", "SEND TARGET": "Send Target", diff --git a/src/types/iitc/core/hooks.d.ts b/src/types/iitc/core/hooks.d.ts index cb483b2c1..a95f19551 100755 --- a/src/types/iitc/core/hooks.d.ts +++ b/src/types/iitc/core/hooks.d.ts @@ -175,6 +175,15 @@ declare global { callback: (e: EventPaneChanged) => void ): void; + /** + * register a callback for an event + * called when the user location or orientation changed. + */ + function addHook( + event: "pluginUserLocation", + callback: (e: EventUserLocation) => void + ): void; + /** * register a callback for an event * (user defined hooks) @@ -276,4 +285,9 @@ declare global { ent: PortalDetailEnt; } | { guid: string; success: false; details: never; ent: never }; + + interface EventUserLocation { + event: "setup" | "onLocationChange" | "onOrientationChange"; + data: { latlng: L.LatLng; direction: number }; + } } From e63927105f711674eb9afb0c9aa199953eb635fb Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Sun, 6 Mar 2022 22:24:12 +0100 Subject: [PATCH 271/275] package updates --- package-lock.json | 19879 ++++++++++---------------------------------- 1 file changed, 4513 insertions(+), 15366 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0406b4fe..2eea41a13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,45 +1,52 @@ { "name": "wasabee-iitc", - "version": "0.18.0", + "version": "0.20.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wasabee-iitc", - "version": "0.18.0", + "version": "0.20.2", "license": "ISC", "dependencies": { + "@fortawesome/fontawesome-svg-core": "^1.2.36", + "@fortawesome/free-solid-svg-icons": "^5.15.4", "arc": "^0.1.1", "color-string": "^1.5.5", "geodesy": "^2.2.1", - "idb": "^6.0.0", + "idb": "^6.1.2", "sortablejs": "^1.12.0" }, "devDependencies": { - "css-loader": "^5.2.4", + "@types/color-string": "^1.5.0", + "@types/jquery": "^3.5.8", + "@types/jqueryui": "^1.12.16", + "@types/leaflet": "^1.7.5", + "@types/spectrum": "^1.8.2", + "@typescript-eslint/eslint-plugin": "^5.9.0", + "@typescript-eslint/parser": "^5.9.0", + "css-loader": "^5.2.6", "del": "^6.0.0", - "eslint": "^7.26.0", + "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", + "eslint-plugin-local-rules": "^1.1.0", "eslint-plugin-prettier": "^3.4.0", + "eslint-webpack-plugin": "^3.0.1", "fancy-log": "^1.3.3", - "gulp": "^4.0.2", - "gulp-eslint": "^6.0.0", - "gulp-inject-file": "^0.0.19", - "gulp-inject-string": "^1.1.1", - "gulp-prettier": "^3.0.0", - "gulp-rename": "^2.0.0", - "gulp-trimlines": "^1.0.1", "html-loader": "^2.1.2", "lodash": "^4.17.21", - "plugin-error": "^1.0.1", - "prettier": "^2.3.0", + "prettier": "^2.3.1", "pretty-quick": "^3.1.0", "raw-loader": "^4.0.2", "style-loader": "^2.0.0", + "through2": "^4.0.2", "to-string-loader": "^1.1.6", + "ts-loader": "^9.2.6", + "tslib": "^2.3.1", + "typescript": "^4.4.4", "url-loader": "^4.1.1", - "webpack": "^5.37.0", - "webpack-cli": "^4.7.2" + "webpack": "^5.38.1", + "webpack-cli": "^4.8.0" } }, "node_modules/@babel/code-frame": { @@ -52,20 +59,26 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", - "dev": true + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, "node_modules/@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.14.0", + "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/highlight/node_modules/ansi-styles": { @@ -140,18 +153,18 @@ } }, "node_modules/@discoveryjs/json-ext": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz", - "integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", + "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", "dev": true, "engines": { "node": ">=10.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", - "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -168,6 +181,77 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", + "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", + "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "^0.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", + "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "^0.2.36" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons/node_modules/@fortawesome/fontawesome-common-types": { + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", + "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -191,9 +275,9 @@ } }, "node_modules/@nodelib/fs.walk": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", - "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -203,10 +287,16 @@ "node": ">= 8" } }, + "node_modules/@types/color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha512-hAhTmfFYVdzgsKwpC9Flc6h9Do64PhKoNxy3YxE0ze+0LIh3a7TrDQAxiujmANQbDRDgGduEz+9sMS+Zd+J7hA==", + "dev": true + }, "node_modules/@types/eslint": { - "version": "7.2.13", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.13.tgz", - "integrity": "sha512-LKmQCWAlnVHvvXq4oasNUMTJJb2GwSyTY8+1C7OH5ILR8mPLaljv1jxL1bXW3xB3jFbQxTKxJAvI8PyjB09aBg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", + "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", "dev": true, "dependencies": { "@types/estree": "*", @@ -214,9 +304,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", - "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -224,179 +314,418 @@ } }, "node_modules/@types/estree": { - "version": "0.0.47", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.47.tgz", - "integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==", + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@types/geojson": { + "version": "7946.0.8", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", + "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==", "dev": true }, + "node_modules/@types/jquery": { + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", + "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", + "dev": true, + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/jqueryui": { + "version": "1.12.16", + "resolved": "https://registry.npmjs.org/@types/jqueryui/-/jqueryui-1.12.16.tgz", + "integrity": "sha512-6huAQDpNlso9ayaUT9amBOA3kj02OCeUWs+UvDmbaJmwkHSg/HLsQOoap/D5uveN9ePwl72N45Bl+Frp5xyG1Q==", + "dev": true, + "dependencies": { + "@types/jquery": "*" + } + }, "node_modules/@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "node_modules/@types/leaflet": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.9.tgz", + "integrity": "sha512-H8vPgD49HKzqM41ArHGZM70g/tfhp8W+JcPxfnF+5H/Xvp+xiP+KQOUNWU8U89fqS1Jj3cpRY/+nbnaHFzwnFA==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, "node_modules/@types/node": { - "version": "15.12.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.1.tgz", - "integrity": "sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==", + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "node_modules/@types/spectrum": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@types/spectrum/-/spectrum-1.8.2.tgz", + "integrity": "sha512-PbEC/2Kipsd7Ch5IX4I2xCpp9nlQgBH+PzThWHV4knd7f0viLDY2w3hJ0QpF4/wwweUPPGoAZyb7W7HS4g+FMw==", + "dev": true, + "dependencies": { + "@types/jquery": "*", + "@types/tinycolor2": "*" + } + }, + "node_modules/@types/tinycolor2": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.3.tgz", + "integrity": "sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ==", "dev": true }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz", + "integrity": "sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.13.0", + "@typescript-eslint/type-utils": "5.13.0", + "@typescript-eslint/utils": "5.13.0", + "debug": "^4.3.2", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.2.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.13.0.tgz", + "integrity": "sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.13.0", + "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/typescript-estree": "5.13.0", + "debug": "^4.3.2" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz", + "integrity": "sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/visitor-keys": "5.13.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz", + "integrity": "sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.13.0", + "debug": "^4.3.2", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.13.0.tgz", + "integrity": "sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz", + "integrity": "sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/visitor-keys": "5.13.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.13.0.tgz", + "integrity": "sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.13.0", + "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/typescript-estree": "5.13.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz", + "integrity": "sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.13.0", + "eslint-visitor-keys": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", "dev": true }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/ast": "1.11.1", "@xtuc/long": "4.2.2" } }, "node_modules/@webpack-cli/configtest": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.4.tgz", - "integrity": "sha512-cs3XLy+UcxiP6bj0A6u7MLLuwdXJ1c3Dtc0RkKg+wiI1g/Ti1om8+/2hc2A2B60NbBNAbMgyBMHvyymWm/j4wQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", + "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", "dev": true, "peerDependencies": { "webpack": "4.x.x || 5.x.x", @@ -404,9 +733,9 @@ } }, "node_modules/@webpack-cli/info": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.3.0.tgz", - "integrity": "sha512-ASiVB3t9LOKHs5DyVUcxpraBXDOKubYu/ihHhU+t1UPpxsivg6Od2E2qU4gJCekfEddzRBzHhzA/Acyw/mlK/w==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", + "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", "dev": true, "dependencies": { "envinfo": "^7.7.3" @@ -416,9 +745,9 @@ } }, "node_modules/@webpack-cli/serve": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.1.tgz", - "integrity": "sha512-4vSVUiOPJLmr45S8rMGy7WDvpWxfFxfP/Qx/cxZFCfvoypTYpPPL1X8VIZMe0WTA+Jr7blUxwUSEZNkjoMTgSw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", + "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", "dev": true, "peerDependencies": { "webpack-cli": "4.x.x" @@ -454,9 +783,9 @@ } }, "node_modules/acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -509,33 +838,6 @@ "node": ">=6" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-gray": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", @@ -549,9 +851,9 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" @@ -581,1136 +883,1120 @@ "node": ">=0.10.0" } }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "node_modules/arc": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/arc/-/arc-0.1.2.tgz", + "integrity": "sha512-bGCkKR675zaomc6HP3dR6hc6HXXnpXrehMkayof2Ql5dZ3f2Bd8o+KfdAruSCcW471K7WFn2pDvSLG8Q0co0dw==", + "engines": { + "node": ">=0.4.0" } }, - "node_modules/anymatch/node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/anymatch/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/anymatch/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/anymatch/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/anymatch/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/anymatch/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/anymatch/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, - "node_modules/anymatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/anymatch/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "remove-trailing-separator": "^1.0.1" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "node_modules/browserslist": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", + "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", "dev": true, "dependencies": { - "buffer-equal": "^1.0.0" + "caniuse-lite": "^1.0.30001312", + "electron-to-chromium": "^1.4.71", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/arc/-/arc-0.1.1.tgz", - "integrity": "sha512-gJsNNbnJW7UMU9ccjBaRh2evSyltbinzRGNPX9aiW28QxbGMtwMDC0YL6lkF73b+y+BUAOT/dUN2DMQDB1Is5w==", - "engines": { - "node": ">=0.4.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" } }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", "dev": true, "dependencies": { - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" } }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "node_modules/caniuse-lite": { + "version": "1.0.30001313", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001313.tgz", + "integrity": "sha512-rI1UN0koZUiKINjysQDuRi2VeSCce3bYJNmDcj3PIKREiAmjakugBul1QSkg/fPrlULYl6oWfGg3PbgOSY9X4Q==", "dev": true, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" } }, - "node_modules/arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "make-iterator": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" } }, - "node_modules/array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "node_modules/clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 4.0" } }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, "dependencies": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/array-initial/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", + "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", "dependencies": { - "is-number": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/array-last/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true, - "engines": { - "node": ">=0.10.0" + "bin": { + "color-support": "bin.js" } }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "node_modules/colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "dev": true + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + }, "engines": { - "node": ">=8" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" } }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, - "node_modules/async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "node_modules/del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { - "async-done": "^1.2.2" + "path-type": "^4.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "bin": { - "atob": "bin/atob.js" + "dependencies": { + "esutils": "^2.0.2" }, "engines": { - "node": ">= 4.5.0" + "node": ">=6.0.0" } }, - "node_modules/bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", "dev": true, "dependencies": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/electron-to-chromium": { + "version": "1.4.76", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.76.tgz", + "integrity": "sha512-3Vftv7cenJtQb+k00McEBZ2vVmZ/x+HEF7pcZONZIkOsESqAqVuACmBxMv0JhzX7u0YltU0vSqRqgBSTAhFUjA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 4" } }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "once": "^1.4.0" } }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "node_modules/enhanced-resolve": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", + "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "ansi-colors": "^4.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6" } }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "bin": { + "envinfo": "dist/cli.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/base/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true }, - "node_modules/beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, "engines": { - "node": ">=0.10.0" + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/eslint-plugin-local-rules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-local-rules/-/eslint-plugin-local-rules-1.1.0.tgz", + "integrity": "sha512-FdPyzxakUKgZkeNM3x/vvRcB6nCjTNbui5gWALhvcaH1R6aCiD37fWtdesagcyBpEe9S9XRHAJ8CJ4rUJ3K9tQ==", + "dev": true + }, + "node_modules/eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0.0" } }, - "node_modules/browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, - "bin": { - "browserslist": "cli.js" + "eslint-visitor-keys": "^2.0.0" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" } }, - "node_modules/buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, "engines": { - "node": ">=0.4.0" + "node": ">=10" } }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/eslint-webpack-plugin": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz", + "integrity": "sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "@types/eslint": "^7.28.2", + "jest-worker": "^27.3.1", + "micromatch": "^4.0.4", + "normalize-path": "^3.0.0", + "schema-utils": "^3.1.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001235", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001235.tgz", - "integrity": "sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A==", - "dev": true, + "node": ">= 12.13.0" + }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0", + "webpack": "^5.0.0" } }, - "node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "node_modules/eslint/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "eslint-visitor-keys": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" + "engines": { + "node": ">=10" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "node_modules/eslint/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "engines": { + "node": ">= 4" } }, - "node_modules/chokidar/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", "dev": true, "dependencies": { - "is-extglob": "^2.1.0" + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, "engines": { - "node": ">=6.0" + "node": ">=4" } }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "dependencies": { - "source-map": "~0.6.0" + "estraverse": "^5.1.0" }, "engines": { - "node": ">= 4.0" + "node": ">=0.10" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=4.0" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { - "node": ">= 10" + "node": ">=4.0" } }, - "node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "engines": { + "node": ">=4.0" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.x" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", "dev": true, "dependencies": { - "ansi-regex": "^2.0.0" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, "engines": { - "node": ">=0.8" + "node": ">=8.6.0" } }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, - "engines": { - "node": ">= 0.10" + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=6" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/clone-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/clone-deep/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/collection-map": { + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/geodesy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/geodesy/-/geodesy-2.3.0.tgz", + "integrity": "sha512-SZIJ8DfIzn5XD5IyNGRQBpTy0mQAn/M3uKgPBcVx4uVVpyIM7tNIJ3mL6dQn+31T/gI6TBdslqLmuQQybeZCqA==", "engines": { - "node": ">=0.10.0" + "node": ">=8.0.0" } }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "pump": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/color-string": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", - "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { "node": ">= 6" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "node_modules/globals": { + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", "dev": true, - "engines": [ - "node >= 0.8" - ], "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "safe-buffer": "~5.1.1" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4.0" } }, - "node_modules/copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" + "bin": { + "he": "bin/he" } }, - "node_modules/css-loader": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.6.tgz", - "integrity": "sha512-0wyN5vXMQZu6BvjbrPdUJvkCzGEO24HC7IS7nW4llc6BBFC+zwR9CKtYGv63Puzsg10L/o12inMY5/2ByzfD6w==", + "node_modules/html-loader": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-2.1.2.tgz", + "integrity": "sha512-XB4O1+6mpLp4qy/3qg5+1QPZ/uXvWtO64hNAX87sKHwcHkp1LJGU7V3sJ9iVmRACElAZXQ4YOO/Lbkx5kYfl9A==", "dev": true, "dependencies": { - "icss-utils": "^5.1.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.15", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.5" + "html-minifier-terser": "^5.1.1", + "parse5": "^6.0.1" }, "engines": { "node": ">= 10.13.0" @@ -1720,271 +2006,218 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.27.0 || ^5.0.0" + "webpack": "^5.0.0" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "node_modules/html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", "dev": true, + "dependencies": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, "bin": { - "cssesc": "bin/cssesc" + "html-minifier-terser": "cli.js" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "engines": { + "node": ">=8.12.0" } }, - "node_modules/dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, - "dependencies": { - "ms": "2.1.2" - }, "engines": { - "node": ">=6.0" + "node": "^10 || ^12 || >= 14" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "node_modules/idb": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", + "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 4" } }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, "engines": { - "node": ">=0.10" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "dependencies": { - "kind-of": "^5.0.2" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true, "engines": { - "node": ">= 0.10" + "node": ">=0.8.19" } }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "dependencies": { - "clone": "^1.0.2" + "engines": { + "node": ">=8" } }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dev": true, "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" + "has": "^1.0.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true, - "engines": { - "node": ">= 0.9" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "dependencies": { - "readable-stream": "~1.1.9" + "node": ">=0.10.0" } }, - "node_modules/duplexer2/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "engines": { + "node": ">=0.12.0" } }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" + "engines": { + "node": ">=6" } }, - "node_modules/each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" + "engines": { + "node": ">=8" } }, - "node_modules/each-props/node_modules/is-plain-object": { + "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", @@ -1996,14798 +2229,4336 @@ "node": ">=0.10.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.3.749", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.749.tgz", - "integrity": "sha512-F+v2zxZgw/fMwPz/VUGIggG4ZndDsYy0vlpthi3tjmDZlcfbhN5mYW0evXUsBr2sUtuDANFtle410A9u/sd/4A==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { - "node": ">= 4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true, - "dependencies": { - "once": "^1.4.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz", - "integrity": "sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==", + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">= 10.13.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8.6" - } - }, - "node_modules/envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" + "node": ">=10" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "is-arrayish": "^0.2.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/error-ex/node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "node_modules/es-module-lexer": { + "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=6.11.5" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8.9.0" } }, - "node_modules/eslint": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz", - "integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==", + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" + "p-locate": "^4.1.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "dependencies": { + "tslib": "^2.0.3" } }, - "node_modules/eslint-plugin-prettier": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz", - "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==", + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=5.0.0", - "prettier": ">=1.13.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } + "node": ">=10" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, "engines": { - "node": ">=8.0.0" + "node": ">= 8" } }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^1.1.0" + "braces": "^3.0.1", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "node": ">=8.6" } }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "dev": true, + "dependencies": { + "mime-db": "1.51.0" + }, "engines": { - "node": ">=10" + "node": ">= 0.6" } }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "estraverse": "^5.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10" + "node": "*" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "dev": true, "engines": { - "node": ">=4.0" + "node": ">=4" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", "dev": true, "dependencies": { - "estraverse": "^5.2.0" + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=4.0" + "node": ">=8" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "node_modules/nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, "engines": { - "node": ">=4.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true }, - "node_modules/event-stream": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.5.tgz", - "integrity": "sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g==", + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", "dev": true, "dependencies": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" + "lower-case": "^2.0.2", + "tslib": "^2.0.3" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } + "node_modules/node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "path-key": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "dependencies": { - "ms": "2.0.0" + "wrappy": "1" } }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "dependencies": { - "homedir-polyfill": "^1.0.1" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ext/node_modules/type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "dependencies": { - "is-extendable": "^0.1.0" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "p-try": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "dependencies": { - "is-descriptor": "^1.0.0" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", "dev": true, "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" + "dot-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "callsites": "^3.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, "engines": { "node": ">= 0.10" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, - "node_modules/fastq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", - "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", "dev": true, "dependencies": { - "reusify": "^1.0.4" + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=0.10.0" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=8" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, - "node_modules/fill-range": { + "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "node": ">=8.6" }, - "engines": { - "node": ">= 0.10" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/findup-sync/node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "find-up": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/findup-sync/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "node_modules/postcss": { + "version": "8.4.7", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz", + "integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==", "dev": true, "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/findup-sync/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/findup-sync/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/findup-sync/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "postcss-selector-parser": "^6.0.4" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/findup-sync/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, "dependencies": { - "is-plain-object": "^2.0.4" + "icss-utils": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/findup-sync/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/postcss-selector-parser": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", + "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/findup-sync/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/findup-sync/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "node_modules/prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "bin": { + "prettier": "bin-prettier.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "fast-diff": "^1.1.2" }, "engines": { - "node": ">= 0.10" + "node": ">=6.0.0" } }, - "node_modules/fined/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/pretty-quick": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.3.tgz", + "integrity": "sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==", "dev": true, "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true, + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + }, + "bin": { + "pretty-quick": "bin/pretty-quick.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13" + }, + "peerDependencies": { + "prettier": ">=2.0.0" } }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "node_modules/pretty-quick/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=0.4.0" } }, - "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" + "safe-buffer": "^5.1.0" } }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fs-mkdirp-stream/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">= 4.0" + "node": ">= 6" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, "dependencies": { - "globule": "~0.1.0" + "resolve": "^1.9.0" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/geodesy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/geodesy/-/geodesy-2.2.1.tgz", - "integrity": "sha512-jhUYGHFZz5hZ/f+lBZiwFNWRhOUV2iiVxyLOT8FixIUJHEDVMgcB1SWQs50P51uTVcVjsngjPAUUNWcWdWiPog==", - "engines": { - "node": ">=8.0.0" + "node": ">= 0.10" } }, - "node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.10" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": "*" + "bin": { + "resolve": "bin/resolve" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "resolve-from": "^5.0.0" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/glob-stream/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "engines": { + "node": ">=4" } }, - "node_modules/glob-stream/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, "engines": { + "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">= 0.10" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "dependencies": { - "find-index": "^0.1.1" - }, - "engines": { - "node": ">= 0.10" + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "randombytes": "^2.1.0" } }, - "node_modules/globals": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", - "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "kind-of": "^6.0.2" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/globby/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { - "node": ">= 4" + "node": ">=8" } }, - "node_modules/globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "dependencies": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" - }, + "is-arrayish": "^0.3.1" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/globule/node_modules/glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "dependencies": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/globule/node_modules/graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "deprecated": "please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js", + "node_modules/sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/globule/node_modules/inherits": { + "node_modules/source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/globule/node_modules/lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "engines": [ - "node", - "rhino" - ] + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } }, - "node_modules/globule/node_modules/lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "node_modules/globule/node_modules/minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "dependencies": { - "lru-cache": "2", - "sigmund": "~1.0.0" - }, - "engines": { - "node": "*" + "safe-buffer": "~5.2.0" } }, - "node_modules/glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "sparkles": "^1.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true - }, - "node_modules/gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "bin": { - "gulp": "bin/gulp.js" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/gulp-cli/node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gulp-eslint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-6.0.0.tgz", - "integrity": "sha512-dCVPSh1sA+UVhn7JSQt7KEb4An2sQNbOdB3PA8UCfxsoPlAKjJHxYHGXdXC7eb+V1FAnilSFFqslPrq037l1ig==", + "node_modules/style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", "dev": true, "dependencies": { - "eslint": "^6.0.0", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.1" - } - }, - "node_modules/gulp-eslint/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/gulp-eslint/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/gulp-eslint/node_modules/astral-regex": { + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gulp-eslint/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" + "node": ">=10.0.0" } }, - "node_modules/gulp-eslint/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/gulp-eslint/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "node_modules/table/node_modules/ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", "dev": true, "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/gulp-eslint/node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/gulp-eslint/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/gulp-eslint/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=6" } }, - "node_modules/gulp-eslint/node_modules/eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" }, "bin": { - "eslint": "bin/eslint.js" + "terser": "bin/terser" }, "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6.0.0" } }, - "node_modules/gulp-eslint/node_modules/eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^1.1.0" + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" }, "engines": { - "node": ">=6" - } - }, - "node_modules/gulp-eslint/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/gulp-eslint/node_modules/espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "node_modules/terser-webpack-plugin/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.4.0" } }, - "node_modules/gulp-eslint/node_modules/file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "node_modules/terser-webpack-plugin/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.0.tgz", + "integrity": "sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A==", "dev": true, "dependencies": { - "flat-cache": "^2.0.1" + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/gulp-eslint/node_modules/flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "node_modules/terser-webpack-plugin/node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", "dev": true, - "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, "engines": { - "node": ">=4" + "node": ">= 8" } }, - "node_modules/gulp-eslint/node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "node_modules/gulp-eslint/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "readable-stream": "3" } }, - "node_modules/gulp-eslint/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/gulp-eslint/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, "engines": { - "node": ">=4" + "node": ">=8.0" } }, - "node_modules/gulp-eslint/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "node_modules/to-string-loader": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/to-string-loader/-/to-string-loader-1.2.0.tgz", + "integrity": "sha512-KsWUL8FccgBW9FPFm4vYoQbOOcO5m6hKOGYoXjbseD9/4Ft+ravXN5jolQ9kTKYcK4zPt1j+khx97GPGnVoi6A==", "dev": true, "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" + "loader-utils": "^1.0.0" } }, - "node_modules/gulp-eslint/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "node_modules/to-string-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "minimist": "^1.2.0" }, - "engines": { - "node": ">= 0.8.0" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/gulp-eslint/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "node_modules/to-string-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, "engines": { - "node": ">=4" + "node": ">=4.0.0" } }, - "node_modules/gulp-eslint/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "node_modules/ts-loader": { + "version": "9.2.7", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.7.tgz", + "integrity": "sha512-Fxh44mKli9QezgbdCXkEJWxnedQ0ead7DXTH+lfXEPedu+Y9EtMJ2aQ9G3Dj1j7Q612E8931rww8NDZha4Tibg==", "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" } }, - "node_modules/gulp-eslint/node_modules/regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true, - "engines": { - "node": ">=6.5.0" - } + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true }, - "node_modules/gulp-eslint/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "tslib": "^1.8.1" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/gulp-eslint/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, - "node_modules/gulp-eslint/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { - "shebang-regex": "^1.0.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/gulp-eslint/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gulp-eslint/node_modules/slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "node_modules/typescript": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", + "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=6" + "node": ">=4.2.0" } }, - "node_modules/gulp-eslint/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" + "punycode": "^2.1.0" } }, - "node_modules/gulp-eslint/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/gulp-eslint/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" + "node": ">= 10.13.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/gulp-eslint/node_modules/table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "dependencies": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/gulp-eslint/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" }, - "engines": { - "node": ">= 0.8.0" + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } } }, - "node_modules/gulp-eslint/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, - "node_modules/gulp-eslint/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true }, - "node_modules/gulp-inject-file": { - "version": "0.0.19", - "resolved": "https://registry.npmjs.org/gulp-inject-file/-/gulp-inject-file-0.0.19.tgz", - "integrity": "sha512-z4DOiGHf0kpJHs3Ayh/WiCP+1LC3uQXlcqDXt+NCU/JCXQhySORCHicTuBYTZ9ZJCrcJ8DW3NlfNjxBMaR8W0w==", + "node_modules/watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "dev": true, "dependencies": { - "event-stream": "^3.3.4", - "gulp": "^3.9.1", - "gulp-util": "^3.0.8", - "lodash": "^2.4.2" - } - }, - "node_modules/gulp-inject-file/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/gulp-inject-file/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, + "node_modules/webpack": { + "version": "5.70.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", + "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.2", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/gulp-inject-file/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "node_modules/webpack-cli": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", + "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", "dev": true, "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.1.1", + "@webpack-cli/info": "^1.4.1", + "@webpack-cli/serve": "^1.6.1", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } } }, - "node_modules/gulp-inject-file/node_modules/clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, "engines": { - "node": "*" + "node": ">= 10" } }, - "node_modules/gulp-inject-file/node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "node_modules/webpack-cli/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/gulp-inject-file/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/webpack-cli/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/gulp-inject-file/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "node": ">=10" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gulp-inject-file/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "node_modules/webpack-cli/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, "engines": { - "node": ">= 0.10" + "node": ">=10.17.0" } }, - "node_modules/gulp-inject-file/node_modules/glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", "dev": true, "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=10.0.0" } }, - "node_modules/gulp-inject-file/node_modules/glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, - "dependencies": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" - }, "engines": { - "node": ">= 0.9" + "node": ">=10.13.0" } }, - "node_modules/gulp-inject-file/node_modules/glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "node_modules/webpack/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true, - "dependencies": { - "gaze": "^0.5.1" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 0.9" + "node": ">=0.4.0" } }, - "node_modules/gulp-inject-file/node_modules/graceful-fs": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", - "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", + "node_modules/webpack/node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", "dev": true, - "dependencies": { - "natives": "^1.1.3" - }, - "engines": { - "node": ">=0.4.0" + "peerDependencies": { + "acorn": "^8" } }, - "node_modules/gulp-inject-file/node_modules/gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" + "isexe": "^2.0.0" }, "bin": { - "gulp": "bin/gulp.js" + "node-which": "bin/node-which" }, "engines": { - "node": ">= 0.9" + "node": ">= 8" } }, - "node_modules/gulp-inject-file/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true }, - "node_modules/gulp-inject-file/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/gulp-inject-file/node_modules/is-descriptor": { + "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, - "node_modules/gulp-inject-file/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" } }, - "node_modules/gulp-inject-file/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" }, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "node_modules/gulp-inject-file/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "@discoveryjs/json-ext": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", + "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, - "dependencies": { - "isobject": "^3.0.1" + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" }, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } } }, - "node_modules/gulp-inject-file/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "@fortawesome/fontawesome-common-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", + "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==" }, - "node_modules/gulp-inject-file/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "@fortawesome/fontawesome-svg-core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", + "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.3.0" } }, - "node_modules/gulp-inject-file/node_modules/liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" + "@fortawesome/free-solid-svg-icons": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", + "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.36" }, - "engines": { - "node": ">= 0.8" + "dependencies": { + "@fortawesome/fontawesome-common-types": { + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", + "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==" + } } }, - "node_modules/gulp-inject-file/node_modules/lodash": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", - "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", "dev": true, - "engines": [ - "node", - "rhino" - ] + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true }, - "node_modules/gulp-inject-file/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" } }, - "node_modules/gulp-inject-file/node_modules/minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "dependencies": { - "brace-expansion": "^1.0.0" - }, - "engines": { - "node": "*" + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" } }, - "node_modules/gulp-inject-file/node_modules/ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "@types/color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha512-hAhTmfFYVdzgsKwpC9Flc6h9Do64PhKoNxy3YxE0ze+0LIh3a7TrDQAxiujmANQbDRDgGduEz+9sMS+Zd+J7hA==", "dev": true }, - "node_modules/gulp-inject-file/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "@types/eslint": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", + "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" } }, - "node_modules/gulp-inject-file/node_modules/semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", "dev": true, - "bin": { - "semver": "bin/semver" + "requires": { + "@types/eslint": "*", + "@types/estree": "*" } }, - "node_modules/gulp-inject-file/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, - "node_modules/gulp-inject-file/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "@types/geojson": { + "version": "7946.0.8", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", + "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==", + "dev": true }, - "node_modules/gulp-inject-file/node_modules/strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "@types/jquery": { + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", + "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", "dev": true, - "dependencies": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" - }, - "bin": { - "strip-bom": "cli.js" - }, - "engines": { - "node": ">=0.10.0" + "requires": { + "@types/sizzle": "*" } }, - "node_modules/gulp-inject-file/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "@types/jqueryui": { + "version": "1.12.16", + "resolved": "https://registry.npmjs.org/@types/jqueryui/-/jqueryui-1.12.16.tgz", + "integrity": "sha512-6huAQDpNlso9ayaUT9amBOA3kj02OCeUWs+UvDmbaJmwkHSg/HLsQOoap/D5uveN9ePwl72N45Bl+Frp5xyG1Q==", "dev": true, - "engines": { - "node": ">=0.8.0" + "requires": { + "@types/jquery": "*" } }, - "node_modules/gulp-inject-file/node_modules/through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/leaflet": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.9.tgz", + "integrity": "sha512-H8vPgD49HKzqM41ArHGZM70g/tfhp8W+JcPxfnF+5H/Xvp+xiP+KQOUNWU8U89fqS1Jj3cpRY/+nbnaHFzwnFA==", "dev": true, - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "requires": { + "@types/geojson": "*" } }, - "node_modules/gulp-inject-file/node_modules/unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, - "node_modules/gulp-inject-file/node_modules/v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "@types/spectrum": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@types/spectrum/-/spectrum-1.8.2.tgz", + "integrity": "sha512-PbEC/2Kipsd7Ch5IX4I2xCpp9nlQgBH+PzThWHV4knd7f0viLDY2w3hJ0QpF4/wwweUPPGoAZyb7W7HS4g+FMw==", "dev": true, - "dependencies": { - "user-home": "^1.1.1" - }, - "engines": { - "node": ">= 0.10.0" + "requires": { + "@types/jquery": "*", + "@types/tinycolor2": "*" } }, - "node_modules/gulp-inject-file/node_modules/vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "@types/tinycolor2": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.3.tgz", + "integrity": "sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz", + "integrity": "sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ==", "dev": true, - "dependencies": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - }, - "engines": { - "node": ">= 0.9" + "requires": { + "@typescript-eslint/scope-manager": "5.13.0", + "@typescript-eslint/type-utils": "5.13.0", + "@typescript-eslint/utils": "5.13.0", + "debug": "^4.3.2", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.2.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" } }, - "node_modules/gulp-inject-file/node_modules/vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "@typescript-eslint/parser": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.13.0.tgz", + "integrity": "sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg==", "dev": true, - "dependencies": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - }, - "engines": { - "node": ">= 0.10" + "requires": { + "@typescript-eslint/scope-manager": "5.13.0", + "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/typescript-estree": "5.13.0", + "debug": "^4.3.2" } }, - "node_modules/gulp-inject-string": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gulp-inject-string/-/gulp-inject-string-1.1.2.tgz", - "integrity": "sha512-+jhEyG+cEqvMdJgxD+7WkO/hDXz7AQl5aP9Rp+f23QaUDi5xme2YNvUjxCTlEySUapn27Pskcq9o8MsBBdvt4g==", + "@typescript-eslint/scope-manager": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz", + "integrity": "sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA==", "dev": true, - "dependencies": { - "event-stream": "3.3.4", - "plugin-error": "^1.0.1" + "requires": { + "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/visitor-keys": "5.13.0" } }, - "node_modules/gulp-inject-string/node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "@typescript-eslint/type-utils": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz", + "integrity": "sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg==", "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" + "requires": { + "@typescript-eslint/utils": "5.13.0", + "debug": "^4.3.2", + "tsutils": "^3.21.0" } }, - "node_modules/gulp-inject-string/node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "@typescript-eslint/types": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.13.0.tgz", + "integrity": "sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg==", "dev": true }, - "node_modules/gulp-inject-string/node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "@typescript-eslint/typescript-estree": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz", + "integrity": "sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA==", "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/gulp-inject-string/node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1" + "requires": { + "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/visitor-keys": "5.13.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" } }, - "node_modules/gulp-prettier": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-prettier/-/gulp-prettier-3.0.0.tgz", - "integrity": "sha512-vZFyC1F+7EjuI2WDUOcbPt9o3ZjdqjFMjr8a9Yk2K8EmNhP1w6X01QAkv5Ym3dsHCBsBA4AEFcYds2vOTSgx0A==", + "@typescript-eslint/utils": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.13.0.tgz", + "integrity": "sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ==", "dev": true, - "dependencies": { - "plugin-error": "^1.0.1", - "prettier": "^2.0.0", - "through2": "^3.0.0" - }, - "engines": { - "node": ">=10" + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.13.0", + "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/typescript-estree": "5.13.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" } }, - "node_modules/gulp-rename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", - "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", + "@typescript-eslint/visitor-keys": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz", + "integrity": "sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g==", "dev": true, - "engines": { - "node": ">=4" + "requires": { + "@typescript-eslint/types": "5.13.0", + "eslint-visitor-keys": "^3.0.0" } }, - "node_modules/gulp-trimlines": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gulp-trimlines/-/gulp-trimlines-1.0.1.tgz", - "integrity": "sha1-exeRa4UMoPBa9BkN0k6aweJunyY=", + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", "dev": true, - "dependencies": { - "through2": "^0.6.3" + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" } }, - "node_modules/gulp-trimlines/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", "dev": true }, - "node_modules/gulp-trimlines/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true }, - "node_modules/gulp-trimlines/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", "dev": true }, - "node_modules/gulp-trimlines/node_modules/through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", "dev": true, - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5", - "dev": true, - "dependencies": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "engines": { - "node": ">=0.10" - } + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true }, - "node_modules/gulp-util/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", "dev": true, - "engines": { - "node": ">=0.10.0" + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" } }, - "node_modules/gulp-util/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", "dev": true, - "engines": { - "node": ">=0.10.0" + "requires": { + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/gulp-util/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "requires": { + "@xtuc/long": "4.2.2" } }, - "node_modules/gulp-util/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true }, - "node_modules/gulp-util/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" } }, - "node_modules/gulp-util/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", "dev": true, - "engines": { - "node": ">=0.8.0" + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, - "node_modules/gulp-util/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" } }, - "node_modules/gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", "dev": true, - "dependencies": { - "glogg": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "@webpack-cli/configtest": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", + "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "requires": {} }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "@webpack-cli/info": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", + "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "requires": { + "envinfo": "^7.7.3" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "@webpack-cli/serve": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", + "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", "dev": true, - "engines": { - "node": ">=8" - } + "requires": {} }, - "node_modules/has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "requires": {} }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "bin": { - "he": "bin/he" + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "requires": {} }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, - "node_modules/html-loader": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-2.1.2.tgz", - "integrity": "sha512-XB4O1+6mpLp4qy/3qg5+1QPZ/uXvWtO64hNAX87sKHwcHkp1LJGU7V3sJ9iVmRACElAZXQ4YOO/Lbkx5kYfl9A==", + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", "dev": true, - "dependencies": { - "html-minifier-terser": "^5.1.1", - "parse5": "^6.0.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "requires": { + "ansi-wrap": "0.1.0" } }, - "node_modules/html-minifier-terser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", - "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.1", - "clean-css": "^4.2.3", - "commander": "^4.1.1", - "he": "^1.2.0", - "param-case": "^3.0.3", - "relateurl": "^0.2.7", - "terser": "^4.6.3" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=6" - } + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "engines": { - "node": ">=8.12.0" + "requires": { + "color-convert": "^2.0.1" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/idb": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.2.tgz", - "integrity": "sha512-1DNDVu3yDhAZkFDlJf0t7r+GLZ248F5pTAtA7V0oVG3yjmV125qZOx3g0XpAEkGZVYQiFDAsSOnGet2bhugc3w==" - }, - "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.2.tgz", - "integrity": "sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/just-debounce": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", - "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", - "dev": true - }, - "node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "dependencies": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/liftoff/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "node_modules/lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "node_modules/lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "node_modules/lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "node_modules/lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "node_modules/lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "node_modules/lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "node_modules/lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "dependencies": { - "lodash._root": "^3.0.0" - } - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "node_modules/lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "node_modules/lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "dependencies": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "node_modules/lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "dependencies": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "node_modules/lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/make-iterator/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "dependencies": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/matchdep/node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/matchdep/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/micromatch/node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/micromatch/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/micromatch/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/mime-db": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", - "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.31", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", - "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", - "dev": true, - "dependencies": { - "mime-db": "1.48.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mri": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", - "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/multimatch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", - "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", - "dev": true, - "dependencies": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/multimatch/node_modules/array-differ": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "dependencies": { - "duplexer2": "0.0.2" - } - }, - "node_modules/mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "dev": true, - "optional": true - }, - "node_modules/nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/natives": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", - "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", - "deprecated": "This module relies on Node.js's internals and will break at some point. Do not use it, and update to graceful-fs@4.x.", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "dependencies": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" - } - }, - "node_modules/orchestrator/node_modules/end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "dependencies": { - "once": "~1.3.0" - } - }, - "node_modules/orchestrator/node_modules/once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "dependencies": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/plugin-error/node_modules/ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "dependencies": { - "ansi-wrap": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plugin-error/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plugin-error/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plugin-error/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz", - "integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==", - "dev": true, - "dependencies": { - "colorette": "^1.2.2", - "nanoid": "^3.1.23", - "source-map-js": "^0.6.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", - "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz", - "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pretty-quick": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.0.tgz", - "integrity": "sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==", - "dev": true, - "dependencies": { - "chalk": "^3.0.0", - "execa": "^4.0.0", - "find-up": "^4.1.0", - "ignore": "^5.1.4", - "mri": "^1.1.5", - "multimatch": "^4.0.0" - }, - "bin": { - "pretty-quick": "bin/pretty-quick.js" - }, - "engines": { - "node": ">=10.13" - }, - "peerDependencies": { - "prettier": ">=2.0.0" - } - }, - "node_modules/pretty-quick/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/raw-loader": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", - "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/readdirp/node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-bom-stream/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.6", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "dependencies": { - "sver-compat": "^1.5.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shallow-clone/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/snapdragon/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sortablejs": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.13.0.tgz", - "integrity": "sha512-RBJirPY0spWCrU5yCmWM1eFs/XgX2J5c6b275/YyxFRgnzPhKl/TDeU2hNR8Dt7ITq66NRPM4UlOt+e5O4CFHg==" - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, - "node_modules/sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", - "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "node_modules/stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", - "dev": true - }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", - "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/table": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", - "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz", - "integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/tapable": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", - "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.3.tgz", - "integrity": "sha512-cxGbMqr6+A2hrIB5ehFIF+F/iST5ZOxvOmy9zih9ySbP1C2oEWQSOUS+2SNBTjzx5xLKO4xnod9eywdfq1Nb9A==", - "dev": true, - "dependencies": { - "jest-worker": "^27.0.2", - "p-limit": "^3.1.0", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "source-map": "^0.6.1", - "terser": "^5.7.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/terser-webpack-plugin/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz", - "integrity": "sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==", - "dev": true, - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin/node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/through2-filter/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-string-loader": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/to-string-loader/-/to-string-loader-1.1.6.tgz", - "integrity": "sha512-VNg62//PS1WfNwrK3n7t6wtK5Vdtx/qeYLLEioW46VMlYUwAYT6wnfB+OwS2FMTCalIHu0tk79D3RXX8ttmZTQ==", - "dev": true, - "dependencies": { - "loader-utils": "^1.0.0" - } - }, - "node_modules/to-string-loader/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/to-string-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/to-through/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", - "dev": true - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/undertaker/node_modules/fast-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", - "dev": true - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url-loader": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", - "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "mime-types": "^2.1.27", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "file-loader": "*", - "webpack": "^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "file-loader": { - "optional": true - } - } - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true, - "bin": { - "user-home": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "dependencies": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - }, - "engines": { - "node": ">= 0.9" - } - }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs/node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/vinyl-fs/node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/vinyl-fs/node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/vinyl-fs/node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/vinyl-sourcemap/node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vinyl-sourcemap/node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/watchpack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", - "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack": { - "version": "5.38.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.38.1.tgz", - "integrity": "sha512-OqRmYD1OJbHZph6RUMD93GcCZy4Z4wC0ele4FXyYF0J6AxO1vOSuIlU1hkS/lDlR9CDYBz64MZRmdbdnFFoT2g==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.47", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.2.1", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.0", - "es-module-lexer": "^0.4.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.2.0", - "webpack-sources": "^2.3.0" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.7.2.tgz", - "integrity": "sha512-mEoLmnmOIZQNiRl0ebnjzQ74Hk0iKS5SiEEnpq3dRezoyR3yPaeQZCMCe+db4524pj1Pd5ghZXjT41KLzIhSLw==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.4", - "@webpack-cli/info": "^1.3.0", - "@webpack-cli/serve": "^1.5.1", - "colorette": "^1.2.1", - "commander": "^7.0.0", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-cli/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/webpack-cli/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/webpack-cli/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/webpack-cli/node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/webpack-cli/node_modules/rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.0.tgz", - "integrity": "sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/acorn": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.3.0.tgz", - "integrity": "sha512-tqPKHZ5CaBJw0Xmy0ZZvLs1qTV+BNFSyvn77ASXkpBNfIRk8ev26fKrD9iLGwGA9zedPao52GSHzq8lyZG0NUw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - } - }, - "node_modules/yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz", - "integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", - "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", - "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", - "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@types/eslint": { - "version": "7.2.13", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.13.tgz", - "integrity": "sha512-LKmQCWAlnVHvvXq4oasNUMTJJb2GwSyTY8+1C7OH5ILR8mPLaljv1jxL1bXW3xB3jFbQxTKxJAvI8PyjB09aBg==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", - "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.48", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz", - "integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", - "dev": true - }, - "@types/node": { - "version": "15.12.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.1.tgz", - "integrity": "sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", - "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", - "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", - "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", - "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", - "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", - "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", - "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", - "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", - "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", - "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", - "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/helper-wasm-section": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-opt": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "@webassemblyjs/wast-printer": "1.11.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", - "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", - "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-buffer": "1.11.0", - "@webassemblyjs/wasm-gen": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", - "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/helper-api-error": "1.11.0", - "@webassemblyjs/helper-wasm-bytecode": "1.11.0", - "@webassemblyjs/ieee754": "1.11.0", - "@webassemblyjs/leb128": "1.11.0", - "@webassemblyjs/utf8": "1.11.0" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", - "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.0", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.4.tgz", - "integrity": "sha512-cs3XLy+UcxiP6bj0A6u7MLLuwdXJ1c3Dtc0RkKg+wiI1g/Ti1om8+/2hc2A2B60NbBNAbMgyBMHvyymWm/j4wQ==", - "dev": true - }, - "@webpack-cli/info": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.3.0.tgz", - "integrity": "sha512-ASiVB3t9LOKHs5DyVUcxpraBXDOKubYu/ihHhU+t1UPpxsivg6Od2E2qU4gJCekfEddzRBzHhzA/Acyw/mlK/w==", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.0.tgz", - "integrity": "sha512-AxpcbdkUhl4248H33LDFgXpFpDE5/BU9rHi2Oj8J4z8JldoMXoSmCe1DXDKcw1ClK64g6fY1Hg+dW20vH81JvQ==", - "dev": true - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, - "requires": {} - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "arc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/arc/-/arc-0.1.1.tgz", - "integrity": "sha512-gJsNNbnJW7UMU9ccjBaRh2evSyltbinzRGNPX9aiW28QxbGMtwMDC0YL6lkF73b+y+BUAOT/dUN2DMQDB1Is5w==" - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - } - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001235", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001235.tgz", - "integrity": "sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A==", - "dev": true - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "dependencies": { - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - } - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - } - }, - "clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "1.1.3" - }, - "dependencies": { - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - } - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "color-string": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", - "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-loader": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.6.tgz", - "integrity": "sha512-0wyN5vXMQZu6BvjbrPdUJvkCzGEO24HC7IS7nW4llc6BBFC+zwR9CKtYGv63Puzsg10L/o12inMY5/2ByzfD6w==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.15", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.5" - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", - "dev": true, - "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - } - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "electron-to-chromium": { - "version": "1.3.749", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.749.tgz", - "integrity": "sha512-F+v2zxZgw/fMwPz/VUGIggG4ZndDsYy0vlpthi3tjmDZlcfbhN5mYW0evXUsBr2sUtuDANFtle410A9u/sd/4A==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz", - "integrity": "sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - } - } - }, - "es-module-lexer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", - "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", - "dev": true - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz", - "integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "globals": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", - "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "table": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", - "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz", - "integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - } - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true, - "requires": {} - }, - "eslint-plugin-prettier": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz", - "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.5.tgz", - "integrity": "sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g==", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "fastq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", - "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - } - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "~0.1.0" - } - }, - "geodesy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/geodesy/-/geodesy-2.2.1.tgz", - "integrity": "sha512-jhUYGHFZz5hZ/f+lBZiwFNWRhOUV2iiVxyLOT8FixIUJHEDVMgcB1SWQs50P51uTVcVjsngjPAUUNWcWdWiPog==" - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "^0.1.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "globals": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", - "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "dependencies": { - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - } - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - } - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - } - } - }, - "gulp-eslint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-6.0.0.tgz", - "integrity": "sha512-dCVPSh1sA+UVhn7JSQt7KEb4An2sQNbOdB3PA8UCfxsoPlAKjJHxYHGXdXC7eb+V1FAnilSFFqslPrq037l1ig==", - "dev": true, - "requires": { - "eslint": "^6.0.0", - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - } - }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - } - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "gulp-inject-file": { - "version": "0.0.19", - "resolved": "https://registry.npmjs.org/gulp-inject-file/-/gulp-inject-file-0.0.19.tgz", - "integrity": "sha512-z4DOiGHf0kpJHs3Ayh/WiCP+1LC3uQXlcqDXt+NCU/JCXQhySORCHicTuBYTZ9ZJCrcJ8DW3NlfNjxBMaR8W0w==", - "dev": true, - "requires": { - "event-stream": "^3.3.4", - "gulp": "^3.9.1", - "gulp-util": "^3.0.8", - "lodash": "^2.4.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "^0.5.1" - } - }, - "graceful-fs": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", - "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", - "dev": true, - "requires": { - "natives": "^1.1.3" - } - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "lodash": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", - "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "^1.0.0" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "^1.1.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - } - } - } - }, - "gulp-inject-string": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gulp-inject-string/-/gulp-inject-string-1.1.2.tgz", - "integrity": "sha512-+jhEyG+cEqvMdJgxD+7WkO/hDXz7AQl5aP9Rp+f23QaUDi5xme2YNvUjxCTlEySUapn27Pskcq9o8MsBBdvt4g==", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "plugin-error": "^1.0.1" - }, - "dependencies": { - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2" - } - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } - } - } - }, - "gulp-prettier": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-prettier/-/gulp-prettier-3.0.0.tgz", - "integrity": "sha512-vZFyC1F+7EjuI2WDUOcbPt9o3ZjdqjFMjr8a9Yk2K8EmNhP1w6X01QAkv5Ym3dsHCBsBA4AEFcYds2vOTSgx0A==", - "dev": true, - "requires": { - "plugin-error": "^1.0.1", - "prettier": "^2.0.0", - "through2": "^3.0.0" - } - }, - "gulp-rename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", - "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", - "dev": true - }, - "gulp-trimlines": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gulp-trimlines/-/gulp-trimlines-1.0.1.tgz", - "integrity": "sha1-exeRa4UMoPBa9BkN0k6aweJunyY=", - "dev": true, - "requires": { - "through2": "^0.6.3" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "html-loader": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-2.1.2.tgz", - "integrity": "sha512-XB4O1+6mpLp4qy/3qg5+1QPZ/uXvWtO64hNAX87sKHwcHkp1LJGU7V3sJ9iVmRACElAZXQ4YOO/Lbkx5kYfl9A==", - "dev": true, - "requires": { - "html-minifier-terser": "^5.1.1", - "parse5": "^6.0.1" - } - }, - "html-minifier-terser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", - "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", - "dev": true, - "requires": { - "camel-case": "^4.1.1", - "clean-css": "^4.2.3", - "commander": "^4.1.1", - "he": "^1.2.0", - "param-case": "^3.0.3", - "relateurl": "^0.2.7", - "terser": "^4.6.3" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "idb": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.2.tgz", - "integrity": "sha512-1DNDVu3yDhAZkFDlJf0t7r+GLZ248F5pTAtA7V0oVG3yjmV125qZOx3g0XpAEkGZVYQiFDAsSOnGet2bhugc3w==" - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "arc": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/arc/-/arc-0.1.2.tgz", + "integrity": "sha512-bGCkKR675zaomc6HP3dR6hc6HXXnpXrehMkayof2Ql5dZ3f2Bd8o+KfdAruSCcW471K7WFn2pDvSLG8Q0co0dw==" }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "sprintf-js": "~1.0.2" } }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-number": { + "array-differ": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", "dev": true }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-stream": { + "astral-regex": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, - "is-windows": { + "balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, - "jest-worker": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.2.tgz", - "integrity": "sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg==", + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "fill-range": "^7.0.1" } }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "browserslist": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", + "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", "dev": true, "requires": { - "minimist": "^1.2.5" + "caniuse-lite": "^1.0.30001312", + "electron-to-chromium": "^1.4.71", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" } }, - "just-debounce": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", - "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", "dev": true, "requires": { - "flush-write-stream": "^1.0.2" + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" } }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } + "caniuse-lite": { + "version": "1.0.30001313", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001313.tgz", + "integrity": "sha512-rI1UN0koZUiKINjysQDuRi2VeSCce3bYJNmDcj3PIKREiAmjakugBul1QSkg/fPrlULYl6oWfGg3PbgOSY9X4Q==", + "dev": true }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "source-map": "~0.6.0" } }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "color-name": "~1.1.4" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true + "color-string": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", + "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", "dev": true }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "lodash._root": "^3.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" } }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "ms": "2.1.2" } }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, - "lru-cache": { + "del": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", "dev": true, "requires": { - "yallist": "^4.0.0" + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" } }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "requires": { - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } + "path-type": "^4.0.0" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "object-visit": "^1.0.0" + "esutils": "^2.0.2" } }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", "dev": true, "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "electron-to-chromium": { + "version": "1.4.76", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.76.tgz", + "integrity": "sha512-3Vftv7cenJtQb+k00McEBZ2vVmZ/x+HEF7pcZONZIkOsESqAqVuACmBxMv0JhzX7u0YltU0vSqRqgBSTAhFUjA==", "dev": true }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - + "once": "^1.4.0" } }, - "mime-db": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", - "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.31", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", - "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "enhanced-resolve": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", + "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", "dev": true, "requires": { - "mime-db": "1.48.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" } }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "ansi-colors": "^4.1.1" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } } }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true } } }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mri": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", - "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", - "dev": true + "requires": {} }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "eslint-plugin-local-rules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-local-rules/-/eslint-plugin-local-rules-1.1.0.tgz", + "integrity": "sha512-FdPyzxakUKgZkeNM3x/vvRcB6nCjTNbui5gWALhvcaH1R6aCiD37fWtdesagcyBpEe9S9XRHAJ8CJ4rUJ3K9tQ==", "dev": true }, - "multimatch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", - "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", "dev": true, "requires": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "array-differ": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", - "dev": true - } + "prettier-linter-helpers": "^1.0.0" } }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "requires": { - "duplexer2": "0.0.2" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" } }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "eslint-webpack-plugin": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz", + "integrity": "sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==", "dev": true, - "optional": true - }, - "nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", - "dev": true + "requires": { + "@types/eslint": "^7.28.2", + "jest-worker": "^27.3.1", + "micromatch": "^4.0.4", + "normalize-path": "^3.0.0", + "schema-utils": "^3.1.1" + } }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" }, "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true } } }, - "natives": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", - "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "natural-compare": { + "esquery": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } } }, - "node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "estraverse": "^5.2.0" }, "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "requires": { - "once": "^1.3.2" + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" } }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", "dev": true, "requires": { - "path-key": "^3.0.0" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" } }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "reusify": "^1.0.4" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { - "wrappy": "1" + "flat-cache": "^3.0.4" } }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "mimic-fn": "^2.1.0" + "to-regex-range": "^5.0.1" } }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" - }, - "dependencies": { - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "~1.3.0" - } - }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1" - } - } + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "p-limit": { + "geodesy": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } + "resolved": "https://registry.npmjs.org/geodesy/-/geodesy-2.3.0.tgz", + "integrity": "sha512-SZIJ8DfIzn5XD5IyNGRQBpTy0mQAn/M3uKgPBcVx4uVVpyIM7tNIJ3mL6dQn+31T/gI6TBdslqLmuQQybeZCqA==" }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "pump": "^3.0.0" } }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { - "aggregate-error": "^3.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "is-glob": "^4.0.1" } }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "globals": { + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", "dev": true, "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "type-fest": "^0.20.2" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { - "error-ex": "^1.2.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" } }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "function-bind": "^1.1.1" } }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { + "has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "html-loader": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-2.1.2.tgz", + "integrity": "sha512-XB4O1+6mpLp4qy/3qg5+1QPZ/uXvWtO64hNAX87sKHwcHkp1LJGU7V3sJ9iVmRACElAZXQ4YOO/Lbkx5kYfl9A==", "dev": true, "requires": { - "path-root-regex": "^0.1.0" + "html-minifier-terser": "^5.1.1", + "parse5": "^6.0.1" } }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", "dev": true, "requires": { - "through": "~2.3" + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" } }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "idb": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", + "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { - "pinkie": "^2.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "requires": { - "find-up": "^4.0.0" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" } }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, - "postcss": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz", - "integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==", + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "colorette": "^1.2.2", - "nanoid": "^3.1.23", - "source-map-js": "^0.6.2" + "once": "^1.3.0", + "wrappy": "1" } }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, - "postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dev": true, "requires": { - "icss-utils": "^5.0.0" + "has": "^1.0.3" } }, - "postcss-selector-parser": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", - "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "is-extglob": "^2.1.1" } }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true }, - "prettier": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz", - "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==", + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "fast-diff": "^1.1.2" + "isobject": "^3.0.1" } }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, - "pretty-quick": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.0.tgz", - "integrity": "sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==", + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "requires": { - "chalk": "^3.0.0", - "execa": "^4.0.0", - "find-up": "^4.1.0", - "ignore": "^5.1.4", - "mri": "^1.1.5", - "multimatch": "^4.0.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "has-flag": "^4.0.0" } - }, - "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true } } }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "requires": { - "safe-buffer": "^5.1.0" + "minimist": "^1.2.5" } }, - "raw-loader": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", - "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "dependencies": { - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - } + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" } }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } + "p-locate": "^4.1.0" } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } + "tslib": "^2.0.3" } }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } + "yallist": "^4.0.0" } }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { - "resolve": "^1.1.6" + "braces": "^3.0.1", + "picomatch": "^2.2.3" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "dev": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "mime-db": "1.51.0" } }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" + "brace-expansion": "^1.1.7" } }, - "remove-bom-stream": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mri": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", "dev": true, "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" + "lower-case": "^2.0.2", + "tslib": "^2.0.3" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { + "node-releases": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", "dev": true }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "path-key": "^3.0.0" } }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } + "wrappy": "1" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "mimic-fn": "^2.1.0" } }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "requires": { - "value-or-function": "^3.0.0" + "aggregate-error": "^3.0.0" } }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", "dev": true, "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", "dev": true, "requires": { - "glob": "^7.1.3" + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "requires": { - "queue-microtask": "^1.2.2" + "find-up": "^4.0.0" } }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "postcss": { + "version": "8.4.7", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz", + "integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==", "dev": true, "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", "dev": true, "requires": { - "ret": "~0.1.10" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "schema-utils": { + "postcss-modules-scope": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", "dev": true, "requires": { - "@types/json-schema": "^7.0.6", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "postcss-selector-parser": "^6.0.4" } }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "icss-utils": "^5.0.0" } }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "postcss-selector-parser": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", + "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", "dev": true, "requires": { - "sver-compat": "^1.5.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" } }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "requires": { - "randombytes": "^2.1.0" + "fast-diff": "^1.1.2" } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "pretty-quick": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.3.tgz", + "integrity": "sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" }, "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "isobject": "^3.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } } } }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { - "shebang-regex": "^3.0.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "requires": { - "is-arrayish": "^0.3.1" + "safe-buffer": "^5.1.0" } }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "resolve": "^1.9.0" } }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "requires": { - "kind-of": "^3.2.0" + "resolve-from": "^5.0.0" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true } } - }, - "sortablejs": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.13.0.tgz", - "integrity": "sha512-RBJirPY0spWCrU5yCmWM1eFs/XgX2J5c6b275/YyxFRgnzPhKl/TDeU2hNR8Dt7ITq66NRPM4UlOt+e5O4CFHg==" - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "source-map-js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", - "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "glob": "^7.1.3" } }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "queue-microtask": "^1.2.2" } }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, - "spdx-correct": { + "schema-utils": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" } }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "lru-cache": "^6.0.0" } }, - "spdx-license-ids": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", - "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", - "dev": true + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "requires": { - "through": "2" + "kind-of": "^6.0.2" } }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "extend-shallow": "^3.0.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } + "shebang-regex": "^3.0.0" } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "is-arrayish": "^0.3.1" } }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "requires": { - "duplexer": "~0.1.1", - "through": "~2.3.4" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" } }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "stream-exhaust": { + "source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } + "safe-buffer": "~5.2.0" } }, "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "ansi-regex": "^5.0.1" } }, "strip-final-newline": { @@ -16821,34 +6592,29 @@ "has-flag": "^4.0.0" } }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true }, "table": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", - "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", "dev": true, "requires": { "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "dependencies": { "ajv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz", - "integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -16866,9 +6632,9 @@ } }, "tapable": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", - "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true }, "terser": { @@ -16891,254 +6657,86 @@ } }, "terser-webpack-plugin": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.3.tgz", - "integrity": "sha512-cxGbMqr6+A2hrIB5ehFIF+F/iST5ZOxvOmy9zih9ySbP1C2oEWQSOUS+2SNBTjzx5xLKO4xnod9eywdfq1Nb9A==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", "dev": true, "requires": { - "jest-worker": "^27.0.2", - "p-limit": "^3.1.0", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", "source-map": "^0.6.1", - "terser": "^5.7.0" + "terser": "^5.7.2" }, "dependencies": { + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, "terser": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz", - "integrity": "sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.0.tgz", + "integrity": "sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A==", "dev": true, "requires": { + "acorn": "^8.5.0", "commander": "^2.20.0", "source-map": "~0.7.2", - "source-map-support": "~0.5.19" + "source-map-support": "~0.5.20" }, "dependencies": { "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - }, - "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "^7.0.0" } }, "to-string-loader": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/to-string-loader/-/to-string-loader-1.1.6.tgz", - "integrity": "sha512-VNg62//PS1WfNwrK3n7t6wtK5Vdtx/qeYLLEioW46VMlYUwAYT6wnfB+OwS2FMTCalIHu0tk79D3RXX8ttmZTQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/to-string-loader/-/to-string-loader-1.2.0.tgz", + "integrity": "sha512-KsWUL8FccgBW9FPFm4vYoQbOOcO5m6hKOGYoXjbseD9/4Ft+ravXN5jolQ9kTKYcK4zPt1j+khx97GPGnVoi6A==", "dev": true, "requires": { "loader-utils": "^1.0.0" @@ -17166,38 +6764,40 @@ } } }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "ts-loader": { + "version": "9.2.7", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.7.tgz", + "integrity": "sha512-Fxh44mKli9QezgbdCXkEJWxnedQ0ead7DXTH+lfXEPedu+Y9EtMJ2aQ9G3Dj1j7Q612E8931rww8NDZha4Tibg==", "dev": true, "requires": { - "through2": "^2.0.3" - }, - "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" } }, "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", "dev": true }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } }, "type-check": { "version": "0.4.0", @@ -17214,116 +6814,10 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "dependencies": { - "fast-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", - "dev": true - } - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "typescript": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", + "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", "dev": true }, "uri-js": { @@ -17335,12 +6829,6 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, "url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", @@ -17352,18 +6840,6 @@ "schema-utils": "^3.0.0" } }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -17376,173 +6852,10 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "dependencies": { - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - } - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - } - } - }, "watchpack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", - "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -17550,68 +6863,69 @@ } }, "webpack": { - "version": "5.38.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.38.1.tgz", - "integrity": "sha512-OqRmYD1OJbHZph6RUMD93GcCZy4Z4wC0ele4FXyYF0J6AxO1vOSuIlU1hkS/lDlR9CDYBz64MZRmdbdnFFoT2g==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.47", - "@webassemblyjs/ast": "1.11.0", - "@webassemblyjs/wasm-edit": "1.11.0", - "@webassemblyjs/wasm-parser": "1.11.0", - "acorn": "^8.2.1", + "version": "5.70.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", + "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.0", - "es-module-lexer": "^0.4.0", + "enhanced-resolve": "^5.9.2", + "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "json-parse-better-errors": "^1.0.2", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.0.0", + "schema-utils": "^3.1.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.1", - "watchpack": "^2.2.0", - "webpack-sources": "^2.3.0" + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" }, "dependencies": { - "@types/estree": { - "version": "0.0.47", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.47.tgz", - "integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==", - "dev": true - }, "acorn": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.3.0.tgz", - "integrity": "sha512-tqPKHZ5CaBJw0Xmy0ZZvLs1qTV+BNFSyvn77ASXkpBNfIRk8ev26fKrD9iLGwGA9zedPao52GSHzq8lyZG0NUw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "requires": {} } } }, "webpack-cli": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.7.1.tgz", - "integrity": "sha512-DJPd63AY53KXWOaD8cB8CaHR0epVP4O4GBIAk6wCPQHJugrAQ0B5kUkCg0c9vkIrD2kA6CXCmtWqKQsiVTo15A==", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", + "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.4", - "@webpack-cli/info": "^1.3.0", - "@webpack-cli/serve": "^1.5.0", - "colorette": "^1.2.1", + "@webpack-cli/configtest": "^1.1.1", + "@webpack-cli/info": "^1.4.1", + "@webpack-cli/serve": "^1.6.1", + "colorette": "^2.0.14", "commander": "^7.0.0", "execa": "^5.0.0", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", "interpret": "^2.2.0", "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", "webpack-merge": "^5.7.3" }, "dependencies": { @@ -17649,21 +6963,6 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true - }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true - }, - "rechoir": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", - "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } } } }, @@ -17678,14 +6977,10 @@ } }, "webpack-sources": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.0.tgz", - "integrity": "sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - } + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true }, "which": { "version": "2.0.2", @@ -17696,12 +6991,6 @@ "isexe": "^2.0.0" } }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, "wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", @@ -17714,159 +7003,17 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true - }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true } } } From c35a1db662c4800d29044bba666d1c17276f8c1a Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:35:47 +0100 Subject: [PATCH 272/275] fix wX crash on missing template data + add types to avoid this situation --- src/code/buttons/uploadButton.js | 2 +- src/code/dialogs/mergeDialog.js | 2 +- src/code/dialogs/stateDialog.js | 5 +- src/code/dialogs/teamListDialog.js | 2 +- src/code/dialogs/trawl.js | 2 +- src/code/error.ts | 7 +- src/code/wX.ts | 193 ++++++++++++++++++++++++++++- 7 files changed, 201 insertions(+), 12 deletions(-) diff --git a/src/code/buttons/uploadButton.js b/src/code/buttons/uploadButton.js index 715d6db97..dbba1b477 100644 --- a/src/code/buttons/uploadButton.js +++ b/src/code/buttons/uploadButton.js @@ -23,7 +23,7 @@ const UploadButton = WButton.extend({ this.type = UploadButton.TYPE; // this.handler = null; const operation = getSelectedOperation(); - this.title = wX("UPLOAD BUTTON HOVER", operation.name); + this.title = wX("UPLOAD BUTTON HOVER", { opName: operation.name }); this._container = container; this.button = this._createButton({ diff --git a/src/code/dialogs/mergeDialog.js b/src/code/dialogs/mergeDialog.js index 3d3cd70eb..221af0ced 100644 --- a/src/code/dialogs/mergeDialog.js +++ b/src/code/dialogs/mergeDialog.js @@ -129,7 +129,7 @@ const MergeDialog = WDialog.extend({ const content = L.DomUtil.create("div", "container"); const desc = L.DomUtil.create("div", "desc", content); - desc.textContent = wX("MERGE_MESSAGE", { opName: this.options.opOwn.name }); + desc.textContent = wX("MERGE_MESSAGE"); L.DomUtil.create("h3", "", content).textContent = wX( "dialog.merge.conflicts" diff --git a/src/code/dialogs/stateDialog.js b/src/code/dialogs/stateDialog.js index 63b86352a..e90ce29df 100644 --- a/src/code/dialogs/stateDialog.js +++ b/src/code/dialogs/stateDialog.js @@ -56,9 +56,8 @@ const StateDialog = WDialog.extend({ } if (this.options.target instanceof WasabeeLink) { - const portal = operation.getPortal(this.options.target.fromPortalId); this._type = "Link"; - this._name = wX("LINK STATE PROMPT", portal.name); + this._name = wX("LINK STATE PROMPT"); divtitle.appendChild( LinkUI.displayFormat(this.options.target, operation) ); @@ -70,7 +69,7 @@ const StateDialog = WDialog.extend({ if (this.options.target instanceof WasabeeMarker) { const portal = operation.getPortal(this.options.target.portalId); this._type = "Marker"; - this._name = wX("MARKER STATE PROMPT", portal.name); + this._name = wX("MARKER STATE PROMPT"); divtitle.appendChild(PortalUI.displayFormat(portal)); const t = L.DomUtil.create("label", null); t.textContent = wX("MARKER STATE"); diff --git a/src/code/dialogs/teamListDialog.js b/src/code/dialogs/teamListDialog.js index 9c7d4823d..5c0b66e63 100644 --- a/src/code/dialogs/teamListDialog.js +++ b/src/code/dialogs/teamListDialog.js @@ -118,7 +118,7 @@ const TeamListDialog = WDialog.extend({ L.DomEvent.stop(ev); const cd = new ConfirmDialog({ title: wX("dialog.leave_team.title", { teamName: obj.Name }), - label: wX("dialog.leave_team.text"), + label: wX("dialog.leave_team.text", { teamName: obj.Name }), type: "team", callback: async () => { try { diff --git a/src/code/dialogs/trawl.js b/src/code/dialogs/trawl.js index 12b08729b..b2516a6ab 100644 --- a/src/code/dialogs/trawl.js +++ b/src/code/dialogs/trawl.js @@ -46,7 +46,7 @@ const TrawlerDialog = WDialog.extend({ const container = L.DomUtil.create("div", "container"); const warning = L.DomUtil.create("label", null, container); - warning.textContent = wX("TRAWLING", tiles); + warning.textContent = wX("TRAWLING"); const stat = L.DomUtil.create("div", null, container); this.remaining = L.DomUtil.create("span", null, stat); this.remaining.textContent = wX("TRAWL_REMAINING", { count: tiles }); diff --git a/src/code/error.ts b/src/code/error.ts index 28c3320e4..f8661782b 100644 --- a/src/code/error.ts +++ b/src/code/error.ts @@ -52,13 +52,14 @@ export class ServerError implements IServerError { toString() { switch (this.code) { case 401: - if (this.error) return wX("NOT LOGGED IN", this); + if (this.error) return wX("NOT LOGGED IN", this as { error: string }); return wX("NOT LOGGED IN SHORT"); case 403: - if (this.error) return wX("PERM DENIED", this); + if (this.error) return wX("PERM DENIED", this as { error: string }); return wX("PERM DENIED SHORT"); case 410: - if (this.error) return wX("NO LONGER AVAILABLE", this); + if (this.error) + return wX("NO LONGER AVAILABLE", this as { error: string }); return wX("NO LONGER AVAILABLE SHORT"); case 412: // for internal use only diff --git a/src/code/wX.ts b/src/code/wX.ts index 835409c2d..3822814a3 100644 --- a/src/code/wX.ts +++ b/src/code/wX.ts @@ -6,7 +6,194 @@ const localStoreKey = statics.constants.LANGUAGE_KEY; const templateRe = /\{ *([\w_ -]+) *\}/g; -export function wX(key: string, data?: object) { +export function wX(key: string): string; +export function wX( + key: "ASSIGN LINK PROMPT", + data: { portalName: string } +): string; +export function wX( + key: "ASSIGN MARKER PROMPT", + data: { portalName: string } +): string; +export function wX( + key: "ASSIGN OUTBOUND PROMPT", + data: { portalName: string } +): string; +export function wX(key: "AUTH TOKEN REJECTED", data: { error: string }): string; +export function wX( + key: "autodraw.fanfield.result", + data: { ap: number; fields: number; links: number } +): string; +export function wX( + key: "autodraw.flipflop.result", + data: { count: number } +): string; +export function wX( + key: "autodraw.homogeneous.missing_split", + data: { count: number } +): string; +export function wX( + key: "autodraw.homogeneous.portals_required", + data: { count: number } +): string; +export function wX( + key: "autodraw.madrid.result", + data: { count: number } +): string; +export function wX( + key: "autodraw.multimax.result", + data: { count: number } +): string; +export function wX( + key: "autodraw.multimax.result_both_side", + data: { count1: number; count2: number } +): string; +export function wX(key: "COMPLETED BY", data: { agentName: string }): string; +export function wX(key: "CON_DEL", data: { opName: string }): string; +export function wX(key: "DEFAULT OP NAME", data: { date: string }): string; +export function wX(key: "DELETE_OP", data: { opName: string }): string; +export function wX( + key: "dialog.agent_comment.title", + data: { agentName: string } +): string; +export function wX(key: "dialog.auth.ott.text", data: { url: string }): string; +export function wX( + key: "dialog.clear_all.text", + data: { opName: string } +): string; +export function wX( + key: "dialog.clear_all.title", + data: { opName: string } +): string; +export function wX( + key: "dialog.clear_links.text", + data: { opName: string } +): string; +export function wX( + key: "dialog.clear_links.title", + data: { opName: string } +): string; +export function wX( + key: "dialog.clear_markers.text", + data: { opName: string } +): string; +export function wX( + key: "dialog.clear_markers.title", + data: { opName: string } +): string; +export function wX( + key: "dialog.checklist.count_fields.no_empty", + data: { fieldCount: number } +): string; +export function wX( + key: "dialog.checklist.count_fields.with_empty", + data: { emptyCount: number; fieldCount: number; linkCount: number } +): string; +export function wX( + key: "dialog.checklist.count_fields.link_from_inside", + data: { count: number } +): string; +export function wX( + key: "dialog.checklist.count_fields.link_from_inside.covered_at_order", + data: { order: number } +): string; +export function wX(key: "dialog.firebase.setup", data: { url: string }): string; +export function wX( + key: "dialog.import.success_message", + data: { count: number; faked: number } +): string; +export function wX( + key: "dialog.leave_team.text", + data: { teamName: string } +): string; +export function wX( + key: "dialog.leave_team.title", + data: { teamName: string } +): string; +export function wX(key: "dialog.merge.zone", data: { name: string }): string; +export function wX( + key: "dialog.ops_list.download", + data: { opName: string } +): string; +export function wX( + key: "dialog.ops_list.last_fetched", + data: { date: string } +): string; +export function wX( + key: "dialog.remove_agent.text", + data: { agentName: string; teamName: string } +): string; +export function wX( + key: "dialog.remove_agent.title", + data: { agentName: string } +): string; +export function wX( + key: "dialog.team_message", + data: { message: string; sender: string } +): string; +export function wX( + key: "dialog.zone_color.text", + data: { zoneName: string } +): string; +export function wX(key: "FAKED", data: { portalId: string }): string; +export function wX(key: "HOURS", data: { hours: number }): string; +export function wX(key: "IMP_NOPE", data: { error: string }): string; +export function wX(key: "IMPORT_OP_SUCCESS", data: { opName: string }): string; +export function wX(key: "IMPORT_OP_TITLE", data: { date: string }): string; +export function wX(key: "KEY_LIST2", data: { opName: string }): string; +export function wX(key: "KNOWN_BLOCK", data: { opName: string }): string; +export function wX( + key: "LINKS2", + data: { portalName: string; incoming: number; outgoing: number } +): string; +export function wX(key: "LOADING1", data: { portalGuid: string }): string; +export function wX(key: "MANAGE_TEAM", data: { teamName: string }): string; +export function wX(key: "MARKER_LIST", data: { opName: string }): string; +export function wX(key: "MINUTES", data: { minutes: number }): string; +export function wX(key: "MM_SET_KEYS_ZONE", data: { zoneName: string }): string; +export function wX(key: "NO LONGER AVAILABLE", data: { error: string }): string; +export function wX(key: "NOT LOGGED IN", data: { error: string }): string; +export function wX(key: "OP DELETED", data: { opID: string }): string; +export function wX(key: "OP PERM DENIED", data: { opID: string }): string; +export function wX(key: "OP_CHECKLIST", data: { opName: string }): string; +export function wX(key: "PERM DENIED", data: { error: string }): string; +export function wX(key: "PERMS", data: { opName: string }): string; +export function wX( + key: "popup.anchor.keys", + data: { onHand: number; required: number } +): string; +export function wX( + key: "PORTAL KEY LIST", + data: { portalName: string } +): string; +export function wX(key: "PORTAL_COUNT", data: { count: number }): string; +export function wX(key: "REM_LOC_CP", data: { opName: string }): string; +export function wX( + key: "REMOVE_TEAM_CONFIRM_LABEL", + data: { teamName: string } +): string; +export function wX( + key: "REMOVE_TEAM_CONFIRM_TITLE", + data: { teamName: string } +): string; +export function wX(key: "SECONDS", data: { seconds: number }): string; +export function wX( + key: "SEND TARGET CONFIRM", + data: { agent: string; portalName: string } +): string; +export function wX(key: "SET_MCOMMENT", data: { portalName: string }): string; +export function wX(key: "SET_PCOMMENT", data: { portalName: string }): string; +export function wX(key: "SKINS_AVAILABLE", data: { count: number }): string; +export function wX(key: "TEAM_CREATED", data: { teamName: string }): string; +export function wX(key: "TRAWL_REMAINING", data: { count: number }): string; +export function wX(key: "UPDATE HOVER", data: { opName: string }): string; +export function wX( + key: "UPLOAD BUTTON HOVER", + data: { opName: string } +): string; +export function wX(key: "WSERVER", data: { url: string }): string; +export function wX(key: "YESNO_DEL", data: { opName: string }): string; +export function wX(key: string, data?: { [key: string]: number | string }) { const lang = getLanguage(); // if the skin system is initialized, switch to it @@ -31,10 +218,12 @@ export function wX(key: string, data?: object) { } if (!s) s = `${key} not in ${lang} or ${defaultLang}`; + if (!data) return s; + return s.replace(templateRe, function (str, key) { const value = data[key]; if (value === undefined) return `{${key}}`; - return value; + return "" + value; }); } From 8dbc3a300c54a7fca24a087dc2f4077e9da9a7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20-=20fisher01?= Date: Fri, 18 Mar 2022 22:21:20 +0100 Subject: [PATCH 273/275] Crowdin updates (#347) --- src/code/translations/Danish.json | 22 +- src/code/translations/English.json | 3 - src/code/translations/Filipino.json | 22 +- src/code/translations/French.json | 24 ++- src/code/translations/German.json | 288 ++++++++++++++------------ src/code/translations/Italian.json | 22 +- src/code/translations/Portuguese.json | 36 +++- src/code/translations/Russian.json | 24 ++- src/code/translations/Spanish.json | 52 +++-- 9 files changed, 301 insertions(+), 192 deletions(-) diff --git a/src/code/translations/Danish.json b/src/code/translations/Danish.json index d090d00a9..fed4717a7 100644 --- a/src/code/translations/Danish.json +++ b/src/code/translations/Danish.json @@ -135,6 +135,22 @@ "dialog.leave_team.title": "Leave: {teamName}", "dialog.link_list.length": "Length", "dialog.link_list.level": "Min Lvl", + "dialog.merge.cancel_upload": "Cancel upload", + "dialog.merge.conflicts": "Conflicts:", + "dialog.merge.local": "Local copy", + "dialog.merge.server": "Server copy", + "dialog.merge.zone": "Zone: {name}", + "dialog.merge.prop.assignedTo": "Assign:", + "dialog.merge.prop.comment": "Comment:", + "dialog.merge.prop.color": "Color:", + "dialog.merge.prop.deltaminutes": "Delta:", + "dialog.merge.prop.fromPortal": "From:", + "dialog.merge.prop.hardness": "Hard:", + "dialog.merge.prop.order": "Order:", + "dialog.merge.prop.state": "State:", + "dialog.merge.prop.toPortal": "To:", + "dialog.merge.prop.zone": "Zone:", + "dialog.merge.prop.zone_points": "Shape has changed", "dialog.online_agents.actions": "Actions", "dialog.online_agents.last_seen": "Last Seen", "dialog.online_agents.title": "Online Agents", @@ -158,6 +174,7 @@ "dialog.team_members.location": "Sharing Location", "dialog.team_members.wd_keys": "Sharing W-D Keys", "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.update_warning": "Wasabee is out of date. Please update using your plugin manager or by going to https://wasabee.rocks", "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", @@ -198,7 +215,6 @@ "HG": "Homogent felt", "HOURS": " ({hours} timer siden)", "HOW_TO_VIDS": "

Sådan-gør-du videoer:

", - "IMP_COMP": "", "IMP_NOPE": "Import mislykkedes.", "IMP_WAS_OP": "Importer Wasabee Operation", "IMPORT_OP_SUCCESS": "Importeret Operation: {opName} lykkedes.", @@ -320,7 +336,6 @@ "PLEASE_SELECT_PORTAL": "Vælg venligst en portal", "popup.anchor.keys": "Keys: {onHand} / {required}", "popup.marker.state_button": "Set State", - "PORT_FAKE": "", "PORTAL KEY LIST": "Nøgleliste for portal {portalName}", "PORTAL_COUNT": "{count} portaler", "PORTAL": "Portal", @@ -367,7 +382,7 @@ "SELECT_ONION_PORTALS": "Lag bygges indefra og ud. Zoom ind til midten, og vælg startportal, og zoom derefter ud til området.", "SELF SWAP": "Kan ikke bytte en portal med sig selv! Vælg en anden portal.", "SEND ANALYTICS": "Send anonyme analysedata", - "SEND LOCATION": "Send placering", + "SEND LOCATION": "Share Location (only when IITC is in foreground)", "SEND TARGET AGENT": "Vælg modtager agent", "SEND TARGET CONFIRM": "Vil du sende {portalName}-målet til {agent}?", "SEND TARGET": "Send mål", @@ -456,7 +471,6 @@ "UPLOAD BUTTON HOVER": "UPLOAD {opName} (ikke på serveren i øjeblikket)", "UPLOADED": "Uploadet", "USE PANES ON MOBILE": "Brug rammer (skal genindlæses)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Brug venligst et gyldigt operationsnavn", "UseVirusPortalAlert": "Brug Virus", "VRLA DESC": "Afhængigt af antallet og typen af anvendte linkforstærkere kan et lavere kildeportal level være tilstrækkeligt.", diff --git a/src/code/translations/English.json b/src/code/translations/English.json index 9fd517e00..1936af7ee 100644 --- a/src/code/translations/English.json +++ b/src/code/translations/English.json @@ -215,7 +215,6 @@ "HG": "Homogeneous Field", "HOURS": " ({hours} hours ago)", "HOW_TO_VIDS": "

How-To Videos:

", - "IMP_COMP": "", "IMP_NOPE": "Import Failed: {error}", "IMP_WAS_OP": "Import Wasabee Operation", "IMPORT_OP_SUCCESS": "Imported Operation: {opName} successfuly.", @@ -337,7 +336,6 @@ "PLEASE_SELECT_PORTAL": "Please select a portal", "popup.anchor.keys": "Keys: {onHand} / {required}", "popup.marker.state_button": "Set State", - "PORT_FAKE": "", "PORTAL KEY LIST": "Key list for portal {portalName}", "PORTAL_COUNT": "{count} portals", "PORTAL": "Portal", @@ -473,7 +471,6 @@ "UPLOAD BUTTON HOVER": "UPLOAD {opName} (not currently on server)", "UPLOADED": "Successfully uploaded", "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Please use a valid operation name", "UseVirusPortalAlert": "Use Virus", "VRLA DESC": "Depending on the number and type of Link Amps used, a lower source portal level might suffice.", diff --git a/src/code/translations/Filipino.json b/src/code/translations/Filipino.json index 26d6b5cb8..9c8ec9a52 100644 --- a/src/code/translations/Filipino.json +++ b/src/code/translations/Filipino.json @@ -135,6 +135,22 @@ "dialog.leave_team.title": "Leave: {teamName}", "dialog.link_list.length": "Length", "dialog.link_list.level": "Min Lvl", + "dialog.merge.cancel_upload": "Cancel upload", + "dialog.merge.conflicts": "Conflicts:", + "dialog.merge.local": "Local copy", + "dialog.merge.server": "Server copy", + "dialog.merge.zone": "Zone: {name}", + "dialog.merge.prop.assignedTo": "Assign:", + "dialog.merge.prop.comment": "Comment:", + "dialog.merge.prop.color": "Color:", + "dialog.merge.prop.deltaminutes": "Delta:", + "dialog.merge.prop.fromPortal": "From:", + "dialog.merge.prop.hardness": "Hard:", + "dialog.merge.prop.order": "Order:", + "dialog.merge.prop.state": "State:", + "dialog.merge.prop.toPortal": "To:", + "dialog.merge.prop.zone": "Zone:", + "dialog.merge.prop.zone_points": "Shape has changed", "dialog.online_agents.actions": "Actions", "dialog.online_agents.last_seen": "Last Seen", "dialog.online_agents.title": "Online Agents", @@ -158,6 +174,7 @@ "dialog.team_members.location": "Sharing Location", "dialog.team_members.wd_keys": "Sharing W-D Keys", "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.update_warning": "Wasabee is out of date. Please update using your plugin manager or by going to https://wasabee.rocks", "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", @@ -198,7 +215,6 @@ "HG": "Homogeneous Field", "HOURS": " ({hours} oras nakalipas)", "HOW_TO_VIDS": "

How-To Videos:

", - "IMP_COMP": "", "IMP_NOPE": "Pag-I-Import Hindi Matagumpay: {error}", "IMP_WAS_OP": "I-Import ang Wasabee operasyon", "IMPORT_OP_SUCCESS": "Na-Import na Operasyon: {opName} Matagumpay.", @@ -320,7 +336,6 @@ "PLEASE_SELECT_PORTAL": "Pumili ng portal", "popup.anchor.keys": "Keys: {onHand} / {required}", "popup.marker.state_button": "Set State", - "PORT_FAKE": "", "PORTAL KEY LIST": "Listahan ng Key para sa Portal {portalName}", "PORTAL_COUNT": "{count} portals", "PORTAL": "Portal", @@ -367,7 +382,7 @@ "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", "SELF SWAP": "Hindi maaari ipagpalit ang portal sa sarili! Pumili ng ibang portal.", "SEND ANALYTICS": "Send Anonymous Analytics", - "SEND LOCATION": "Ipaladala ang Lokasyon", + "SEND LOCATION": "Share Location (only when IITC is in foreground)", "SEND TARGET AGENT": "Select target recipient", "SEND TARGET CONFIRM": "Gusto mong ipadala ang {portalName} target sa {agent}?", "SEND TARGET": "Ipadala ang Target", @@ -456,7 +471,6 @@ "UPLOAD BUTTON HOVER": "UPLOAD {opName} (kasalukuyang wala sa server)", "UPLOADED": "Matagumpay na i-upload", "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Gumamit ng naaayon na pangalan ng operasyon", "UseVirusPortalAlert": "Gumamit ng Virus", "VRLA DESC": "Depende sa dami at uri ng Link Amp, ang mas mababang panimulang portal level ay maaaring piliin.", diff --git a/src/code/translations/French.json b/src/code/translations/French.json index 9bfa43239..7c16d04bc 100644 --- a/src/code/translations/French.json +++ b/src/code/translations/French.json @@ -135,6 +135,22 @@ "dialog.leave_team.title": "Quitter : {teamName}", "dialog.link_list.length": "Longueur", "dialog.link_list.level": "Niv Min", + "dialog.merge.cancel_upload": "Annuler", + "dialog.merge.conflicts": "Conflits :", + "dialog.merge.local": "Copie locale", + "dialog.merge.server": "Copie du serveur", + "dialog.merge.zone": "Zone : {name}", + "dialog.merge.prop.assignedTo": "Assigné :", + "dialog.merge.prop.comment": "Commentaire :", + "dialog.merge.prop.color": "Couleur :", + "dialog.merge.prop.deltaminutes": "Delta :", + "dialog.merge.prop.fromPortal": "De :", + "dialog.merge.prop.hardness": "Difficulté :", + "dialog.merge.prop.order": "Ordre :", + "dialog.merge.prop.state": "État :", + "dialog.merge.prop.toPortal": "Vers :", + "dialog.merge.prop.zone": "Zone :", + "dialog.merge.prop.zone_points": "La forme a été modifiée", "dialog.online_agents.actions": "Action", "dialog.online_agents.last_seen": "Dernière activité", "dialog.online_agents.title": "Agents en ligne", @@ -158,6 +174,7 @@ "dialog.team_members.location": "Partage de position", "dialog.team_members.wd_keys": "Partage de clés W-D", "dialog.team_message": "Message d'équipe: « {message} » de {sender}", + "dialog.update_warning": "Wasabee est obsolète. Veuillez mettre à jour en utilisant votre gestionnaire de plugin ou en allant sur https://wasabee.rocks", "dialog.zone_color.title": "Colorier la zone", "dialog.zone_color.text": "Colorier tous les liens dans la zone {zoneName}", "dialog.zones.color": "Couleur", @@ -198,7 +215,6 @@ "HG": "Field homogène", "HOURS": "(il y a {hours} heures)", "HOW_TO_VIDS": "

Tuto:

", - "IMP_COMP": "", "IMP_NOPE": "Echec de l'importation: {error}", "IMP_WAS_OP": "Importer les opérations Wasabee", "IMPORT_OP_SUCCESS": "Importer l'opération : {opName} Reussi.", @@ -254,7 +270,7 @@ "MERGE_CHANGES_MERGE": "Résultat après fusion", "MERGE_CHANGES_REMOTE": "Changements sur le serveur", "MERGE_LOCAL": "Locale", - "MERGE_MESSAGE": "L'opération \"{opName}\" a changé localement ainsi que sur le serveur. Voulez vous fusionné vos modifications à la version du serveur, ou utiliser la version du serveur ou bien conserver la version locale intacte ? (ou ne rien faire et laisser ça à plus tard)", + "MERGE_MESSAGE": "Les modifications locales et du serveur sont en conflit. Vous devez résoudre les conflits que Wasabee n'a pas réussi à résoudre lui-même. Sélectionnez la version à conserver pour chaque conflit non résolu. Vous pouvez également ignorer tous les conflits et utiliser la copie du serveur, ou vous pouvez simplement garder la copie locale intacte.", "MERGE_REBASE": "Fusion", "MERGE_REPLACE": "Remplacer", "MERGE_TITLE": "Fusion des versions locale et serveur", @@ -320,7 +336,6 @@ "PLEASE_SELECT_PORTAL": "Selectionner un portail", "popup.anchor.keys": "Clés : {onHand} / {required}", "popup.marker.state_button": "Définir l'état", - "PORT_FAKE": "", "PORTAL KEY LIST": "Clés du portail {portalName}", "PORTAL_COUNT": "{count} portails", "PORTAL": "Portail", @@ -367,7 +382,7 @@ "SELECT_ONION_PORTALS": "Les couches sont construites de la plus petite à la plus grande, avec au plus trois fields par portail en commençant par le portal défini, puis en utilisant les portails visibles.", "SELF SWAP": "Le portail selectionné est le même. Selectionnez un autre portail.", "SEND ANALYTICS": "Envoyer des statistiques anonymes", - "SEND LOCATION": "Partager sa position", + "SEND LOCATION": "Partager sa position (uniquement lorsque l'IITC est au premier plan)", "SEND TARGET AGENT": "Sélectionner l'agent cible.", "SEND TARGET CONFIRM": "Voulez vous signaler la cible {portalName} à {agent} ?", "SEND TARGET": "Envoyer la cible", @@ -456,7 +471,6 @@ "UPLOAD BUTTON HOVER": "Envoyer {opName} au serveur", "UPLOADED": "Envoi reussi", "USE PANES ON MOBILE": "Volet latéral (rechargement nécessaire)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Utiliser un nom d'opération valide", "UseVirusPortalAlert": "Virus", "VRLA DESC": "Le niveau nécessaire du portail peut être plus faible en fonction du type des Link Amp utilisés.", diff --git a/src/code/translations/German.json b/src/code/translations/German.json index 38ca21896..81f9be093 100644 --- a/src/code/translations/German.json +++ b/src/code/translations/German.json @@ -47,16 +47,16 @@ "AUTODRAWS": "Wasabee Auto-draw Optionen", "AUTODRAW_PORTALS_SET": "Portale", "autodraw.common.draw_button": "Draw", - "autodraw.fanfield.result": "Fanfield found {links} links and {fields} fields for {ap} AP", + "autodraw.fanfield.result": "Fanfield hat {links} Links und {fields} Felder für {ap} AP gefunden", "autodraw.flipflop.result": "Flip flop: hat {count} Links gefunden", - "autodraw.homogeneous.missing_split": "Unable to find {count} splits, try less depth or a different region", - "autodraw.homogeneous.order": "Order", - "autodraw.homogeneous.portals_required": "{count} required", - "autodraw.madrid.auto_determined": "Auto-determined", - "autodraw.madrid.balanced": "Balanced", - "autodraw.madrid.result": "Madrid found {count} layers", - "autodraw.multimax.result": "Multimax found {count} layers", - "autodraw.multimax.result_both_side": "Multimax found {count1} and {count2} layers", + "autodraw.homogeneous.missing_split": "Konnte {count} Teilungen nicht finden, versuche weniger Tiefe oder eine andere Region", + "autodraw.homogeneous.order": "Ordnung", + "autodraw.homogeneous.portals_required": "{count} erforderlich", + "autodraw.madrid.auto_determined": "Automatisch bestimmt", + "autodraw.madrid.balanced": "Ausgeglichen", + "autodraw.madrid.result": "Madrid hat {count} Ebenen gefunden", + "autodraw.multimax.result": "Multimax hat {count} Ebenen gefunden", + "autodraw.multimax.result_both_side": "Multimax hat {count1} und {count2} Ebenen gefunden", "autodraw.onion.variant": "Option", "autodraw.onion.variant.equilateral": "~Gleichseitig", "autodraw.onion.variant.grow": "Los!", @@ -102,71 +102,88 @@ "DELETE_OP": "Lösche {opName}", "DESCRIP_PLACEHOLD": "Beschreibung (optional)", "DestroyPortalAlert": "Zerstören", - "dialog.about.download_mobile_app": "

Wasabee App:

", + "dialog.about.download_mobile_app": "

Wasabee App:

", "dialog.agent_comment.text": "Comment:", - "dialog.agent_comment.title": "Set comment for {agentName}", - "dialog.auth.ott.button": "One Time Token Login", - "dialog.auth.ott.text": "Get a token from the Wasabee Server, then paste it here", - "dialog.auth.ott.title": "One Time Token", - "dialog.blockers.clear_automark": "Clear Automark", - "dialog.clear_all.text": "Do you want to reset {opName}?", + "dialog.agent_comment.title": "Kommentar für {agentName} einfügen", + "dialog.auth.ott.button": "Einmal-Token Login", + "dialog.auth.ott.text": "Holen Sie sich einen Token vom Wasabee Server, dann fügen Sie diesen hier ein", + "dialog.auth.ott.title": "Einmal-Token", + "dialog.blockers.clear_automark": "Automarkierung löschen", + "dialog.clear_all.text": "Möchten Sie {opName} zurücksetzen?", "dialog.clear_all.title": "Clear: {opName}", - "dialog.clear_links.text": "Do you want to remove all links from {opName}?", - "dialog.clear_links.title": "Clear Links: {opName}", - "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", + "dialog.clear_links.text": "Möchten Sie alle Links von {opName} entfernen?", + "dialog.clear_links.title": "Links löschen: {opName}", + "dialog.clear_markers.text": "Möchten Sie alle Markierungen von {opName} entfernen?", "dialog.clear_markers.title": "Clear Markers: {opName}", "dialog.checklist.count_fields": "Count fields", "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", "dialog.checklist.count_fields.link_from_inside": "Found {count} links from covered portals", - "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", - "dialog.common.commands": "Commands", + "dialog.checklist.count_fields.link_from_inside.covered_at_order": " bei {order} per Link ", + "dialog.common.commands": "Befehle", "dialog.common.commands_short": "Cmds", - "dialog.common.delete": "Delete", + "dialog.common.delete": "Löschen", "dialog.common.name": "Name", - "dialog.common.off": "Off", - "dialog.common.on": "On", - "dialog.common.owner": "Owner", + "dialog.common.off": "Aus", + "dialog.common.on": "Ein", + "dialog.common.owner": "Eigentümer", "dialog.common.zone_all": "All", - "dialog.firebase.setup": "Visit {url} and press the button to authorize live updates. You will need to reload IITC afterward.", - "dialog.import.url": "Fill from URL", + "dialog.firebase.setup": "Besuche {url} und drücke den Button, um Live-Updates zu autorisieren. Du musst IITC später neu laden.", + "dialog.import.url": "Von URL befüllen", "dialog.import.success_message": "Import abgeschlossen. {count} Portale gefunden und {faked} gefälscht verwendet. Bitte nutze die Swap-Funktion, um gefälschte Portale zu den echten Portalen am gleichen Ort zu bewegen. Das Einzoomen der 'Laden'-Portale in der Checkliste kann sie zum Laden zwingen.", "dialog.leave_team.text": "If you leave {teamName} you cannot rejoin unless the owner re-adds you.", - "dialog.leave_team.title": "Leave: {teamName}", - "dialog.link_list.length": "Length", + "dialog.leave_team.title": "Verlassen: {teamName}", + "dialog.link_list.length": "Länge", "dialog.link_list.level": "Min Lvl", + "dialog.merge.cancel_upload": "Upload abbrechen", + "dialog.merge.conflicts": "Konflikte:", + "dialog.merge.local": "Lokale Kopie", + "dialog.merge.server": "Server-Kopie", + "dialog.merge.zone": "Zone: {name}", + "dialog.merge.prop.assignedTo": "Zuweisen:", + "dialog.merge.prop.comment": "Kommentar:", + "dialog.merge.prop.color": "Farbe:", + "dialog.merge.prop.deltaminutes": "Delta:", + "dialog.merge.prop.fromPortal": "Von:", + "dialog.merge.prop.hardness": "Schwiergkeitsgrad:", + "dialog.merge.prop.order": "Reihenfolge:", + "dialog.merge.prop.state": "Status:", + "dialog.merge.prop.toPortal": "Nach:", + "dialog.merge.prop.zone": "Zone:", + "dialog.merge.prop.zone_points": "Shape has changed", "dialog.online_agents.actions": "Actions", - "dialog.online_agents.last_seen": "Last Seen", - "dialog.online_agents.title": "Online Agents", - "dialog.op_settings.zones": "Zones", + "dialog.online_agents.last_seen": "Zuletzt gesehen", + "dialog.online_agents.title": "Agenten online", + "dialog.op_settings.zones": "Zonen", "dialog.ops_list.background_disable": "Disable background", - "dialog.ops_list.background_enable": "Show in background", - "dialog.ops_list.download": "Download {opName}", - "dialog.ops_list.last_fetched": "Last fetched: {date}", + "dialog.ops_list.background_enable": "Im Hintergrund anzeigen", + "dialog.ops_list.download": "{opName} herunterladen", + "dialog.ops_list.last_fetched": "Zuletzt abgerufen: {date}", "dialog.ops_list.local_change": "Local has changed", "dialog.ops_list.remote_change": "Remote has changed", - "dialog.ops_list.toggle_hide": "Toggle Show/Hide", - "dialog.ops_list.unhide_ops": "Unhide all OPs", - "dialog.remove_agent.text": "Do you want to remove {agentName} from {teamName}?", + "dialog.ops_list.toggle_hide": "Ein-/Ausblenden umschalten", + "dialog.ops_list.unhide_ops": "Alle OPs anzeigen", + "dialog.remove_agent.text": "Möchten Sie {agentName} aus {teamName} entfernen?", "dialog.remove_agent.title": "Remove: {agentName}", "dialog.setcomment.portal_hardness": "Schwierigkeitsgrad", - "dialog.team_list.load_wd_keys": "Load W-D Keys", - "dialog.team_list.share_wd_keys": "Share W-D Keys", - "dialog.team_manage.join_link": "Join Link", - "dialog.team_manage.join_link.create": "Create", - "dialog.team_manage.join_link.revoke": "Revoke", - "dialog.team_members.location": "Sharing Location", - "dialog.team_members.wd_keys": "Sharing W-D Keys", - "dialog.team_message": "Team announcement: “{message}” from {sender}", - "dialog.zone_color.title": "Zone Color", + "dialog.team_list.load_wd_keys": "W-D-Schlüssel laden", + "dialog.team_list.share_wd_keys": "W-D Schlüssel teilen", + "dialog.team_manage.join_link": "Beitrittslink", + "dialog.team_manage.join_link.create": "Erzeugen", + "dialog.team_manage.join_link.revoke": "Widerrufen", + "dialog.team_members.location": "Standort wird geteilt", + "dialog.team_members.wd_keys": "W-D Schlüssel teilen", + "dialog.team_message": "Teamankündigung: „{message}“ von {sender}", + "dialog.update_warning": "Wasabee ist veraltet. Bitte aktualisiere über deinen Plugin Manager oder gehe zu https://wasabee.rocks", + "dialog.zone_color.title": "Zonenfarbe", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", - "dialog.zones.color": "Color", + "dialog.zones.color": "Farbe", "dialog.zones.color_links": "Color links", "dialog.zones.delete_zone_shape": "Reset the shape", "dialog.zones.draw_zone_shape": "Draw the boundaries", "dialog.zones.id": "ID", "dialog.zones.stop_drawing": "Stop drawing", - "dialog.zones.title": "Zones", + "dialog.zones.title": "Zonen", "DRAW TOOLS FORMAT": "Draw Tools Format", "DUPE_OP": "Dupliziere Operation", "END_PORT": "Endportal", @@ -198,7 +215,6 @@ "HG": "Homogenes Feld", "HOURS": "vor ({hours} Stunden)", "HOW_TO_VIDS": "

Erklärungsvideos:

", - "IMP_COMP": "", "IMP_NOPE": "Import Fehlgeschlagen: {error}", "IMP_WAS_OP": "Importiere Wasabee Operation", "IMPORT_OP_SUCCESS": "Importierte Operation: {opName}. Erfolgreich.", @@ -293,17 +309,17 @@ "NTNAME": "Name", "OK": "OK", "ON_HAND": "Verfügbar", - "ONION_WAS_TAKEN": "Onion", - "ONION": "Draw", + "ONION_WAS_TAKEN": "Zwiebel", + "ONION": "Zeichnen", "ONLY_DT_IMP": " (nur für DrawTools imports)", - "OP DELETED": "Operation removed from server: {opID}", + "OP DELETED": "Operation vom Server entfernt: {opID}", "OP PERM DENIED": "Keine Berechtigung für Operation: {opID}", "OP_BUTTON": "Operation", "OP_CHECKLIST": "Operation Checkliste: {opName}", "OP_NAME_UNSET": "Operationsname ist leer.", - "OP_PERMS": "Op Permissions", - "OP_SETTINGS_BUTTON": "Op ⚙", - "OP_SETTINGS_TITLE": "Operation Settings", + "OP_PERMS": "OP-Berechtigungen", + "OP_SETTINGS_BUTTON": "OP ⚙", + "OP_SETTINGS_TITLE": "Operationseinstellungen", "OPEN_REQUEST": "[öffne Anfrage]", "OPER_COLOR": "Operation Color:", "OPER_NAME": "Operation Name:", @@ -311,35 +327,34 @@ "OPS BUTTON TITLE": "Operationen", "OPS BUTTON": "Ops", "ORDER": "Reihenfolge", - "OtherPortalAlert": "Other", + "OtherPortalAlert": "Sonstiges", "PASTE_INSTRUCT": "Füge einen Wasabee Drawtools export hier ein.\n\nWasabee kann nicht mit dem Standard intel format umgehen.\n\nEs gibt einen Experimentellen Import vom IITC-DrawTools format.\n\n Vor dem Importieren bitte sicherstellen das alles geladen ist und die IITC es zwischengespeichert hat. Jedes nicht zwischengespeicherte Portal wird verfälscht. \n\nDu musst die 'Wechsel' Funktion verwenden um die verfälschten Portale zu korrigieren. (Sie sollten bereits an der richtigen Position sein - aber dem falschen Portal zugeordnet).", "pending": "Ausstehend", "PERM DENIED": "Keine Berechtigung: {error}", "PERM DENIED SHORT": "Keine Berechtigung", - "PERMS": "{opName} permissions", + "PERMS": "{opName} Berechtigungen", "PLEASE_SELECT_PORTAL": "Bitte wähle ein Portal", - "popup.anchor.keys": "Keys: {onHand} / {required}", - "popup.marker.state_button": "Set State", - "PORT_FAKE": "", - "PORTAL KEY LIST": "Key list for portal {portalName}", - "PORTAL_COUNT": "{count} portals", + "popup.anchor.keys": "Schlüssel: {onHand} / {required}", + "popup.marker.state_button": "Status setzen", + "PORTAL KEY LIST": "Schlüsselliste für Portal {portalName}", + "PORTAL_COUNT": "{count} Portale", "PORTAL": "Portal", - "QD BUTTON CHANGE COLOR": "Click to change next links color", + "QD BUTTON CHANGE COLOR": "Klicken, um die nächste Linkfarbe zu ändern", "QD BUTTON END": "Klicken um das Feld zeichnen zu beenden", - "QD BUTTON TOGGLE MODE": "Click to change draw mode", - "QD CHANGE COLOR": "Change color", + "QD BUTTON TOGGLE MODE": "Klicken, um den Zeichenmodus zu ändern", + "QD CHANGE COLOR": "Farbe ändern", "QD END": "Ende", "QD TITLE": "Schnelle Layer Zeichnung", - "QD TOGGLE MODE": "Change mode", + "QD TOGGLE MODE": "Modus ändern", "QDBASE": "Basis Link", "QDCONT": "Klicke auf ein Portal der Kette.", "QDNEXT": "Klicke auf das zweite Ankerportal.", "QDSTART": "Klicke auf das erste Ankerportal.", "READ_SHORT": "RO", "READ": "lesen", - "RechargePortalAlert": "Recharge", + "RechargePortalAlert": "Aufladen", "REFERENCE_TIME": "Reference Time:", - "REM_LOC_CP": "Remove local copy of {opName}", + "REM_LOC_CP": "Lokale Kopie von {opName} entfernen", "REMOVE_TEAM_CONFIRM_LABEL": "Möchtest du {teamName} permanent vom Server entfernen?", "REMOVE_TEAM_CONFIRM_TITLE": "Entferne Team {teamName}", "REMOVE_TEAM": "Team entfernen:", @@ -348,26 +363,26 @@ "RENAME": "Umbenennen", "REQUIRED": "Benötigt", "RESET": "Reset", - "REVERSE": "Reverse", + "REVERSE": "Umkehren", "ROCKS_COM": "enl.rocks community:", "ROLE": "Rolle", - "SAVELINKS TITLE": "Save Links", - "SAVELINKS_DRAW": "Save Links", - "SAVELINKS": "Save Links", + "SAVELINKS TITLE": "Links speichern", + "SAVELINKS_DRAW": "Links speichern", + "SAVELINKS": "Links speichern", "SECONDS": "vor ({seconds} Sekunden)", "SEL_SB_ANCHOR": "Wähle einen Anker, Zomme in das Areal und füge es zum Starburst hinzu.", - "SEL_SB_ANCHOR2": "Zoom out. Make sure portals have all loaded, then click draw.", + "SEL_SB_ANCHOR2": "Zoomen Sie heraus. Stellen Sie sicher, dass Portale alle geladen sind, und klicken Sie dann auf zeichnen.", "SEL_SL_ANCHOR": "Select the portal to save the links of. Click save links button and look at checklist.", "SEL_SRC_ANC2": "Lege Quelle und Anker 2 fest", "SEL_SRC_PORT": "Wähle ein Quellportal", "SELECT PORTAL": "Portal zum senden auswählen", "SELECT_FAN_PORTALS": "Wähle ein Ankerportal, wähle ein Startportal und ein Endportal, danach zoome in die Gegend des Fächers. Warte bis alle Portale geladen sind. Drücke anschließend den 'Fächerfeld' Knopf.", - "SELECT_FAN_PORTALS2": "Wait for all portals to load, then click draw.", + "SELECT_FAN_PORTALS2": "Warten Sie, bis alle Portale geladen wurden, und klicken Sie dann auf Zeichen.", "SELECT_INSTRUCTIONS": "Wähle zwei Ankerportale. Zoome in die Gegend der Portalkette - warte bis die Portale geladen sind und drücke den 'Maximale Feldanzahl' Knopf.", "SELECT_ONION_PORTALS": "Layers build from the inside out. Zoom in to center and select starting portal, then zoom out to area.", "SELF SWAP": "Du kannst das Portal nicht mit sich selbst tauschen - Wähle ein anderes.", - "SEND ANALYTICS": "Send Anonymous Analytics", - "SEND LOCATION": "Sende Standort", + "SEND ANALYTICS": "Anonymisierte Analysedaten senden", + "SEND LOCATION": "Share Location (only when IITC is in foreground)", "SEND TARGET AGENT": "Select target recipient", "SEND TARGET CONFIRM": "Möchtest du {portalName} an {agent} senden?", "SEND TARGET": "Sende Ziel", @@ -378,28 +393,28 @@ "SET_LINK_COMMENT": "Set comment for link:", "SET_LINKS_ZONES": "Set Links to Zones", "SET_MARKER_COMMENT": "Set comment for marker on:", - "SET_MARKER_TYPE_TITLE": "Change marker type", + "SET_MARKER_TYPE_TITLE": "Markierungstyp ändern", "SET_MARKERS_ZONES": "Set Markers to Zones", "SET_MCOMMENT": "Setze Kommentar für Markierung: {portalName}", "SET_NEW_OP": "Bitte gebe einen neuen Operationnamen ein", "SET_PCOMMENT": "Setze Kommentar für Portal: {portalName}", "SET_PORT_COMMENT": "Set comment for portal:", - "SET_PORTAL_COMMENT": "Set Portal Comment", + "SET_PORTAL_COMMENT": "Portalkommentar festlegen", "SET": "setzen", - "SETTINGS_TOOLBOX": "Wasabee Settings", - "SETTINGS_TITLE": "Advanced Settings", - "SKINS_AVAILABLE": "There are {count} available skins.", - "SKINS_BUTTON": "Configure Skins", - "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", - "SKINS_MANAGE_TITLE": "Manage skins", - "SKIP_CONFIRM_ALWAYS": "Never ask (use with caution)", - "SKIP_CONFIRM_ENTITY": "Only ask for team/op", - "SKIP_CONFIRM_NEVER": "Always ask", - "SKIP_CONFIRM": "Skip confirmation", - "SOURCE_PORT": "Source Portal", + "SETTINGS_TOOLBOX": "Wasabee-Einstellungen", + "SETTINGS_TITLE": "Erweiterte Einstellungen", + "SKINS_AVAILABLE": "Es gibt {count} verfügbare Skins.", + "SKINS_BUTTON": "Skins konfigurieren", + "SKINS_DESCRIPTION": "Verfügbare Skins befinden sich in der rechten Spalte. Verschieben Sie Skins, die Sie verwenden möchten, auf die linke Spalte.", + "SKINS_MANAGE_TITLE": "Skins verwalten", + "SKIP_CONFIRM_ALWAYS": "Nie nachfragen (mit Vorsicht zu verwenden)", + "SKIP_CONFIRM_ENTITY": "Nur nach Team/Op fragen", + "SKIP_CONFIRM_NEVER": "Immer nachfragen", + "SKIP_CONFIRM": "Bestätigung überspringen", + "SOURCE_PORT": "Quellportal", "STARBURST TITLE": "Starburst ", - "STARBURST_DRAW": "Draw", - "STARBURST": "Starburst", + "STARBURST_DRAW": "Zeichnen", + "STARBURST": "Linkstern", "START_PORT": "Startportal", "STATE": "Status", "SUPPORT_INSTRUCT": "Für Hilfe trete bitte der Telegram Gruppe bei The Wasabee User Telegram Channel ", @@ -410,59 +425,58 @@ "SYNC DONE": "Download abgeschlossen
Klicken Sie HIER für Hinweise, Tipps und Dokumentation.", "SYNC": "Download verfügbarer Operationen", "TARGET SENT": "Ziel gesendet", - "TEAM STATE": "Share Location", + "TEAM STATE": "Standort teilen", "TEAM_CREATED": "Team {teamName} erstellt.", - "TEAM_NAME": "Team Name", + "TEAM_NAME": "Team-Name", "TEAM": "Team", "TEAMS BUTTON TITLE": "Auflistung Wasabee Teams", "TEAMS BUTTON": "Teams", "TO_PORT": "zu Portal", - "toolbar.quick_delete.apply.text": "Apply", - "toolbar.quick_delete.apply.title": "Delete selected links/markers", - "toolbar.quick_delete.cancel.text": "Cancel", - "toolbar.quick_delete.cancel.title": "Cancel", - "toolbar.quick_delete.stop.text": "Stop", - "toolbar.quick_delete.stop.title": "Exit delete mode", - "toolbar.quick_delete.title": "Quick delete", - "toolbar.quick_delete.tooltip.toggle_mode": "Click on features to mark for deletion", - "toolbar.quick_delete.tooltip.quick_mode": "Click on features to delete instantly", - "toolbar.quick_draw.tooltip.star_mode.anchor": "Select the star anchor", - "toolbar.quick_draw.tooltip.star_mode.portal": "Select a portal", - "toolbar.quick_draw.tooltip.single_mode.first": "Click first portal", - "toolbar.quick_draw.tooltip.single_mode.next": "Click next portal", - "toolbar.quick_draw.tooltip.portal_fail": "Portal data not loaded, please try again", - "toolbar.wasabee.settings": "Settings", - "toolbox.teammates": "Teammates Online", + "toolbar.quick_delete.apply.text": "Übernehmen", + "toolbar.quick_delete.apply.title": "Ausgewählte Links/Marker löschen", + "toolbar.quick_delete.cancel.text": "Abbrechen", + "toolbar.quick_delete.cancel.title": "Abbrechen", + "toolbar.quick_delete.stop.text": "Stoppen", + "toolbar.quick_delete.stop.title": "Löschmodus beenden", + "toolbar.quick_delete.title": "Schnell-Löschen", + "toolbar.quick_delete.tooltip.toggle_mode": "Auf Objekte klicken um diese zur Löschung zu markieren", + "toolbar.quick_delete.tooltip.quick_mode": "Klicken Sie auf Objekte um diese sofort zu löschen", + "toolbar.quick_draw.tooltip.star_mode.anchor": "Wählen Sie den Linkstern-Anker", + "toolbar.quick_draw.tooltip.star_mode.portal": "Ein Portal auswählen", + "toolbar.quick_draw.tooltip.single_mode.first": "Erstes Portal anklicken", + "toolbar.quick_draw.tooltip.single_mode.next": "Nächstes Portal anklicken", + "toolbar.quick_draw.tooltip.portal_fail": "Portaldaten nicht geladen, bitte versuchen Sie es erneut", + "toolbar.wasabee.settings": "Einstellungen", + "toolbox.teammates": "Teammitglieder online", "TRAWL SKIP TILES": "Trawl Skip Tiles", "TRAWL TITLE": "Trawl Lanes", - "TRAWL WARNING": "This will load the tile data under all drawn links. This is a slow process.", - "TRAWL_AUTOMARK": "Auto-mark blockers after trawling", - "TRAWL_BULK_LOAD_WARNING": "This method loads the tile data as quickly as possible. Use at your own risk.", + "TRAWL WARNING": "Dies wird die Daten alle Quadranten unter allen gezeichneten Links laden. Dies ist ein langsamer Prozess.", + "TRAWL_AUTOMARK": "Blocker nach Suche automatisch markieren", + "TRAWL_BULK_LOAD_WARNING": "Diese Methode lädt die Daten der Quadranten so schnell wie möglich. Die Verwendung erfolgt auf eigene Gefahr.", "TRAWL_BULK_LOAD": "Bulk Load Tile Data", "TRAWL_CLEAR_MARKERS": "Clear virus/destroy markers before trawling", - "TRAWL_REMAINING": "{count} tiles remaining", - "TRAWL": "Trawl for Blockers", - "TRAWLING": "Trawling the lanes for blockers, close this dialog to stop", + "TRAWL_REMAINING": "Noch {count} Quadranten", + "TRAWL": "Suche nach Blockern", + "TRAWLING": "Suche die Linkschneisen nach Blockern ab, schließen Sie diesen Dialog um abzubrechen", "TYPE": "Typ", "UNASSIGNED": "Nicht zugewiesenen", "UNKNOWN": "Unbekannt", "UPDATE HOVER": "UPDATE {opName} auf dem Server", "UPDATE PERM DENIED": "You do not have permission to update", "UPDATE_CONFLICT_DESC": "The OP has been modified on server since last sync. Do you want to replace the server version by the current one?", - "UPDATE_CONFLICT_TITLE": "Conflict detected with server", + "UPDATE_CONFLICT_TITLE": "Konflikt mit Server gefunden", "UPDATE_COUNT": "Aktualisiere Anzahl", "UPDATED": "Erfolgreich aktualisiert", "UpgradePortalAlert": "Upgrade", "UPLOAD BUTTON HOVER": "UPLOAD {opName} (aktuell nicht auf dem Server)", "UPLOADED": "Erfolgreich hochgeladen", "USE PANES ON MOBILE": "Use panes (need reload)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Bitte verwende einen gültigen Operationsnamen", - "UseVirusPortalAlert": "Use Virus", + "UseVirusPortalAlert": "Virus benutzen", "VRLA DESC": "Ausgehend von der Anzahl und Typ von Link-Amps könnte ein niedrigeres Portallevel ausreichen", "VRLA": "L8+ einige VRLA", "WASABEE BUTTON TITLE": "Wasabee: Es ist grün und bringt Schlümpfe zum heulen.", - "WASABEE_D_LIST": "Input Defensive Key Count", + "WASABEE_D_LIST": "Eingabe defensiver Schlüssel", "WD BUTTON TITLE": "Speicher Verteidigungs Schlüssel", "WD BUTTON": "W-D Schlüssel", "WRITE_SHORT": "RW", @@ -473,28 +487,28 @@ "ZONE": "Zoniert", "smallScreen": { "ADD_LINKS": "+ Links", - "ADD_MARKER": "+ Marker", - "BLOCKER TITLE": "Blockers", - "CHECKLIST BUTTON": "Check", - "CLEAROPS BUTTON": "Clear", + "ADD_MARKER": "+ Markierungen", + "BLOCKER TITLE": "Blocker", + "CHECKLIST BUTTON": "Überprüfen", + "CLEAROPS BUTTON": "Löschen", "EXPORT OP": "Xport", "FANFIELD": "Draw", - "FANFIELD2": "Draw Fan Field", - "KEYS": "Keys", - "LOG IN": "Log In", - "LOG_OUT": "Log Out", - "MARKER LIST": "Markers", - "MARKERS BUTTON TITLE": "Markers", + "FANFIELD2": "Fächerfeld zeichnen", + "KEYS": "Schlüssel", + "LOG IN": "Einloggen", + "LOG_OUT": "Ausloggen", + "MARKER LIST": "Markierungen", + "MARKERS BUTTON TITLE": "Markierungen", "MAX": "Fan", "MM": "Multi", "MULTI_M_TITLE": "Draw Max Layers", - "MULTI_M": "Draw", - "NEWOP BUTTON": "New Op", - "OPS BUTTON": "Select OP", - "QD END": "End", - "STARBURST_DRAW": "Draw", - "STARBURST": "Star", + "MULTI_M": "Zeichnen", + "NEWOP BUTTON": "Neue Op", + "OPS BUTTON": "OP wählen", + "QD END": "Ende", + "STARBURST_DRAW": "Zeichnen", + "STARBURST": "Stern", "TEAMS BUTTON": "Teams", - "WD BUTTON": "W-D Keys" + "WD BUTTON": "W-D Schlüssel" } } \ No newline at end of file diff --git a/src/code/translations/Italian.json b/src/code/translations/Italian.json index f7ad1219d..251993885 100644 --- a/src/code/translations/Italian.json +++ b/src/code/translations/Italian.json @@ -135,6 +135,22 @@ "dialog.leave_team.title": "Lascia: {teamName}", "dialog.link_list.length": "Lunghezza", "dialog.link_list.level": "Livello minimo", + "dialog.merge.cancel_upload": "Cancel upload", + "dialog.merge.conflicts": "Conflicts:", + "dialog.merge.local": "Local copy", + "dialog.merge.server": "Server copy", + "dialog.merge.zone": "Zone: {name}", + "dialog.merge.prop.assignedTo": "Assign:", + "dialog.merge.prop.comment": "Comment:", + "dialog.merge.prop.color": "Color:", + "dialog.merge.prop.deltaminutes": "Delta:", + "dialog.merge.prop.fromPortal": "From:", + "dialog.merge.prop.hardness": "Hard:", + "dialog.merge.prop.order": "Order:", + "dialog.merge.prop.state": "State:", + "dialog.merge.prop.toPortal": "To:", + "dialog.merge.prop.zone": "Zone:", + "dialog.merge.prop.zone_points": "Shape has changed", "dialog.online_agents.actions": "Azioni", "dialog.online_agents.last_seen": "Ultimo accesso", "dialog.online_agents.title": "Agenti Online", @@ -158,6 +174,7 @@ "dialog.team_members.location": "Sharing Location", "dialog.team_members.wd_keys": "Sharing W-D Keys", "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.update_warning": "Wasabee is out of date. Please update using your plugin manager or by going to https://wasabee.rocks", "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", @@ -198,7 +215,6 @@ "HG": "Field Omogeneo", "HOURS": " ({hours} ore fa)", "HOW_TO_VIDS": "

Video tutorial:

", - "IMP_COMP": "", "IMP_NOPE": "Importazione Fallita: {error}", "IMP_WAS_OP": "Importa Operazione Wasabee", "IMPORT_OP_SUCCESS": "Importata Operazione: {opName} con successo.", @@ -320,7 +336,6 @@ "PLEASE_SELECT_PORTAL": "Seleziona un portale", "popup.anchor.keys": "Keys: {onHand} / {required}", "popup.marker.state_button": "Set State", - "PORT_FAKE": "", "PORTAL KEY LIST": "Lista Chiavi per Portale: {portalName}", "PORTAL_COUNT": "{count} Portali", "PORTAL": "Portale", @@ -367,7 +382,7 @@ "SELECT_ONION_PORTALS": "Strati creati da dentro a fuori. Zooma sul centro e seleziona il portale di inizio, poi zooma indietro sull'area.", "SELF SWAP": "Non si può scambiare un portale con se stesso! Seleziona un altro portale.", "SEND ANALYTICS": "Invia dati di utilizzo anonimi", - "SEND LOCATION": "Invia posizione", + "SEND LOCATION": "Share Location (only when IITC is in foreground)", "SEND TARGET AGENT": "Seleziona destinatario target", "SEND TARGET CONFIRM": "Vuoi inviare il target {portalName} a {agent}?", "SEND TARGET": "Invia target", @@ -456,7 +471,6 @@ "UPLOAD BUTTON HOVER": "CARICA {opName} (al momento non sul server)", "UPLOADED": "Caricato con successo", "USE PANES ON MOBILE": "Usa riquadri (richiede reload)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Usa un nome operazione valido", "UseVirusPortalAlert": "Usare Virus", "VRLA DESC": "In base al tipo e al numero di Link Amp usati, potrebbe bastare un portale di origine di livello più basso.", diff --git a/src/code/translations/Portuguese.json b/src/code/translations/Portuguese.json index c0bc8028c..28526bfb2 100644 --- a/src/code/translations/Portuguese.json +++ b/src/code/translations/Portuguese.json @@ -122,7 +122,7 @@ "dialog.checklist.count_fields.link_from_inside.covered_at_order": " em {order} por link ", "dialog.common.commands": "Comandos", "dialog.common.commands_short": "Cmds", - "dialog.common.delete": "Delete", + "dialog.common.delete": "Apagar", "dialog.common.name": "Nome", "dialog.common.off": "Desligar", "dialog.common.on": "Ligar", @@ -135,6 +135,22 @@ "dialog.leave_team.title": "Deixar: {teamName}", "dialog.link_list.length": "Comprimento", "dialog.link_list.level": "Min Lvl", + "dialog.merge.cancel_upload": "Cancelar carregamento", + "dialog.merge.conflicts": "Conflitos:", + "dialog.merge.local": "Cópia local", + "dialog.merge.server": "Cópia do servidor", + "dialog.merge.zone": "Zona: {name}", + "dialog.merge.prop.assignedTo": "Atribuir:", + "dialog.merge.prop.comment": "Comentario:", + "dialog.merge.prop.color": "Cor:", + "dialog.merge.prop.deltaminutes": "Delta:", + "dialog.merge.prop.fromPortal": "De:", + "dialog.merge.prop.hardness": "Difícil:", + "dialog.merge.prop.order": "Pedido:", + "dialog.merge.prop.state": "Estado:", + "dialog.merge.prop.toPortal": "Para:", + "dialog.merge.prop.zone": "Zona:", + "dialog.merge.prop.zone_points": "A forma foi alterada", "dialog.online_agents.actions": "Ações", "dialog.online_agents.last_seen": "Visto pela última vez", "dialog.online_agents.title": "Agentes Online", @@ -158,14 +174,15 @@ "dialog.team_members.location": "A partilhar a localização", "dialog.team_members.wd_keys": "Partilhar chaves W-D", "dialog.team_message": "Anúncio de equipa: “{message}” de {sender}", + "dialog.update_warning": "O Wasabee está desatualizado. Atualize a usar seu gerenciador de plugins ou indo para https://wasabee.rocks", "dialog.zone_color.title": "Cor da zona", "dialog.zone_color.text": "Definir a cor de todos os links na zona {zoneName}", "dialog.zones.color": "Cor", - "dialog.zones.color_links": "Color links", - "dialog.zones.delete_zone_shape": "Reset the shape", - "dialog.zones.draw_zone_shape": "Draw the boundaries", + "dialog.zones.color_links": "Cor de Link", + "dialog.zones.delete_zone_shape": "Resetar a forma", + "dialog.zones.draw_zone_shape": "Desenhar limites dos blocos", "dialog.zones.id": "ID", - "dialog.zones.stop_drawing": "Stop drawing", + "dialog.zones.stop_drawing": "Parar de desenhar", "dialog.zones.title": "Zonas", "DRAW TOOLS FORMAT": "Formato Draw Tools", "DUPE_OP": "Duplicar Operação", @@ -198,7 +215,6 @@ "HG": "Campo Homogêneo", "HOURS": " ({hours} horas atrás)", "HOW_TO_VIDS": "

Vídeos de instruções:

", - "IMP_COMP": "", "IMP_NOPE": "A Importação Falhou: {error}", "IMP_WAS_OP": "Importar Operação Wasabee", "IMPORT_OP_SUCCESS": "OP Importada: {opName} successfuly.", @@ -320,7 +336,6 @@ "PLEASE_SELECT_PORTAL": "Seleciona um portal", "popup.anchor.keys": "Chaves: {onHand} / {required}", "popup.marker.state_button": "Definir estado", - "PORT_FAKE": "", "PORTAL KEY LIST": "Lista de chaves para portal {portalName}", "PORTAL_COUNT": "{count} portais", "PORTAL": "Portal", @@ -367,7 +382,7 @@ "SELECT_ONION_PORTALS": "As camadas são construídas de dentro para fora. Aumenta o zoom para o centro e seleciona o portal inicial, em seguida, diminui o zoom para a área.", "SELF SWAP": "Não é possível trocar um portal contigo mesmo! Seleciona um portal diferente.", "SEND ANALYTICS": "Enviar análises anônimas", - "SEND LOCATION": "Enviar localização", + "SEND LOCATION": "Partilhar localização (somente quando o IITC estiver em primeiro plano)", "SEND TARGET AGENT": "Selecionar o destinatário alvo", "SEND TARGET CONFIRM": "Queres enviar {portalName} alvo para {agent}?", "SEND TARGET": "Enviar alvo", @@ -386,8 +401,8 @@ "SET_PORT_COMMENT": "Definir comentário para portal:", "SET_PORTAL_COMMENT": "Definir comentário do portal", "SET": "definir", - "SETTINGS_TOOLBOX": "Wasabee Settings", - "SETTINGS_TITLE": "Advanced Settings", + "SETTINGS_TOOLBOX": "Configurações do Wasabee", + "SETTINGS_TITLE": "Definições avançadas", "SKINS_AVAILABLE": "Existem {count} skins disponíveis.", "SKINS_BUTTON": "Configurar Skins", "SKINS_DESCRIPTION": "Gerenciar as skins disponíveis movendo o tema para a coluna da esquerda. Quanto mais baixo na coluna, maior será a prioridade para o UI.", @@ -456,7 +471,6 @@ "UPLOAD BUTTON HOVER": "UPLOAD {opName} (atualmente não está no servidor)", "UPLOADED": "Carregado com sucesso", "USE PANES ON MOBILE": "Usar painéis (precisa recarregar)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Usa um nome de operação válido", "UseVirusPortalAlert": "Usar Virus", "VRLA DESC": "Dependendo do número e tipo de Link Amps usados, um nível de portal de origem inferior pode ser suficiente.", diff --git a/src/code/translations/Russian.json b/src/code/translations/Russian.json index 70ba15aea..7a627ac46 100644 --- a/src/code/translations/Russian.json +++ b/src/code/translations/Russian.json @@ -135,6 +135,22 @@ "dialog.leave_team.title": "Покинуть: {teamName}", "dialog.link_list.length": "Длина", "dialog.link_list.level": "Мин. уровень", + "dialog.merge.cancel_upload": "Отменить загрузку", + "dialog.merge.conflicts": "Конфликты:", + "dialog.merge.local": "Локальная копия", + "dialog.merge.server": "Серверная копия", + "dialog.merge.zone": "Зона: {name}", + "dialog.merge.prop.assignedTo": "Назначить:", + "dialog.merge.prop.comment": "Комментарий:", + "dialog.merge.prop.color": "Цвет:", + "dialog.merge.prop.deltaminutes": "Дельта:", + "dialog.merge.prop.fromPortal": "От:", + "dialog.merge.prop.hardness": "Hard:", + "dialog.merge.prop.order": "Порядок:", + "dialog.merge.prop.state": "Статус:", + "dialog.merge.prop.toPortal": "К:", + "dialog.merge.prop.zone": "Зона:", + "dialog.merge.prop.zone_points": "Форма изменилась", "dialog.online_agents.actions": "Действия", "dialog.online_agents.last_seen": "Последняя активность", "dialog.online_agents.title": "Агенты онлайн", @@ -158,11 +174,12 @@ "dialog.team_members.location": "Делится местоположением", "dialog.team_members.wd_keys": "Делится ключами на руках", "dialog.team_message": "Объявление команде: \"{message}\" от {sender}", + "dialog.update_warning": "Wasabee устарело. Пожалуйста, обнови через менеджер плагинов или по ссылке https://wasabee.rocks", "dialog.zone_color.title": "Цвет зоны", "dialog.zone_color.text": "Задать цвет всем линкам в зоне {zoneName}", "dialog.zones.color": "Цвет", "dialog.zones.color_links": "Задать цвет линкам", - "dialog.zones.delete_zone_shape": "Reset the shape", + "dialog.zones.delete_zone_shape": "Сбросить очертание зоны", "dialog.zones.draw_zone_shape": "Нарисовать границы", "dialog.zones.id": "ID", "dialog.zones.stop_drawing": "Закончить рисовать", @@ -198,7 +215,6 @@ "HG": "Гомогенное поле", "HOURS": " ({hours} часов назад)", "HOW_TO_VIDS": "

Обучающие видео:

", - "IMP_COMP": "", "IMP_NOPE": "Ошибка импорта.", "IMP_WAS_OP": "Импортировать ОПРЦ Wasabee", "IMPORT_OP_SUCCESS": "ОПРЦ: {opName} импортирована успешно.", @@ -320,7 +336,6 @@ "PLEASE_SELECT_PORTAL": "Выбери портал", "popup.anchor.keys": "Ключи: {onHand} / {required}", "popup.marker.state_button": "Задать статус", - "PORT_FAKE": "", "PORTAL KEY LIST": "Список ключей для портала {portalName}", "PORTAL_COUNT": "{count} порталов", "PORTAL": "Портал", @@ -367,7 +382,7 @@ "SELECT_ONION_PORTALS": "Слои строятся изнутри наружу. Приблизь масштаб в центр и выбери начальный портал, затем отдали масштаб на всю область.", "SELF SWAP": "Нельзя заменить портал на тот же самый! Выбери другой портал.", "SEND ANALYTICS": "Отправить аналитику анонимно", - "SEND LOCATION": "Отправить местоположение", + "SEND LOCATION": "Share Location (only when IITC is in foreground)", "SEND TARGET AGENT": "Выбрать получателя цели", "SEND TARGET CONFIRM": "Хочешь отправить цель {portalName} агенту {agent}?", "SEND TARGET": "Отправить цель", @@ -456,7 +471,6 @@ "UPLOAD BUTTON HOVER": "ЗАГРУЗИТЬ {opName} на сервер (пока что её там нет)", "UPLOADED": "Успешно загружено на сервер", "USE PANES ON MOBILE": "Использовать панели (нужна перезагрузка)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Используй действительное название операции", "UseVirusPortalAlert": "Использовать вирус", "VRLA DESC": "В зависимости от количества и типа использованных ламп может быть достаточно более низкого уровня портала для линковки.", diff --git a/src/code/translations/Spanish.json b/src/code/translations/Spanish.json index ca044a027..d62b246bd 100644 --- a/src/code/translations/Spanish.json +++ b/src/code/translations/Spanish.json @@ -49,14 +49,14 @@ "autodraw.common.draw_button": "Dibujar", "autodraw.fanfield.result": "Fanfield ha encontrado {links} enlaces y {fields} campos para {ap} AP", "autodraw.flipflop.result": "Flip flop: encontró {count} enlaces", - "autodraw.homogeneous.missing_split": "Unable to find {count} splits, try less depth or a different region", + "autodraw.homogeneous.missing_split": "Imposible encontrar {count} divisiones, prueba menos nivel o una región diferente", "autodraw.homogeneous.order": "Orden", "autodraw.homogeneous.portals_required": "{count} requeridos", "autodraw.madrid.auto_determined": "Auto-determinado", "autodraw.madrid.balanced": "Equilibrado", "autodraw.madrid.result": "Madrid ha encontrado {count} capas", "autodraw.multimax.result": "Multimax ha encontrado {count} capas", - "autodraw.multimax.result_both_side": "Multimax found {count1} and {count2} layers", + "autodraw.multimax.result_both_side": "Multimax encontró {count1} y {count2} capas", "autodraw.onion.variant": "Opción", "autodraw.onion.variant.equilateral": "~Equilátero", "autodraw.onion.variant.grow": "Permitir que crezca", @@ -108,17 +108,17 @@ "dialog.auth.ott.button": "Inicio de sesión con token de un único uso", "dialog.auth.ott.text": "Obtén un token en el Servidor Wasabee y pégalo aquí después", "dialog.auth.ott.title": "Token de un sólo uso", - "dialog.blockers.clear_automark": "Clear Automark", - "dialog.clear_all.text": "Do you want to reset {opName}?", - "dialog.clear_all.title": "Clear: {opName}", - "dialog.clear_links.text": "Do you want to remove all links from {opName}?", - "dialog.clear_links.title": "Clear Links: {opName}", - "dialog.clear_markers.text": "Do you want to remove all markers from {opName}?", - "dialog.clear_markers.title": "Clear Markers: {opName}", - "dialog.checklist.count_fields": "Count fields", - "dialog.checklist.count_fields.no_empty": "Found {fieldCount} fields and no empty field", - "dialog.checklist.count_fields.with_empty": "Found {fieldCount} fields and {emptyCount} empty field(s) on {linkCount} link(s)", - "dialog.checklist.count_fields.link_from_inside": "Found {count} links from covered portals", + "dialog.blockers.clear_automark": "Limpiar Automarcado", + "dialog.clear_all.text": "¿Quieres reiniciar {opName}?", + "dialog.clear_all.title": "Limpiar: {opName}", + "dialog.clear_links.text": "¿Quieres eliminar todos los enlaces de {opName}?", + "dialog.clear_links.title": "Eliminar enlaces: {opName}", + "dialog.clear_markers.text": "¿Quieres eliminar todos los marcadores de {opName}?", + "dialog.clear_markers.title": "Eliminar marcadores: {opName}", + "dialog.checklist.count_fields": "Contar campos", + "dialog.checklist.count_fields.no_empty": "Se encontraron {fieldCount} campos y ningún campo vacío", + "dialog.checklist.count_fields.with_empty": "Se encontraron {fieldCount} campos y {emptyCount} campo(s) vacío(s) con {linkCount} enlace(s)", + "dialog.checklist.count_fields.link_from_inside": "Se han encontrado {count} enlaces desde portales cubiertos", "dialog.checklist.count_fields.link_from_inside.covered_at_order": " at {order} by link ", "dialog.common.commands": "Commands", "dialog.common.commands_short": "Cmds", @@ -135,6 +135,22 @@ "dialog.leave_team.title": "Leave: {teamName}", "dialog.link_list.length": "Longitud", "dialog.link_list.level": "Nivel min.", + "dialog.merge.cancel_upload": "Cancelar subida", + "dialog.merge.conflicts": "Conflictos:", + "dialog.merge.local": "Copia local", + "dialog.merge.server": "Copia del servidor", + "dialog.merge.zone": "Zona: {name}", + "dialog.merge.prop.assignedTo": "Asignar:", + "dialog.merge.prop.comment": "Comentario:", + "dialog.merge.prop.color": "Color:", + "dialog.merge.prop.deltaminutes": "Delta:", + "dialog.merge.prop.fromPortal": "Desde:", + "dialog.merge.prop.hardness": "Dificultad:", + "dialog.merge.prop.order": "Orden:", + "dialog.merge.prop.state": "Estado:", + "dialog.merge.prop.toPortal": "Hasta:", + "dialog.merge.prop.zone": "Zona:", + "dialog.merge.prop.zone_points": "La forma ha cambiado", "dialog.online_agents.actions": "Acciones", "dialog.online_agents.last_seen": "Visto por última vez", "dialog.online_agents.title": "Agentes activos", @@ -158,6 +174,7 @@ "dialog.team_members.location": "Sharing Location", "dialog.team_members.wd_keys": "Sharing W-D Keys", "dialog.team_message": "Team announcement: “{message}” from {sender}", + "dialog.update_warning": "Wasabee está desactualizado. Por favor, actualice usando su gestor de complementos o vaya a https://wasabee.rocks", "dialog.zone_color.title": "Zone Color", "dialog.zone_color.text": "Set the color of all links in zone {zoneName}", "dialog.zones.color": "Color", @@ -198,7 +215,6 @@ "HG": "Campo homogéneo", "HOURS": "(Hace {hours} horas)", "HOW_TO_VIDS": "

Videos de Cómo Se Hace:

", - "IMP_COMP": "", "IMP_NOPE": "Importación Falló: {error}", "IMP_WAS_OP": "Importar Operación Wasabee", "IMPORT_OP_SUCCESS": "Operación {opName} Importada Exitosamente.", @@ -320,7 +336,6 @@ "PLEASE_SELECT_PORTAL": "Por favor, seleccionar un portal", "popup.anchor.keys": "Keys: {onHand} / {required}", "popup.marker.state_button": "Set State", - "PORT_FAKE": "", "PORTAL KEY LIST": "Lista de Llaves del Portal {portalName}", "PORTAL_COUNT": "{count} portales", "PORTAL": "Portal", @@ -367,7 +382,7 @@ "SELECT_ONION_PORTALS": "Las capas se hacen de dentro hacia afuera. Acércate al centro y selecciona el portal de inicio. Luego aléjate para ver un área mayor.", "SELF SWAP": "¡No se puede intercambiar un portal consigo mismo! Selecciona un portal diferente.", "SEND ANALYTICS": "Enviar analíticas anónimas", - "SEND LOCATION": "Enviar Ubicación", + "SEND LOCATION": "Share Location (only when IITC is in foreground)", "SEND TARGET AGENT": "Selecciona un destinatario", "SEND TARGET CONFIRM": "¿Quieres enviar el {portalName} objetivo a {agent}?", "SEND TARGET": "Enviar Objetivo", @@ -386,8 +401,8 @@ "SET_PORT_COMMENT": "Definir comentario para el portal", "SET_PORTAL_COMMENT": "Definir comentarios del portal", "SET": "definir", - "SETTINGS_TOOLBOX": "Wasabee Settings", - "SETTINGS_TITLE": "Advanced Settings", + "SETTINGS_TOOLBOX": "Ajustes de Wasabee", + "SETTINGS_TITLE": "Ajustes avanzados", "SKINS_AVAILABLE": "Hay {count} skins disponibles.", "SKINS_BUTTON": "Configurar skins", "SKINS_DESCRIPTION": "Available skin packs are located in the right columns. Move skins you wish to use to the left columns.", @@ -456,7 +471,6 @@ "UPLOAD BUTTON HOVER": "CARGAR {opName} (no se encuentra actualmente en el servidor)", "UPLOADED": "Cargado exitosamente", "USE PANES ON MOBILE": "Usar paneles (es necesario recargar)", - "USE_SWAP_INSTRUCT": "", "USE_VALID_NAME": "Por favor, utiliza un nombre de operación válido", "UseVirusPortalAlert": "Usar Virus", "VRLA DESC": "Dependiendo del número y tipo de Link Amps usados, un portal de origen de menor nivel puede ser suficiente.", From 43e01380fbcc0129fccd4eceafcd7bb607a590b9 Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 18 Mar 2022 22:29:52 +0100 Subject: [PATCH 274/275] update npm packages --- package-lock.json | 1686 +++++++++++++-------------------------------- package.json | 54 +- 2 files changed, 519 insertions(+), 1221 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2eea41a13..27a8aa9db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,244 +1,123 @@ { "name": "wasabee-iitc", - "version": "0.20.2", + "version": "0.20.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wasabee-iitc", - "version": "0.20.2", + "version": "0.20.3", "license": "ISC", "dependencies": { - "@fortawesome/fontawesome-svg-core": "^1.2.36", - "@fortawesome/free-solid-svg-icons": "^5.15.4", - "arc": "^0.1.1", - "color-string": "^1.5.5", - "geodesy": "^2.2.1", - "idb": "^6.1.2", - "sortablejs": "^1.12.0" + "@fortawesome/fontawesome-svg-core": "^6.1.0", + "@fortawesome/free-solid-svg-icons": "^6.1.0", + "arc": "^0.1.2", + "color-string": "^1.9.0", + "geodesy": "^2.3.0", + "idb": "^7.0.1", + "sortablejs": "^1.14.0" }, "devDependencies": { - "@types/color-string": "^1.5.0", - "@types/jquery": "^3.5.8", + "@types/color-string": "^1.5.2", + "@types/jquery": "^3.5.14", "@types/jqueryui": "^1.12.16", - "@types/leaflet": "^1.7.5", + "@types/leaflet": "^1.7.9", "@types/spectrum": "^1.8.2", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", - "css-loader": "^5.2.6", + "@typescript-eslint/eslint-plugin": "^5.15.0", + "@typescript-eslint/parser": "^5.15.0", + "css-loader": "^6.7.1", "del": "^6.0.0", - "eslint": "^7.32.0", - "eslint-config-prettier": "^8.3.0", + "eslint": "^8.11.0", + "eslint-config-prettier": "^8.5.0", "eslint-plugin-local-rules": "^1.1.0", - "eslint-plugin-prettier": "^3.4.0", - "eslint-webpack-plugin": "^3.0.1", - "fancy-log": "^1.3.3", - "html-loader": "^2.1.2", + "eslint-plugin-prettier": "^4.0.0", + "eslint-webpack-plugin": "^3.1.1", + "fancy-log": "^2.0.0", + "html-loader": "^3.1.0", "lodash": "^4.17.21", - "prettier": "^2.3.1", - "pretty-quick": "^3.1.0", + "prettier": "^2.6.0", + "pretty-quick": "^3.1.3", "raw-loader": "^4.0.2", - "style-loader": "^2.0.0", + "style-loader": "^3.3.1", "through2": "^4.0.2", - "to-string-loader": "^1.1.6", - "ts-loader": "^9.2.6", + "to-string-loader": "^1.2.0", + "ts-loader": "^9.2.8", "tslib": "^2.3.1", - "typescript": "^4.4.4", + "typescript": "^4.6.2", "url-loader": "^4.1.1", - "webpack": "^5.38.1", - "webpack-cli": "^4.8.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" + "webpack": "^5.70.0", + "webpack-cli": "^4.9.2" } }, "node_modules/@discoveryjs/json-ext": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", - "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, "engines": { "node": ">=10.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", + "debug": "^4.3.2", + "espree": "^9.3.1", "globals": "^13.9.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", - "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.0.tgz", + "integrity": "sha512-lFIJ5opxOKG9q88xOsuJJAdRZ+2WRldsZwUR/7MJoOMUMhF/LkHUjwWACIEPTa5Wo6uTDHvGRIX+XutdN7zYxA==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", - "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.0.tgz", + "integrity": "sha512-racj+/EDnMZN0jcuHePOa+9kdHHOCpCAbBvVRnEi4G4DA5SWQiT/uXJ8WcfVEbLN51vPJjhukP4o+zH0cfYplg==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "6.1.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "5.15.4", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", - "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.0.tgz", + "integrity": "sha512-OOr0jRHl5d41RzBS3sZh5Z3HmdPjMr43PxxKlYeLtQxFSixPf4sJFVM12/rTepB2m0rVShI0vtjHQmzOTlBaXg==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.36" + "@fortawesome/fontawesome-common-types": "6.1.0" }, "engines": { "node": ">=6" } }, - "node_modules/@fortawesome/free-solid-svg-icons/node_modules/@fortawesome/fontawesome-common-types": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", - "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", - "hasInstallScript": true, - "engines": { - "node": ">=6" - } - }, "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", + "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.4" }, @@ -344,9 +223,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.10.tgz", + "integrity": "sha512-BLO9bBq59vW3fxCpD4o0N4U+DXsvwvIcl+jofw0frQo/GrBFC+/jRZj1E7kgp6dvTyNmA4y6JCV5Id/r3mNP5A==", "dev": true }, "node_modules/@types/leaflet": { @@ -393,14 +272,14 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz", - "integrity": "sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", + "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.13.0", - "@typescript-eslint/type-utils": "5.13.0", - "@typescript-eslint/utils": "5.13.0", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/type-utils": "5.15.0", + "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -426,14 +305,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.13.0.tgz", - "integrity": "sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", + "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.13.0", - "@typescript-eslint/types": "5.13.0", - "@typescript-eslint/typescript-estree": "5.13.0", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/typescript-estree": "5.15.0", "debug": "^4.3.2" }, "engines": { @@ -453,13 +332,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz", - "integrity": "sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", + "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.13.0", - "@typescript-eslint/visitor-keys": "5.13.0" + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/visitor-keys": "5.15.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -470,12 +349,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz", - "integrity": "sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", + "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.13.0", + "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "tsutils": "^3.21.0" }, @@ -496,9 +375,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.13.0.tgz", - "integrity": "sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", + "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -509,13 +388,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz", - "integrity": "sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", + "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.13.0", - "@typescript-eslint/visitor-keys": "5.13.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/visitor-keys": "5.15.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -536,15 +415,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.13.0.tgz", - "integrity": "sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", + "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.13.0", - "@typescript-eslint/types": "5.13.0", - "@typescript-eslint/typescript-estree": "5.13.0", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/typescript-estree": "5.15.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -560,12 +439,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz", - "integrity": "sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", + "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/types": "5.15.0", "eslint-visitor-keys": "^3.0.0" }, "engines": { @@ -771,9 +650,9 @@ "dev": true }, "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -782,6 +661,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -829,27 +717,6 @@ "ajv": "^6.9.1" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -874,15 +741,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/arc": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/arc/-/arc-0.1.2.tgz", @@ -892,13 +750,10 @@ } }, "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-differ": { "version": "3.0.0", @@ -927,15 +782,6 @@ "node": ">=8" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -974,13 +820,23 @@ } }, "node_modules/browserslist": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", - "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", + "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], "dependencies": { - "caniuse-lite": "^1.0.30001312", - "electron-to-chromium": "^1.4.71", + "caniuse-lite": "^1.0.30001317", + "electron-to-chromium": "^1.4.84", "escalade": "^3.1.1", "node-releases": "^2.0.2", "picocolors": "^1.0.0" @@ -990,10 +846,6 @@ }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" } }, "node_modules/buffer-from": { @@ -1022,9 +874,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001313", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001313.tgz", - "integrity": "sha512-rI1UN0koZUiKINjysQDuRi2VeSCce3bYJNmDcj3PIKREiAmjakugBul1QSkg/fPrlULYl6oWfGg3PbgOSY9X4Q==", + "version": "1.0.30001317", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz", + "integrity": "sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==", "dev": true, "funding": { "type": "opencollective", @@ -1057,15 +909,15 @@ } }, "node_modules/clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", + "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", "dev": true, "dependencies": { "source-map": "~0.6.0" }, "engines": { - "node": ">= 4.0" + "node": ">= 10.0" } }, "node_modules/clean-stack": { @@ -1133,12 +985,12 @@ "dev": true }, "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, "engines": { - "node": ">= 6" + "node": ">= 12" } }, "node_modules/concat-map": { @@ -1162,31 +1014,29 @@ } }, "node_modules/css-loader": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", - "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.15", + "postcss": "^8.4.7", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.0", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^3.0.0", + "postcss-value-parser": "^4.2.0", "semver": "^7.3.5" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.27.0 || ^5.0.0" + "webpack": "^5.0.0" } }, "node_modules/cssesc": { @@ -1202,9 +1052,9 @@ } }, "node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -1281,15 +1131,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.76", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.76.tgz", - "integrity": "sha512-3Vftv7cenJtQb+k00McEBZ2vVmZ/x+HEF7pcZONZIkOsESqAqVuACmBxMv0JhzX7u0YltU0vSqRqgBSTAhFUjA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "1.4.88", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.88.tgz", + "integrity": "sha512-oA7mzccefkvTNi9u7DXmT0LqvhnOiN2BhSrKerta7HeUC1cLoIwtbf2wL+Ah2ozh5KQd3/1njrGrwDBXx6d14Q==", "dev": true }, "node_modules/emojis-list": { @@ -1323,18 +1167,6 @@ "node": ">=10.13.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -1375,49 +1207,44 @@ } }, "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", + "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", "dev": true, "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", + "@eslint/eslintrc": "^1.2.1", + "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", - "debug": "^4.0.1", + "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", + "glob-parent": "^6.0.1", "globals": "^13.6.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, @@ -1425,7 +1252,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1450,9 +1277,9 @@ "dev": true }, "node_modules/eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", + "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0" @@ -1461,8 +1288,8 @@ "node": ">=6.0.0" }, "peerDependencies": { - "eslint": ">=5.0.0", - "prettier": ">=1.13.0" + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" }, "peerDependenciesMeta": { "eslint-config-prettier": { @@ -1543,82 +1370,40 @@ "webpack": "^5.0.0" } }, - "node_modules/eslint/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { - "node": ">= 4" + "node": ">=4.0" } }, "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, "dependencies": { - "acorn": "^7.4.0", + "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/esquery": { @@ -1714,18 +1499,15 @@ } }, "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-2.0.0.tgz", + "integrity": "sha512-9CzxZbACXMUXW13tS0tI8XsGGmxWzO2DmYrGuBJOJ8k8q2K7hwfJA5qHjuPPe8wtsco33YR9wc+Rlr5wYFvhSA==", "dev": true, "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" + "color-support": "^1.1.3" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, "node_modules/fast-deep-equal": { @@ -1756,6 +1538,18 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1901,15 +1695,15 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, "node_modules/glob-to-regexp": { @@ -1919,9 +1713,9 @@ "dev": true }, "node_modules/globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1990,16 +1784,16 @@ } }, "node_modules/html-loader": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-2.1.2.tgz", - "integrity": "sha512-XB4O1+6mpLp4qy/3qg5+1QPZ/uXvWtO64hNAX87sKHwcHkp1LJGU7V3sJ9iVmRACElAZXQ4YOO/Lbkx5kYfl9A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-3.1.0.tgz", + "integrity": "sha512-ycMYFRiCF7YANcLDNP72kh3Po5pTcH+bROzdDwh00iVOAY/BwvpuZ1BKPziQ35Dk9D+UD84VGX1Lu/H4HpO4fw==", "dev": true, "dependencies": { - "html-minifier-terser": "^5.1.1", + "html-minifier-terser": "^6.0.2", "parse5": "^6.0.1" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", @@ -2010,24 +1804,24 @@ } }, "node_modules/html-minifier-terser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", - "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", "dev": true, "dependencies": { - "camel-case": "^4.1.1", - "clean-css": "^4.2.3", - "commander": "^4.1.1", + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", "he": "^1.2.0", - "param-case": "^3.0.3", + "param-case": "^3.0.4", "relateurl": "^0.2.7", - "terser": "^4.6.3" + "terser": "^5.10.0" }, "bin": { "html-minifier-terser": "cli.js" }, "engines": { - "node": ">=6" + "node": ">=12" } }, "node_modules/human-signals": { @@ -2052,9 +1846,9 @@ } }, "node_modules/idb": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", + "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==" }, "node_modules/ignore": { "version": "5.2.0", @@ -2169,15 +1963,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2285,20 +2070,13 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -2406,12 +2184,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -2462,21 +2234,21 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -2715,15 +2487,6 @@ "node": ">=6" } }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -2813,10 +2576,20 @@ } }, "node_modules/postcss": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz", - "integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==", + "version": "8.4.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", + "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], "dependencies": { "nanoid": "^3.3.1", "picocolors": "^1.0.0", @@ -2824,10 +2597,6 @@ }, "engines": { "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" } }, "node_modules/postcss-modules-extract-imports": { @@ -2918,15 +2687,18 @@ } }, "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/prettier-linter-helpers": { @@ -2977,15 +2749,6 @@ "node": ">=8" } }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -3101,15 +2864,6 @@ "node": ">= 0.10" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -3323,23 +3077,6 @@ "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/sortablejs": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", @@ -3373,12 +3110,6 @@ "source-map": "^0.6.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3388,20 +3119,6 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3436,23 +3153,19 @@ } }, "node_modules/style-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", - "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, "engines": { - "node": ">= 10.13.0" + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "webpack": "^5.0.0" } }, "node_modules/supports-color": { @@ -3479,44 +3192,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -3527,20 +3202,21 @@ } }, "node_modules/terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", + "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", "dev": true, "dependencies": { + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" } }, "node_modules/terser-webpack-plugin": { @@ -3577,43 +3253,13 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/commander": { + "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.0.tgz", - "integrity": "sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A==", - "dev": true, - "dependencies": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin/node_modules/terser/node_modules/source-map": { + "node_modules/terser/node_modules/source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", @@ -3622,12 +3268,6 @@ "node": ">= 8" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3643,15 +3283,6 @@ "readable-stream": "3" } }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3700,9 +3331,9 @@ } }, "node_modules/ts-loader": { - "version": "9.2.7", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.7.tgz", - "integrity": "sha512-Fxh44mKli9QezgbdCXkEJWxnedQ0ead7DXTH+lfXEPedu+Y9EtMJ2aQ9G3Dj1j7Q612E8931rww8NDZha4Tibg==", + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", + "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", "dev": true, "dependencies": { "chalk": "^4.1.0", @@ -4008,27 +3639,6 @@ "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/webpack/node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4073,156 +3683,57 @@ } }, "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "@discoveryjs/json-ext": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", - "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, "requires": { "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", + "debug": "^4.3.2", + "espree": "^9.3.1", "globals": "^13.9.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - } } }, "@fortawesome/fontawesome-common-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", - "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.0.tgz", + "integrity": "sha512-lFIJ5opxOKG9q88xOsuJJAdRZ+2WRldsZwUR/7MJoOMUMhF/LkHUjwWACIEPTa5Wo6uTDHvGRIX+XutdN7zYxA==" }, "@fortawesome/fontawesome-svg-core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", - "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.0.tgz", + "integrity": "sha512-racj+/EDnMZN0jcuHePOa+9kdHHOCpCAbBvVRnEi4G4DA5SWQiT/uXJ8WcfVEbLN51vPJjhukP4o+zH0cfYplg==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "6.1.0" } }, "@fortawesome/free-solid-svg-icons": { - "version": "5.15.4", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", - "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.0.tgz", + "integrity": "sha512-OOr0jRHl5d41RzBS3sZh5Z3HmdPjMr43PxxKlYeLtQxFSixPf4sJFVM12/rTepB2m0rVShI0vtjHQmzOTlBaXg==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.2.36" - }, - "dependencies": { - "@fortawesome/fontawesome-common-types": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", - "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==" - } + "@fortawesome/fontawesome-common-types": "6.1.0" } }, "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.0", + "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.4" } @@ -4316,9 +3827,9 @@ } }, "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.10.tgz", + "integrity": "sha512-BLO9bBq59vW3fxCpD4o0N4U+DXsvwvIcl+jofw0frQo/GrBFC+/jRZj1E7kgp6dvTyNmA4y6JCV5Id/r3mNP5A==", "dev": true }, "@types/leaflet": { @@ -4365,14 +3876,14 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz", - "integrity": "sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", + "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.13.0", - "@typescript-eslint/type-utils": "5.13.0", - "@typescript-eslint/utils": "5.13.0", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/type-utils": "5.15.0", + "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -4382,52 +3893,52 @@ } }, "@typescript-eslint/parser": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.13.0.tgz", - "integrity": "sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", + "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.13.0", - "@typescript-eslint/types": "5.13.0", - "@typescript-eslint/typescript-estree": "5.13.0", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/typescript-estree": "5.15.0", "debug": "^4.3.2" } }, "@typescript-eslint/scope-manager": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz", - "integrity": "sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", + "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.13.0", - "@typescript-eslint/visitor-keys": "5.13.0" + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/visitor-keys": "5.15.0" } }, "@typescript-eslint/type-utils": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz", - "integrity": "sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", + "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.13.0", + "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.13.0.tgz", - "integrity": "sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", + "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz", - "integrity": "sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", + "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.13.0", - "@typescript-eslint/visitor-keys": "5.13.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/visitor-keys": "5.15.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -4436,26 +3947,26 @@ } }, "@typescript-eslint/utils": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.13.0.tgz", - "integrity": "sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", + "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.13.0", - "@typescript-eslint/types": "5.13.0", - "@typescript-eslint/typescript-estree": "5.13.0", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/typescript-estree": "5.15.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/visitor-keys": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz", - "integrity": "sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", + "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.13.0", + "@typescript-eslint/types": "5.15.0", "eslint-visitor-keys": "^3.0.0" } }, @@ -4641,11 +4152,18 @@ "dev": true }, "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "requires": {} + }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -4682,21 +4200,6 @@ "dev": true, "requires": {} }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4712,25 +4215,16 @@ "color-convert": "^2.0.1" } }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, "arc": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/arc/-/arc-0.1.2.tgz", "integrity": "sha512-bGCkKR675zaomc6HP3dR6hc6HXXnpXrehMkayof2Ql5dZ3f2Bd8o+KfdAruSCcW471K7WFn2pDvSLG8Q0co0dw==" }, "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "array-differ": { "version": "3.0.0", @@ -4750,12 +4244,6 @@ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -4788,13 +4276,13 @@ } }, "browserslist": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", - "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", + "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001312", - "electron-to-chromium": "^1.4.71", + "caniuse-lite": "^1.0.30001317", + "electron-to-chromium": "^1.4.84", "escalade": "^3.1.1", "node-releases": "^2.0.2", "picocolors": "^1.0.0" @@ -4823,9 +4311,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001313", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001313.tgz", - "integrity": "sha512-rI1UN0koZUiKINjysQDuRi2VeSCce3bYJNmDcj3PIKREiAmjakugBul1QSkg/fPrlULYl6oWfGg3PbgOSY9X4Q==", + "version": "1.0.30001317", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz", + "integrity": "sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==", "dev": true }, "chalk": { @@ -4845,9 +4333,9 @@ "dev": true }, "clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", + "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", "dev": true, "requires": { "source-map": "~0.6.0" @@ -4906,9 +4394,9 @@ "dev": true }, "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true }, "concat-map": { @@ -4929,20 +4417,18 @@ } }, "css-loader": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", - "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", "dev": true, "requires": { "icss-utils": "^5.1.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.15", + "postcss": "^8.4.7", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.0", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^3.0.0", + "postcss-value-parser": "^4.2.0", "semver": "^7.3.5" } }, @@ -4953,9 +4439,9 @@ "dev": true }, "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -5012,15 +4498,9 @@ } }, "electron-to-chromium": { - "version": "1.4.76", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.76.tgz", - "integrity": "sha512-3Vftv7cenJtQb+k00McEBZ2vVmZ/x+HEF7pcZONZIkOsESqAqVuACmBxMv0JhzX7u0YltU0vSqRqgBSTAhFUjA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "1.4.88", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.88.tgz", + "integrity": "sha512-oA7mzccefkvTNi9u7DXmT0LqvhnOiN2BhSrKerta7HeUC1cLoIwtbf2wL+Ah2ozh5KQd3/1njrGrwDBXx6d14Q==", "dev": true }, "emojis-list": { @@ -5048,15 +4528,6 @@ "tapable": "^2.2.0" } }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, "envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -5082,80 +4553,62 @@ "dev": true }, "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", + "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", "dev": true, "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", + "@eslint/eslintrc": "^1.2.1", + "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", - "debug": "^4.0.1", + "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", + "glob-parent": "^6.0.1", "globals": "^13.6.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" } }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -5174,9 +4627,9 @@ "dev": true }, "eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", + "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" @@ -5229,30 +4682,16 @@ } }, "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, "requires": { - "acorn": "^7.4.0", + "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } + "eslint-visitor-keys": "^3.3.0" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, "esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -5323,15 +4762,12 @@ } }, "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-2.0.0.tgz", + "integrity": "sha512-9CzxZbACXMUXW13tS0tI8XsGGmxWzO2DmYrGuBJOJ8k8q2K7hwfJA5qHjuPPe8wtsco33YR9wc+Rlr5wYFvhSA==", "dev": true, "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" + "color-support": "^1.1.3" } }, "fast-deep-equal": { @@ -5357,6 +4793,17 @@ "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } } }, "fast-json-stable-stringify": { @@ -5477,12 +4924,12 @@ } }, "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" } }, "glob-to-regexp": { @@ -5492,9 +4939,9 @@ "dev": true }, "globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -5542,28 +4989,28 @@ "dev": true }, "html-loader": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-2.1.2.tgz", - "integrity": "sha512-XB4O1+6mpLp4qy/3qg5+1QPZ/uXvWtO64hNAX87sKHwcHkp1LJGU7V3sJ9iVmRACElAZXQ4YOO/Lbkx5kYfl9A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-3.1.0.tgz", + "integrity": "sha512-ycMYFRiCF7YANcLDNP72kh3Po5pTcH+bROzdDwh00iVOAY/BwvpuZ1BKPziQ35Dk9D+UD84VGX1Lu/H4HpO4fw==", "dev": true, "requires": { - "html-minifier-terser": "^5.1.1", + "html-minifier-terser": "^6.0.2", "parse5": "^6.0.1" } }, "html-minifier-terser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", - "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", "dev": true, "requires": { - "camel-case": "^4.1.1", - "clean-css": "^4.2.3", - "commander": "^4.1.1", + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", "he": "^1.2.0", - "param-case": "^3.0.3", + "param-case": "^3.0.4", "relateurl": "^0.2.7", - "terser": "^4.6.3" + "terser": "^5.10.0" } }, "human-signals": { @@ -5580,9 +5027,9 @@ "requires": {} }, "idb": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", + "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==" }, "ignore": { "version": "5.2.0", @@ -5664,12 +5111,6 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -5746,20 +5187,13 @@ } } }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" } }, "json-parse-better-errors": { @@ -5843,12 +5277,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, "lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -5890,18 +5318,18 @@ } }, "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true }, "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "requires": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" } }, "mimic-fn": { @@ -6083,12 +5511,6 @@ "callsites": "^3.0.0" } }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -6157,9 +5579,9 @@ } }, "postcss": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz", - "integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==", + "version": "8.4.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", + "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", "dev": true, "requires": { "nanoid": "^3.3.1", @@ -6226,9 +5648,9 @@ "dev": true }, "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==", "dev": true }, "prettier-linter-helpers": { @@ -6266,12 +5688,6 @@ } } }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -6345,12 +5761,6 @@ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", "dev": true }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -6488,17 +5898,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, "sortablejs": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", @@ -6526,12 +5925,6 @@ "source-map": "^0.6.0" } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -6541,17 +5934,6 @@ "safe-buffer": "~5.2.0" } }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -6574,14 +5956,11 @@ "dev": true }, "style-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", - "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - } + "requires": {} }, "supports-color": { "version": "7.2.0", @@ -6598,39 +5977,6 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, - "table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, "tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -6638,14 +5984,15 @@ "dev": true }, "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", + "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", "dev": true, "requires": { + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" }, "dependencies": { "commander": { @@ -6653,6 +6000,12 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true } } }, @@ -6667,40 +6020,6 @@ "serialize-javascript": "^6.0.0", "source-map": "^0.6.1", "terser": "^5.7.2" - }, - "dependencies": { - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "terser": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.0.tgz", - "integrity": "sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A==", - "dev": true, - "requires": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - } } }, "text-table": { @@ -6718,12 +6037,6 @@ "readable-stream": "3" } }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6765,9 +6078,9 @@ } }, "ts-loader": { - "version": "9.2.7", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.7.tgz", - "integrity": "sha512-Fxh44mKli9QezgbdCXkEJWxnedQ0ead7DXTH+lfXEPedu+Y9EtMJ2aQ9G3Dj1j7Q612E8931rww8NDZha4Tibg==", + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", + "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", "dev": true, "requires": { "chalk": "^4.1.0", @@ -6892,21 +6205,6 @@ "terser-webpack-plugin": "^5.1.3", "watchpack": "^2.3.1", "webpack-sources": "^3.2.3" - }, - "dependencies": { - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - } } }, "webpack-cli": { diff --git a/package.json b/package.json index de2b6833f..903ed6c17 100644 --- a/package.json +++ b/package.json @@ -5,35 +5,35 @@ "main": "gulpfile.js", "private": true, "devDependencies": { - "@types/color-string": "^1.5.0", - "@types/jquery": "^3.5.8", + "@types/color-string": "^1.5.2", + "@types/jquery": "^3.5.14", "@types/jqueryui": "^1.12.16", - "@types/leaflet": "^1.7.5", + "@types/leaflet": "^1.7.9", "@types/spectrum": "^1.8.2", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", - "css-loader": "^5.2.6", + "@typescript-eslint/eslint-plugin": "^5.15.0", + "@typescript-eslint/parser": "^5.15.0", + "css-loader": "^6.7.1", "del": "^6.0.0", - "eslint": "^7.32.0", - "eslint-config-prettier": "^8.3.0", + "eslint": "^8.11.0", + "eslint-config-prettier": "^8.5.0", "eslint-plugin-local-rules": "^1.1.0", - "eslint-plugin-prettier": "^3.4.0", - "eslint-webpack-plugin": "^3.0.1", - "fancy-log": "^1.3.3", - "html-loader": "^2.1.2", + "eslint-plugin-prettier": "^4.0.0", + "eslint-webpack-plugin": "^3.1.1", + "fancy-log": "^2.0.0", + "html-loader": "^3.1.0", "lodash": "^4.17.21", - "prettier": "^2.3.1", - "pretty-quick": "^3.1.0", + "prettier": "^2.6.0", + "pretty-quick": "^3.1.3", "raw-loader": "^4.0.2", - "style-loader": "^2.0.0", + "style-loader": "^3.3.1", "through2": "^4.0.2", - "to-string-loader": "^1.1.6", - "ts-loader": "^9.2.6", + "to-string-loader": "^1.2.0", + "ts-loader": "^9.2.8", "tslib": "^2.3.1", - "typescript": "^4.4.4", + "typescript": "^4.6.2", "url-loader": "^4.1.1", - "webpack": "^5.38.1", - "webpack-cli": "^4.8.0" + "webpack": "^5.70.0", + "webpack-cli": "^4.9.2" }, "scripts": { "build": "webpack --progress --env build=prod", @@ -57,13 +57,13 @@ }, "homepage": "https://github.com/wasabee-project/Wasabee-IITC/blob/master/README.md", "dependencies": { - "@fortawesome/fontawesome-svg-core": "^1.2.36", - "@fortawesome/free-solid-svg-icons": "^5.15.4", - "arc": "^0.1.1", - "color-string": "^1.5.5", - "geodesy": "^2.2.1", - "idb": "^6.1.2", - "sortablejs": "^1.12.0" + "@fortawesome/fontawesome-svg-core": "^6.1.0", + "@fortawesome/free-solid-svg-icons": "^6.1.0", + "arc": "^0.1.2", + "color-string": "^1.9.0", + "geodesy": "^2.3.0", + "idb": "^7.0.1", + "sortablejs": "^1.14.0" }, "typings": "src/code/index.d.ts" } From 9e621d589aec378ef14a39feb765b63072df802e Mon Sep 17 00:00:00 2001 From: LeJeu <64744459+le-jeu@users.noreply.github.com> Date: Fri, 18 Mar 2022 22:51:08 +0100 Subject: [PATCH 275/275] bump 0.21 --- package-lock.json | 4 ++-- package.json | 2 +- plugin.config.json | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 27a8aa9db..955f589ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wasabee-iitc", - "version": "0.20.3", + "version": "0.21.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wasabee-iitc", - "version": "0.20.3", + "version": "0.21.1", "license": "ISC", "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.1.0", diff --git a/package.json b/package.json index 903ed6c17..52928c7e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wasabee-iitc", - "version": "0.20.3", + "version": "0.21.1", "description": "IITC Plugin for Wasabee Project", "main": "gulpfile.js", "private": true, diff --git a/plugin.config.json b/plugin.config.json index 6d1c9c8bd..1ee9425e3 100644 --- a/plugin.config.json +++ b/plugin.config.json @@ -3,25 +3,25 @@ "prod": { "downloadURL": "https://cdn2.wasabee.rocks/iitcplugin/prod/wasabee.user.js", "updateURL": "https://cdn2.wasabee.rocks/iitcplugin/prod/wasabee.meta.js", - "version": "0.20.BUILDDATE" + "version": "0.21.BUILDDATE" }, "dev": { "downloadURL": "https://cdn2.wasabee.rocks/iitcplugin/latest/dev/wasabee.user.js", "updateURL": "https://cdn2.wasabee.rocks/iitcplugin/latest/dev/wasabee.meta.js", - "version": "0.20.BUILDDATE-dev" + "version": "0.21.BUILDDATE-dev" }, "testing": { "downloadURL": "https://wasabee-project.github.io/Wasabee-IITC/testing/wasabee.user.js", "updateURL": "https://wasabee-project.github.io/Wasabee-IITC/testing/wasabee.meta.js", - "version": "0.20.BUILDDATE-testing" + "version": "0.21.BUILDDATE-testing" }, "pr": { - "version": "0.20-pr" + "version": "0.21-pr" }, "scot": { "downloadURL": "https://am.wasabee.rocks/static/dev/wasabee.user.js", "updateURL": "https://am.wasabee.rocks/static/dev/wasabee.meta.js", - "version": "0.20.BUILDDATE-scot" + "version": "0.21.BUILDDATE-scot" }, "common": { "id": "Wasabee.user.js",