From cbc3d5191177658578c130779dc63cd7910c6d66 Mon Sep 17 00:00:00 2001 From: yukamend Date: Wed, 27 Jul 2022 11:47:02 +0200 Subject: [PATCH 001/537] add Table.tsx and Tabs.tsx --- src/components/dao/dao.js | 182 ++++++------- src/components/dao/dao.scss | 357 +++++++++++++------------- src/func-components/Table/index.tsx | 382 ++++++++++++++++++++++++++++ src/func-components/Tabs/index.tsx | 85 +++++++ src/hooks/useBreakpoint.ts | 9 + tsconfig.json | 1 + 6 files changed, 753 insertions(+), 263 deletions(-) create mode 100644 src/func-components/Table/index.tsx create mode 100644 src/func-components/Tabs/index.tsx create mode 100644 src/hooks/useBreakpoint.ts diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index e438319c..e5fb04fe 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -10,10 +10,14 @@ import { TextInput } from '../editor/elements'; import { InputAdornment } from '@mui/material' import './dao.scss'; import debounce from 'lodash.debounce'; +import Table from '../../func-components/Table'; +import Tabs from '../../func-components/Tabs'; // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR +const TableHeader = ['Token', '', 'Ref', 'Near', 'Total'] + export default class DaoComponent extends Component { static contextType = useWalletSelector(); @@ -50,10 +54,10 @@ export default class DaoComponent extends Component { "get_fee", {} ) - .then(createMulticallFee => { - this.fee = createMulticallFee; - this.loadInfos() - }); + .then(createMulticallFee => { + this.fee = createMulticallFee; + this.loadInfos() + }); document.addEventListener('onaddressesupdated', (e) => this.onAddressesUpdated(e)) @@ -71,9 +75,9 @@ export default class DaoComponent extends Component { * * @returns {object} ID and info of proposal to create multicall instance, */ - proposalAlreadyExists (dao) { + proposalAlreadyExists(dao) { // Date.now() returns timestamp in milliseconds, SputnikDAO uses nanoseconds - const currentTime = Big( Date.now() ).times("1000000"); + const currentTime = Big(Date.now()).times("1000000"); const lastProposalId = dao.lastProposalId; const proposalPeriod = dao.policy.proposal_period; @@ -85,9 +89,9 @@ export default class DaoComponent extends Component { const proposals = res.filter(p => { // discard if not active proposal to create multicall instance if ( - ! (p.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) - || ! (p.kind?.FunctionCall?.actions?.[0]?.method_name === "create") - || ! (p.status === 'InProgress') + !(p.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) + || !(p.kind?.FunctionCall?.actions?.[0]?.method_name === "create") + || !(p.status === 'InProgress') ) { return false; } @@ -104,8 +108,8 @@ export default class DaoComponent extends Component { } // No "Create multicall" proposals found. else return { proposal_id: -1, proposal_info: {} }; - - }).catch(e => {}) + + }).catch(e => { }) } @@ -183,7 +187,7 @@ export default class DaoComponent extends Component { }; if ( - noContract.isBad + noContract.isBad && !noDao.isBad // base.sputnik-dao.near does not exist && !loading && this.lastAddr === document.querySelector(".address-container input")._valueTracker.getValue() // disappear while debouncing @@ -191,18 +195,18 @@ export default class DaoComponent extends Component { // no create multicall proposal exists if (proposed === -1) { // ... and user can propose FunctionCall - if ( canPropose ) { + if (canPropose) { return ( <>
{/* hint: you can use "genesis" or "test" as DAO to get to this message */} - {`A multicall instance can only be created for `} - - { dao.address } + {`A multicall instance can only be created for `} + + {dao.address} {` by making a proposal.`}
- ) - } + } // ... and user cannot propose FunctionCall else { return ( @@ -224,11 +228,11 @@ export default class DaoComponent extends Component { // create multicall proposal exists else if (proposed !== -1) { // user does not have rights to VoteApprove - if ( !canApprove ) { + if (!canApprove) { return (
{`Proposal to create a multicall exists (#${proposed}), but you have no voting permissions on this DAO.`} -
+
Proposal on Astro @@ -236,11 +240,11 @@ export default class DaoComponent extends Component { ) } // user can VoteApprove and already voted - else if ( proposedInfo.votes[accountId] ) { + else if (proposedInfo.votes[accountId]) { return (
{`You have voted on creating a multicall instance for this DAO. It will be created as soon as the proposal passes voting.`} -
+
Proposal on Astro @@ -253,12 +257,12 @@ export default class DaoComponent extends Component { <>
{/* hint: you can use "genesis" or "test" as DAO to get to this message */} - {`There exists a proposal (#${proposed}) to create a multicall instance for this DAO. `} - + {`There exists a proposal (#${proposed}) to create a multicall instance for this DAO. `} + Open on AstroDAO
-
- -

Tokens

-
    - {infos.tokens.map(t =>
  • {this.toLink(t)}
  • )} -
-
+ +

Tokens

+ + , + + <>

Tokens

+
    + {infos.tokens.map(t =>
  • {this.toLink(t)}
  • )} +
+ + ] + } /> +

Jobs

@@ -450,7 +462,7 @@ export default class DaoComponent extends Component { {`${infos.bond !== "..." ? toNEAR(infos.bond) : "..."} Ⓝ`}
- + } diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 244960c4..e1323bc4 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -1,194 +1,195 @@ -@use 'sass/mixin'; -@use 'sass/size'; -@use 'sass/color'; -@use 'sass/font'; -@use 'sass/animation'; +@use "sass/mixin"; +@use "sass/size"; +@use "sass/color"; +@use "sass/font"; +@use "sass/animation"; .dao-container { - @include mixin.page-wrapper; - display: flex; - flex-flow: column nowrap; - .address-container { - @include mixin.center-items; - flex-flow: row nowrap; - width: auto; - .MuiTextField-root { - width: calc(100% - 2 * size.$gap); - max-width: 100ch; - text-align: left; - margin: calc(size.$gap - 0.5 * size.$large-text) size.$gap; - .MuiInputBase-root { - font-size: size.$large-text; - color: color.$darkish; - input { - padding: 0; - padding-left: 0.5 * size.$gap; - } - &.Mui-error { - color: darken(color.$red, 10%); - } - - } - fieldset { - border: none; - border-bottom: 2px solid currentColor; - border-radius: 0; - } - p { - display: none; - } + @include mixin.page-wrapper; + display: flex; + flex-flow: column nowrap; + .address-container { + @include mixin.center-items; + flex-flow: row nowrap; + width: auto; + .MuiTextField-root { + width: calc(100% - 2 * size.$gap); + max-width: 100ch; + text-align: left; + margin: calc(size.$gap - 0.5 * size.$large-text) size.$gap; + .MuiInputBase-root { + font-size: size.$large-text; + color: color.$darkish; + input { + padding: 0; + padding-left: 0.5 * size.$gap; } - .MuiInputAdornment-root { - width: fit-content; - p { - display: block !important; - font-size: size.$large-text !important; - color: color.$darkish; - } + &.Mui-error { + color: darken(color.$red, 10%); } + } + fieldset { + border: none; + border-bottom: 2px solid currentColor; + border-radius: 0; + } + p { + display: none; + } } - &::before { - content: ''; - position: fixed; - top: 0; - left: 0; - height: calc(2.5 * size.$gap - 0.5 * (size.$gap - size.$large-text)); - min-width: 100%; - background-color: color.$light; + .MuiInputAdornment-root { + width: fit-content; + p { + display: block !important; + font-size: size.$large-text !important; + color: color.$darkish; + } } - .info-container { - @include mixin.full; - display: grid; - justify-items: unset; - gap: size.$gap; - padding: size.$gap; - width: calc(100% - 2* size.$gap); - grid-template: repeat(8, 1fr) / repeat(8, 1fr); - &.error, - &.loader { - display: flex; - flex-flow: column; - justify-content: center; - align-items: center; - font-size: size.$text; - p.red { - color: color.$red; - } - p.green { - color: color.$green; - } + } + &::before { + content: ""; + position: fixed; + top: 0; + left: 0; + height: calc(2.5 * size.$gap - 0.5 * (size.$gap - size.$large-text)); + min-width: 100%; + background-color: color.$light; + } + .info-container { + @include mixin.full; + display: grid; + justify-items: unset; + gap: size.$gap; + padding: size.$gap; + width: calc(100% - 2 * size.$gap); + grid-template: repeat(8, 1fr) / repeat(8, 1fr); + &.error, + &.loader { + display: flex; + flex-flow: column; + justify-content: center; + align-items: center; + font-size: size.$text; + p.red { + color: color.$red; + } + p.green { + color: color.$green; + } + } + .info-text { + font-size: size.$text; + color: color.$dark; + max-width: 40em; + a { + color: darken(color.$blue, 20%) !important; + } + } + .info-card { + display: flex; + position: relative; + flex-flow: column nowrap; + background-color: rgba(color.$lightest, 0.25); + border-radius: size.$task-radius; + font-size: size.$small-text; + overflow: hidden; + .title { + padding: 0.5 * size.$gap size.$gap; + font-size: size.$large-text; + span { + float: right; } - .info-text { - font-size: size.$text; - color: color.$dark; - max-width: 40em; - a { - color: darken(color.$blue, 20%) !important; - } + } + @for $i from 0 to 3 { + .MuiSvgIcon-root:nth-of-type(#{$i + 1}) { + position: absolute; + font-size: size.$large-text; + top: 0.5 * size.$gap; + right: calc( + 0.5 * size.$gap + $i * (size.$large-text + 0.25 * size.$gap) + ); + cursor: pointer; } - .info-card { - display: flex; + } + ul { + display: flex; + flex-flow: column nowrap; + li { + margin-right: 0.5 * size.$gap; + span { position: relative; - flex-flow: column nowrap; - background-color: rgba(color.$lightest, 0.25); - border-radius: size.$task-radius; - font-size: size.$small-text; - overflow: hidden; - .title { - padding: 0.5 * size.$gap size.$gap; - font-size: size.$large-text; - span { - float: right; - } - } - @for $i from 0 to 3 { - .MuiSvgIcon-root:nth-of-type(#{$i + 1}) { - position: absolute; - font-size: size.$large-text; - top: 0.5 * size.$gap; - right: calc(0.5 * size.$gap + $i * (size.$large-text + 0.25 * size.$gap)); - cursor: pointer; - } - } - ul { - display: flex; - flex-flow: column nowrap; - li { - margin-right: 0.5 * size.$gap; - span { - position: relative; - display: block; - width: 100%; - a { - color: darken(color.$blue, 20%) !important; - } - .MuiSvgIcon-root { - visibility: hidden; - position: absolute; - font-size: size.$large-text; - top: auto !important; - bottom: auto !important; - right: 0 !important; - cursor: pointer; - } - } - &:hover { - background-color: color.$lightest; - span > .MuiSvgIcon-root { - visibility: visible; - } - } - } - } - &.admins { - grid-area: 1 / 1 / 9 / 3; - } - &.tokens { - grid-area: 1 / 3 / 9 / 5; + display: block; + width: 100%; + a { + color: darken(color.$blue, 20%) !important; } - &.jobs { - grid-area: 1 / 6 / 8 / 9; - position: relative; - .scroll-wrapper { - @include mixin.no-scrollbar; - overflow-y: scroll; - position: absolute; - top: calc(size.$large-text + 1.5 * size.$gap); - bottom: 0; - left: 0; - right: 0; - .job { - position: relative; - margin: size.$gap; - margin-top: 0; - border-radius: size.$task-radius; - background-color: color.$lightest; - pre { - padding: 0.5 * size.$gap; - font-family: font.$code; - font-size: size.$small-text; - } - } - } + .MuiSvgIcon-root { + visibility: hidden; + position: absolute; + font-size: size.$large-text; + top: auto !important; + bottom: auto !important; + right: 0 !important; + cursor: pointer; } - &.bond { - grid-area: 8 / 6 / 9 / 9; - .title { - @include mixin.center-items(space-between, center); - height: 100%; - } + } + &:hover { + background-color: color.$lightest; + span > .MuiSvgIcon-root { + visibility: visible; } + } } - .create-multicall { - width: fit-content; - align-self: center; - font-size: size.$text; - padding: 0.25em 0.75em; - border-radius: 0.5em; - background-color: color.$green; - &.proposal-exists { - background-color: color.$blue !important; + } + &.admins { + grid-area: 1 / 1 / 9 / 3; + } + &.tokens { + grid-area: 1 / 3 / 9 / 6; + } + &.jobs { + grid-area: 1 / 6 / 8 / 9; + position: relative; + .scroll-wrapper { + @include mixin.no-scrollbar; + overflow-y: scroll; + position: absolute; + top: calc(size.$large-text + 1.5 * size.$gap); + bottom: 0; + left: 0; + right: 0; + .job { + position: relative; + margin: size.$gap; + margin-top: 0; + border-radius: size.$task-radius; + background-color: color.$lightest; + pre { + padding: 0.5 * size.$gap; + font-family: font.$code; + font-size: size.$small-text; } + } } + } + &.bond { + grid-area: 8 / 6 / 9 / 9; + .title { + @include mixin.center-items(space-between, center); + height: 100%; + } + } + } + .create-multicall { + width: fit-content; + align-self: center; + font-size: size.$text; + padding: 0.25em 0.75em; + border-radius: 0.5em; + background-color: color.$green; + &.proposal-exists { + background-color: color.$blue !important; + } } -} \ No newline at end of file + } +} diff --git a/src/func-components/Table/index.tsx b/src/func-components/Table/index.tsx new file mode 100644 index 00000000..cc90c539 --- /dev/null +++ b/src/func-components/Table/index.tsx @@ -0,0 +1,382 @@ +import { + TableContainer, + TableHead, + TableCell, + TableRow, + TableBody, + Box, + Typography, + styled, + IconButton, + Collapse, + TableSortLabel, +} from "@mui/material"; +import { useState } from "react"; +import useBreakpoint from "../../hooks/useBreakpoint"; +import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; +import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; +import React from "react"; +// import { visuallyHidden } from '@mui/utils' + +const StyledTableContainer = styled(TableContainer)({ + display: "table", + borderRadius: "40px", + "& .MuiTableCell-root": { + borderBottom: "none", + fontWeight: 400, + padding: "14px 20px", + "&:first-of-type": { + paddingLeft: 20, + }, + "&:last-child": { + paddingRight: 20, + }, + }, + "& table": { + width: "100%", + borderCollapse: "separate", + borderSpacing: "0 8px", + }, +}); + +const StyledTableHead = styled(TableHead)(({ theme }) => ({ + borderRadius: 8, + overflow: "hidden", + "& .MuiTableCell-root": { + fontSize: "12px", + whiteSpace: "pre", + lineHeight: "12px", + background: "rgba(255, 255, 255, 0.08)", + padding: "12px 20px 12px 0", + color: theme.palette.text.secondary, + borderBottom: "none", + "& .MuiTableSortLabel-root": { + fontWeight: 400, + fontSize: "12px!important", + color: theme.palette.text.secondary, + }, + "&:first-of-type": { + paddingLeft: 20, + borderTopLeftRadius: 8, + }, + "&:last-child": { + paddingRight: 20, + borderTopRightRadius: 8, + }, + }, +})); + +const StyledTableRow = styled(TableRow, { shouldForwardProp: () => true })<{ + variant: "outlined" | "grey"; + fontSize?: string; +}>(({ variant, theme, fontSize }) => ({ + height: 80, + borderRadius: "16px", + overflow: "hidden", + position: "relative", + whiteSpace: "pre", + background: variant === "outlined" ? "transparent" : "#b4ccca", + "& + tr .MuiCollapse-root": { + background: + variant === "outlined" ? "transparent" : theme.palette.background.default, + }, + "& .MuiTableCell-root": { + fontSize: (fontSize ?? "16px") + "!important", + justifyContent: "flex-start", + paddingLeft: 0, + border: "1px solid", + borderColor: variant === "outlined" ? "#00000010" : "transparent", + borderRight: "none", + borderLeft: "none", + "& .MuiTypography-root": { + fontSize: (fontSize ?? "16px") + "!important", + }, + "&:first-of-type": { + borderLeft: "1px solid", + borderColor: variant === "outlined" ? "#00000010" : "transparent", + paddingLeft: "20px", + borderTopLeftRadius: 16, + borderBottomLeftRadius: 16, + }, + "&:last-child": { + borderRight: "1px solid", + borderColor: variant === "outlined" ? "#00000010" : "transparent", + paddingRight: "20px", + borderTopRightRadius: 16, + borderBottomRightRadius: 16, + }, + }, + "&:hover": { + "& + tr .MuiCollapse-root": { + backgroundColor: variant === "outlined" ? "#E2E7F020" : "#dcefea", + }, + backgroundColor: variant === "outlined" ? "#E2E7F020" : "#dcefea", + }, +})); + +const Card = styled("div")({ + backgroundColor: "rgba(255, 255, 255, 0.08)", + border: "1px solid rgba(0, 0, 0, 0.1)", + borderRadius: 16, + padding: 16, + "& > div": { + width: "100%", + }, +}); + +const sortIcon = ({ className }: { className: string }) => ( + + + + +); + +const CardRow = styled("div")(` + display: flex; + justify-content: space-between; + grid-template-columns: auto 100%; + > div:first-of-type { + white-space: nowrap; + } + > div:last-child { + width: 100%; + display: flex; + justify-content: flex-end; + align-items: center; + } + `); + +export default function Table({ + header, + rows, + variant = "grey", + collapsible, + hiddenParts, + fontSize, + sortHeaders, + order, + orderBy, + createSortfunction, +}: { + sortHeaders?: string[]; + header: string[]; + rows: (string | number | JSX.Element)[][]; + variant?: "outlined" | "grey"; + collapsible?: boolean; + hiddenParts?: JSX.Element[]; + fontSize?: string; + order?: "asc" | "desc"; + orderBy?: string; + createSortfunction?: (label: string) => () => void; +}) { + const matches = useBreakpoint("md"); + + return ( + <> + {matches ? ( + <> + {rows.map((data, index) => ( + + + {header.map((headerString, index) => ( + + + {headerString} + + theme.palette.text.secondary }} + component="div" + > + {data[index] ?? null} + + {collapsible && index + 1 === header.length && ( + setIsOpen(open => !open)} + sx={{ flexGrow: 0 }} + > + + {/* {isOpen ? : } */} + + )} + + ))} + + + ))} + + ) : ( + +
+ + + {header.map((string, idx) => ( + + {sortHeaders && + sortHeaders.includes(string) && + order && + orderBy && + createSortfunction ? ( + + orderBy === string + ? order === "desc" + ? theme.palette.primary.main + : "#00000099" + : "#00000099", + }, + "& .MuiTableSortLabel-iconDirectionAsc .sort-up": { + fill: (theme) => + orderBy === string + ? order === "asc" + ? theme.palette.primary.main + : "#00000099" + : "#00000099", + }, + }} + > + {string} + + {/* + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + */} + + ) : ( + string + )} + + ))} + + + + {rows.map((row, idx) => ( + + ))} + +
+ + )} + + ); +} + +function Row({ + row, + variant, + collapsible, + hiddenPart, + fontSize, +}: { + row: (string | number | JSX.Element)[]; + variant: "outlined" | "grey"; + collapsible?: boolean; + hiddenPart?: JSX.Element; + fontSize?: string; +}) { + const [isOpen, setIsOpen] = useState(false); + + return ( + <> + + {row.map((data, idx) => ( + {data} + ))} + {collapsible && ( + + setIsOpen((open) => !open)} + sx={{ flexGrow: 0 }} + > + {isOpen ? : } + + + )} + + {collapsible && ( + + + + + {hiddenPart} + + + + + )} + + ); +} diff --git a/src/func-components/Tabs/index.tsx b/src/func-components/Tabs/index.tsx new file mode 100644 index 00000000..3e9add85 --- /dev/null +++ b/src/func-components/Tabs/index.tsx @@ -0,0 +1,85 @@ +import React, { useCallback } from "react"; +import { Tabs as MuiTabs, Tab, Box, TabProps } from "@mui/material"; + +interface Props { + titles: string[] | JSX.Element[]; + contents: React.ReactNode[]; + customCurrentTab?: number; + customOnChange?: (val: number) => void; + tabPadding?: string; + fontWeight?: number; +} + +function TabPanel({ + children, + value, + index, +}: { + children: React.ReactNode; + value: number; + index: number; +}) { + return ; +} + +export default function Tabs(props: Props) { + const { titles, contents, customCurrentTab, customOnChange, tabPadding } = + props; + const [value, setValue] = React.useState(0); + + const onChange = useCallback( + (e: React.ChangeEvent, value: any) => { + customOnChange ? customOnChange(value) : setValue(value); + }, + [customOnChange] + ); + + return ( + + + + {titles.map((tab, idx) => ( + theme.palette.text.primary, + opacity: 0.4, + "&.Mui-selected": { + color: (theme) => theme.palette.text.primary, + opacity: 1, + }, + }} + /> + ))} + + + {contents.map((content, idx) => ( + + {content} + + ))} + + ); +} diff --git a/src/hooks/useBreakpoint.ts b/src/hooks/useBreakpoint.ts new file mode 100644 index 00000000..e2d70b7c --- /dev/null +++ b/src/hooks/useBreakpoint.ts @@ -0,0 +1,9 @@ +import { useMediaQuery, useTheme } from '@mui/material' +import { Breakpoint } from '@mui/material/styles' + +export default function useBreakpoint(breakpoint: Breakpoint = 'sm') { + const theme = useTheme() + const matches = useMediaQuery(theme.breakpoints.down(breakpoint)) + + return matches +} diff --git a/tsconfig.json b/tsconfig.json index 776437ab..93d0314b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "jsx": "react", "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, From 4eab6eac2ce1b4c8c679769c3e18dbb1fbf9bdd1 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sat, 30 Jul 2022 18:59:12 +0200 Subject: [PATCH 002/537] add Fungible Token contract class --- src/near-config.js | 4 +- src/utils/contracts/fungibleToken.ts | 89 ++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 src/utils/contracts/fungibleToken.ts diff --git a/src/near-config.js b/src/near-config.js index b6175625..f209e23d 100644 --- a/src/near-config.js +++ b/src/near-config.js @@ -12,7 +12,7 @@ function getConfig(env) { CRONCAT_MANAGER_ADDRESS: "manager_v1.croncat.near", nodeUrl: 'https://rpc.mainnet.near.org', walletUrl: 'https://wallet.near.org', - helperUrl: 'https://helper.mainnet.near.org', + helperUrl: 'https://api.kitwallet.app', explorerUrl: 'https://explorer.mainnet.near.org', } case 'development': @@ -26,7 +26,7 @@ function getConfig(env) { CRONCAT_MANAGER_ADDRESS: "manager_v1.croncat.testnet", nodeUrl: 'https://rpc.testnet.near.org', walletUrl: 'https://wallet.testnet.near.org', - helperUrl: 'https://helper.testnet.near.org', + helperUrl: 'https://testnet-api.kitwallet.app', explorerUrl: 'https://explorer.testnet.near.org', } case 'betanet': diff --git a/src/utils/contracts/fungibleToken.ts b/src/utils/contracts/fungibleToken.ts new file mode 100644 index 00000000..6be12501 --- /dev/null +++ b/src/utils/contracts/fungibleToken.ts @@ -0,0 +1,89 @@ +import { view } from "../wallet"; + + +// Fungible token metadata follows NEP-148. See: https://nomicon.io/Standards/Tokens/FungibleToken/Metadata +type FungibleTokenMetadata = { + spec: string; + name: string; + symbol: string; + icon?: string|null; // optional + reference?: string|null; // optional + reference_hash?: string|null; // optional + decimals: number; +} + +// TODO: support NEP-145 for storage methods. See: https://nomicon.io/Standards/StorageManagement + + +// Fungible token core follow NEP-141. See: https://nomicon.io/Standards/Tokens/FungibleToken/Core +class FungibleToken { + + address: string; + // needs initialization, but start with empty metadata + metadata: FungibleTokenMetadata = { spec: "", name: "", symbol: "", decimals: -1 }; + // token total supply + totalSupply: string = ""; + // DAO instance is ready when info (policy...) are fetched & assigned correctly + ready: boolean = false; + + + // shouldn't be used directly, use init() instead + constructor(dao_address: string) { + this.address = dao_address; + } + + // used to create and initialize a FungibleToken instance + static async init (tokenAddress: string): Promise { + // verify address is a SputnikDAO, fetch DAO info and mark it ready + const newToken = new FungibleToken(tokenAddress); + const [ metadata, totalSupply ] = await Promise.all([ + // on failure set policy to default policy (empty) + newToken.ftMetadata().catch(err => { return newToken.metadata }), + // on failure ste last proposal ID to default (-1) + newToken.ftTotalSupply().catch(err => { return newToken.totalSupply }) + ]); + newToken.metadata = metadata; + newToken.totalSupply = totalSupply; + // set DAO to ready if address is a DAO and lastProposalID + policy got updated. + if ( + newToken.totalSupply !== "" + && newToken.metadata.decimals >= 0 + ) { + newToken.ready = true; + } + return newToken; + } + + async ftMetadata (): Promise { + return view(this.address, "ft_metadata", {}); + } + + async ftTotalSupply (): Promise { + return view(this.address, "ft_total_supply", {}); + } + + async ftBalanceOf (accountId: string): Promise { + return view(this.address, "ft_balance_of", { account_id: accountId }); + } + + static async getLikelyTokenContracts (accountId: string): Promise { + const response = await fetch( + `${window.nearConfig.helperUrl}/account/${accountId}/likelyTokens`, + { method: "GET", headers: { "Content-type": "application/json; charset=utf-8" } } + ); + + // on success: return list of likely tokens owned by accountId + if (response.ok) { + return (await response.json()); + } + // on error: return empty list + else { + return []; + } + } + +} + +export{ + FungibleToken +} From fe7f30bfe8e27de80d9a646b929ac07275953a2c Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sat, 30 Jul 2022 20:36:16 +0200 Subject: [PATCH 003/537] remove DAO references in Fungible Token class --- src/utils/contracts/fungibleToken.ts | 14 +++++++------- src/utils/contracts/sputnik-dao.ts | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/utils/contracts/fungibleToken.ts b/src/utils/contracts/fungibleToken.ts index 6be12501..0efa7265 100644 --- a/src/utils/contracts/fungibleToken.ts +++ b/src/utils/contracts/fungibleToken.ts @@ -23,28 +23,28 @@ class FungibleToken { metadata: FungibleTokenMetadata = { spec: "", name: "", symbol: "", decimals: -1 }; // token total supply totalSupply: string = ""; - // DAO instance is ready when info (policy...) are fetched & assigned correctly + // Token instance is ready when info (metadata...) are fetched & assigned correctly ready: boolean = false; // shouldn't be used directly, use init() instead - constructor(dao_address: string) { - this.address = dao_address; + constructor(tokenAddress: string) { + this.address = tokenAddress; } // used to create and initialize a FungibleToken instance static async init (tokenAddress: string): Promise { - // verify address is a SputnikDAO, fetch DAO info and mark it ready + // fetch token info and mark it ready const newToken = new FungibleToken(tokenAddress); const [ metadata, totalSupply ] = await Promise.all([ - // on failure set policy to default policy (empty) + // on failure set metadata to default metadata (empty) newToken.ftMetadata().catch(err => { return newToken.metadata }), - // on failure ste last proposal ID to default (-1) + // on failure set total supply to default (empty string) newToken.ftTotalSupply().catch(err => { return newToken.totalSupply }) ]); newToken.metadata = metadata; newToken.totalSupply = totalSupply; - // set DAO to ready if address is a DAO and lastProposalID + policy got updated. + // set ready to true if token info successfully got updated. if ( newToken.totalSupply !== "" && newToken.metadata.decimals >= 0 diff --git a/src/utils/contracts/sputnik-dao.ts b/src/utils/contracts/sputnik-dao.ts index 3505814c..def6a7d0 100644 --- a/src/utils/contracts/sputnik-dao.ts +++ b/src/utils/contracts/sputnik-dao.ts @@ -122,7 +122,7 @@ class SputnikDAO { SputnikDAO.isSputnikDAO(dao_address).catch(err => { return false }), // on failure set policy to default policy (empty) newDAO.getPolicy().catch(err => { return newDAO.policy }), - // on failure ste last proposal ID to default (-1) + // on failure set last proposal ID to default (-1) newDAO.getLastProposalId().catch(err => { return newDAO.lastProposalId }) ]); newDAO.policy = daoPolicy; From 18fb269f90b8f7d1f6e9a88ecc1403a07fbce111 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sun, 28 Aug 2022 16:31:59 +0200 Subject: [PATCH 004/537] add RPC method to fetch basic account Info --- src/utils/contracts/generic.ts | 8 ++------ src/utils/contracts/multicall.ts | 8 ++------ src/utils/contracts/sputnik-dao.ts | 8 ++------ src/utils/wallet.ts | 27 ++++++++++++++++++++++++++- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/utils/contracts/generic.ts b/src/utils/contracts/generic.ts index 4f8d88b1..92346980 100644 --- a/src/utils/contracts/generic.ts +++ b/src/utils/contracts/generic.ts @@ -1,4 +1,4 @@ -import { rpcProvider } from "../wallet" +import { viewAccount } from "../wallet" /** @@ -8,11 +8,7 @@ import { rpcProvider } from "../wallet" * @param {string} address */ async function hasContract (address: string): Promise { - const accountInfo: any = await rpcProvider.query({ - request_type: "view_account", - finality: "final", - account_id: address - }); + const accountInfo = await viewAccount(address); const codeHash: string = accountInfo.code_hash; return codeHash !== "11111111111111111111111111111111"; } diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index b0a9c508..d33693d2 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -1,4 +1,4 @@ -import { rpcProvider } from "../wallet"; +import { viewAccount } from "../wallet"; const FACTORY_ADDRESS_SELECTOR: Record = { "mainnet": "v1.multicall.near", @@ -33,11 +33,7 @@ export default class Multicall { * @param accountId */ static async isMulticall(accountId: string): Promise { - const accountInfo: any = await rpcProvider.query({ - request_type: "view_account", - finality: "final", - account_id: accountId - }); + const accountInfo = await viewAccount(accountId); const codeHash: string = accountInfo.code_hash; return Multicall.CONTRACT_CODE_HASHES.includes(codeHash); } diff --git a/src/utils/contracts/sputnik-dao.ts b/src/utils/contracts/sputnik-dao.ts index def6a7d0..d0e120fe 100644 --- a/src/utils/contracts/sputnik-dao.ts +++ b/src/utils/contracts/sputnik-dao.ts @@ -1,4 +1,4 @@ -import { tx, view, rpcProvider } from "../wallet"; +import { tx, view, viewAccount } from "../wallet"; import { toGas } from "../converter"; import { ArgsAccount } from "../args"; @@ -145,11 +145,7 @@ class SputnikDAO { * @param accountId */ static async isSputnikDAO (accountId: string): Promise { - const accountInfo: any = await rpcProvider.query({ - request_type: "view_account", - finality: "final", - account_id: accountId - }); + const accountInfo = await viewAccount(accountId); const codeHash: string = accountInfo.code_hash; return SputnikDAO.CONTRACT_CODE_HASHES.includes(codeHash); } diff --git a/src/utils/wallet.ts b/src/utils/wallet.ts index 55f03592..068c16b0 100644 --- a/src/utils/wallet.ts +++ b/src/utils/wallet.ts @@ -53,6 +53,7 @@ async function tx ( /** * make view calls using RPC, no need for user to sign in. + * see: https://docs.near.org/api/rpc/contracts#call-a-contract-function * * @param addr * @param func @@ -77,5 +78,29 @@ async function view ( return JSON.parse( String.fromCharCode(... response.result) ); } +/** + * queries RPC for basic account information. + * see: https://docs.near.org/api/rpc/contracts#view-account + * + * @param accountId + */ +async function viewAccount (accountId: string): Promise<{ + amount: string; + locked: string; + code_hash: string; + storage_usage: number; + storage_paid_at: number; + block_height: number; + block_hash: string +}> { + const accountInfo: any = await rpcProvider.query({ + request_type: "view_account", + finality: "final", + account_id: accountId + }); + + return accountInfo; +} + -export { tx, view, rpcProvider }; +export { tx, view, viewAccount, rpcProvider }; From c414104a439be37e63dadd01174eceadab3a13c9 Mon Sep 17 00:00:00 2001 From: yukamend Date: Mon, 5 Sep 2022 22:42:48 +0200 Subject: [PATCH 005/537] add token balances table + restructure dao page --- src/components/dao/dao.js | 146 ++++++++++++++++++-------- src/components/dao/dao.scss | 8 +- src/func-components/Table/index.tsx | 8 +- src/func-components/Tabs/PageTabs.tsx | 42 ++++++++ src/func-components/Tabs/index.tsx | 67 +++++++----- 5 files changed, 198 insertions(+), 73 deletions(-) create mode 100644 src/func-components/Tabs/PageTabs.tsx diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index aaaf416d..db958430 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -1,10 +1,10 @@ -import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from '@mui/icons-material'; +import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined, ConstructionOutlined } from '@mui/icons-material'; import { Base64 } from 'js-base64'; import React, { Component } from 'react'; import { ArgsAccount, ArgsError } from '../../utils/args'; import { STORAGE } from '../../utils/persistent'; -import { toNEAR, toYocto, Big } from '../../utils/converter'; -import { view } from '../../utils/wallet'; +import { toNEAR, toYocto, Big, formatTokenAmount } from '../../utils/converter'; +import { view, viewAccount } from '../../utils/wallet'; import { useWalletSelector } from '../../contexts/walletSelectorContext'; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from '../../utils/contracts/sputnik-dao'; import { TextInput } from '../editor/elements'; @@ -13,11 +13,13 @@ import './dao.scss'; import debounce from 'lodash.debounce'; import Table from '../../func-components/Table'; import Tabs from '../../func-components/Tabs'; - +import PageTabs from '../../func-components/Tabs/PageTabs'; +import { FungibleToken } from '../../utils/contracts/fungibleToken'; +import * as nearAPI from 'near-api-js' // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR -const TableHeader = ['Token', '', 'Ref', 'Near', 'Total'] +const TableHeader = ['Token', '', 'Multicall', 'DAO', 'Total'] export default class DaoComponent extends Component { static contextType = useWalletSelector(); @@ -42,6 +44,7 @@ export default class DaoComponent extends Component { loading: false, proposed: -1, proposedInfo: {}, + rowContent: null, infos: { admins: [], tokens: [], @@ -295,7 +298,7 @@ export default class DaoComponent extends Component { job(job) { return ( -
+
{job.is_active @@ -360,13 +363,17 @@ export default class DaoComponent extends Component { view(multicall, "get_tokens", {}).catch(e => { }), view(multicall, "get_jobs", {}).catch(e => { }), view(multicall, "get_job_bond", {}).catch(e => { }), - this.proposalAlreadyExists(newDAO).catch(e => { }) + this.proposalAlreadyExists(newDAO).catch(e => { }), + this.balancesToRows(multicall, newDAO).catch(e => { }), + this.nearInfo(multicall, newDAO).catch(e => { }) ]) - .then(([admins, tokens, jobs, bond, createMulticallProposalInfo]) => { + .then(([admins, tokens, jobs, bond, createMulticallProposalInfo, rows, nearBalance]) => { const { proposal_id, proposal_info } = createMulticallProposalInfo; + rows.unshift(nearBalance) newState = { dao: newDAO, + rowContent: rows, infos: { admins: admins, tokens: tokens, @@ -387,9 +394,61 @@ export default class DaoComponent extends Component { } + async tokenInfo(multicall, dao) { + const tokenAddrList = await FungibleToken.getLikelyTokenContracts(multicall) + + const likelyTokenList = await Promise.all(tokenAddrList.map((address) => + FungibleToken.init(address) + )) + + const tokenList = likelyTokenList.filter(tkn => tkn.ready === true) + + const balances = await Promise.all(tokenList.map(async (tkn) => { + const [multicallBalance, daoBalance] = await Promise.all([tkn.ftBalanceOf(multicall), tkn.ftBalanceOf(dao.address)]) + return { + token: tkn, + multicallBalance: multicallBalance, + daoBalance: daoBalance, + total: Big(multicallBalance).add(daoBalance).toFixed() + } + })) + + return balances.filter(el => Big(el.total).gt('0')) + } + + + balancesToRows(multicall, dao) { + return this.tokenInfo(multicall, dao).then( + res => res.map( + row => [row.token.metadata.symbol, row.token.metadata.icon, formatTokenAmount(row.multicallBalance, row.token.metadata.decimals, 2), formatTokenAmount(row.daoBalance, row.token.metadata.decimals, 2), formatTokenAmount(row.total, row.token.metadata.decimals, 2)] + ) + ) + } + + async nearInfo() { + + const { addr, dao } = this.state; + + const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; + + const nearBalanceMulticall = (await viewAccount(multicall)).amount + const nearBalanceDao = (await viewAccount(dao.address)).amount + + return ['NEAR', 'https://s2.coinmarketcap.com/static/img/coins/64x64/6535.png', formatTokenAmount(nearBalanceMulticall, 24, 2), formatTokenAmount(nearBalanceDao, 24, 2), formatTokenAmount(Big(nearBalanceDao).add(nearBalanceMulticall).toFixed(), 24, 2)] + } + + displayToken() { + // format to show small balances + } + + + + + getContent() { const { selector: walletSelector } = this.context; - const { infos, loading } = this.state; + const { infos, loading, rowContent } = this.state; + // if user not logged in, remind him to sign in. // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) @@ -428,43 +487,46 @@ export default class DaoComponent extends Component { } // infos found - return
-
- -

Admins

-
    - {infos.admins.map(a =>
  • {this.toLink(a)}
  • )} -
-
-
- -

Tokens

- - , - - <>

Tokens

+ return ( + +
+ +

Admins

+
    + {infos.admins.map(a =>
  • {this.toLink(a)}
  • )} +
+
+
+ +

Jobs

+
+ {infos.jobs.map(j => this.job(j))} +
+
+

Job Bond + {`${infos.bond !== "..." ? toNEAR(infos.bond) : "..."} Ⓝ`} +

+
+ , +
+
+ + +

Token Balances

+ +
+ +
+

Whitelisted Tokens

    {infos.tokens.map(t =>
  • {this.toLink(t)}
  • )} -
- - ] - } /> -
-
- -

Jobs

-
- {infos.jobs.map(j => this.job(j))} + + +
- -
-

Job Bond - {`${infos.bond !== "..." ? toNEAR(infos.bond) : "..."} Ⓝ`} -

-
- + ]} />) } render() { diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index e1323bc4..0932836b 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -145,10 +145,14 @@ grid-area: 1 / 1 / 9 / 3; } &.tokens { - grid-area: 1 / 3 / 9 / 6; + padding-bottom: size.$gap; + grid-area: 1 / 1 / 9 / 6; + } + &.wtokens { + grid-area: 1/ 6 / 9 / 9; } &.jobs { - grid-area: 1 / 6 / 8 / 9; + grid-area: 1 / 3 / 8 / 9; position: relative; .scroll-wrapper { @include mixin.no-scrollbar; diff --git a/src/func-components/Table/index.tsx b/src/func-components/Table/index.tsx index cc90c539..29faa661 100644 --- a/src/func-components/Table/index.tsx +++ b/src/func-components/Table/index.tsx @@ -172,6 +172,7 @@ export default function Table({ order, orderBy, createSortfunction, + icons, }: { sortHeaders?: string[]; header: string[]; @@ -183,6 +184,7 @@ export default function Table({ order?: "asc" | "desc"; orderBy?: string; createSortfunction?: (label: string) => () => void; + icons?: boolean; }) { const matches = useBreakpoint("md"); @@ -333,7 +335,11 @@ function Row({ } > {row.map((data, idx) => ( - {data} + <> + + {idx === 1 ? : data} + + ))} {collapsible && ( diff --git a/src/func-components/Tabs/PageTabs.tsx b/src/func-components/Tabs/PageTabs.tsx new file mode 100644 index 00000000..6307ece1 --- /dev/null +++ b/src/func-components/Tabs/PageTabs.tsx @@ -0,0 +1,42 @@ +import { Tab, TabProps } from "@mui/material"; +import React from "react"; +import Tabs from "./index"; + +export default function PageTabs({ contents }: { contents: JSX.Element[] }) { + return ( + + ); +} + +function CustomTab(props: TabProps) { + return ( + + ); +} diff --git a/src/func-components/Tabs/index.tsx b/src/func-components/Tabs/index.tsx index 3e9add85..4791dfb3 100644 --- a/src/func-components/Tabs/index.tsx +++ b/src/func-components/Tabs/index.tsx @@ -6,6 +6,7 @@ interface Props { contents: React.ReactNode[]; customCurrentTab?: number; customOnChange?: (val: number) => void; + CustomTab?: React.FC; tabPadding?: string; fontWeight?: number; } @@ -23,8 +24,14 @@ function TabPanel({ } export default function Tabs(props: Props) { - const { titles, contents, customCurrentTab, customOnChange, tabPadding } = - props; + const { + titles, + contents, + customCurrentTab, + customOnChange, + tabPadding, + CustomTab, + } = props; const [value, setValue] = React.useState(0); const onChange = useCallback( @@ -36,39 +43,43 @@ export default function Tabs(props: Props) { return ( - + - {titles.map((tab, idx) => ( - theme.palette.text.primary, - opacity: 0.4, - "&.Mui-selected": { - color: (theme) => theme.palette.text.primary, - opacity: 1, - }, - }} - /> - ))} + {CustomTab + ? titles.map((tab, idx) => ) + : titles.map((tab, idx) => ( + theme.palette.text.primary, + opacity: 0.4, + "&.Mui-selected": { + color: (theme) => theme.palette.text.primary, + opacity: 1, + }, + }} + /> + ))} {contents.map((content, idx) => ( From 01bf07410d9b7e7ad0ced96bf9cb1ac109536bfd Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Tue, 6 Sep 2022 14:15:00 +0200 Subject: [PATCH 006/537] Fix prettier issues --- src/components/dao/dao.js | 330 +++++++++++++++++-------------- src/utils/contracts/multicall.ts | 2 +- 2 files changed, 181 insertions(+), 151 deletions(-) diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index 5565ff54..96cce329 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -1,25 +1,25 @@ -import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined, ConstructionOutlined } from '@mui/icons-material'; -import { Base64 } from 'js-base64'; -import React, { Component } from 'react'; -import { ArgsAccount, ArgsError } from '../../utils/args'; -import { STORAGE } from '../../utils/persistent'; -import { toNEAR, toYocto, Big, formatTokenAmount } from '../../utils/converter'; -import { view, viewAccount } from '../../utils/wallet'; -import { useWalletSelector } from '../../contexts/walletSelectorContext'; -import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from '../../utils/contracts/sputnik-dao'; -import { TextInput } from '../editor/elements'; -import { InputAdornment } from '@mui/material' -import './dao.scss'; -import debounce from 'lodash.debounce'; -import Table from '../../func-components/Table'; -import Tabs from '../../func-components/Tabs'; -import PageTabs from '../../func-components/Tabs/PageTabs'; -import { FungibleToken } from '../../utils/contracts/fungibleToken'; -import * as nearAPI from 'near-api-js' +import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; +import { Base64 } from "js-base64"; +import React, { Component } from "react"; +import { ArgsAccount, ArgsError } from "../../utils/args"; +import { STORAGE } from "../../utils/persistent"; +import { toNEAR, toYocto, Big, formatTokenAmount } from "../../utils/converter"; +import { view, viewAccount } from "../../utils/wallet"; +import { useWalletSelector } from "../../contexts/walletSelectorContext"; +import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; +import { TextInput } from "../editor/elements"; +import { InputAdornment } from "@mui/material"; +import "./dao.scss"; +import debounce from "lodash.debounce"; +import Table from "../../func-components/Table"; +import Tabs from "../../func-components/Tabs"; +import PageTabs from "../../func-components/Tabs/PageTabs"; +import { FungibleToken } from "../../utils/contracts/fungibleToken"; +import * as nearAPI from "near-api-js"; // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR -const TableHeader = ['Token', '', 'Multicall', 'DAO', 'Total'] +const TableHeader = ["Token", "", "Multicall", "DAO", "Total"]; export default class DaoComponent extends Component { static contextType = useWalletSelector(); @@ -101,16 +101,15 @@ export default class DaoComponent extends Component { return expirationTime.gt(currentTime) ? true : false; }); - // If there many "Create multicall" proposals, return latest. - if (proposals.length > 0) { - const lastProposal = proposals.pop(); - return { proposal_id: lastProposal.id, proposal_info: lastProposal }; - } - // No "Create multicall" proposals found. - else return { proposal_id: -1, proposal_info: {} }; - - }).catch(e => { }) - + // If there many "Create multicall" proposals, return latest. + if (proposals.length > 0) { + const lastProposal = proposals.pop(); + return { proposal_id: lastProposal.id, proposal_info: lastProposal }; + } + // No "Create multicall" proposals found. + else return { proposal_id: -1, proposal_info: {} }; + }) + .catch((e) => {}); } onAddressesUpdated() { @@ -186,10 +185,10 @@ export default class DaoComponent extends Component { }; if ( - noContract.isBad - && !noDao.isBad // base.sputnik-dao.near does not exist - && !loading - && this.lastAddr === document.querySelector(".address-container input")._valueTracker.getValue() // disappear while debouncing + noContract.isBad && + !noDao.isBad && // base.sputnik-dao.near does not exist + !loading && + this.lastAddr === document.querySelector(".address-container input")._valueTracker.getValue() // disappear while debouncing ) { // no create multicall proposal exists if (proposed === -1) { @@ -200,7 +199,11 @@ export default class DaoComponent extends Component {
{/* hint: you can use "genesis" or "test" as DAO to get to this message */} {`A multicall instance can only be created for `} - + {dao.address} {` by making a proposal.`} @@ -214,7 +217,7 @@ export default class DaoComponent extends Component { Propose - ) + ); } // ... and user cannot propose FunctionCall else { @@ -234,7 +237,11 @@ export default class DaoComponent extends Component {
{`Proposal to create a multicall exists (#${proposed}), but you have no voting permissions on this DAO.`}
- + Proposal on Astro
@@ -246,7 +253,11 @@ export default class DaoComponent extends Component {
{`You have voted on creating a multicall instance for this DAO. It will be created as soon as the proposal passes voting.`}
- + Proposal on Astro
@@ -259,7 +270,11 @@ export default class DaoComponent extends Component {
{/* hint: you can use "genesis" or "test" as DAO to get to this message */} {`There exists a proposal (#${proposed}) to create a multicall instance for this DAO. `} - + Open on AstroDAO
@@ -279,7 +294,6 @@ export default class DaoComponent extends Component { } toLink(address, deleteIcon = false) { - const addr = new ArgsAccount(address); return ( @@ -355,96 +369,99 @@ export default class DaoComponent extends Component { noContract.isBad = true; } }), - view(multicall, "get_tokens", {}).catch(e => { }), - view(multicall, "get_jobs", {}).catch(e => { }), - view(multicall, "get_job_bond", {}).catch(e => { }), - this.proposalAlreadyExists(newDAO).catch(e => { }), - this.balancesToRows(multicall, newDAO).catch(e => { }), - this.nearInfo(multicall, newDAO).catch(e => { }) - ]) - .then(([admins, tokens, jobs, bond, createMulticallProposalInfo, rows, nearBalance]) => { - const { proposal_id, proposal_info } = createMulticallProposalInfo; - rows.unshift(nearBalance) - - newState = { - dao: newDAO, - rowContent: rows, - infos: { - admins: admins, - tokens: tokens, - jobs: jobs, - bond: bond - }, - loading: false, - proposed: proposal_id, - proposedInfo: proposal_info - } + view(multicall, "get_tokens", {}).catch((e) => {}), + view(multicall, "get_jobs", {}).catch((e) => {}), + view(multicall, "get_job_bond", {}).catch((e) => {}), + this.proposalAlreadyExists(newDAO).catch((e) => {}), + this.balancesToRows(multicall, newDAO).catch((e) => {}), + this.nearInfo(multicall, newDAO).catch((e) => {}), + ]).then(([admins, tokens, jobs, bond, createMulticallProposalInfo, rows, nearBalance]) => { + const { proposal_id, proposal_info } = createMulticallProposalInfo; + rows.unshift(nearBalance); + + newState = { + dao: newDAO, + rowContent: rows, + infos: { + admins: admins, + tokens: tokens, + jobs: jobs, + bond: bond, + }, + loading: false, + proposed: proposal_id, + proposedInfo: proposal_info, + }; - // update visuals - this.setState(newState); - }) + // update visuals + this.setState(newState); + }); } - }); - } async tokenInfo(multicall, dao) { - const tokenAddrList = await FungibleToken.getLikelyTokenContracts(multicall) - - const likelyTokenList = await Promise.all(tokenAddrList.map((address) => - FungibleToken.init(address) - )) - - const tokenList = likelyTokenList.filter(tkn => tkn.ready === true) - - const balances = await Promise.all(tokenList.map(async (tkn) => { - const [multicallBalance, daoBalance] = await Promise.all([tkn.ftBalanceOf(multicall), tkn.ftBalanceOf(dao.address)]) - return { - token: tkn, - multicallBalance: multicallBalance, - daoBalance: daoBalance, - total: Big(multicallBalance).add(daoBalance).toFixed() - } - })) + const tokenAddrList = await FungibleToken.getLikelyTokenContracts(multicall); + + const likelyTokenList = await Promise.all(tokenAddrList.map((address) => FungibleToken.init(address))); + + const tokenList = likelyTokenList.filter((tkn) => tkn.ready === true); + + const balances = await Promise.all( + tokenList.map(async (tkn) => { + const [multicallBalance, daoBalance] = await Promise.all([ + tkn.ftBalanceOf(multicall), + tkn.ftBalanceOf(dao.address), + ]); + return { + token: tkn, + multicallBalance: multicallBalance, + daoBalance: daoBalance, + total: Big(multicallBalance).add(daoBalance).toFixed(), + }; + }) + ); - return balances.filter(el => Big(el.total).gt('0')) + return balances.filter((el) => Big(el.total).gt("0")); } - balancesToRows(multicall, dao) { - return this.tokenInfo(multicall, dao).then( - res => res.map( - row => [row.token.metadata.symbol, row.token.metadata.icon, formatTokenAmount(row.multicallBalance, row.token.metadata.decimals, 2), formatTokenAmount(row.daoBalance, row.token.metadata.decimals, 2), formatTokenAmount(row.total, row.token.metadata.decimals, 2)] - ) - ) + return this.tokenInfo(multicall, dao).then((res) => + res.map((row) => [ + row.token.metadata.symbol, + row.token.metadata.icon, + formatTokenAmount(row.multicallBalance, row.token.metadata.decimals, 2), + formatTokenAmount(row.daoBalance, row.token.metadata.decimals, 2), + formatTokenAmount(row.total, row.token.metadata.decimals, 2), + ]) + ); } async nearInfo() { - const { addr, dao } = this.state; const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; - const nearBalanceMulticall = (await viewAccount(multicall)).amount - const nearBalanceDao = (await viewAccount(dao.address)).amount + const nearBalanceMulticall = (await viewAccount(multicall)).amount; + const nearBalanceDao = (await viewAccount(dao.address)).amount; - return ['NEAR', 'https://s2.coinmarketcap.com/static/img/coins/64x64/6535.png', formatTokenAmount(nearBalanceMulticall, 24, 2), formatTokenAmount(nearBalanceDao, 24, 2), formatTokenAmount(Big(nearBalanceDao).add(nearBalanceMulticall).toFixed(), 24, 2)] + return [ + "NEAR", + "https://s2.coinmarketcap.com/static/img/coins/64x64/6535.png", + formatTokenAmount(nearBalanceMulticall, 24, 2), + formatTokenAmount(nearBalanceDao, 24, 2), + formatTokenAmount(Big(nearBalanceDao).add(nearBalanceMulticall).toFixed(), 24, 2), + ]; } displayToken() { // format to show small balances } - - - - getContent() { const { selector: walletSelector } = this.context; const { infos, loading, rowContent } = this.state; - // if user not logged in, remind him to sign in. // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) if (!walletSelector.isSignedIn()) return
Please sign in to continue
; @@ -452,19 +469,26 @@ export default class DaoComponent extends Component { // errors to display const displayErrorsList = ["addr", "noDao", "noContract"]; const displayErrors = Object.keys(this.errors) - .filter(e => this.errors[e].isBad && displayErrorsList.includes(e)) - .map(e =>

- {this.errors[e].isBad ? '\u2717' : '\u2714'} - {this.errors[e].message} -

); + .filter((e) => this.errors[e].isBad && displayErrorsList.includes(e)) + .map((e) => ( +

+ {this.errors[e].isBad ? "\u2717" : "\u2714"} + {this.errors[e].message} +

+ )); if (displayErrors.length > 0) - return (<> -
-
{displayErrors}
- {this.createMulticall()} -
- ); + return ( + <> +
+
{displayErrors}
+ {this.createMulticall()} +
+ + ); // loading ... if (loading) return
; @@ -477,45 +501,51 @@ export default class DaoComponent extends Component { // infos found return ( - -
- -

Admins

-
    - {infos.admins.map(a =>
  • {this.toLink(a)}
  • )} -
-
-
- -

Jobs

-
- {infos.jobs.map(j => this.job(j))} + +
+ +

Admins

+
    + {infos.admins.map((a) => ( +
  • {this.toLink(a)}
  • + ))} +
-
-

Job Bond - {`${infos.bond !== "..." ? toNEAR(infos.bond) : "..."} Ⓝ`} -

-
-
, -
-
- - -

Token Balances

- -
- -
-

Whitelisted Tokens

-
    - {infos.tokens.map(t =>
  • {this.toLink(t)}
  • )} -
- -
- - - ]} />) +
+ +

Jobs

+
{infos.jobs.map((j) => this.job(j))}
+
+
+

+ Job Bond + {`${infos.bond !== "..." ? toNEAR(infos.bond) : "..."} Ⓝ`} +

+
+ , +
+
+

Token Balances

+ +
+ +
+

Whitelisted Tokens

+
    + {infos.tokens.map((t) => ( +
  • {this.toLink(t)}
  • + ))} +
+
+ , + ]} + /> + ); } render() { diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index f3f17605..4e6b003e 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -31,7 +31,7 @@ export default class Multicall { * * @param accountId */ - static async isMulticall(accountId: string): Promise { + static async isMulticall(accountId: string): Promise { const accountInfo = await viewAccount(accountId); const codeHash: string = accountInfo.code_hash; return Multicall.CONTRACT_CODE_HASHES.includes(codeHash); From 05511c6c4dd565f9fea11deedb31cdcb5a5272f3 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Tue, 6 Sep 2022 21:31:13 +0200 Subject: [PATCH 007/537] Add NEP-145 class and integrate it with NEP-141 --- src/components/dao/dao.js | 2 +- src/utils/contracts/fungibleToken.ts | 89 --------------- src/utils/standards/fungibleToken.ts | 93 ++++++++++++++++ src/utils/standards/storageManagement.ts | 133 +++++++++++++++++++++++ 4 files changed, 227 insertions(+), 90 deletions(-) delete mode 100644 src/utils/contracts/fungibleToken.ts create mode 100644 src/utils/standards/fungibleToken.ts create mode 100644 src/utils/standards/storageManagement.ts diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index 96cce329..8df5865f 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -14,7 +14,7 @@ import debounce from "lodash.debounce"; import Table from "../../func-components/Table"; import Tabs from "../../func-components/Tabs"; import PageTabs from "../../func-components/Tabs/PageTabs"; -import { FungibleToken } from "../../utils/contracts/fungibleToken"; +import { FungibleToken } from "../../utils/standards/fungibleToken"; import * as nearAPI from "near-api-js"; // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR diff --git a/src/utils/contracts/fungibleToken.ts b/src/utils/contracts/fungibleToken.ts deleted file mode 100644 index 0efa7265..00000000 --- a/src/utils/contracts/fungibleToken.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { view } from "../wallet"; - - -// Fungible token metadata follows NEP-148. See: https://nomicon.io/Standards/Tokens/FungibleToken/Metadata -type FungibleTokenMetadata = { - spec: string; - name: string; - symbol: string; - icon?: string|null; // optional - reference?: string|null; // optional - reference_hash?: string|null; // optional - decimals: number; -} - -// TODO: support NEP-145 for storage methods. See: https://nomicon.io/Standards/StorageManagement - - -// Fungible token core follow NEP-141. See: https://nomicon.io/Standards/Tokens/FungibleToken/Core -class FungibleToken { - - address: string; - // needs initialization, but start with empty metadata - metadata: FungibleTokenMetadata = { spec: "", name: "", symbol: "", decimals: -1 }; - // token total supply - totalSupply: string = ""; - // Token instance is ready when info (metadata...) are fetched & assigned correctly - ready: boolean = false; - - - // shouldn't be used directly, use init() instead - constructor(tokenAddress: string) { - this.address = tokenAddress; - } - - // used to create and initialize a FungibleToken instance - static async init (tokenAddress: string): Promise { - // fetch token info and mark it ready - const newToken = new FungibleToken(tokenAddress); - const [ metadata, totalSupply ] = await Promise.all([ - // on failure set metadata to default metadata (empty) - newToken.ftMetadata().catch(err => { return newToken.metadata }), - // on failure set total supply to default (empty string) - newToken.ftTotalSupply().catch(err => { return newToken.totalSupply }) - ]); - newToken.metadata = metadata; - newToken.totalSupply = totalSupply; - // set ready to true if token info successfully got updated. - if ( - newToken.totalSupply !== "" - && newToken.metadata.decimals >= 0 - ) { - newToken.ready = true; - } - return newToken; - } - - async ftMetadata (): Promise { - return view(this.address, "ft_metadata", {}); - } - - async ftTotalSupply (): Promise { - return view(this.address, "ft_total_supply", {}); - } - - async ftBalanceOf (accountId: string): Promise { - return view(this.address, "ft_balance_of", { account_id: accountId }); - } - - static async getLikelyTokenContracts (accountId: string): Promise { - const response = await fetch( - `${window.nearConfig.helperUrl}/account/${accountId}/likelyTokens`, - { method: "GET", headers: { "Content-type": "application/json; charset=utf-8" } } - ); - - // on success: return list of likely tokens owned by accountId - if (response.ok) { - return (await response.json()); - } - // on error: return empty list - else { - return []; - } - } - -} - -export{ - FungibleToken -} diff --git a/src/utils/standards/fungibleToken.ts b/src/utils/standards/fungibleToken.ts new file mode 100644 index 00000000..ccbc2aab --- /dev/null +++ b/src/utils/standards/fungibleToken.ts @@ -0,0 +1,93 @@ +import { view } from "../wallet"; +import { StorageManagement } from "./storageManagement"; +import type { StorageBalance, StorageBalanceBounds } from "./storageManagement"; + +// Fungible token metadata follows NEP-148. See: https://nomicon.io/Standards/Tokens/FungibleToken/Metadata +type FungibleTokenMetadata = { + spec: string; + name: string; + symbol: string; + icon?: string | null; // optional + reference?: string | null; // optional + reference_hash?: string | null; // optional + decimals: number; +}; + +// Fungible token core follow NEP-141. See: https://nomicon.io/Standards/Tokens/FungibleToken/Core +// Also implements NEP-145 for storage management. See: https://nomicon.io/Standards/StorageManagement +class FungibleToken extends StorageManagement { + address: string; + // needs initialization, but start with empty metadata + metadata: FungibleTokenMetadata = { spec: "", name: "", symbol: "", decimals: -1 }; + // token total supply + totalSupply: string = ""; + // storage balance bounds. Needs initialization, but starts with "0" values + // Users must have at least the min amount to receive tokens. + storageBounds: StorageBalanceBounds = { min: "0", max: "0" }; + // Token instance is ready when info (metadata...) are fetched & assigned correctly + ready: boolean = false; + + // shouldn't be used directly, use init() instead + constructor(tokenAddress: string) { + super(tokenAddress); + this.address = tokenAddress; + } + + // used to create and initialize a FungibleToken instance + static async init(tokenAddress: string): Promise { + // fetch token info and mark it ready + const newToken = new FungibleToken(tokenAddress); + const [metadata, totalSupply, storageBounds] = await Promise.all([ + // on failure set metadata to default metadata (empty) + newToken.ftMetadata().catch((err) => { + return newToken.metadata; + }), + // on failure set total supply to default (empty string) + newToken.ftTotalSupply().catch((err) => { + return newToken.totalSupply; + }), + // get storage balance bounds + newToken.storageBalanceBounds().catch((err) => { + return { min: "0", max: "0" }; + }), + ]); + newToken.metadata = metadata; + newToken.totalSupply = totalSupply; + newToken.storageBounds = storageBounds; + // set ready to true if token info successfully got updated. + if (newToken.totalSupply !== "" && newToken.metadata.decimals >= 0) { + newToken.ready = true; + } + return newToken; + } + + async ftMetadata(): Promise { + return view(this.address, "ft_metadata", {}); + } + + async ftTotalSupply(): Promise { + return view(this.address, "ft_total_supply", {}); + } + + async ftBalanceOf(accountId: string): Promise { + return view(this.address, "ft_balance_of", { account_id: accountId }); + } + + static async getLikelyTokenContracts(accountId: string): Promise { + const response = await fetch(`${window.nearConfig.helperUrl}/account/${accountId}/likelyTokens`, { + method: "GET", + headers: { "Content-type": "application/json; charset=utf-8" }, + }); + + // on success: return list of likely tokens owned by accountId + if (response.ok) { + return await response.json(); + } + // on error: return empty list + else { + return []; + } + } +} + +export { FungibleToken }; diff --git a/src/utils/standards/storageManagement.ts b/src/utils/standards/storageManagement.ts new file mode 100644 index 00000000..30f49cf0 --- /dev/null +++ b/src/utils/standards/storageManagement.ts @@ -0,0 +1,133 @@ +import { tx, view } from "../wallet"; +import { toGas, toYocto } from "../converter"; + +// Storage management standard follow NEP-145. See: https://nomicon.io/Standards/StorageManagement +class StorageManagement { + address: string; + + constructor(contractAddress: string) { + this.address = contractAddress; + } + + /****************/ + /* VIEW METHODS */ + /****************/ + // Returns minimum and maximum allowed balance amounts to interact with this + // contract. See StorageBalanceBounds. + async storageBalanceBounds(): Promise { + return view(this.address, "storage_balance_bounds", {}); + } + + // Returns the StorageBalance structure of the valid `account_id` + // provided. Must panic if `account_id` is invalid. + // + // If `account_id` is not registered, must return `null`. + async storageBalanceOf(accountId: string): Promise { + const balance = await view(this.address, "storage_balance_of", { account_id: accountId }); + // storage standard returns null for non registered users. We return 0 balance instead + if (balance === null) return { total: "0", available: "0" }; + else return balance; + } + + /************************************/ + /* CHANGE METHODS on fungible token */ + /************************************/ + // Payable method that receives an attached deposit of Ⓝ for a given account. + // + // If `account_id` is omitted, the deposit MUST go toward predecessor account. + // If provided, deposit MUST go toward this account. If invalid, contract MUST + // panic. + // + // If `registration_only=true`, contract MUST refund above the minimum balance + // if the account wasn't registered and refund full deposit if already + // registered. + // + // The `storage_balance_of.total` + `attached_deposit` in excess of + // `storage_balance_bounds.max` must be refunded to predecessor account. + // + // Returns the StorageBalance structure showing updated balances. + // IMPORTANT!!! This method has an extra parameter "amount" to control the amount in attached deposit + async storageDeposit(accountId: string, registrationOnly: boolean, amount: string): Promise { + return tx( + this.address, + "storage_deposit", + { + account_id: accountId, + registration_only: registrationOnly, + }, + toGas("5"), // 5 Tgas + amount + ); + } + + // Withdraw specified amount of available Ⓝ for predecessor account. + // + // This method is safe to call. It MUST NOT remove data. + // + // `amount` is sent as a string representing an unsigned 128-bit integer. If + // omitted, contract MUST refund full `available` balance. If `amount` exceeds + // predecessor account's available balance, contract MUST panic. + // + // If predecessor account not registered, contract MUST panic. + // + // MUST require exactly 1 yoctoNEAR attached balance to prevent restricted + // function-call access-key call (UX wallet security) + // + // Returns the StorageBalance structure showing updated balances. + + /* storageWithdraw(amount: string | null): Promise; */ + + // Unregisters the predecessor account and returns the storage NEAR deposit. + // + // If the predecessor account is not registered, the function MUST return + // `false` without panic. + // + // If `force=true` the function SHOULD ignore existing account data, such as + // non-zero balances on an FT contract (that is, it should burn such balances), + // and close the account. Contract MAY panic if it doesn't support forced + // unregistration, or if it can't force unregister for the particular situation + // (example: too much data to delete at once). + // + // If `force=false` or `force` is omitted, the contract MUST panic if caller + // has existing account data, such as a positive registered balance (eg token + // holdings). + // + // MUST require exactly 1 yoctoNEAR attached balance to prevent restricted + // function-call access-key call (UX wallet security) + // + // Returns `true` iff the account was successfully unregistered. + // Returns `false` iff account was not registered before. + + /* storageUnregister(force: boolean | null): Promise; */ +} + +// The structure that will be returned for the methods: +// * `storage_deposit` +// * `storage_withdraw` +// * `storage_balance_of` +// The `total` and `available` values are string representations of unsigned +// 128-bit integers showing the balance of a specific account in yoctoⓃ. +type StorageBalance = { + total: string; + available: string; +}; + +// The below structure will be returned for the method `storage_balance_bounds`. +// Both `min` and `max` are string representations of unsigned 128-bit integers. +// +// `min` is the amount of tokens required to start using this contract at all +// (eg to register with the contract). If a new contract user attaches `min` +// NEAR to a `storage_deposit` call, subsequent calls to `storage_balance_of` +// for this user must show their `total` equal to `min` and `available=0` . +// +// A contract may implement `max` equal to `min` if it only charges for initial +// registration, and does not adjust per-user storage over time. A contract +// which implements `max` must refund deposits that would increase a user's +// storage balance beyond this amount. +type StorageBalanceBounds = { + min: string; + max: string | null; +}; + +export { StorageManagement }; +export type { StorageBalance, StorageBalanceBounds }; From 992af514db4a35f93142101485085ba218082dcf Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Wed, 7 Sep 2022 19:14:04 +0200 Subject: [PATCH 008/537] add multicall view helper methods. Move multicall proposing functions to SputnikDAO class --- src/components/dao/dao.js | 6 +- src/components/export/export.js | 35 +++++--- src/components/wallet/wallet.js | 98 +-------------------- src/families/multicall/transfer.js | 2 +- src/utils/contracts/multicall.ts | 111 ++++++++++++++++++++++-- src/utils/contracts/sputnik-dao.ts | 131 ++++++++++++++++++++++++++--- 6 files changed, 255 insertions(+), 128 deletions(-) diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index cb6aa8d8..4f745158 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -3,7 +3,7 @@ import { Base64 } from "js-base64"; import React, { Component } from "react"; import { ArgsAccount, ArgsError } from "../../utils/args"; import { STORAGE } from "../../utils/persistent"; -import { toNEAR, toYocto, Big } from "../../utils/converter"; +import { toNEAR, toYocto, toGas, Big } from "../../utils/converter"; import { view } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; @@ -169,7 +169,7 @@ export default class DaoComponent extends Component { }) ), deposit: depo.toFixed(), - gas: "150000000000000", + gas: toGas("150"), // 150 Tgas }, ], }, @@ -204,7 +204,7 @@ export default class DaoComponent extends Component {
- - - {header.map((string, idx) => ( - - {sortHeaders && - sortHeaders.includes(string) && - order && - orderBy && - createSortfunction ? ( - - orderBy === string - ? order === "desc" - ? theme.palette.primary.main - : "#00000099" - : "#00000099", - }, - "& .MuiTableSortLabel-iconDirectionAsc .sort-up": { - fill: (theme) => - orderBy === string - ? order === "asc" - ? theme.palette.primary.main - : "#00000099" - : "#00000099", - }, - }} - > - {string} + {matches ? ( + <> + {rows.map((data, index) => ( + + + {header.map((headerString, index) => ( + + + {headerString} + + theme.palette.text.secondary }} + component="div" + > + {data[index] ?? null} + + {collapsible && index + 1 === header.length && ( + setIsOpen(open => !open)} + sx={{ flexGrow: 0 }} + > + + {/* {isOpen ? : } */} + + )} + + ))} + + + ))} + + ) : ( + +
+ + + {header.map((string, idx) => ( + + {sortHeaders && + sortHeaders.includes(string) && + order && + orderBy && + createSortfunction ? ( + + orderBy === string + ? order === "desc" + ? theme.palette.primary.main + : "#00000099" + : "#00000099", + }, + "& .MuiTableSortLabel-iconDirectionAsc .sort-up": { + fill: (theme) => + orderBy === string + ? order === "asc" + ? theme.palette.primary.main + : "#00000099" + : "#00000099", + }, + }} + > + {string} - {/* + {/* {order === 'desc' ? 'sorted descending' : 'sorted ascending'} */} - - ) : ( - string - )} - - ))} - - - - {rows.map((row, idx) => ( - - ))} - -
- - )} - - ); + + ) : ( + string + )} + + ))} + + + + {rows.map((row, idx) => ( + + ))} + + + + )} + + ); } function Row({ - row, - variant, - collapsible, - hiddenPart, - fontSize, + row, + variant, + collapsible, + hiddenPart, + fontSize, }: { - row: (string | number | JSX.Element)[]; - variant: "outlined" | "grey"; - collapsible?: boolean; - hiddenPart?: JSX.Element; - fontSize?: string; + row: (string | number | JSX.Element)[]; + variant: "outlined" | "grey"; + collapsible?: boolean; + hiddenPart?: JSX.Element; + fontSize?: string; }) { - const [isOpen, setIsOpen] = useState(false); + const [isOpen, setIsOpen] = useState(false); - return ( - <> - - {row.map((data, idx) => ( - <> - - {idx === 1 ? : data} - - - ))} - {collapsible && ( - - setIsOpen((open) => !open)} - sx={{ flexGrow: 0 }} - > - {isOpen ? : } - - - )} - - {collapsible && ( - - - + - - {hiddenPart} - - - - - )} - - ); + {row.map((data, idx) => ( + <> + + {idx === 1 ? ( + + ) : ( + data + )} + + + ))} + {collapsible && ( + + setIsOpen((open) => !open)} + sx={{ flexGrow: 0 }} + > + {isOpen ? : } + + + )} + + {collapsible && ( + + + + + {hiddenPart} + + + + + )} + + ); } From 0e2aa5865150e1df7dad868a83a4169fc2cf1754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 12:36:26 +0400 Subject: [PATCH 011/537] chore: Use named exports & Apply formatting --- src/components/dao/dao.js | 17 ++- src/func-components/Table/index.tsx | 80 ++++++++----- src/func-components/Tabs/PageTabs.tsx | 70 ++++++----- src/func-components/Tabs/index.tsx | 160 ++++++++++++-------------- 4 files changed, 164 insertions(+), 163 deletions(-) diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index e3bf01b3..aabfdd5a 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -1,6 +1,10 @@ +import { InputAdornment } from "@mui/material"; import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; import { Base64 } from "js-base64"; +import debounce from "lodash.debounce"; +import * as nearAPI from "near-api-js"; import React, { Component } from "react"; + import { ArgsAccount, ArgsError } from "../../utils/args"; import { STORAGE } from "../../utils/persistent"; import { toNEAR, toYocto, Big, formatTokenAmount } from "../../utils/converter"; @@ -8,14 +12,11 @@ import { view, viewAccount } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; import { TextInput } from "../editor/elements"; -import { InputAdornment } from "@mui/material"; -import "./dao.scss"; -import debounce from "lodash.debounce"; -import Table from "../../func-components/Table"; -import Tabs from "../../func-components/Tabs"; -import PageTabs from "../../func-components/Tabs/PageTabs"; +import { Table } from "../../func-components/Table"; +import { PageTabs } from "../../func-components/Tabs/PageTabs"; import { FungibleToken } from "../../utils/standards/fungibleToken"; -import * as nearAPI from "near-api-js"; +import "./dao.scss"; + // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR @@ -551,8 +552,6 @@ export default class DaoComponent extends Component { render() { const { addr } = this.state; - console.log(this.state); - return (
diff --git a/src/func-components/Table/index.tsx b/src/func-components/Table/index.tsx index 365f4250..8c0f7ff6 100644 --- a/src/func-components/Table/index.tsx +++ b/src/func-components/Table/index.tsx @@ -11,12 +11,13 @@ import { Collapse, TableSortLabel, } from "@mui/material"; -import { useState } from "react"; -import useBreakpoint from "../../hooks/useBreakpoint"; + +// import { visuallyHidden } from '@mui/utils' import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; -import React from "react"; -// import { visuallyHidden } from '@mui/utils' +import React, { useState } from "react"; + +import useBreakpoint from "../../hooks/useBreakpoint"; const StyledTableContainer = styled(TableContainer)({ display: "table", @@ -76,9 +77,11 @@ const StyledTableRow = styled(TableRow, { shouldForwardProp: () => true })<{ position: "relative", whiteSpace: "pre", background: variant === "outlined" ? "transparent" : "#b4ccca", + "& + tr .MuiCollapse-root": { background: variant === "outlined" ? "transparent" : theme.palette.background.default, }, + "& .MuiTableCell-root": { fontSize: (fontSize ?? "16px") + "!important", justifyContent: "flex-start", @@ -87,9 +90,11 @@ const StyledTableRow = styled(TableRow, { shouldForwardProp: () => true })<{ borderColor: variant === "outlined" ? "#00000010" : "transparent", borderRight: "none", borderLeft: "none", + "& .MuiTypography-root": { fontSize: (fontSize ?? "16px") + "!important", }, + "&:first-of-type": { borderLeft: "1px solid", borderColor: variant === "outlined" ? "#00000010" : "transparent", @@ -97,6 +102,7 @@ const StyledTableRow = styled(TableRow, { shouldForwardProp: () => true })<{ borderTopLeftRadius: 16, borderBottomLeftRadius: 16, }, + "&:last-child": { borderRight: "1px solid", borderColor: variant === "outlined" ? "#00000010" : "transparent", @@ -105,10 +111,12 @@ const StyledTableRow = styled(TableRow, { shouldForwardProp: () => true })<{ borderBottomRightRadius: 16, }, }, + "&:hover": { "& + tr .MuiCollapse-root": { backgroundColor: variant === "outlined" ? "#E2E7F020" : "#dcefea", }, + backgroundColor: variant === "outlined" ? "#E2E7F020" : "#dcefea", }, })); @@ -118,6 +126,7 @@ const Card = styled("div")({ border: "1px solid rgba(0, 0, 0, 0.1)", borderRadius: 16, padding: 16, + "& > div": { width: "100%", }, @@ -137,6 +146,7 @@ const sortIcon = ({ className }: { className: string }) => ( d="M1.0875 6.5791L3 8.48743L4.9125 6.5791L5.5 7.1666L3 9.6666L0.5 7.1666L1.0875 6.5791Z" fill="#00000099" /> + div:first-of-type { white-space: nowrap; } + > div:last-child { width: 100%; display: flex; @@ -160,7 +172,7 @@ const CardRow = styled("div")(` } `); -export default function Table({ +export const Table = ({ header, rows, variant = "grey", @@ -184,7 +196,7 @@ export default function Table({ orderBy?: string; createSortfunction?: (label: string) => () => void; icons?: boolean; -}) { +}) => { const matches = useBreakpoint("md"); return ( @@ -209,12 +221,14 @@ export default function Table({ > {headerString} + theme.palette.text.secondary }} component="div" > {data[index] ?? null} + {collapsible && index + 1 === header.length && ( - {header.map((string, idx) => ( - + {header.map((string, index) => ( + {sortHeaders && sortHeaders.includes(string) && order && @@ -254,6 +268,7 @@ export default function Table({ transform: "none", opacity: 1, }, + "& .MuiTableSortLabel-iconDirectionDesc .sort-down": { fill: (theme) => orderBy === string @@ -262,6 +277,7 @@ export default function Table({ : "#00000099" : "#00000099", }, + "& .MuiTableSortLabel-iconDirectionAsc .sort-up": { fill: (theme) => orderBy === string @@ -285,15 +301,16 @@ export default function Table({ ))} + - {rows.map((row, idx) => ( + {rows.map((row, index) => ( ))} @@ -302,9 +319,9 @@ export default function Table({ )} ); -} +}; -function Row({ +const Row = ({ row, variant, collapsible, @@ -316,7 +333,7 @@ function Row({ collapsible?: boolean; hiddenPart?: JSX.Element; fontSize?: string; -}) { +}) => { const [isOpen, setIsOpen] = useState(false); return ( @@ -329,6 +346,7 @@ function Row({ ? { borderBottomLeftRadius: 0, borderBottomRightRadius: 0, + "& .MuiTableCell-root": { "&:first-of-type": { borderBottomLeftRadius: 0 }, "&:last-child": { borderBottomRightRadius: 0 }, @@ -337,23 +355,22 @@ function Row({ : undefined } > - {row.map((data, idx) => ( - <> - - {idx === 1 ? ( - - ) : ( - data - )} - - + {row.map((data, index) => ( + + {index === 1 ? ( + + ) : ( + data + )} + ))} + {collapsible && ( )} + {collapsible && ( ); -} +}; diff --git a/src/func-components/Tabs/PageTabs.tsx b/src/func-components/Tabs/PageTabs.tsx index 6307ece1..80dfdef9 100644 --- a/src/func-components/Tabs/PageTabs.tsx +++ b/src/func-components/Tabs/PageTabs.tsx @@ -1,42 +1,40 @@ import { Tab, TabProps } from "@mui/material"; import React from "react"; -import Tabs from "./index"; -export default function PageTabs({ contents }: { contents: JSX.Element[] }) { - return ( - - ); -} +import { Tabs } from "./index"; -function CustomTab(props: TabProps) { - return ( +const CustomTab = (props: TabProps) => ( +); + +export const PageTabs = ({ contents }: { contents: JSX.Element[] }) => ( + - ); -} +); diff --git a/src/func-components/Tabs/index.tsx b/src/func-components/Tabs/index.tsx index 4791dfb3..9e034c52 100644 --- a/src/func-components/Tabs/index.tsx +++ b/src/func-components/Tabs/index.tsx @@ -2,95 +2,81 @@ import React, { useCallback } from "react"; import { Tabs as MuiTabs, Tab, Box, TabProps } from "@mui/material"; interface Props { - titles: string[] | JSX.Element[]; - contents: React.ReactNode[]; - customCurrentTab?: number; - customOnChange?: (val: number) => void; - CustomTab?: React.FC; - tabPadding?: string; - fontWeight?: number; + titles: string[] | JSX.Element[]; + contents: React.ReactNode[]; + customCurrentTab?: number; + customOnChange?: (val: number) => void; + CustomTab?: React.FC; + tabPadding?: string; + fontWeight?: number; } -function TabPanel({ - children, - value, - index, -}: { - children: React.ReactNode; - value: number; - index: number; -}) { - return ; -} +const TabPanel = ({ children, value, index }: { children: React.ReactNode; value: number; index: number }) => ( + +); -export default function Tabs(props: Props) { - const { - titles, - contents, - customCurrentTab, - customOnChange, - tabPadding, - CustomTab, - } = props; - const [value, setValue] = React.useState(0); +export const Tabs = ({ titles, contents, customCurrentTab, customOnChange, tabPadding, CustomTab }: Props) => { + const [value, setValue] = React.useState(0); - const onChange = useCallback( - (e: React.ChangeEvent, value: any) => { - customOnChange ? customOnChange(value) : setValue(value); - }, - [customOnChange] - ); + const onChange = useCallback( + (e: React.ChangeEvent, value: any) => { + customOnChange ? customOnChange(value) : setValue(value); + }, + [customOnChange] + ); - return ( - - - - {CustomTab - ? titles.map((tab, idx) => ) - : titles.map((tab, idx) => ( - theme.palette.text.primary, - opacity: 0.4, - "&.Mui-selected": { - color: (theme) => theme.palette.text.primary, - opacity: 1, - }, - }} - /> - ))} - - - {contents.map((content, idx) => ( - - {content} - - ))} - - ); -} + return ( + + + + {CustomTab + ? titles.map((tab, idx) => ( + + )) + : titles.map((tab, idx) => ( + theme.palette.text.primary, + opacity: 0.4, + "&.Mui-selected": { + color: (theme) => theme.palette.text.primary, + opacity: 1, + }, + }} + /> + ))} + + + + {contents.map((content, idx) => ( + + {content} + + ))} + + ); +}; From 811983b65f3a6528b3775fffa81115b40a6c3cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 13:11:07 +0400 Subject: [PATCH 012/537] chore: Use consistent fs structure --- src/components/dao/dao.js | 4 +- src/func-components/Tabs/PageTabs.tsx | 40 ------------------- src/hooks/useBreakpoint.ts | 9 ----- .../ui/components/table}/index.tsx | 2 +- .../ui/components/tabs}/index.tsx | 38 +++++++++++++++++- src/shared/ui/lib/breakpoints.ts | 8 ++++ 6 files changed, 48 insertions(+), 53 deletions(-) delete mode 100644 src/func-components/Tabs/PageTabs.tsx delete mode 100644 src/hooks/useBreakpoint.ts rename src/{func-components/Table => shared/ui/components/table}/index.tsx (99%) rename src/{func-components/Tabs => shared/ui/components/tabs}/index.tsx (79%) create mode 100644 src/shared/ui/lib/breakpoints.ts diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index aabfdd5a..7874b6fc 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -12,8 +12,8 @@ import { view, viewAccount } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; import { TextInput } from "../editor/elements"; -import { Table } from "../../func-components/Table"; -import { PageTabs } from "../../func-components/Tabs/PageTabs"; +import { Table } from "../../shared/ui/components/table"; +import { PageTabs } from "../../shared/ui/components/tabs"; import { FungibleToken } from "../../utils/standards/fungibleToken"; import "./dao.scss"; diff --git a/src/func-components/Tabs/PageTabs.tsx b/src/func-components/Tabs/PageTabs.tsx deleted file mode 100644 index 80dfdef9..00000000 --- a/src/func-components/Tabs/PageTabs.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Tab, TabProps } from "@mui/material"; -import React from "react"; - -import { Tabs } from "./index"; - -const CustomTab = (props: TabProps) => ( - -); - -export const PageTabs = ({ contents }: { contents: JSX.Element[] }) => ( - -); diff --git a/src/hooks/useBreakpoint.ts b/src/hooks/useBreakpoint.ts deleted file mode 100644 index e2d70b7c..00000000 --- a/src/hooks/useBreakpoint.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useMediaQuery, useTheme } from '@mui/material' -import { Breakpoint } from '@mui/material/styles' - -export default function useBreakpoint(breakpoint: Breakpoint = 'sm') { - const theme = useTheme() - const matches = useMediaQuery(theme.breakpoints.down(breakpoint)) - - return matches -} diff --git a/src/func-components/Table/index.tsx b/src/shared/ui/components/table/index.tsx similarity index 99% rename from src/func-components/Table/index.tsx rename to src/shared/ui/components/table/index.tsx index 8c0f7ff6..8267ef89 100644 --- a/src/func-components/Table/index.tsx +++ b/src/shared/ui/components/table/index.tsx @@ -17,7 +17,7 @@ import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; import React, { useState } from "react"; -import useBreakpoint from "../../hooks/useBreakpoint"; +import { useBreakpoint } from "../../lib/breakpoints"; const StyledTableContainer = styled(TableContainer)({ display: "table", diff --git a/src/func-components/Tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx similarity index 79% rename from src/func-components/Tabs/index.tsx rename to src/shared/ui/components/tabs/index.tsx index 9e034c52..87911655 100644 --- a/src/func-components/Tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -1,5 +1,5 @@ -import React, { useCallback } from "react"; import { Tabs as MuiTabs, Tab, Box, TabProps } from "@mui/material"; +import React, { useCallback } from "react"; interface Props { titles: string[] | JSX.Element[]; @@ -15,6 +15,34 @@ const TabPanel = ({ children, value, index }: { children: React.ReactNode; value ); +const CustomTab = (props: TabProps) => ( + +); + export const Tabs = ({ titles, contents, customCurrentTab, customOnChange, tabPadding, CustomTab }: Props) => { const [value, setValue] = React.useState(0); @@ -80,3 +108,11 @@ export const Tabs = ({ titles, contents, customCurrentTab, customOnChange, tabPa ); }; + +export const PageTabs = ({ contents }: { contents: JSX.Element[] }) => ( + +); diff --git a/src/shared/ui/lib/breakpoints.ts b/src/shared/ui/lib/breakpoints.ts new file mode 100644 index 00000000..8271c568 --- /dev/null +++ b/src/shared/ui/lib/breakpoints.ts @@ -0,0 +1,8 @@ +import { useMediaQuery, useTheme } from "@mui/material"; +import { Breakpoint } from "@mui/material/styles"; + +export const useBreakpoint = (breakpoint: Breakpoint = "sm") => { + const theme = useTheme(); + + return useMediaQuery(theme.breakpoints.down(breakpoint)); +}; From b104dee3f7def3a2b5da7ebc718347421210a7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 14:30:37 +0400 Subject: [PATCH 013/537] Allow to pass arbitrary content into table row cells --- src/shared/ui/components/table/index.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/shared/ui/components/table/index.tsx b/src/shared/ui/components/table/index.tsx index 8267ef89..329eb830 100644 --- a/src/shared/ui/components/table/index.tsx +++ b/src/shared/ui/components/table/index.tsx @@ -355,19 +355,12 @@ const Row = ({ : undefined } > - {row.map((data, index) => ( + {row.map((content, index) => ( - {index === 1 ? ( - - ) : ( - data - )} + {content} ))} From 2965e317ac8c10eba58b9c759ed8bd97d13fdd76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 17:11:02 +0400 Subject: [PATCH 014/537] Add NEAR SVG icon --- src/shared/ui/components/icons/index.ts | 1 + src/shared/ui/components/icons/near.tsx | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 src/shared/ui/components/icons/index.ts create mode 100644 src/shared/ui/components/icons/near.tsx diff --git a/src/shared/ui/components/icons/index.ts b/src/shared/ui/components/icons/index.ts new file mode 100644 index 00000000..78ea3186 --- /dev/null +++ b/src/shared/ui/components/icons/index.ts @@ -0,0 +1 @@ +export { NearProtocolFilled } from "./near"; diff --git a/src/shared/ui/components/icons/near.tsx b/src/shared/ui/components/icons/near.tsx new file mode 100644 index 00000000..26c29d67 --- /dev/null +++ b/src/shared/ui/components/icons/near.tsx @@ -0,0 +1,8 @@ +import { SvgIcon, SvgIconProps } from "@mui/material"; +import React from "react"; + +export const NearProtocolFilled = (props: SvgIconProps) => ( + + + +); From cb5007410d6446a463f723712154d3055b377b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 17:35:47 +0400 Subject: [PATCH 015/537] Update NEAR SVG icon styles --- src/shared/ui/components/icons/near.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shared/ui/components/icons/near.tsx b/src/shared/ui/components/icons/near.tsx index 26c29d67..0736388f 100644 --- a/src/shared/ui/components/icons/near.tsx +++ b/src/shared/ui/components/icons/near.tsx @@ -2,7 +2,11 @@ import { SvgIcon, SvgIconProps } from "@mui/material"; import React from "react"; export const NearProtocolFilled = (props: SvgIconProps) => ( - + ); From 81c03936830d92a3553fbd8c4be6f28db2e1daa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 17:36:46 +0400 Subject: [PATCH 016/537] feat: Update token balances table --- src/components/dao/dao.js | 280 +++++++++++++++++++++----------------- 1 file changed, 157 insertions(+), 123 deletions(-) diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index 7874b6fc..9b5be68a 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -12,15 +12,16 @@ import { view, viewAccount } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; import { TextInput } from "../editor/elements"; +import { FungibleToken } from "../../utils/standards/fungibleToken"; import { Table } from "../../shared/ui/components/table"; import { PageTabs } from "../../shared/ui/components/tabs"; -import { FungibleToken } from "../../utils/standards/fungibleToken"; +import { NearProtocolFilled } from "../../shared/ui/components/icons"; import "./dao.scss"; // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR -const TableHeader = ["Token", "", "Multicall", "DAO", "Total"]; +const TableHeader = ["Token", "Multicall", "DAO", "Total"]; export default class DaoComponent extends Component { static contextType = useWalletSelector(); @@ -48,7 +49,7 @@ export default class DaoComponent extends Component { loading: false, proposed: -1, proposedInfo: {}, - rowContent: null, + rowContent: [["...", "...", "...", "..."]], info: { admins: [], tokens: [], @@ -141,28 +142,34 @@ export default class DaoComponent extends Component { createMulticall() { const { accountId } = this.context; - - if (this.fee === undefined) return; - const { loading, addr, dao, proposed, proposedInfo } = this.state; const { noContract, noDao } = this.errors; - // happens if wallet not logged in or DAO object not initialized yet - if (dao?.ready !== true) return <>; + if ( + this.fee === undefined || + // wallet not logged in or DAO object not initialized yet + dao?.ready !== true + ) { + return null; + } const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; const depo = Big(this.fee).plus(MIN_INSTANCE_BALANCE); + // can user propose a FunctionCall to DAO? const canPropose = dao.checkUserPermission(accountId, ProposalAction.AddProposal, ProposalKind.FunctionCall); + // can user vote approve a FunctionCall on the DAO? const canApprove = dao.checkUserPermission(accountId, ProposalAction.VoteApprove, ProposalKind.FunctionCall); const args = { proposal: { description: `create multicall instance for this DAO at ${multicall}`, + kind: { FunctionCall: { receiver_id: window.nearConfig.MULTICALL_FACTORY_ADDRESS, + actions: [ { method_name: "create", @@ -173,9 +180,11 @@ export default class DaoComponent extends Component { croncat_manager: window.nearConfig.CRONCAT_MANAGER_ADDRESS, job_bond: dao.policy.proposal_bond, }, + public_key: "HdJuXFRBKMEXuzEsXVscdd3aoBvEGGXDKQ3JoNhqJ4uU", }) ), + deposit: depo.toFixed(), gas: "150000000000000", }, @@ -187,14 +196,18 @@ export default class DaoComponent extends Component { if ( noContract.isBad && - !noDao.isBad && // base.sputnik-dao.near does not exist + // base.sputnik-dao.near does not exist + !noDao.isBad && !loading && - this.lastAddr === document.querySelector(".address-container input")._valueTracker.getValue() // disappear while debouncing + // disappear while debouncing + this.lastAddr === document.querySelector(".address-container input")._valueTracker.getValue() ) { - // no create multicall proposal exists if (proposed === -1) { - // ... and user can propose FunctionCall + // no create multicall proposal exists + if (canPropose) { + // ... and user can propose FunctionCall + return ( <>
@@ -209,6 +222,7 @@ export default class DaoComponent extends Component { {` by making a proposal.`}
+ ); - } - // ... and user cannot propose FunctionCall - else { + } else { + // ... and user cannot propose FunctionCall + return (
{/* hint: you can use "ref-community-board-testnet" as DAO to get to this message */} @@ -229,11 +243,12 @@ export default class DaoComponent extends Component {
); } - } - // create multicall proposal exists - else if (proposed !== -1) { - // user does not have rights to VoteApprove + } else if (proposed !== -1) { + // create multicall proposal exists + if (!canApprove) { + // user does not have rights to VoteApprove + return (
{`Proposal to create a multicall exists (#${proposed}), but you have no voting permissions on this DAO.`} @@ -247,9 +262,9 @@ export default class DaoComponent extends Component {
); - } - // user can VoteApprove and already voted - else if (proposedInfo.votes[accountId]) { + } else if (proposedInfo.votes[accountId]) { + // user can VoteApprove and already voted + return (
{`You have voted on creating a multicall instance for this DAO. It will be created as soon as the proposal passes voting.`} @@ -263,9 +278,9 @@ export default class DaoComponent extends Component {
); - } - // user can VoteApprove and did NOT vote yet. - else { + } else { + // user can VoteApprove and did NOT vote yet. + return ( <>
@@ -279,6 +294,7 @@ export default class DaoComponent extends Component { Open on AstroDAO
+
, +

Token Balances

+

Whitelisted Tokens

    @@ -572,6 +605,7 @@ export default class DaoComponent extends Component { }} />
+ {this.getContent()} ); From 2a4457320eeef071b8b339cd86781f569993cd40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 19:41:31 +0400 Subject: [PATCH 017/537] Create components namespace for tokens & Add token label component --- src/components/token/token.scss | 16 ++++++++++++++++ src/components/token/token.tsx | 26 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/components/token/token.scss create mode 100644 src/components/token/token.tsx diff --git a/src/components/token/token.scss b/src/components/token/token.scss new file mode 100644 index 00000000..fd048905 --- /dev/null +++ b/src/components/token/token.scss @@ -0,0 +1,16 @@ +@use "sass/mixin"; + +.token-label { + display: flex; + align-items: center; + gap: 14px; + + .icon { + width: 32px; + height: 32px; + } + + .symbol { + font-weight: bold; + } +} diff --git a/src/components/token/token.tsx b/src/components/token/token.tsx new file mode 100644 index 00000000..7187141f --- /dev/null +++ b/src/components/token/token.tsx @@ -0,0 +1,26 @@ +import React from "react"; + +import { NearGenericTokenIconFilled } from "../../shared/ui/components/icons/near"; +import "./token.scss"; + +export const TokenLabel = ({ + icon = , + symbol, +}: { + icon: string | JSX.Element; + symbol: string; +}) => ( + + {typeof icon === "string" ? ( + + ) : ( + {icon} + )} + + {symbol} + +); From 9e1a12925209138836079c831b72fc36eef3873c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 19:42:52 +0400 Subject: [PATCH 018/537] Add generic NEAR token SVG icon --- src/components/token/token.tsx | 2 +- src/shared/ui/components/icons/index.ts | 2 +- src/shared/ui/components/icons/near.tsx | 29 +++++++++++++++++++++++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/components/token/token.tsx b/src/components/token/token.tsx index 7187141f..6e1e031e 100644 --- a/src/components/token/token.tsx +++ b/src/components/token/token.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { NearGenericTokenIconFilled } from "../../shared/ui/components/icons/near"; +import { NearGenericTokenIconFilled } from "../../shared/ui/components/icons"; import "./token.scss"; export const TokenLabel = ({ diff --git a/src/shared/ui/components/icons/index.ts b/src/shared/ui/components/icons/index.ts index 78ea3186..f94a64a7 100644 --- a/src/shared/ui/components/icons/index.ts +++ b/src/shared/ui/components/icons/index.ts @@ -1 +1 @@ -export { NearProtocolFilled } from "./near"; +export { NearIconFilled, NearGenericTokenIconFilled } from "./near"; diff --git a/src/shared/ui/components/icons/near.tsx b/src/shared/ui/components/icons/near.tsx index 0736388f..877f9634 100644 --- a/src/shared/ui/components/icons/near.tsx +++ b/src/shared/ui/components/icons/near.tsx @@ -1,12 +1,37 @@ import { SvgIcon, SvgIconProps } from "@mui/material"; import React from "react"; -export const NearProtocolFilled = (props: SvgIconProps) => ( +export const NearIconFilled = (props: SvgIconProps) => ( ); + +export const NearGenericTokenIconFilled = (props: SvgIconProps) => ( + + + + +); From ecd5e10bb04ed344068ee92283c608ccb86e945f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Sep 2022 19:45:43 +0400 Subject: [PATCH 019/537] feat: Use token label component --- src/components/dao/dao.js | 68 +++++++++++++++------------------ src/components/token/token.scss | 3 +- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index 9b5be68a..75bfa8df 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -5,6 +5,7 @@ import debounce from "lodash.debounce"; import * as nearAPI from "near-api-js"; import React, { Component } from "react"; +import { TokenLabel } from "../token/token"; import { ArgsAccount, ArgsError } from "../../utils/args"; import { STORAGE } from "../../utils/persistent"; import { toNEAR, toYocto, Big, formatTokenAmount } from "../../utils/converter"; @@ -15,7 +16,7 @@ import { TextInput } from "../editor/elements"; import { FungibleToken } from "../../utils/standards/fungibleToken"; import { Table } from "../../shared/ui/components/table"; import { PageTabs } from "../../shared/ui/components/tabs"; -import { NearProtocolFilled } from "../../shared/ui/components/icons"; +import { NearIconFilled } from "../../shared/ui/components/icons"; import "./dao.scss"; // minimum balance a multicall instance needs for storage + state. @@ -338,6 +339,24 @@ export default class DaoComponent extends Component { ); } + async nearInfo() { + const { addr, dao } = this.state; + const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; + const nearBalanceMulticall = (await viewAccount(multicall)).amount; + const nearBalanceDao = (await viewAccount(dao.address)).amount; + + return [ + } + symbol="NEAR" + />, + + formatTokenAmount(nearBalanceMulticall, 24, 2), + formatTokenAmount(nearBalanceDao, 24, 2), + formatTokenAmount(Big(nearBalanceDao).add(nearBalanceMulticall).toFixed(), 24, 2), + ]; + } + async tokenInfo(multicall, dao) { const tokenAddrList = await FungibleToken.getLikelyTokenContracts(multicall); const likelyTokenList = await Promise.all(tokenAddrList.map((address) => FungibleToken.init(address))); @@ -365,16 +384,7 @@ export default class DaoComponent extends Component { balancesToRows(multicall, dao) { return this.tokenInfo(multicall, dao).then((res) => res.map(({ token, multicallBalance, daoBalance, total }) => [ - - - - {token.metadata.symbol} - , - + , formatTokenAmount(multicallBalance, token.metadata.decimals, 2), formatTokenAmount(daoBalance, token.metadata.decimals, 2), formatTokenAmount(total, token.metadata.decimals, 2), @@ -382,24 +392,6 @@ export default class DaoComponent extends Component { ); } - async nearInfo() { - const { addr, dao } = this.state; - const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; - const nearBalanceMulticall = (await viewAccount(multicall)).amount; - const nearBalanceDao = (await viewAccount(dao.address)).amount; - - return [ - - - NEAR - , - - formatTokenAmount(nearBalanceMulticall, 24, 2), - formatTokenAmount(nearBalanceDao, 24, 2), - formatTokenAmount(Big(nearBalanceDao).add(nearBalanceMulticall).toFixed(), 24, 2), - ]; - } - displayToken() { // format to show small balances } @@ -544,6 +536,15 @@ export default class DaoComponent extends Component { +
+

Whitelisted Tokens

+
    + {info.tokens.map((token) => ( +
  • {this.toLink(token)}
  • + ))} +
+
+

Jobs

@@ -567,15 +568,6 @@ export default class DaoComponent extends Component { rows={rowContent} />
- -
-

Whitelisted Tokens

-
    - {info.tokens.map((token) => ( -
  • {this.toLink(token)}
  • - ))} -
-
, ]} /> diff --git a/src/components/token/token.scss b/src/components/token/token.scss index fd048905..aac7cbb6 100644 --- a/src/components/token/token.scss +++ b/src/components/token/token.scss @@ -5,7 +5,8 @@ align-items: center; gap: 14px; - .icon { + .icon, + .icon svg { width: 32px; height: 32px; } From e23650988cf57fcfcab1f13dab1205d62e9f2e44 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Thu, 8 Sep 2022 19:05:26 +0200 Subject: [PATCH 020/537] use multicall object on DAO page to fetch and save info --- src/components/dao/dao.js | 130 +++++++++++++++---------------- src/components/wallet/wallet.js | 2 + src/utils/contracts/multicall.ts | 8 ++ 3 files changed, 71 insertions(+), 69 deletions(-) diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index 4f745158..25121c40 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -1,12 +1,14 @@ +// TODO: use Multical helper class to fetch & store infos, like admins, tokens etc... + import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; import { Base64 } from "js-base64"; import React, { Component } from "react"; import { ArgsAccount, ArgsError } from "../../utils/args"; import { STORAGE } from "../../utils/persistent"; import { toNEAR, toYocto, toGas, Big } from "../../utils/converter"; -import { view } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; +import { Multicall } from "../../utils/contracts/multicall"; import { TextInput } from "../editor/elements"; import { InputAdornment } from "@mui/material"; import "./dao.scss"; @@ -38,19 +40,17 @@ export default class DaoComponent extends Component { this.state = { addr: this.getBaseAddress(STORAGE.addresses.dao), dao: new SputnikDAO(STORAGE.addresses.dao), + multicall: new Multicall(STORAGE.addresses.multicall), loading: false, proposed: -1, proposedInfo: {}, infos: { - admins: [], - tokens: [], jobs: [], - bond: "...", }, }; - view(window.nearConfig.MULTICALL_FACTORY_ADDRESS, "get_fee", {}).then((createMulticallFee) => { - this.fee = createMulticallFee; + Multicall.getFactoryFee().then((multicallFactoryFee) => { + this.fee = multicallFactoryFee; this.loadInfos(); }); @@ -82,7 +82,7 @@ export default class DaoComponent extends Component { const proposals = res.filter((p) => { // discard if not active proposal to create multicall instance if ( - !(p.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) || + !(p.kind?.FunctionCall?.receiver_id === Multicall.FACTORY_ADDRESS) || !(p.kind?.FunctionCall?.actions?.[0]?.method_name === "create") || !(p.status === "InProgress") ) { @@ -124,8 +124,8 @@ export default class DaoComponent extends Component { let base; if (address.endsWith("." + SputnikDAO.FACTORY_ADDRESS)) base = address.split("." + SputnikDAO.FACTORY_ADDRESS)[0]; - else if (address.endsWith("." + window.nearConfig.MULTICALL_FACTORY_ADDRESS)) - base = address.split("." + window.nearConfig.MULTICALL_FACTORY_ADDRESS)[0]; + else if (address.endsWith("." + Multicall.FACTORY_ADDRESS)) + base = address.split("." + Multicall.FACTORY_ADDRESS)[0]; else base = address; return new ArgsAccount(base); @@ -136,13 +136,12 @@ export default class DaoComponent extends Component { if (this.fee === undefined) return; - const { loading, addr, dao, proposed, proposedInfo } = this.state; + const { loading, dao, multicall, proposed, proposedInfo } = this.state; const { noContract, noDao } = this.errors; // happens if wallet not logged in or DAO object not initialized yet if (dao?.ready !== true) return <>; - const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; const depo = Big(this.fee).plus(MIN_INSTANCE_BALANCE); // can user propose a FunctionCall to DAO? const canPropose = dao.checkUserPermission(accountId, ProposalAction.AddProposal, ProposalKind.FunctionCall); @@ -151,10 +150,10 @@ export default class DaoComponent extends Component { const args = { proposal: { - description: `create multicall instance for this DAO at ${multicall}`, + description: `create multicall instance for this DAO at ${multicall.address}`, kind: { FunctionCall: { - receiver_id: window.nearConfig.MULTICALL_FACTORY_ADDRESS, + receiver_id: Multicall.FACTORY_ADDRESS, actions: [ { method_name: "create", @@ -179,7 +178,7 @@ export default class DaoComponent extends Component { if ( noContract.isBad && - !noDao.isBad && // base.sputnik-dao.near does not exist + !noDao.isBad && !loading && this.lastAddr === document.querySelector(".address-container input")._valueTracker.getValue() // disappear while debouncing ) { @@ -318,7 +317,7 @@ export default class DaoComponent extends Component { const { addr: addrError, noContract, noDao } = this.errors; const { addr } = this.state; - const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; + const multicallAddress = `${addr.value}.${Multicall.FACTORY_ADDRESS}`; const daoAddress = `${addr.value}.${SputnikDAO.FACTORY_ADDRESS}`; if (this.lastAddr === addr.value) return; @@ -339,59 +338,52 @@ export default class DaoComponent extends Component { let newState = {}; - // initialize DAO object - SputnikDAO.init(daoAddress) - .catch((e) => {}) - .then((newDAO) => { - // DAO not ready => either no SputnikDAO contract on the chosen address - // or some error happened during DAO object init. - if (!newDAO.ready) { - noContract.isBad = true; - noDao.isBad = true; - this.setState({ + // initialize DAO and multicall objects + Promise.all([ + SputnikDAO.init(daoAddress).catch((e) => {}), + Multicall.init(multicallAddress).catch((e) => {}), + ]).then(([newDAO, newMulticall]) => { + // DAO or multicall not ready => either no contract on the chosen address + // or some error happened during object initialization. + if (!newDAO.ready || !newMulticall.ready) { + noContract.isBad = !newMulticall.ready; + noDao.isBad = !newDAO.ready; + this.setState({ + dao: newDAO, + multicall: newMulticall, + loading: false, + }); + return; + } + // DAO and multicall correctly initialized, try to fetch multicall info + else { + Promise.all([ + newMulticall.getJobs().catch((e) => {}), + this.proposalAlreadyExists(newDAO).catch((e) => {}), + ]).then(([jobs, createMulticallProposalInfo]) => { + const { proposal_id, proposal_info } = createMulticallProposalInfo; + + newState = { dao: newDAO, + multicall: newMulticall, + infos: { + jobs: jobs, + }, loading: false, - }); - return; - } - // DAO correctly initialized, try to fetch multicall info - else { - Promise.all([ - view(multicall, "get_admins", {}).catch((e) => { - if (e.type === "AccountDoesNotExist" && e.toString().includes(` ${multicall} `)) { - noContract.isBad = true; - } - }), - view(multicall, "get_tokens", {}).catch((e) => {}), - view(multicall, "get_jobs", {}).catch((e) => {}), - view(multicall, "get_job_bond", {}).catch((e) => {}), - this.proposalAlreadyExists(newDAO).catch((e) => {}), - ]).then(([admins, tokens, jobs, bond, createMulticallProposalInfo]) => { - const { proposal_id, proposal_info } = createMulticallProposalInfo; - - newState = { - dao: newDAO, - infos: { - admins: admins, - tokens: tokens, - jobs: jobs, - bond: bond, - }, - loading: false, - proposed: proposal_id, - proposedInfo: proposal_info, - }; - - // update visuals - this.setState(newState); - }); - } - }); + proposed: proposal_id, + proposedInfo: proposal_info, + }; + + // update visuals + this.setState(newState); + }); + } + }); } getContent() { const { selector: walletSelector } = this.context; - const { infos, loading } = this.state; + const { infos, multicall, loading } = this.state; // if user not logged in, remind him to sign in. // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) @@ -425,8 +417,8 @@ export default class DaoComponent extends Component { if (loading) return
; // everything should be loaded - if (!infos.admins || !infos.tokens || !infos.bond) { - console.error("infos incomplete", infos); + if (!multicall.admins || !multicall.tokensWhitelist || !multicall.jobBond) { + console.error("multicall infos incomplete", multicall); return
Unexpected error! Multicall might be outdated.
; } @@ -437,8 +429,8 @@ export default class DaoComponent extends Component {

Admins

    - {infos.admins.map((a) => ( -
  • {this.toLink(a)}
  • + {multicall.admins.map((a) => ( +
  • {this.toLink(a)}
  • ))}
@@ -446,8 +438,8 @@ export default class DaoComponent extends Component {

Tokens

    - {infos.tokens.map((t) => ( -
  • {this.toLink(t)}
  • + {multicall.tokensWhitelist.map((t) => ( +
  • {this.toLink(t)}
  • ))}
@@ -459,7 +451,7 @@ export default class DaoComponent extends Component {

Job Bond - {`${infos.bond !== "..." ? toNEAR(infos.bond) : "..."} Ⓝ`} + {`${multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "..."} Ⓝ`}

diff --git a/src/components/wallet/wallet.js b/src/components/wallet/wallet.js index 8b1eebd9..2c554a08 100644 --- a/src/components/wallet/wallet.js +++ b/src/components/wallet/wallet.js @@ -1,3 +1,5 @@ +// TODO: use Multical helper class to fetch & store infos, like admins, tokens etc... + import React, { Component } from "react"; import { view } from "../../utils/wallet"; import { STORAGE } from "../../utils/persistent"; diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index 0e83c6db..40f25bf1 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -111,6 +111,14 @@ class Multicall { return Multicall.CONTRACT_CODE_HASHES.includes(codeHash); } + /** + * Multicall's factory has an admin-controlled fee to be + * paid upon creating a new multicall instance contract + */ + static async getFactoryFee(): Promise { + return view(this.FACTORY_ADDRESS, "get_fee", {}); + } + /** * get list of admins */ From b1845fc5c61f03ed7d7769911b8a68893222dc21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Sep 2022 10:11:26 +0400 Subject: [PATCH 021/537] wip: Rework tabs --- src/shared/ui/components/tabs/index.tsx | 140 ++++++++---------------- 1 file changed, 45 insertions(+), 95 deletions(-) diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx index 87911655..15403d4b 100644 --- a/src/shared/ui/components/tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -1,118 +1,68 @@ -import { Tabs as MuiTabs, Tab, Box, TabProps } from "@mui/material"; -import React, { useCallback } from "react"; +import { Tabs as MuiTabs, Tab, Box } from "@mui/material"; +import clsx from "clsx"; +import React, { Fragment, useCallback } from "react"; interface Props { titles: string[] | JSX.Element[]; - contents: React.ReactNode[]; - customCurrentTab?: number; - customOnChange?: (val: number) => void; - CustomTab?: React.FC; - tabPadding?: string; + content: React.ReactNode[]; fontWeight?: number; } -const TabPanel = ({ children, value, index }: { children: React.ReactNode; value: number; index: number }) => ( - -); - -const CustomTab = (props: TabProps) => ( - -); - -export const Tabs = ({ titles, contents, customCurrentTab, customOnChange, tabPadding, CustomTab }: Props) => { - const [value, setValue] = React.useState(0); +export const Tabs = ({ titles, content }: Props) => { + const [activeТаbIndex, activeTabSwitch] = React.useState(0); const onChange = useCallback( - (e: React.ChangeEvent, value: any) => { - customOnChange ? customOnChange(value) : setValue(value); - }, - [customOnChange] + (_event: React.ChangeEvent, value: any) => activeTabSwitch(value), + [activeTabSwitch] ); return ( - + - {CustomTab - ? titles.map((tab, idx) => ( - - )) - : titles.map((tab, idx) => ( - theme.palette.text.primary, - opacity: 0.4, - "&.Mui-selected": { - color: (theme) => theme.palette.text.primary, - opacity: 1, - }, - }} - /> - ))} + {titles.map((title, index) => ( + + ))} - {contents.map((content, idx) => ( - - {content} - - ))} + {content.map( + (tabPanelContent, tabIndex) => + activeТаbIndex === tabIndex && {tabPanelContent} + )} ); }; - -export const PageTabs = ({ contents }: { contents: JSX.Element[] }) => ( - -); From 2f37fb7ae1026a8d308a244a87d72839fe902008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Sep 2022 10:12:12 +0400 Subject: [PATCH 022/537] wip: Rework dao page layout --- src/components.js | 2 +- src/components/dao/dao.scss | 337 +++++++++++------------- src/components/dao/{dao.jsx => dao.tsx} | 99 +++---- src/components/dao/funds.scss | 19 ++ src/components/dao/multicall.scss | 63 +++++ src/pages/dao-page.jsx | 2 +- 6 files changed, 296 insertions(+), 226 deletions(-) rename src/components/dao/{dao.jsx => dao.tsx} (89%) create mode 100644 src/components/dao/funds.scss create mode 100644 src/components/dao/multicall.scss diff --git a/src/components.js b/src/components.js index 0ffd6533..cbe490c5 100644 --- a/src/components.js +++ b/src/components.js @@ -7,6 +7,6 @@ export { Editor } from "./components/editor/editor.jsx"; export { Export } from "./components/export/export.jsx"; export { Wallet } from "./components/wallet/wallet.jsx"; export { Sidebar } from "./components/sidebar/sidebar.jsx"; -export { Dao } from "./components/dao/dao.jsx"; +export { Dao } from "./components/dao/dao.tsx"; export { Tooltip } from "./components/tooltip/tooltip.jsx"; export { PopupMenu } from "./components/popup-menu/popup-menu.jsx"; diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 0932836b..026d416a 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -5,195 +5,178 @@ @use "sass/animation"; .dao-container { - @include mixin.page-wrapper; - display: flex; - flex-flow: column nowrap; - .address-container { - @include mixin.center-items; - flex-flow: row nowrap; - width: auto; - .MuiTextField-root { - width: calc(100% - 2 * size.$gap); - max-width: 100ch; - text-align: left; - margin: calc(size.$gap - 0.5 * size.$large-text) size.$gap; - .MuiInputBase-root { - font-size: size.$large-text; - color: color.$darkish; - input { - padding: 0; - padding-left: 0.5 * size.$gap; + @include mixin.page-wrapper; + display: flex; + flex-flow: column nowrap; + + .address-container { + @include mixin.center-items; + flex-flow: row nowrap; + width: auto; + + .MuiTextField-root { + width: calc(100% - 2 * size.$gap); + max-width: 100ch; + text-align: left; + margin: calc(size.$gap - 0.5 * size.$large-text) size.$gap; + + .MuiInputBase-root { + font-size: size.$large-text; + color: color.$darkish; + + input { + padding: 0; + padding-left: 0.5 * size.$gap; + } + + &.Mui-error { + color: darken(color.$red, 10%); + } + } + + fieldset { + border: none; + border-bottom: 2px solid currentColor; + border-radius: 0; + } + + p { + display: none; + } } - &.Mui-error { - color: darken(color.$red, 10%); + + .MuiInputAdornment-root { + width: fit-content; + + p { + display: block !important; + font-size: size.$large-text !important; + color: color.$darkish; + } } - } - fieldset { - border: none; - border-bottom: 2px solid currentColor; - border-radius: 0; - } - p { - display: none; - } - } - .MuiInputAdornment-root { - width: fit-content; - p { - display: block !important; - font-size: size.$large-text !important; - color: color.$darkish; - } - } - } - &::before { - content: ""; - position: fixed; - top: 0; - left: 0; - height: calc(2.5 * size.$gap - 0.5 * (size.$gap - size.$large-text)); - min-width: 100%; - background-color: color.$light; - } - .info-container { - @include mixin.full; - display: grid; - justify-items: unset; - gap: size.$gap; - padding: size.$gap; - width: calc(100% - 2 * size.$gap); - grid-template: repeat(8, 1fr) / repeat(8, 1fr); - &.error, - &.loader { - display: flex; - flex-flow: column; - justify-content: center; - align-items: center; - font-size: size.$text; - p.red { - color: color.$red; - } - p.green { - color: color.$green; - } } - .info-text { - font-size: size.$text; - color: color.$dark; - max-width: 40em; - a { - color: darken(color.$blue, 20%) !important; - } + + &::before { + content: ""; + position: fixed; + top: 0; + left: 0; + height: calc(2.5 * size.$gap - 0.5 * (size.$gap - size.$large-text)); + min-width: 100%; + background-color: color.$light; } - .info-card { - display: flex; - position: relative; - flex-flow: column nowrap; - background-color: rgba(color.$lightest, 0.25); - border-radius: size.$task-radius; - font-size: size.$small-text; - overflow: hidden; - .title { - padding: 0.5 * size.$gap size.$gap; - font-size: size.$large-text; - span { - float: right; - } - } - @for $i from 0 to 3 { - .MuiSvgIcon-root:nth-of-type(#{$i + 1}) { - position: absolute; - font-size: size.$large-text; - top: 0.5 * size.$gap; - right: calc( - 0.5 * size.$gap + $i * (size.$large-text + 0.25 * size.$gap) - ); - cursor: pointer; - } - } - ul { - display: flex; - flex-flow: column nowrap; - li { - margin-right: 0.5 * size.$gap; - span { - position: relative; - display: block; - width: 100%; - a { - color: darken(color.$blue, 20%) !important; + + .info-container { + @include mixin.full; + display: grid; + gap: size.$gap; + padding: size.$gap; + max-width: 1024px; + + &.error, + &.loader { + display: flex; + flex-flow: column; + justify-content: center; + align-items: center; + font-size: size.$text; + + p.red { + color: color.$red; } - .MuiSvgIcon-root { - visibility: hidden; - position: absolute; - font-size: size.$large-text; - top: auto !important; - bottom: auto !important; - right: 0 !important; - cursor: pointer; + + p.green { + color: color.$green; } - } - &:hover { - background-color: color.$lightest; - span > .MuiSvgIcon-root { - visibility: visible; + } + + .info-text { + font-size: size.$text; + color: color.$dark; + max-width: 40em; + + a { + color: darken(color.$blue, 20%) !important; } - } } - } - &.admins { - grid-area: 1 / 1 / 9 / 3; - } - &.tokens { - padding-bottom: size.$gap; - grid-area: 1 / 1 / 9 / 6; - } - &.wtokens { - grid-area: 1/ 6 / 9 / 9; - } - &.jobs { - grid-area: 1 / 3 / 8 / 9; - position: relative; - .scroll-wrapper { - @include mixin.no-scrollbar; - overflow-y: scroll; - position: absolute; - top: calc(size.$large-text + 1.5 * size.$gap); - bottom: 0; - left: 0; - right: 0; - .job { + + .info-card { + display: flex; + flex-flow: column nowrap; position: relative; - margin: size.$gap; - margin-top: 0; + background-color: rgba(color.$lightest, 0.25); border-radius: size.$task-radius; - background-color: color.$lightest; - pre { - padding: 0.5 * size.$gap; - font-family: font.$code; - font-size: size.$small-text; + font-size: size.$small-text; + overflow: hidden; + + .title { + padding: 0.5 * size.$gap size.$gap; + font-size: size.$large-text; + + span { + float: right; + } + } + + @for $i from 0 to 3 { + .MuiSvgIcon-root:nth-of-type(#{$i + 1}) { + position: absolute; + font-size: size.$large-text; + top: 0.5 * size.$gap; + right: calc(0.5 * size.$gap + $i * (size.$large-text + 0.25 * size.$gap)); + cursor: pointer; + } + } + + ul { + display: flex; + flex-flow: column nowrap; + + li { + margin-right: 0.5 * size.$gap; + + span { + position: relative; + display: block; + width: 100%; + + a { + color: darken(color.$blue, 20%) !important; + } + + .MuiSvgIcon-root { + visibility: hidden; + position: absolute; + font-size: size.$large-text; + top: auto !important; + bottom: auto !important; + right: 0 !important; + cursor: pointer; + } + } + + &:hover { + background-color: color.$lightest; + + span > .MuiSvgIcon-root { + visibility: visible; + } + } + } } - } } - } - &.bond { - grid-area: 8 / 6 / 9 / 9; - .title { - @include mixin.center-items(space-between, center); - height: 100%; + + .create-multicall { + width: fit-content; + align-self: center; + font-size: size.$text; + padding: 0.25em 0.75em; + border-radius: 0.5em; + background-color: color.$green; + + &.proposal-exists { + background-color: color.$blue !important; + } } - } - } - .create-multicall { - width: fit-content; - align-self: center; - font-size: size.$text; - padding: 0.25em 0.75em; - border-radius: 0.5em; - background-color: color.$green; - &.proposal-exists { - background-color: color.$blue !important; - } } - } } diff --git a/src/components/dao/dao.jsx b/src/components/dao/dao.tsx similarity index 89% rename from src/components/dao/dao.jsx rename to src/components/dao/dao.tsx index 6c61b74a..3165d311 100644 --- a/src/components/dao/dao.jsx +++ b/src/components/dao/dao.tsx @@ -1,4 +1,4 @@ -import { InputAdornment } from "@mui/material"; +import { InputAdornment, Tab, TabProps } from "@mui/material"; import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; @@ -15,9 +15,11 @@ import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils import { TextInput } from "../editor/elements"; import { FungibleToken } from "../../utils/standards/fungibleToken"; import { Table } from "../../shared/ui/components/table"; -import { PageTabs } from "../../shared/ui/components/tabs"; +import { Tabs } from "../../shared/ui/components/tabs"; import { NearIconFilled } from "../../shared/ui/components/icons"; import "./dao.scss"; +import "./funds.scss"; +import "./multicall.scss"; // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR @@ -445,7 +447,7 @@ export class Dao extends Component { view(multicall, "get_jobs", {}).catch((e) => {}), view(multicall, "get_job_bond", {}).catch((e) => {}), this.proposalAlreadyExists(dao).catch((e) => {}), - this.nearInfo(multicall, dao).catch((e) => {}), + this.nearInfo().catch((e) => {}), this.balancesToRows(multicall, dao).catch((e) => {}), ]).then( ([ @@ -483,12 +485,11 @@ export class Dao extends Component { // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) if (!walletSelector.isSignedIn()) { - // if user not logged in, remind him to sign in. return
Please sign in to continue
; } - // errors to display const displayErrorsList = ["addr", "noDao", "noContract"]; + const displayErrors = Object.keys(this.errors) .filter((e) => this.errors[e].isBad && displayErrorsList.includes(e)) .map((e) => ( @@ -511,7 +512,6 @@ export class Dao extends Component { ); - // loading ... if (loading) return
; // everything should be loaded @@ -520,55 +520,60 @@ export class Dao extends Component { return
Unexpected error! Multicall might be outdated.
; } - // info found return ( - -
- -

Admins

- -
    - {info.admins.map((admin) => ( -
  • {this.toLink(admin)}
  • - ))} -
-
+ +
+
+ +

Admins

+ +
    + {info.admins.map((admin) => ( +
  • {this.toLink(admin)}
  • + ))} +
+
-
-

Whitelisted Tokens

-
    - {info.tokens.map((token) => ( -
  • {this.toLink(token)}
  • - ))} -
-
+
+

Whitelisted Tokens

-
- -

Jobs

-
{info.jobs.map((j) => this.job(j))}
-
+
    + {info.tokens.map((token) => ( +
  • {this.toLink(token)}
  • + ))} +
+
+ +
+ +

Jobs

+
{info.jobs.map((j) => this.job(j))}
+
-
-

- Job Bond - {`${info.bond !== "..." ? toNEAR(info.bond) : "..."} Ⓝ`} -

+
+

+ Job Bond + {`${info.bond !== "..." ? toNEAR(info.bond) : "..."} Ⓝ`} +

+
-
, + , -
-
-

Token Balances

+
+
+
+

Fungible Token Balances

-
+
+ - , + , ]} /> ); diff --git a/src/components/dao/funds.scss b/src/components/dao/funds.scss new file mode 100644 index 00000000..58c56344 --- /dev/null +++ b/src/components/dao/funds.scss @@ -0,0 +1,19 @@ +@use "sass/color"; +@use "sass/font"; +@use "sass/mixin"; +@use "sass/size"; + +.funds-tab { + &.content { + @include mixin.center-items(center, initial); + + .info-container { + grid-template: "balances" 1fr / 1fr; + } + + .balances { + grid-area: balances; + padding-bottom: size.$gap; + } + } +} diff --git a/src/components/dao/multicall.scss b/src/components/dao/multicall.scss new file mode 100644 index 00000000..8fbef5e8 --- /dev/null +++ b/src/components/dao/multicall.scss @@ -0,0 +1,63 @@ +@use "sass/color"; +@use "sass/font"; +@use "sass/mixin"; +@use "sass/size"; + +.multicall-tab { + &.content { + @include mixin.center-items(center, initial); + + .info-container { + grid-template: + "admins jobs" 6fr + "token-whitelist jobs" 5fr + "token-whitelist job-bond" 1fr / 1fr 1fr; + } + + .admins { + grid-area: admins; + } + + .token-whitelist { + grid-area: token-whitelist; + } + + .jobs { + grid-area: jobs; + position: relative; + + .scroll-wrapper { + @include mixin.no-scrollbar; + overflow-y: scroll; + position: absolute; + top: calc(size.$large-text + 1.5 * size.$gap); + bottom: 0; + left: 0; + right: 0; + + .job { + position: relative; + margin: size.$gap; + margin-top: 0; + border-radius: size.$task-radius; + background-color: color.$lightest; + + pre { + padding: 0.5 * size.$gap; + font-family: font.$code; + font-size: size.$small-text; + } + } + } + } + + .job-bond { + grid-area: job-bond; + + .title { + @include mixin.center-items(space-between, center); + height: 100%; + } + } + } +} diff --git a/src/pages/dao-page.jsx b/src/pages/dao-page.jsx index d7329c80..e90ba16a 100644 --- a/src/pages/dao-page.jsx +++ b/src/pages/dao-page.jsx @@ -4,7 +4,7 @@ import { Dao, Sidebar } from "../components.js"; export const DaoPage = () => { window.PAGE = "dao"; - // TODO: remove "full" prop + // TODO: remove "full" prop from Sidebar return ( <> From 81e2cf4b34c205575b6b2ff497a1a29237c1f308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Sep 2022 10:23:35 +0400 Subject: [PATCH 023/537] chore: Clarify naming --- src/components/dao/dao.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index 3165d311..17c9952f 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -52,7 +52,7 @@ export class Dao extends Component { loading: false, proposed: -1, proposedInfo: {}, - rowContent: [["...", "...", "...", "..."]], + fungibleTokenBalances: [["...", "...", "...", "..."]], info: { admins: [], tokens: [], @@ -456,12 +456,12 @@ export class Dao extends Component { jobs, bond, { proposal_id, proposal_info }, - nearBalances, - fungibleTokenBalances, + nearTokenBalances, + customTokensBalances, ]) => this.setState({ dao, - rowContent: [nearBalances, ...fungibleTokenBalances], + fungibleTokenBalances: [nearTokenBalances, ...customTokensBalances], info: { admins: admins, @@ -481,7 +481,7 @@ export class Dao extends Component { getContent() { const { selector: walletSelector } = this.context; - const { info, loading, rowContent } = this.state; + const { info, loading, fungibleTokenBalances } = this.state; // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) if (!walletSelector.isSignedIn()) { @@ -569,7 +569,7 @@ export class Dao extends Component {
From e72b7eeec283bf999befa0a889e14fa47b23463b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Sep 2022 10:23:58 +0400 Subject: [PATCH 024/537] wip: Update tab buttons style --- src/shared/ui/components/tabs/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx index 15403d4b..60ab3aed 100644 --- a/src/shared/ui/components/tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -43,9 +43,9 @@ export const Tabs = ({ titles, content }: Props) => { textTransform: "none", borderRadius: 1, background: "transparent", - color: "#e0e0e0", + color: "#2a2a2a", fontSize: "16px", - border: "1px solid #e0e0e0 ", + border: "1px solid #A4BAB8", opacity: 1, "&.Mui-selected": { From ba6d2e3a96d6966d93ea8a17986c7b29b53aa96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Sep 2022 10:31:20 +0400 Subject: [PATCH 025/537] wip: Center pending animation and error message --- src/components/dao/dao.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 026d416a..99231802 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -77,6 +77,7 @@ &.loader { display: flex; flex-flow: column; + align-self: center; justify-content: center; align-items: center; font-size: size.$text; From 138b762c69f0c6638eaa41e61a16137e3ca7a5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Sep 2022 10:43:23 +0400 Subject: [PATCH 026/537] fix: Add undefined table row workaround --- src/shared/ui/components/table/index.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/shared/ui/components/table/index.tsx b/src/shared/ui/components/table/index.tsx index 329eb830..f233d3b9 100644 --- a/src/shared/ui/components/table/index.tsx +++ b/src/shared/ui/components/table/index.tsx @@ -355,14 +355,15 @@ const Row = ({ : undefined } > - {row.map((content, index) => ( - - {content} - - ))} + {row && + row.map((content, index) => ( + + {content} + + ))} {collapsible && ( @@ -382,7 +383,7 @@ const Row = ({ Date: Sun, 11 Sep 2022 11:43:25 +0200 Subject: [PATCH 027/537] use multicall class in wallet component --- src/components/wallet/wallet.js | 35 +++++++++++--------------- src/contexts/walletSelectorContext.tsx | 3 ++- src/near-config.js | 2 -- src/utils/contracts/multicall.ts | 2 +- 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/components/wallet/wallet.js b/src/components/wallet/wallet.js index 2c554a08..fc87f5ce 100644 --- a/src/components/wallet/wallet.js +++ b/src/components/wallet/wallet.js @@ -5,6 +5,7 @@ import { view } from "../../utils/wallet"; import { STORAGE } from "../../utils/persistent"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; +import { Multicall } from "../../utils/contracts/multicall"; import Autocomplete from "@mui/material/Autocomplete"; import TextField from "@mui/material/TextField"; import { Icon } from "@mui/material"; @@ -72,7 +73,7 @@ export default class Wallet extends Component { }); } - connectDao(dao) { + connectDao(daoAddress) { const { accountId } = this.context; const { noDao, noRights, noContract } = this.errors; @@ -81,35 +82,27 @@ export default class Wallet extends Component { noDao.isBad = false; noContract.isBad = false; - const multicall = dao.replace(SputnikDAO.FACTORY_ADDRESS, window.nearConfig.MULTICALL_FACTORY_ADDRESS); + const multicallAddress = daoAddress.replace(SputnikDAO.FACTORY_ADDRESS, Multicall.FACTORY_ADDRESS); Promise.all([ - SputnikDAO.init(dao).catch((e) => {}), - view(multicall, "get_admins", {}).catch((e) => { - if ( - (e.type === "AccountDoesNotExist" && e.toString().includes(` ${multicall} `)) || - (e.type === "CodeDoesNotExist" && e.toString().includes(`${multicall}`)) || - e.toString().includes("MethodNotFound") - ) - noContract.isBad = true; - else console.error(e, { ...e }); - - window.MENU?.forceUpdate(); - }), + // on failure return non-initialized DAO instance (per default: ready = false) + SputnikDAO.init(daoAddress).catch((e) => new SputnikDAO(daoAddress)), + Multicall.isMulticall(multicallAddress).catch((e) => false), ]) - .then(([initializedDAO, admins]) => { - if (!initializedDAO.ready) { - noDao.isBad = true; + .then(([newDAO, hasMulticall]) => { + if (!newDAO.ready || !hasMulticall) { + noDao.isBad = !newDAO.ready; + noContract.isBad = !hasMulticall; MENU.forceUpdate(); return; } this.setState({ - currentDAO: initializedDAO, + currentDAO: newDAO, }); // can user propose FunctionCall to DAO? - const canPropose = initializedDAO.checkUserPermission( + const canPropose = newDAO.checkUserPermission( accountId, ProposalAction.AddProposal, ProposalKind.FunctionCall @@ -122,7 +115,7 @@ export default class Wallet extends Component { .finally(() => { let color = "red"; - if (ArgsAccount.isValid(dao) && !noDao.isBad) color = "yellow"; + if (ArgsAccount.isValid(daoAddress) && !noDao.isBad) color = "yellow"; if (!noContract.isBad) color = ""; @@ -224,7 +217,7 @@ export default class Wallet extends Component { STORAGE.addresses.dao = newValue ?? ""; STORAGE.addresses.multicall = newValue?.replace( SputnikDAO.FACTORY_ADDRESS, - window.nearConfig.MULTICALL_FACTORY_ADDRESS + Multicall.FACTORY_ADDRESS ); this.daoSearchDebounced(newValue); }} diff --git a/src/contexts/walletSelectorContext.tsx b/src/contexts/walletSelectorContext.tsx index c212404c..96f03427 100644 --- a/src/contexts/walletSelectorContext.tsx +++ b/src/contexts/walletSelectorContext.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useEffect, useState } from "react"; +import { Multicall } from "../utils/contracts/multicall"; import { map, distinctUntilChanged } from "rxjs"; import { setupWalletSelector } from "@near-wallet-selector/core"; import type { WalletSelector, AccountState } from "@near-wallet-selector/core"; @@ -59,7 +60,7 @@ export const WalletSelectorContextProvider: React.FC = ({ children }) => { ], }); const _modal = setupModal(_selector, { - contractId: window.nearConfig.MULTICALL_FACTORY_ADDRESS, + contractId: Multicall.FACTORY_ADDRESS, theme: "dark", }); const state = _selector.store.getState(); diff --git a/src/near-config.js b/src/near-config.js index c32816ed..58d5e58f 100644 --- a/src/near-config.js +++ b/src/near-config.js @@ -4,7 +4,6 @@ function getConfig(env) { case "mainnet": return { networkId: "mainnet", - MULTICALL_FACTORY_ADDRESS: "v1.multicall.near", WNEAR_ADDRESS: "wrap.near", EXAMPLE_ADDRESS: "example.near", REF_EXCHANGE_ADDRESS: "v2.ref-finance.near", @@ -18,7 +17,6 @@ function getConfig(env) { case "testnet": return { networkId: "testnet", - MULTICALL_FACTORY_ADDRESS: "v1_03.multicall.testnet", WNEAR_ADDRESS: "wrap.testnet", EXAMPLE_ADDRESS: "example.testnet", REF_EXCHANGE_ADDRESS: "ref-finance-101.testnet", diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index 40f25bf1..296e76c0 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -26,7 +26,7 @@ type JobSchema = { start_at: string; // string encoded number (u64) run_count: number; is_active: boolean; - multicalls: object[]; // object schema here is MulticallArgs (TODO: add MulticallArgs schema) + multicalls: MulticallArgs[]; }; type FunctionCall = { From ff87c34e6e36657be9254f917190f7da05455c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 12 Sep 2022 16:08:57 +0400 Subject: [PATCH 028/537] Update token label component --- src/components/dao/dao.tsx | 13 +++------ src/components/token/token.tsx | 26 ----------------- .../components/token-label/token-label.scss} | 0 .../ui/components/token-label/token-label.tsx | 28 +++++++++++++++++++ 4 files changed, 32 insertions(+), 35 deletions(-) delete mode 100644 src/components/token/token.tsx rename src/{components/token/token.scss => shared/ui/components/token-label/token-label.scss} (100%) create mode 100644 src/shared/ui/components/token-label/token-label.tsx diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index 17c9952f..d5007603 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -5,7 +5,7 @@ import debounce from "lodash.debounce"; import * as nearAPI from "near-api-js"; import React, { Component } from "react"; -import { TokenLabel } from "../token/token"; +import { TokenLabel } from "../../shared/ui/components/token-label/token-label"; import { ArgsAccount, ArgsError } from "../../utils/args"; import { STORAGE } from "../../utils/persistent"; import { toNEAR, toYocto, Big, formatTokenAmount } from "../../utils/converter"; @@ -16,7 +16,6 @@ import { TextInput } from "../editor/elements"; import { FungibleToken } from "../../utils/standards/fungibleToken"; import { Table } from "../../shared/ui/components/table"; import { Tabs } from "../../shared/ui/components/tabs"; -import { NearIconFilled } from "../../shared/ui/components/icons"; import "./dao.scss"; import "./funds.scss"; import "./multicall.scss"; @@ -348,11 +347,7 @@ export class Dao extends Component { const nearBalanceDao = (await viewAccount(dao.address)).amount; return [ - } - symbol="NEAR" - />, - + , formatTokenAmount(nearBalanceMulticall, 24, 2), formatTokenAmount(nearBalanceDao, 24, 2), formatTokenAmount(Big(nearBalanceDao).add(nearBalanceMulticall).toFixed(), 24, 2), @@ -384,8 +379,8 @@ export class Dao extends Component { } balancesToRows(multicall, dao) { - return this.tokenInfo(multicall, dao).then((res) => - res.map(({ token, multicallBalance, daoBalance, total }) => [ + return this.tokenInfo(multicall, dao).then((response) => + response.map(({ token, multicallBalance, daoBalance, total }) => [ , formatTokenAmount(multicallBalance, token.metadata.decimals, 2), formatTokenAmount(daoBalance, token.metadata.decimals, 2), diff --git a/src/components/token/token.tsx b/src/components/token/token.tsx deleted file mode 100644 index 6e1e031e..00000000 --- a/src/components/token/token.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from "react"; - -import { NearGenericTokenIconFilled } from "../../shared/ui/components/icons"; -import "./token.scss"; - -export const TokenLabel = ({ - icon = , - symbol, -}: { - icon: string | JSX.Element; - symbol: string; -}) => ( - - {typeof icon === "string" ? ( - - ) : ( - {icon} - )} - - {symbol} - -); diff --git a/src/components/token/token.scss b/src/shared/ui/components/token-label/token-label.scss similarity index 100% rename from src/components/token/token.scss rename to src/shared/ui/components/token-label/token-label.scss diff --git a/src/shared/ui/components/token-label/token-label.tsx b/src/shared/ui/components/token-label/token-label.tsx new file mode 100644 index 00000000..ee16af8a --- /dev/null +++ b/src/shared/ui/components/token-label/token-label.tsx @@ -0,0 +1,28 @@ +import React from "react"; + +import { NearGenericTokenIconFilled, NearIconFilled } from "../icons"; +import "./token-label.scss"; + +export const TokenLabel = ({ + icon = , + native, + symbol, +}: { + icon?: string | JSX.Element | null; + native?: boolean; + symbol?: string; +}) => ( + + {!native && typeof icon === "string" ? ( + + ) : ( + {native ? : icon} + )} + + {native ? "NEAR" : symbol} + +); From a449be7c99df858205aaf7b46fba1b0460d18dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 12 Sep 2022 17:56:26 +0400 Subject: [PATCH 029/537] chore: Use consistent field name for `Multicall` address --- src/utils/contracts/multicall.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index 4e6b003e..44b727f7 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -19,10 +19,10 @@ export default class Multicall { static FACTORY_ADDRESS: string = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; static CONTRACT_CODE_HASHES: string[] = CONTRACT_CODE_HASHES_SELECTOR[window.NEAR_ENV]; - MULTICALL_ADDRESS: string; + address: string; constructor(multicall_address: string) { - this.MULTICALL_ADDRESS = multicall_address; + this.address = multicall_address; } /** From 37755cd341f37fdbfaec34631bd347f2ab937b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 12 Sep 2022 19:37:18 +0400 Subject: [PATCH 030/537] chore: Add equality check for `Args` & Add sub-account address getter for `ArgsAccount` --- src/utils/args.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/utils/args.ts b/src/utils/args.ts index cafcee94..418626ba 100644 --- a/src/utils/args.ts +++ b/src/utils/args.ts @@ -1,5 +1,6 @@ import { unitToDecimals, SIMPLE_NUM_REGEX, convert, Big } from "./converter"; import { BigSource } from "big.js"; +import { SputnikDAO } from "./contracts/sputnik-dao"; export default abstract class Args { private types = { @@ -42,6 +43,10 @@ export default abstract class Args { this.decimals = decimals; } + static equals = (oneInstance: Args, anotherInstance: Args) => oneInstance.value === anotherInstance.value; + + equals = (anotherInstance: Args) => Args.equals(this.value, anotherInstance.value); + toString = () => this.value.toString(); getUnit = (): {} => ({ @@ -64,6 +69,20 @@ class ArgsAccount extends Args { super("string", value); } + static getSubAccountAddress = (address: string) => { + let result; + + if (address.endsWith("." + SputnikDAO.FACTORY_ADDRESS)) + result = address.split("." + SputnikDAO.FACTORY_ADDRESS)[0]; + else if (address.endsWith("." + window.nearConfig.MULTICALL_FACTORY_ADDRESS)) + result = address.split("." + window.nearConfig.MULTICALL_FACTORY_ADDRESS)[0]; + else result = address; + + return new ArgsAccount(result); + }; + + getSubAccountAddress = () => ArgsAccount.getSubAccountAddress(this.value); + static isValid = (value: ArgsAccount | string): boolean => { if (typeof value === "string") { value = new ArgsAccount(value); From f21c153a6fd623ccbedb6e14dc9bd6d9c6e442f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 12 Sep 2022 20:04:47 +0400 Subject: [PATCH 031/537] Create separate FT balances component placeholder --- src/components/token/fungible.scss | 0 src/components/token/fungible.tsx | 31 ++++++++++++++++++++++++++++++ src/components/token/index.ts | 1 + 3 files changed, 32 insertions(+) create mode 100644 src/components/token/fungible.scss create mode 100644 src/components/token/fungible.tsx create mode 100644 src/components/token/index.ts diff --git a/src/components/token/fungible.scss b/src/components/token/fungible.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/components/token/fungible.tsx b/src/components/token/fungible.tsx new file mode 100644 index 00000000..a191634d --- /dev/null +++ b/src/components/token/fungible.tsx @@ -0,0 +1,31 @@ +import { InputAdornment, Tab, TabProps } from "@mui/material"; +import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; +import { Base64 } from "js-base64"; +import debounce from "lodash.debounce"; +import * as nearAPI from "near-api-js"; +import React, { Component } from "react"; + +import { TokenLabel } from "../../shared/ui/components/token-label/token-label"; +import { ArgsAccount, ArgsError } from "../../utils/args"; +import { STORAGE } from "../../utils/persistent"; +import { toNEAR, toYocto, Big, formatTokenAmount } from "../../utils/converter"; +import { view, viewAccount } from "../../utils/wallet"; +import { useWalletSelector } from "../../contexts/walletSelectorContext"; +import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; +import { TextInput } from "../editor/elements"; +import { FungibleToken } from "../../utils/standards/fungibleToken"; +import { Table } from "../../shared/ui/components/table"; +import { Tabs } from "../../shared/ui/components/tabs"; + +export const FungibleTokenBalances = ({ className }: { className?: string }) => { + return ( +
+

Fungible Token Balances

+ +
+ + ); +}; diff --git a/src/components/token/index.ts b/src/components/token/index.ts new file mode 100644 index 00000000..96d082c1 --- /dev/null +++ b/src/components/token/index.ts @@ -0,0 +1 @@ +export { FungibleTokenBalances } from "./fungible"; From c708728ec4b227c2102dba085304897191e4d3ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 13 Sep 2022 00:39:19 +0400 Subject: [PATCH 032/537] chore: Fix Args equality checker --- src/utils/args.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/args.ts b/src/utils/args.ts index 418626ba..238ee5bc 100644 --- a/src/utils/args.ts +++ b/src/utils/args.ts @@ -45,7 +45,7 @@ export default abstract class Args { static equals = (oneInstance: Args, anotherInstance: Args) => oneInstance.value === anotherInstance.value; - equals = (anotherInstance: Args) => Args.equals(this.value, anotherInstance.value); + equals = (anotherInstance: Args) => Args.equals(this, anotherInstance); toString = () => this.value.toString(); From 9535b98efe188b6c6dff3ed51e477c76cec524b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 13 Sep 2022 01:55:51 +0400 Subject: [PATCH 033/537] chore: Use named export --- src/families/multicall/transfer.jsx | 2 +- src/utils/contracts/multicall.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/families/multicall/transfer.jsx b/src/families/multicall/transfer.jsx index 508f7f31..f495ed6d 100644 --- a/src/families/multicall/transfer.jsx +++ b/src/families/multicall/transfer.jsx @@ -6,7 +6,7 @@ import { errorMsg } from "../../utils/errors"; import { STORAGE } from "../../utils/persistent"; import { toGas, toYocto, formatTokenAmount, unitToDecimals } from "../../utils/converter"; import { BaseTask } from "../base"; -import Multicall from "../../utils/contracts/multicall"; +import { Multicall } from "../../utils/contracts/multicall"; import "./multicall.scss"; import { TextInput, TextInputWithUnits } from "../../components/editor/elements"; diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index 44b727f7..608eb241 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -15,7 +15,7 @@ const CONTRACT_CODE_HASHES_SELECTOR: Record = { ], }; -export default class Multicall { +export class Multicall { static FACTORY_ADDRESS: string = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; static CONTRACT_CODE_HASHES: string[] = CONTRACT_CODE_HASHES_SELECTOR[window.NEAR_ENV]; From 7205559bab3fdc9aa0f465287ed1d9d30aacf180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 13 Sep 2022 02:03:50 +0400 Subject: [PATCH 034/537] feat: Implement fungible token balances lazy loading --- src/components/dao/dao.tsx | 302 ++++++++------------ src/components/token/fungible.tsx | 31 -- src/components/token/index.ts | 2 +- src/components/token/model/balances.ts | 74 +++++ src/components/token/types.d.ts | 8 + src/components/token/{ => ui}/fungible.scss | 0 src/components/token/ui/fungible.tsx | 47 +++ 7 files changed, 248 insertions(+), 216 deletions(-) delete mode 100644 src/components/token/fungible.tsx create mode 100644 src/components/token/model/balances.ts create mode 100644 src/components/token/types.d.ts rename src/components/token/{ => ui}/fungible.scss (100%) create mode 100644 src/components/token/ui/fungible.tsx diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index d5007603..eb8fdba4 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -1,20 +1,18 @@ -import { InputAdornment, Tab, TabProps } from "@mui/material"; +import { InputAdornment } from "@mui/material"; import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; -import * as nearAPI from "near-api-js"; import React, { Component } from "react"; -import { TokenLabel } from "../../shared/ui/components/token-label/token-label"; import { ArgsAccount, ArgsError } from "../../utils/args"; import { STORAGE } from "../../utils/persistent"; -import { toNEAR, toYocto, Big, formatTokenAmount } from "../../utils/converter"; -import { view, viewAccount } from "../../utils/wallet"; +import { toNEAR, toYocto, Big } from "../../utils/converter"; +import { view } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; import { TextInput } from "../editor/elements"; -import { FungibleToken } from "../../utils/standards/fungibleToken"; -import { Table } from "../../shared/ui/components/table"; +import { FungibleTokenBalances } from "../token"; +import { Multicall } from "../../utils/contracts/multicall"; import { Tabs } from "../../shared/ui/components/tabs"; import "./dao.scss"; import "./funds.scss"; @@ -23,40 +21,47 @@ import "./multicall.scss"; // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR -const TableHeader = ["Token", "Multicall", "DAO", "Total"]; - -export class Dao extends Component { - static contextType = useWalletSelector(); - - errors = { - addr: new ArgsError( - "Invalid NEAR address", - (value) => ArgsAccount.isValid(value), - !ArgsAccount.isValid(STORAGE.addresses.dao) - ), - noDao: new ArgsError("Sputnik DAO not found on given address", (value) => this.errors.noDao.isBad), - noContract: new ArgsError("DAO has no multicall instance", (value) => this.errors.noContract.isBad), +interface Props {} + +interface State { + name: ArgsAccount; + dao: SputnikDAO; + multicall: Multicall; + loading: boolean; + proposed: number; + proposedInfo: object; + + info: { + admins: string[]; + tokens: string[]; + jobs: unknown[]; + jobBond: string; }; +} - loadInfoDebounced = debounce(() => this.loadInfo(), 400); - - lastAddr; - - constructor(props) { +export class Dao extends Component { + constructor(props: Props) { super(props); this.state = { - addr: this.getBaseAddress(STORAGE.addresses.dao), + name: ArgsAccount.getSubAccountAddress(STORAGE.addresses.dao), dao: new SputnikDAO(STORAGE.addresses.dao), + + multicall: new Multicall( + `${ArgsAccount.getSubAccountAddress(STORAGE.addresses.dao).value}.${ + window.nearConfig.MULTICALL_FACTORY_ADDRESS + }` + ), + loading: false, proposed: -1, proposedInfo: {}, - fungibleTokenBalances: [["...", "...", "...", "..."]], + info: { admins: [], tokens: [], jobs: [], - bond: "...", + jobBond: "...", }, }; @@ -64,13 +69,23 @@ export class Dao extends Component { this.fee = createMulticallFee; this.loadInfo(); }); - - document.addEventListener("onaddressesupdated", (e) => this.onAddressesUpdated(e)); } - componentDidMount() { - window.DAO_COMPONENT = this; - } + static contextType = useWalletSelector(); + + errors = { + name: new ArgsError( + "Invalid NEAR address", + (value) => ArgsAccount.isValid(value), + !ArgsAccount.isValid(STORAGE.addresses.dao) + ), + noDao: new ArgsError("Sputnik DAO not found on given address", (value) => this.errors.noDao.isBad), + noContract: new ArgsError("DAO has no multicall instance", (value) => this.errors.noContract.isBad), + }; + + loadInfoDebounced = debounce(() => this.loadInfo(), 400); + + lastAddr; /** * check if DAO has a proposal to create multicall instance. @@ -78,7 +93,7 @@ export class Dao extends Component { * * @returns {object} ID and info of proposal to create multicall instance, */ - proposalAlreadyExists(dao) { + proposalAlreadyExists(dao: SputnikDAO) { // Date.now() returns timestamp in milliseconds, SputnikDAO uses nanoseconds const currentTime = Big(Date.now()).times("1000000"); const lastProposalId = dao.lastProposalId; @@ -89,18 +104,18 @@ export class Dao extends Component { from_index: lastProposalId < 100 ? 0 : lastProposalId - 100, limit: 100, }) - .then((res) => { - const proposals = res.filter((p) => { + .then((response) => { + const proposals = response.filter((proposal) => { // discard if not active proposal to create multicall instance if ( - !(p.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) || - !(p.kind?.FunctionCall?.actions?.[0]?.method_name === "create") || - !(p.status === "InProgress") + !(proposal.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) || + !(proposal.kind?.FunctionCall?.actions?.[0]?.method_name === "create") || + !(proposal.status === "InProgress") ) { return false; } // calculate proposal expiration timestamp in nanoseconds - const expirationTime = Big(p.submission_time).add(proposalPeriod); + const expirationTime = Big(proposal.submission_time).add(proposalPeriod); // check if proposal expired return expirationTime.gt(currentTime) ? true : false; }); @@ -108,7 +123,7 @@ export class Dao extends Component { // If there many "Create multicall" proposals, return latest. if (proposals.length > 0) { const lastProposal = proposals.pop(); - return { proposal_id: lastProposal.id, proposal_info: lastProposal }; + return { proposal_id: lastProposal?.id, proposal_info: lastProposal }; } // No "Create multicall" proposals found. else return { proposal_id: -1, proposal_info: {} }; @@ -116,35 +131,9 @@ export class Dao extends Component { .catch((e) => {}); } - onAddressesUpdated() { - if (this.getBaseAddress(STORAGE.addresses.dao) !== this.state.addr.value) { - this.setState( - { - addr: this.getBaseAddress(STORAGE.addresses.dao), - }, - () => { - this.errors.addr.validOrNull(this.state.addr); - this.loadInfo(); - this.forceUpdate(); - } - ); - } - } - - getBaseAddress(address) { - let base; - if (address.endsWith("." + SputnikDAO.FACTORY_ADDRESS)) - base = address.split("." + SputnikDAO.FACTORY_ADDRESS)[0]; - else if (address.endsWith("." + window.nearConfig.MULTICALL_FACTORY_ADDRESS)) - base = address.split("." + window.nearConfig.MULTICALL_FACTORY_ADDRESS)[0]; - else base = address; - - return new ArgsAccount(base); - } - createMulticall() { const { accountId } = this.context; - const { loading, addr, dao, proposed, proposedInfo } = this.state; + const { loading, name, dao, proposed, proposedInfo } = this.state; const { noContract, noDao } = this.errors; if ( @@ -155,7 +144,6 @@ export class Dao extends Component { return null; } - const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; const depo = Big(this.fee).plus(MIN_INSTANCE_BALANCE); // can user propose a FunctionCall to DAO? @@ -166,7 +154,7 @@ export class Dao extends Component { const args = { proposal: { - description: `create multicall instance for this DAO at ${multicall}`, + description: `create multicall instance for this DAO at ${this.state.multicall.address}`, kind: { FunctionCall: { @@ -313,16 +301,16 @@ export class Dao extends Component { } toLink(address, deleteIcon = false) { - const addr = new ArgsAccount(address); + const name = new ArgsAccount(address); return ( - {addr.value} + {name.value} {deleteIcon ? : null} @@ -340,68 +328,15 @@ export class Dao extends Component { ); } - async nearInfo() { - const { addr, dao } = this.state; - const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; - const nearBalanceMulticall = (await viewAccount(multicall)).amount; - const nearBalanceDao = (await viewAccount(dao.address)).amount; - - return [ - , - formatTokenAmount(nearBalanceMulticall, 24, 2), - formatTokenAmount(nearBalanceDao, 24, 2), - formatTokenAmount(Big(nearBalanceDao).add(nearBalanceMulticall).toFixed(), 24, 2), - ]; - } - - async tokenInfo(multicall, dao) { - const tokenAddrList = await FungibleToken.getLikelyTokenContracts(multicall); - const likelyTokenList = await Promise.all(tokenAddrList.map((address) => FungibleToken.init(address))); - const tokenList = likelyTokenList.filter((token) => token.ready === true); - - const balances = await Promise.all( - tokenList.map(async (token) => { - const [multicallBalance, daoBalance] = await Promise.all([ - token.ftBalanceOf(multicall), - token.ftBalanceOf(dao.address), - ]); - - return { - token, - multicallBalance: multicallBalance, - daoBalance: daoBalance, - total: Big(multicallBalance).add(daoBalance).toFixed(), - }; - }) - ); - - return balances.filter((el) => Big(el.total).gt("0")); - } - - balancesToRows(multicall, dao) { - return this.tokenInfo(multicall, dao).then((response) => - response.map(({ token, multicallBalance, daoBalance, total }) => [ - , - formatTokenAmount(multicallBalance, token.metadata.decimals, 2), - formatTokenAmount(daoBalance, token.metadata.decimals, 2), - formatTokenAmount(total, token.metadata.decimals, 2), - ]) - ); - } - - displayToken() { - // format to show small balances - } - loadInfo() { - const { addr: addrError, noContract, noDao } = this.errors; - const { addr } = this.state; + const { name: addrError, noContract, noDao } = this.errors; + const { name } = this.state; - const multicall = `${addr.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; - const daoAddress = `${addr.value}.${SputnikDAO.FACTORY_ADDRESS}`; - if (this.lastAddr === addr.value) return; + const multicallAddress = `${name.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; + const daoAddress = `${name.value}.${SputnikDAO.FACTORY_ADDRESS}`; + if (this.lastAddr === name.value) return; - this.lastAddr = addr.value; + this.lastAddr = name.value; noContract.isBad = false; noDao.isBad = false; @@ -420,55 +355,34 @@ export class Dao extends Component { SputnikDAO.init(daoAddress) .catch((e) => {}) .then((dao) => { - if (!dao.ready) { + if (!dao?.ready) { // DAO not ready => either no SputnikDAO contract on the chosen address // or some error happened during DAO object init. - noContract.isBad = true; noDao.isBad = true; this.setState({ dao, loading: false }); return; } else { // DAO correctly initialized, try to fetch multicall info - Promise.all([ - view(multicall, "get_admins", {}).catch((e) => { - if (e.type === "AccountDoesNotExist" && e.toString().includes(` ${multicall} `)) { + view(multicallAddress, "get_admins", {}).catch((e) => { + if (e.type === "AccountDoesNotExist" && e.toString().includes(` ${multicallAddress} `)) { noContract.isBad = true; } }), - view(multicall, "get_tokens", {}).catch((e) => {}), - view(multicall, "get_jobs", {}).catch((e) => {}), - view(multicall, "get_job_bond", {}).catch((e) => {}), + view(multicallAddress, "get_tokens", {}).catch((e) => {}), + view(multicallAddress, "get_jobs", {}).catch((e) => {}), + view(multicallAddress, "get_job_bond", {}).catch((e) => {}), this.proposalAlreadyExists(dao).catch((e) => {}), - this.nearInfo().catch((e) => {}), - this.balancesToRows(multicall, dao).catch((e) => {}), - ]).then( - ([ - admins, - tokens, - jobs, - bond, - { proposal_id, proposal_info }, - nearTokenBalances, - customTokensBalances, - ]) => - this.setState({ - dao, - fungibleTokenBalances: [nearTokenBalances, ...customTokensBalances], - - info: { - admins: admins, - tokens: tokens, - jobs: jobs, - bond: bond, - }, - - loading: false, - proposed: proposal_id, - proposedInfo: proposal_info, - }) + ]).then(([admins, tokens, jobs, jobBond, proposalData]) => + this.setState((prevState) => ({ + dao, + info: { admins, tokens, jobs, jobBond }, + loading: false, + proposed: proposalData?.proposal_id, + proposedInfo: proposalData?.proposal_info || prevState.proposedInfo, + })) ); } }); @@ -476,14 +390,14 @@ export class Dao extends Component { getContent() { const { selector: walletSelector } = this.context; - const { info, loading, fungibleTokenBalances } = this.state; + const { info, loading } = this.state; // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) if (!walletSelector.isSignedIn()) { return
Please sign in to continue
; } - const displayErrorsList = ["addr", "noDao", "noContract"]; + const displayErrorsList = ["name", "noDao", "noContract"]; const displayErrors = Object.keys(this.errors) .filter((e) => this.errors[e].isBad && displayErrorsList.includes(e)) @@ -510,7 +424,7 @@ export class Dao extends Component { if (loading) return
; // everything should be loaded - if (!info.admins || !info.tokens || !info.bond) { + if (!info.admins || !info.tokens || !info.jobBond) { console.error("info incomplete", info); return
Unexpected error! Multicall might be outdated.
; } @@ -551,7 +465,7 @@ export class Dao extends Component {

Job Bond - {`${info.bond !== "..." ? toNEAR(info.bond) : "..."} Ⓝ`} + {`${info.jobBond !== "..." ? toNEAR(info.jobBond) : "..."} Ⓝ`}

@@ -559,14 +473,11 @@ export class Dao extends Component {
-
-

Fungible Token Balances

- -
- + , ]} @@ -574,18 +485,41 @@ export class Dao extends Component { ); } - render() { - const { addr } = this.state; + onAddressesUpdated() { + if (!this.state.name.equals(ArgsAccount.getSubAccountAddress(STORAGE.addresses.dao))) { + this.setState( + { + name: ArgsAccount.getSubAccountAddress(STORAGE.addresses.dao), + + multicall: new Multicall( + `${ArgsAccount.getSubAccountAddress(STORAGE.addresses.dao).value}.${ + window.nearConfig.MULTICALL_FACTORY_ADDRESS + }` + ), + }, + () => { + this.errors.name.validOrNull(this.state.name); + this.loadInfo(); + this.forceUpdate(); + } + ); + } + } + componentDidMount(): void { + document.addEventListener("onaddressesupdated", () => this.onAddressesUpdated()); + } + + render() { return (
{ - if (this.state.addr.isValid) { + if (this.state.name.isValid()) { this.loadInfoDebounced(); } this.forceUpdate(); diff --git a/src/components/token/fungible.tsx b/src/components/token/fungible.tsx deleted file mode 100644 index a191634d..00000000 --- a/src/components/token/fungible.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { InputAdornment, Tab, TabProps } from "@mui/material"; -import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; -import { Base64 } from "js-base64"; -import debounce from "lodash.debounce"; -import * as nearAPI from "near-api-js"; -import React, { Component } from "react"; - -import { TokenLabel } from "../../shared/ui/components/token-label/token-label"; -import { ArgsAccount, ArgsError } from "../../utils/args"; -import { STORAGE } from "../../utils/persistent"; -import { toNEAR, toYocto, Big, formatTokenAmount } from "../../utils/converter"; -import { view, viewAccount } from "../../utils/wallet"; -import { useWalletSelector } from "../../contexts/walletSelectorContext"; -import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; -import { TextInput } from "../editor/elements"; -import { FungibleToken } from "../../utils/standards/fungibleToken"; -import { Table } from "../../shared/ui/components/table"; -import { Tabs } from "../../shared/ui/components/tabs"; - -export const FungibleTokenBalances = ({ className }: { className?: string }) => { - return ( -
-

Fungible Token Balances

- -
- - ); -}; diff --git a/src/components/token/index.ts b/src/components/token/index.ts index 96d082c1..db7d5d7b 100644 --- a/src/components/token/index.ts +++ b/src/components/token/index.ts @@ -1 +1 @@ -export { FungibleTokenBalances } from "./fungible"; +export { FungibleTokenBalances } from "./ui/fungible"; diff --git a/src/components/token/model/balances.ts b/src/components/token/model/balances.ts new file mode 100644 index 00000000..128bb08e --- /dev/null +++ b/src/components/token/model/balances.ts @@ -0,0 +1,74 @@ +import { useEffect, useState } from "react"; + +import { Big } from "../../../utils/converter"; +import { viewAccount } from "../../../utils/wallet"; +import { FungibleToken } from "../../../utils/standards/fungibleToken"; +import { ContractsData } from "../types"; + +type NativeTokenData = { + data: { dao: string; multicall: string } | null; + loading: boolean; +}; + +const nativeTokenDataFx = async ({ dao, multicall }: ContractsData, callback: (data: NativeTokenData) => void) => + callback({ + data: { + dao: (await viewAccount(dao.address)).amount, + multicall: (await viewAccount(multicall.address)).amount, + }, + + loading: false, + }); + +const useNativeTokenData = (args: ContractsData) => { + const [state, stateUpdate] = useState({ data: null, loading: true }); + + useEffect(() => void nativeTokenDataFx(args, stateUpdate), []); + + return state; +}; + +type CustomTokensData = { + data: { dao: string; multicall: string; token: FungibleToken; total: string }[] | null; + loading: boolean; +}; + +const customTokensDataFx = async ({ dao, multicall }: ContractsData, callback: (data: CustomTokensData) => void) => { + const tokenAddrList = await FungibleToken.getLikelyTokenContracts(multicall.address); + const likelyTokenList = await Promise.all(tokenAddrList.map((address) => FungibleToken.init(address))); + const tokenList = likelyTokenList.filter((token) => token.ready === true); + + const balances = await Promise.all( + tokenList.map(async (token) => { + const [multicallBalance, daoBalance] = await Promise.all([ + token.ftBalanceOf(multicall.address), + token.ftBalanceOf(dao.address), + ]); + + return { + dao: daoBalance, + multicall: multicallBalance, + token, + total: Big(multicallBalance).add(daoBalance).toFixed(), + }; + }) + ); + + return callback({ + data: balances.filter((el) => Big(el.total).gt("0")), + loading: false, + }); +}; + +const useCustomTokensData = (args: ContractsData) => { + const [state, stateUpdate] = useState({ data: null, loading: true }); + + useEffect(() => void customTokensDataFx(args, stateUpdate), []); + + return state; +}; + +export const BalancesModel = { + useCustomTokensData, + useNativeTokenData, +}; diff --git a/src/components/token/types.d.ts b/src/components/token/types.d.ts new file mode 100644 index 00000000..c1656c9d --- /dev/null +++ b/src/components/token/types.d.ts @@ -0,0 +1,8 @@ +import { SputnikDAO } from "../../utils/contracts/sputnik-dao"; +import { FungibleToken } from "../../utils/standards/fungibleToken"; +import { Multicall } from "../../utils/contracts/multicall"; + +export interface ContractsData { + dao: SputnikDAO; + multicall: Multicall; +} diff --git a/src/components/token/fungible.scss b/src/components/token/ui/fungible.scss similarity index 100% rename from src/components/token/fungible.scss rename to src/components/token/ui/fungible.scss diff --git a/src/components/token/ui/fungible.tsx b/src/components/token/ui/fungible.tsx new file mode 100644 index 00000000..4d6ccf95 --- /dev/null +++ b/src/components/token/ui/fungible.tsx @@ -0,0 +1,47 @@ +import React from "react"; + +import { TokenLabel } from "../../../shared/ui/components/token-label/token-label"; +import { Big, formatTokenAmount } from "../../../utils/converter"; +import { Table } from "../../../shared/ui/components/table"; +import { ContractsData } from "../types"; +import { BalancesModel } from "../model/balances"; + +interface Props extends ContractsData { + className?: string; +} + +export const FungibleTokenBalances = ({ className, dao, multicall }: Props) => { + const nativeToken = BalancesModel.useNativeTokenData({ dao, multicall }); + const customTokens = BalancesModel.useCustomTokensData({ dao, multicall }); + + const tableContent = [ + !nativeToken.loading && nativeToken.data + ? [ + , + formatTokenAmount(nativeToken.data.multicall, 24, 2), + formatTokenAmount(nativeToken.data.dao, 24, 2), + formatTokenAmount(Big(nativeToken.data.dao).add(nativeToken.data.multicall).toFixed(), 24, 2), + ] + : [], + + ...(!customTokens.loading && customTokens.data + ? customTokens.data.map(({ token: { metadata }, ...customToken }) => [ + , + formatTokenAmount(customToken.multicall, metadata.decimals, 2), + formatTokenAmount(customToken.dao, metadata.decimals, 2), + formatTokenAmount(customToken.total, metadata.decimals, 2), + ]) + : []), + ]; + + return ( +
+

Fungible Token Balances

+ +
0 ? tableContent : [["...", "...", "...", "..."]]} + /> + + ); +}; From c50753a8bf874574870f0112e9842b9d97422ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 13 Sep 2022 13:57:05 +0400 Subject: [PATCH 035/537] Fix generic token icon rendering --- src/shared/ui/components/token-label/token-label.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/components/token-label/token-label.tsx b/src/shared/ui/components/token-label/token-label.tsx index ee16af8a..e8199593 100644 --- a/src/shared/ui/components/token-label/token-label.tsx +++ b/src/shared/ui/components/token-label/token-label.tsx @@ -4,7 +4,7 @@ import { NearGenericTokenIconFilled, NearIconFilled } from "../icons"; import "./token-label.scss"; export const TokenLabel = ({ - icon = , + icon, native, symbol, }: { @@ -20,7 +20,7 @@ export const TokenLabel = ({ src={icon} /> ) : ( - {native ? : icon} + {native ? : icon || } )} {native ? "NEAR" : symbol} From 9e30905d4a6182e6f49abbc4294e61f4f5d627c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Sep 2022 18:39:40 +0400 Subject: [PATCH 036/537] chore: Move balances conversion into model --- src/components/token/model/balances.ts | 43 ++++++++++++++++---------- src/components/token/ui/fungible.tsx | 18 ++++------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/components/token/model/balances.ts b/src/components/token/model/balances.ts index 128bb08e..1bce9879 100644 --- a/src/components/token/model/balances.ts +++ b/src/components/token/model/balances.ts @@ -1,24 +1,29 @@ import { useEffect, useState } from "react"; -import { Big } from "../../../utils/converter"; +import { Big, formatTokenAmount } from "../../../utils/converter"; import { viewAccount } from "../../../utils/wallet"; import { FungibleToken } from "../../../utils/standards/fungibleToken"; import { ContractsData } from "../types"; type NativeTokenData = { - data: { dao: string; multicall: string } | null; + data: { dao: string; multicall: string; total: string } | null; loading: boolean; }; -const nativeTokenDataFx = async ({ dao, multicall }: ContractsData, callback: (data: NativeTokenData) => void) => - callback({ +const nativeTokenDataFx = async ({ dao, multicall }: ContractsData, callback: (data: NativeTokenData) => void) => { + const daoRawBalance = (await viewAccount(dao.address)).amount, + multicallRawBalance = (await viewAccount(multicall.address)).amount; + + return callback({ data: { - dao: (await viewAccount(dao.address)).amount, - multicall: (await viewAccount(multicall.address)).amount, + dao: formatTokenAmount(daoRawBalance, 24, 2), + multicall: formatTokenAmount(multicallRawBalance, 24, 2), + total: formatTokenAmount(Big(daoRawBalance).add(multicallRawBalance).toFixed(), 24, 2), }, loading: false, }); +}; const useNativeTokenData = (args: ContractsData) => { const [state, stateUpdate] = useState({ data: null, loading: true }); @@ -29,27 +34,31 @@ const useNativeTokenData = (args: ContractsData) => { }; type CustomTokensData = { - data: { dao: string; multicall: string; token: FungibleToken; total: string }[] | null; + data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; loading: boolean; }; const customTokensDataFx = async ({ dao, multicall }: ContractsData, callback: (data: CustomTokensData) => void) => { - const tokenAddrList = await FungibleToken.getLikelyTokenContracts(multicall.address); - const likelyTokenList = await Promise.all(tokenAddrList.map((address) => FungibleToken.init(address))); - const tokenList = likelyTokenList.filter((token) => token.ready === true); + const tokenAddrList = await FungibleToken.getLikelyTokenContracts(multicall.address), + likelyTokenList = await Promise.all(tokenAddrList.map((address) => FungibleToken.init(address))), + tokenList = likelyTokenList.filter((token) => token.ready === true); const balances = await Promise.all( tokenList.map(async (token) => { - const [multicallBalance, daoBalance] = await Promise.all([ - token.ftBalanceOf(multicall.address), + const rawBalances = await Promise.all([ token.ftBalanceOf(dao.address), - ]); + token.ftBalanceOf(multicall.address), + ]).then(([daoRawBalance, multicallRawBalance]) => ({ + dao: daoRawBalance, + multicall: multicallRawBalance, + total: Big(multicallRawBalance).add(daoRawBalance).toFixed(), + })); return { - dao: daoBalance, - multicall: multicallBalance, - token, - total: Big(multicallBalance).add(daoBalance).toFixed(), + metadata: token.metadata, + dao: formatTokenAmount(rawBalances.dao, token.metadata.decimals, 2), + multicall: formatTokenAmount(rawBalances.multicall, token.metadata.decimals, 2), + total: formatTokenAmount(rawBalances.total, token.metadata.decimals, 2), }; }) ); diff --git a/src/components/token/ui/fungible.tsx b/src/components/token/ui/fungible.tsx index 4d6ccf95..bd55826c 100644 --- a/src/components/token/ui/fungible.tsx +++ b/src/components/token/ui/fungible.tsx @@ -1,7 +1,6 @@ import React from "react"; import { TokenLabel } from "../../../shared/ui/components/token-label/token-label"; -import { Big, formatTokenAmount } from "../../../utils/converter"; import { Table } from "../../../shared/ui/components/table"; import { ContractsData } from "../types"; import { BalancesModel } from "../model/balances"; @@ -16,20 +15,15 @@ export const FungibleTokenBalances = ({ className, dao, multicall }: Props) => { const tableContent = [ !nativeToken.loading && nativeToken.data - ? [ - , - formatTokenAmount(nativeToken.data.multicall, 24, 2), - formatTokenAmount(nativeToken.data.dao, 24, 2), - formatTokenAmount(Big(nativeToken.data.dao).add(nativeToken.data.multicall).toFixed(), 24, 2), - ] + ? [, nativeToken.data.multicall, nativeToken.data.dao, nativeToken.data.total] : [], ...(!customTokens.loading && customTokens.data - ? customTokens.data.map(({ token: { metadata }, ...customToken }) => [ - , - formatTokenAmount(customToken.multicall, metadata.decimals, 2), - formatTokenAmount(customToken.dao, metadata.decimals, 2), - formatTokenAmount(customToken.total, metadata.decimals, 2), + ? customTokens.data.map((customToken) => [ + , + customToken.multicall, + customToken.dao, + customToken.total, ]) : []), ]; From cbb4483ee8cf41b8305752eb474dbfe79e3675e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Sep 2022 19:02:11 +0400 Subject: [PATCH 037/537] chore: Remove empty unused file --- src/components/token/ui/fungible.scss | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/components/token/ui/fungible.scss diff --git a/src/components/token/ui/fungible.scss b/src/components/token/ui/fungible.scss deleted file mode 100644 index e69de29b..00000000 From 4de3bac80be89685ef4a5520f71ec591663033df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Sep 2022 19:44:09 +0400 Subject: [PATCH 038/537] wip: Fix loader styles --- sass/_base.scss | 12 +++++++----- src/components/dao/dao.scss | 3 +-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/sass/_base.scss b/sass/_base.scss index 9233a96d..e14f1a9a 100644 --- a/sass/_base.scss +++ b/sass/_base.scss @@ -71,16 +71,18 @@ } .loader { - display: inline-block; - width: 80px; - height: 80px; + display: flex; + align-self: center; + align-items: center; + justify-content: center; + width: 100px; + height: 100px; &::after { content: " "; display: block; width: 64px; height: 64px; - margin: 8px; - border-radius: 50%; + border-radius: 100%; border: 6px solid color.$lightish; border-color: color.$lightish transparent color.$lightish transparent; animation: lds-dual-ring 1.2s linear infinite; diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 99231802..a7edb107 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -73,8 +73,7 @@ padding: size.$gap; max-width: 1024px; - &.error, - &.loader { + &.error { display: flex; flex-flow: column; align-self: center; From 0753bb46bc3c9f97368556e5af7a85eb37184de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Sep 2022 20:05:09 +0400 Subject: [PATCH 039/537] wip: Allow to pass nullish values as table rows --- src/shared/ui/components/table/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/components/table/index.tsx b/src/shared/ui/components/table/index.tsx index f233d3b9..49507796 100644 --- a/src/shared/ui/components/table/index.tsx +++ b/src/shared/ui/components/table/index.tsx @@ -187,7 +187,7 @@ export const Table = ({ }: { sortHeaders?: string[]; header: string[]; - rows: (string | number | JSX.Element)[][]; + rows: ((string | number | JSX.Element)[] | null)[]; variant?: "outlined" | "grey"; collapsible?: boolean; hiddenParts?: JSX.Element[]; @@ -226,7 +226,7 @@ export const Table = ({ sx={{ color: (theme) => theme.palette.text.secondary }} component="div" > - {data[index] ?? null} + {data && data[index]} {collapsible && index + 1 === header.length && ( From a89be633863111d4f0c159e73337cd7db59ae506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Sep 2022 20:07:15 +0400 Subject: [PATCH 040/537] feat: Add loading animation for balances --- src/components/dao/dao.tsx | 2 +- src/components/token/ui/fungible.tsx | 45 ++++++++++++++++------------ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index eb8fdba4..b14b3669 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -421,7 +421,7 @@ export class Dao extends Component { ); - if (loading) return
; + if (loading) return
; // everything should be loaded if (!info.admins || !info.tokens || !info.jobBond) { diff --git a/src/components/token/ui/fungible.tsx b/src/components/token/ui/fungible.tsx index bd55826c..99caddf5 100644 --- a/src/components/token/ui/fungible.tsx +++ b/src/components/token/ui/fungible.tsx @@ -10,32 +10,39 @@ interface Props extends ContractsData { } export const FungibleTokenBalances = ({ className, dao, multicall }: Props) => { - const nativeToken = BalancesModel.useNativeTokenData({ dao, multicall }); - const customTokens = BalancesModel.useCustomTokensData({ dao, multicall }); + const nativeToken = BalancesModel.useNativeTokenData({ dao, multicall }), + customTokens = BalancesModel.useCustomTokensData({ dao, multicall }), + loading = nativeToken.loading || customTokens.loading; const tableContent = [ - !nativeToken.loading && nativeToken.data - ? [, nativeToken.data.multicall, nativeToken.data.dao, nativeToken.data.total] - : [], - - ...(!customTokens.loading && customTokens.data - ? customTokens.data.map((customToken) => [ - , - customToken.multicall, - customToken.dao, - customToken.total, - ]) - : []), - ]; + nativeToken.data && [ + , + nativeToken.data.multicall, + nativeToken.data.dao, + nativeToken.data.total, + ], + ].concat( + customTokens.data && + customTokens.data.map((customToken) => [ + , + customToken.multicall, + customToken.dao, + customToken.total, + ]) + ); return (

Fungible Token Balances

-
0 ? tableContent : [["...", "...", "...", "..."]]} - /> + {loading ? ( +
+ ) : ( +
0 ? tableContent : [["...", "...", "...", "..."]]} + /> + )} ); }; From 7b09c30b69203768c7dcc82e59e77eb478a9c7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Sep 2022 23:15:41 +0400 Subject: [PATCH 041/537] wip: Add global `disabled` style --- src/components/dialog/dialog.scss | 4 ---- src/global.scss | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/dialog/dialog.scss b/src/components/dialog/dialog.scss index a74e9626..63086405 100644 --- a/src/components/dialog/dialog.scss +++ b/src/components/dialog/dialog.scss @@ -49,10 +49,6 @@ &.done { background-color: color.$green; } - &.disabled { - background-color: color.$darkish; - cursor: not-allowed; - } } } } diff --git a/src/global.scss b/src/global.scss index c4b5e2b2..633472e9 100644 --- a/src/global.scss +++ b/src/global.scss @@ -46,6 +46,12 @@ button { cursor: pointer; } +.disabled { + background-color: color.$darkest !important; + color: rgba(232, 230, 227, 0.3); + cursor: not-allowed !important; +} + .warn { color: color.$yellow; } From 79f5924ad2cc3b7923ea5461b34b6994d7653204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Sep 2022 23:18:54 +0400 Subject: [PATCH 042/537] fix: Disable dapp multicall login if DAO has no multicall instance --- src/components/popup-menu/popup-menu.jsx | 5 +++-- src/components/sidebar/sidebar.jsx | 11 +++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/popup-menu/popup-menu.jsx b/src/components/popup-menu/popup-menu.jsx index 860358d4..50fb2691 100644 --- a/src/components/popup-menu/popup-menu.jsx +++ b/src/components/popup-menu/popup-menu.jsx @@ -9,10 +9,11 @@ export const PopupMenu = ({ icon, items, triggerClassName }) => (
0 ? tableContent : [["...", "...", "...", "..."]]} + rows={tableContent} /> )} diff --git a/src/shared/ui/components/table/index.scss b/src/shared/ui/components/table/index.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/shared/ui/components/table/index.tsx b/src/shared/ui/components/table/index.tsx index 49507796..47a06c09 100644 --- a/src/shared/ui/components/table/index.tsx +++ b/src/shared/ui/components/table/index.tsx @@ -1,23 +1,8 @@ -import { - TableContainer, - TableHead, - TableCell, - TableRow, - TableBody, - Box, - Typography, - styled, - IconButton, - Collapse, - TableSortLabel, -} from "@mui/material"; - -// import { visuallyHidden } from '@mui/utils' -import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; -import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; -import React, { useState } from "react"; +import { TableContainer, TableHead, TableCell, TableRow as MuiTableRow, TableBody, styled } from "@mui/material"; +import React from "react"; import { useBreakpoint } from "../../lib/breakpoints"; +import { TableRow, TableRowCard, TableRowDefault, TableRowProps } from "./row"; const StyledTableContainer = styled(TableContainer)({ display: "table", @@ -67,135 +52,12 @@ const StyledTableHead = styled(TableHead)(({ theme }) => ({ }, })); -const StyledTableRow = styled(TableRow, { shouldForwardProp: () => true })<{ - variant: "outlined" | "grey"; - fontSize?: string; -}>(({ variant, theme, fontSize }) => ({ - height: 80, - borderRadius: "16px", - overflow: "hidden", - position: "relative", - whiteSpace: "pre", - background: variant === "outlined" ? "transparent" : "#b4ccca", - - "& + tr .MuiCollapse-root": { - background: variant === "outlined" ? "transparent" : theme.palette.background.default, - }, - - "& .MuiTableCell-root": { - fontSize: (fontSize ?? "16px") + "!important", - justifyContent: "flex-start", - paddingLeft: 0, - border: "1px solid", - borderColor: variant === "outlined" ? "#00000010" : "transparent", - borderRight: "none", - borderLeft: "none", - - "& .MuiTypography-root": { - fontSize: (fontSize ?? "16px") + "!important", - }, - - "&:first-of-type": { - borderLeft: "1px solid", - borderColor: variant === "outlined" ? "#00000010" : "transparent", - paddingLeft: "20px", - borderTopLeftRadius: 16, - borderBottomLeftRadius: 16, - }, - - "&:last-child": { - borderRight: "1px solid", - borderColor: variant === "outlined" ? "#00000010" : "transparent", - paddingRight: "20px", - borderTopRightRadius: 16, - borderBottomRightRadius: 16, - }, - }, - - "&:hover": { - "& + tr .MuiCollapse-root": { - backgroundColor: variant === "outlined" ? "#E2E7F020" : "#dcefea", - }, - - backgroundColor: variant === "outlined" ? "#E2E7F020" : "#dcefea", - }, -})); - -const Card = styled("div")({ - backgroundColor: "rgba(255, 255, 255, 0.08)", - border: "1px solid rgba(0, 0, 0, 0.1)", - borderRadius: 16, - padding: 16, - - "& > div": { - width: "100%", - }, -}); - -const sortIcon = ({ className }: { className: string }) => ( - - - - - -); - -const CardRow = styled("div")(` - display: flex; - justify-content: space-between; - grid-template-columns: auto 100%; - - > div:first-of-type { - white-space: nowrap; - } - - > div:last-child { - width: 100%; - display: flex; - justify-content: flex-end; - align-items: center; - } - `); - export const Table = ({ header, - rows, - variant = "grey", - collapsible, - hiddenParts, - fontSize, - sortHeaders, - order, - orderBy, - createSortfunction, - icons, + rows = [["...", "...", "...", "..."]], }: { - sortHeaders?: string[]; - header: string[]; - rows: ((string | number | JSX.Element)[] | null)[]; - variant?: "outlined" | "grey"; - collapsible?: boolean; - hiddenParts?: JSX.Element[]; - fontSize?: string; - order?: "asc" | "desc"; - orderBy?: string; - createSortfunction?: (label: string) => () => void; - icons?: boolean; + header: TableRowProps["headerCells"]; + rows?: TableRowProps["cells"][]; }) => { const matches = useBreakpoint("md"); @@ -203,114 +65,30 @@ export const Table = ({ <> {matches ? ( <> - {rows.map((data, index) => ( - - - {header.map((headerString, index) => ( - - - {headerString} - - - theme.palette.text.secondary }} - component="div" - > - {data && data[index]} - - - {collapsible && index + 1 === header.length && ( - setIsOpen(open => !open)} - sx={{ flexGrow: 0 }} - > - - {/* {isOpen ? : } */} - - )} - - ))} - - + {rows.map((cells, index) => ( + ))} ) : (
- - {header.map((string, index) => ( - - {sortHeaders && - sortHeaders.includes(string) && - order && - orderBy && - createSortfunction ? ( - - orderBy === string - ? order === "desc" - ? theme.palette.primary.main - : "#00000099" - : "#00000099", - }, - - "& .MuiTableSortLabel-iconDirectionAsc .sort-up": { - fill: (theme) => - orderBy === string - ? order === "asc" - ? theme.palette.primary.main - : "#00000099" - : "#00000099", - }, - }} - > - {string} - - {/* - {order === 'desc' ? 'sorted descending' : 'sorted ascending'} - */} - - ) : ( - string - )} - + + {header.map((headerCell, index) => ( + {headerCell} ))} - + - {rows.map((row, index) => ( - ( + ))} @@ -320,97 +98,3 @@ export const Table = ({ ); }; - -const Row = ({ - row, - variant, - collapsible, - hiddenPart, - fontSize, -}: { - row: (string | number | JSX.Element)[]; - variant: "outlined" | "grey"; - collapsible?: boolean; - hiddenPart?: JSX.Element; - fontSize?: string; -}) => { - const [isOpen, setIsOpen] = useState(false); - - return ( - <> - - {row && - row.map((content, index) => ( - - {content} - - ))} - - {collapsible && ( - - setIsOpen((open) => !open)} - sx={{ flexGrow: 0 }} - > - {isOpen ? : } - - - )} - - - {collapsible && ( - - - - - {hiddenPart} - - - - - )} - - ); -}; diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss new file mode 100644 index 00000000..c8fe5a62 --- /dev/null +++ b/src/shared/ui/components/table/row.scss @@ -0,0 +1,71 @@ +.table-row-default { + height: 80px; + border-radius: 16px; + overflow: hidden; + position: relative; + white-space: pre; + background: #b4ccca; + font-family: "Titillium Web"; + + & .MuiTableCell-root { + font-size: 16px; + justify-content: flex-start; + padding-left: 0; + border: 1px solid; + border-color: transparent; + border-right: none; + border-left: none; + + & .MuiTypography-root { + font-size: 16px; + } + + &:first-of-type { + border-left: 1px solid; + border-color: transparent; + padding-left: 20px; + border-top-left-radius: 16px; + border-bottom-left-radius: 16px; + } + + &:last-child { + border-right: 1px solid; + border-color: transparent; + padding-right: 20px; + border-top-right-radius: 16px; + border-bottom-right-radius: 16px; + } + } + + &:hover { + background-color: #dcefea; + } +} + +.table-row-card { + display: flex; + flex-direction: column; + gap: 16px; + border: "1px solid rgba(0, 0, 0, 0.1)"; + border-radius: 16px; + padding: 16px; + width: 100%; + background-color: rgba(255, 255, 255, 0.08); + + .content { + display: flex; + justify-content: space-between; + grid-template-columns: auto 100%; + + > div:first-of-type { + white-space: nowrap; + } + + > div:last-child { + width: 100%; + display: flex; + justify-content: flex-end; + align-items: center; + } + } +} diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx new file mode 100644 index 00000000..f170c2df --- /dev/null +++ b/src/shared/ui/components/table/row.tsx @@ -0,0 +1,52 @@ +import { TableCell, TableRow as MuiTableRow, Typography } from "@mui/material"; +import React from "react"; + +import "./row.scss"; + +interface TableRowDefaultProps { + cells?: (string | number | JSX.Element)[] | null; +} + +export const TableRowDefault = ({ cells }: TableRowDefaultProps) => ( + <> + + {cells && cells.map((cell, index) => {cell})} + + +); + +interface TableRowCardProps extends TableRowDefaultProps { + headerCells: string[]; +} + +export const TableRowCard = ({ cells, headerCells }: TableRowCardProps) => ( +
+ {headerCells.map((headerCell, headerCellIndex) => ( +
+ + {headerCell} + + + {cells && cells[headerCellIndex]} +
+ ))} +
+); + +export interface TableRowProps extends TableRowDefaultProps, TableRowCardProps {} + +export const TableRow = (props: TableRowProps) => ( + <> + + + +); diff --git a/src/shared/ui/components/tabs/styles.scss b/src/shared/ui/components/tabs/styles.scss new file mode 100644 index 00000000..e69de29b From ba5eeaa24c9ef0a212d46c8e60eb93395003b7fd Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Wed, 21 Sep 2022 21:37:44 +0200 Subject: [PATCH 075/537] add TS type to DAO page context --- src/components/dao/dao.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index 6396d9b8..8bd42a14 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -20,6 +20,7 @@ import clsx from "clsx"; // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR +const Ctx = useWalletSelector(); interface Props {} @@ -73,7 +74,8 @@ export class Dao extends Component { }); } - static contextType = useWalletSelector(); + static contextType = Ctx; + declare context: React.ContextType; errors = { name: new ArgsError( @@ -134,7 +136,7 @@ export class Dao extends Component { } createMulticall() { - const { accountId } = this.context; + const { accountId } = this.context!; const { loading, name, dao, proposed, proposedInfo } = this.state; const { noContract, noDao } = this.errors; @@ -149,10 +151,10 @@ export class Dao extends Component { const depo = Big(this.fee).plus(MIN_INSTANCE_BALANCE); // can user propose a FunctionCall to DAO? - const canPropose = dao.checkUserPermission(accountId, ProposalAction.AddProposal, ProposalKind.FunctionCall); + const canPropose = dao.checkUserPermission(accountId!, ProposalAction.AddProposal, ProposalKind.FunctionCall); // can user vote approve a FunctionCall on the DAO? - const canApprove = dao.checkUserPermission(accountId, ProposalAction.VoteApprove, ProposalKind.FunctionCall); + const canApprove = dao.checkUserPermission(accountId!, ProposalAction.VoteApprove, ProposalKind.FunctionCall); const args = { proposal: { @@ -394,7 +396,7 @@ export class Dao extends Component { } getContent() { - const { selector: walletSelector } = this.context; + const { selector: walletSelector } = this.context!; const { info, loading, activeTab } = this.state; // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) From 32c5a3536f8e03f4b7baf1b84fd5483a7d8e566a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 22 Sep 2022 01:40:57 +0400 Subject: [PATCH 076/537] chore: Add Todo Tree extension to workspace recommendations --- .vscode/extensions.json | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 2c6ac5b3..aec05715 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,3 @@ { - "recommendations": [ - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode" - ] -} \ No newline at end of file + "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "Gruntfuggly.todo-tree"] +} From 62195d608a2d27a76bcb1ee8423cdcf4e03c873e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 22 Sep 2022 08:03:11 +0400 Subject: [PATCH 077/537] wip: Rework table & tabs --- sass/_base.scss | 19 --- sass/_size.scss | 2 +- src/components/dao/dao.scss | 121 +++------------- src/components/dao/dao.tsx | 132 +++++++++--------- src/components/dao/funds.scss | 1 + src/components/dao/multicall.scss | 2 + src/components/menu/menu.jsx | 16 +-- src/components/menu/menu.scss | 76 ++++++---- src/components/token/ui/fungible.tsx | 9 +- src/global.scss | 8 -- src/shared/ui/components/card/index.scss | 69 +++++++++ src/shared/ui/components/card/index.tsx | 12 ++ src/shared/ui/components/table/index.scss | 49 +++++++ src/shared/ui/components/table/index.tsx | 76 +++------- src/shared/ui/components/table/row.scss | 20 ++- src/shared/ui/components/table/row.tsx | 10 +- src/shared/ui/components/tabs/index.tsx | 89 +++++------- src/shared/ui/components/tabs/item.scss | 41 ++++++ src/shared/ui/components/tabs/item.tsx | 26 ++++ src/shared/ui/components/tabs/layout.scss | 22 +++ src/shared/ui/components/tabs/layout.tsx | 30 ++++ src/shared/ui/components/tabs/styles.scss | 0 .../{token-label.scss => index.scss} | 0 .../{token-label.tsx => index.tsx} | 2 +- src/shared/ui/lib/breakpoints.ts | 8 -- 25 files changed, 467 insertions(+), 373 deletions(-) create mode 100644 src/shared/ui/components/card/index.scss create mode 100644 src/shared/ui/components/card/index.tsx create mode 100644 src/shared/ui/components/tabs/item.scss create mode 100644 src/shared/ui/components/tabs/item.tsx create mode 100644 src/shared/ui/components/tabs/layout.scss create mode 100644 src/shared/ui/components/tabs/layout.tsx delete mode 100644 src/shared/ui/components/tabs/styles.scss rename src/shared/ui/components/token-label/{token-label.scss => index.scss} (100%) rename src/shared/ui/components/token-label/{token-label.tsx => index.tsx} (95%) delete mode 100644 src/shared/ui/lib/breakpoints.ts diff --git a/sass/_base.scss b/sass/_base.scss index 0db20c40..cd5be854 100644 --- a/sass/_base.scss +++ b/sass/_base.scss @@ -56,25 +56,6 @@ flex: 1; } -.tab-panel { - display: none; -} - -.tab-panel.active { - @include mixin.center-items; - height: calc(100% - size.$tab-list-height - 2 * size.$gap); - flex-flow: column; - gap: size.$gap; - - & > div { - display: flex; - flex-flow: column nowrap; - height: calc(100% - size.$gap); - width: calc(100% - (2 * size.$gap)); - padding: 0 size.$gap size.$gap size.$gap; - } -} - .loader { display: flex; align-self: center; diff --git a/sass/_size.scss b/sass/_size.scss index ed7ea027..8437eed2 100644 --- a/sass/_size.scss +++ b/sass/_size.scss @@ -15,5 +15,5 @@ $task-radius: 2.4rem; $menu-width: 0rem; // 25vw; -$tab-list-height: 3.2rem; +$Tab-buttons-height: 3.2rem; $sidebar-width: 2 * $gap; diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 5e984a56..4ce88bb5 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -4,7 +4,7 @@ @use "sass/font"; @use "sass/animation"; -.dao-container { +.DaoPage-root { @include mixin.page-wrapper; display: flex; flex-flow: column nowrap; @@ -14,6 +14,7 @@ flex-flow: row nowrap; max-width: 120rem; margin: 0 auto; + .address-container { @include mixin.center-items; flex-flow: row nowrap; @@ -60,32 +61,6 @@ } } } - .tab-list { - @include mixin.center-items; - box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); - background-color: color.$lightest; - border-radius: size.$task-radius; - padding: 0; - height: size.$tab-list-height; - overflow: hidden; - z-index: 1; - button { - flex: 1; - padding: 0; - width: 30%; - height: 100%; - padding: 0 size.$gap; - font-size: size.$text; - background-color: transparent; - &:focus, - &:hover { - background-color: rgba(color.$white, 0.1); - } - &.active-tab { - background-color: color.$white; - } - } - } } &::before { @@ -105,16 +80,6 @@ max-width: 120rem; max-height: calc(100% - (4.5 * size.$gap - 0.5 * (size.$gap - size.$large-text))); - &.tab-panel { - width: 100%; - height: 100%; - margin: 0 auto; - - &.active { - display: grid; - } - } - &.error { display: flex; flex-flow: column; @@ -142,72 +107,6 @@ } } - .info-card { - display: flex; - flex-flow: column nowrap; - position: relative; - background-color: rgba(color.$lightest, 0.25); - border-radius: size.$task-radius; - font-size: size.$small-text; - overflow: scroll; - - .title { - padding: 0.5 * size.$gap size.$gap; - font-size: size.$large-text; - - span { - float: right; - } - } - - @for $i from 0 to 3 { - .MuiSvgIcon-root:nth-of-type(#{$i + 1}) { - position: absolute; - font-size: size.$large-text; - top: 0.5 * size.$gap; - right: calc(0.5 * size.$gap + $i * (size.$large-text + 0.25 * size.$gap)); - cursor: pointer; - } - } - - ul { - display: flex; - flex-flow: column nowrap; - - li { - margin-right: 0.5 * size.$gap; - - span { - position: relative; - display: block; - width: 100%; - - a { - color: darken(color.$blue, 20%) !important; - } - - .MuiSvgIcon-root { - visibility: hidden; - position: absolute; - font-size: size.$large-text; - top: auto !important; - bottom: auto !important; - right: 0 !important; - cursor: pointer; - } - } - - &:hover { - background-color: color.$lightest; - - span > .MuiSvgIcon-root { - visibility: visible; - } - } - } - } - } - .create-multicall { width: fit-content; align-self: center; @@ -222,3 +121,19 @@ } } } + +.DaoPageTabs-buttonsPanel { + position: absolute; + top: 1vmax; + left: 16vw; +} + +.DaoPageTabs-contentSpace { + width: 100%; + height: 100%; + margin: 0 auto; + + &.active { + display: grid; + } +} diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index 8bd42a14..e61f1342 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -1,5 +1,6 @@ import { InputAdornment } from "@mui/material"; import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; +import clsx from "clsx"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import React, { Component } from "react"; @@ -10,13 +11,14 @@ import { toNEAR, toYocto, Big } from "../../utils/converter"; import { view } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; +import { Multicall } from "../../utils/contracts/multicall"; +import { Card } from "../../shared/ui/components/card"; +import { Tabs } from "../../shared/ui/components/tabs"; import { TextInput } from "../editor/elements"; import { FungibleTokenBalances } from "../token"; -import { Multicall } from "../../utils/contracts/multicall"; import "./dao.scss"; import "./funds.scss"; import "./multicall.scss"; -import clsx from "clsx"; // minimum balance a multicall instance needs for storage + state. const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR @@ -58,7 +60,6 @@ export class Dao extends Component { loading: false, proposed: -1, proposedInfo: {}, - activeTab: 0, info: { admins: [], @@ -437,51 +438,65 @@ export class Dao extends Component { } return ( - <> -
-
- -

Admins

- -
    - {info.admins.map((admin) => ( -
  • {this.toLink(admin)}
  • - ))} -
-
- -
-

Whitelisted Tokens

- -
    - {info.tokens.map((token) => ( -
  • {this.toLink(token)}
  • - ))} -
-
- -
- -

Jobs

-
{info.jobs.map((j) => this.job(j))}
-
- -
-

- Job Bond - {`${info.jobBond !== "..." ? toNEAR(info.jobBond) : "..."} Ⓝ`} -

-
-
- -
- -
- + + + +

Admins

+ +
    + {info.admins.map((admin) => ( +
  • {this.toLink(admin)}
  • + ))} +
+
+ + +

Whitelisted Tokens

+ +
    + {info.tokens.map((token) => ( +
  • {this.toLink(token)}
  • + ))} +
+
+ + + +

Jobs

+
{info.jobs.map((j) => this.job(j))}
+
+ + +

+ Job Bond + {`${info.jobBond !== "..." ? toNEAR(info.jobBond) : "..."} Ⓝ`} +

+
+ + ), + }, + { + title: "Funds", + + content: ( +
+ +
+ ), + }, + ]} + /> ); } @@ -511,29 +526,12 @@ export class Dao extends Component { document.addEventListener("onaddressesupdated", () => this.onAddressesUpdated()); } - changeTab = (newTab: number) => this.setState({ activeTab: newTab }); - render() { const { activeTab } = this.state; + return ( -
+
-
- - - -
-
-
-
+
+
-
+
-
+
-
+
diff --git a/src/components/menu/menu.scss b/src/components/menu/menu.scss index 6fd5e980..674b9903 100644 --- a/src/components/menu/menu.scss +++ b/src/components/menu/menu.scss @@ -15,33 +15,59 @@ border-radius: size.$task-radius; z-index: 2; transition: width animation.$menu-expand-time ease-out; - .tabs { +} + +.EditorTabs-root { + height: 100%; + + .Tab-buttons { + @include mixin.center-items; + box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); + border-radius: size.$task-radius; + margin: size.$gap; + padding: 0; + width: calc(100% - 2 * size.$gap); + height: size.$Tab-buttons-height; + overflow: hidden; + + button { + flex: 1; + padding: 0; + width: 30%; + height: 100%; + font-size: size.$text; + color: color.$light-text; + background-color: transparent; + &:focus, + &:hover { + background-color: rgba(color.$white, 0.1); + } + + &.is-active { + color: color.$text; + background-color: color.$white; + } + } + } + + .TabsItem-panel { + display: none; + width: 100%; height: 100%; - .tab-list { + margin: 0 auto; + + &.is-active { @include mixin.center-items; - box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); - border-radius: size.$task-radius; - margin: size.$gap; - padding: 0; - width: calc(100% - 2 * size.$gap); - height: size.$tab-list-height; - overflow: hidden; - button { - flex: 1; - padding: 0; - width: 30%; - height: 100%; - font-size: size.$text; - color: color.$light-text; - background-color: transparent; - &:focus, - &:hover { - background-color: rgba(color.$white, 0.1); - } - &.active-tab { - color: color.$text; - background-color: color.$white; - } + height: calc(100% - size.$Tab-buttons-height - 2 * size.$gap); + flex-flow: column; + gap: size.$gap; + + & > div { + display: flex; + flex-flow: column nowrap; + height: calc(100% - size.$gap); + width: calc(100% - (2 * size.$gap)); + padding: 0 size.$gap size.$gap size.$gap; } } } diff --git a/src/components/token/ui/fungible.tsx b/src/components/token/ui/fungible.tsx index 67aeb25b..c1b41945 100644 --- a/src/components/token/ui/fungible.tsx +++ b/src/components/token/ui/fungible.tsx @@ -1,9 +1,10 @@ import React from "react"; -import { TokenLabel } from "../../../shared/ui/components/token-label/token-label"; +import { TokenLabel } from "../../../shared/ui/components/token-label"; import { Table } from "../../../shared/ui/components/table"; -import { ContractsData } from "../types"; +import { Card } from "../../../shared/ui/components/card"; import { BalancesModel } from "../model/balances"; +import { ContractsData } from "../types"; interface FungibleTokenBalancesProps extends ContractsData { className?: string; @@ -32,7 +33,7 @@ export const FungibleTokenBalances = ({ className, dao, multicall }: FungibleTok ); return ( -
+

Fungible Token Balances

{loading ? ( @@ -43,6 +44,6 @@ export const FungibleTokenBalances = ({ className, dao, multicall }: FungibleTok rows={tableContent} /> )} -
+ ); }; diff --git a/src/global.scss b/src/global.scss index 5a2b418b..7feb79b9 100644 --- a/src/global.scss +++ b/src/global.scss @@ -3,17 +3,9 @@ @use "sass/font"; @use "sass/mixin"; -// displays -// alignment -// sizes -// colors -// fonts - * { margin: 0; font-family: font.$text; - // outline: 1px solid aqua; - // background-color: rgba(aqua, 0.1); } body, diff --git a/src/shared/ui/components/card/index.scss b/src/shared/ui/components/card/index.scss new file mode 100644 index 00000000..1b7862e1 --- /dev/null +++ b/src/shared/ui/components/card/index.scss @@ -0,0 +1,69 @@ +@use "sass/size"; +@use "sass/color"; + +.Card { + display: flex; + flex-flow: column nowrap; + position: relative; + padding: calc(size.$gap / 6); + background-color: rgba(color.$lightest, 0.25); + border-radius: size.$task-radius; + font-size: size.$small-text; + overflow: scroll; + + .title { + padding: 0.5 * size.$gap size.$gap; + font-size: size.$large-text; + + span { + float: right; + } + } + + @for $i from 0 to 3 { + .MuiSvgIcon-root:nth-of-type(#{$i + 1}) { + position: absolute; + font-size: size.$large-text; + top: calc(0.5 * size.$gap + size.$gap / 6); + right: calc(0.5 * size.$gap + $i * (size.$large-text + 0.25 * size.$gap) + size.$gap / 6); + cursor: pointer; + } + } + + ul { + display: flex; + flex-flow: column nowrap; + + li { + margin-right: 0.5 * size.$gap; + + span { + position: relative; + display: block; + width: 100%; + + a { + color: darken(color.$blue, 20%) !important; + } + + .MuiSvgIcon-root { + visibility: hidden; + position: absolute; + font-size: size.$large-text; + top: auto !important; + bottom: auto !important; + right: 0 !important; + cursor: pointer; + } + } + + &:hover { + background-color: color.$lightest; + + span > .MuiSvgIcon-root { + visibility: visible; + } + } + } + } +} diff --git a/src/shared/ui/components/card/index.tsx b/src/shared/ui/components/card/index.tsx new file mode 100644 index 00000000..538a4d79 --- /dev/null +++ b/src/shared/ui/components/card/index.tsx @@ -0,0 +1,12 @@ +import clsx from "clsx"; +import React from "react"; + +import "./index.scss"; + +const NAMESPACE = "Card"; + +export interface CardProps extends React.PropsWithChildren, React.HTMLAttributes {} + +export const Card = ({ children, className }: CardProps) => ( +
{children}
+); diff --git a/src/shared/ui/components/table/index.scss b/src/shared/ui/components/table/index.scss index e69de29b..de0ab843 100644 --- a/src/shared/ui/components/table/index.scss +++ b/src/shared/ui/components/table/index.scss @@ -0,0 +1,49 @@ +@use "sass/color"; +@use "sass/font"; + +.table-container { + display: table; + border-radius: 40px; + font-family: font.$text; + + & .MuiTableCell-root { + border-bottom: none; + padding: 14px 20px; + font-weight: 400; + } + + & table { + width: 100%; + border-collapse: separate; + border-spacing: 0 1.6ch; + } +} + +.table-head { + overflow: hidden; + background-color: color.$lightest; + color: color.$text; + + & .MuiTableCell-root { + border-bottom: none; + padding: 12px 20px; + font-size: 12px; + line-height: 12px; + white-space: pre; + + &:first-of-type { + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; + } + + &:last-of-type { + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; + } + } +} + +.Table--column { + display: grid; + gap: 1.6ch; +} diff --git a/src/shared/ui/components/table/index.tsx b/src/shared/ui/components/table/index.tsx index 47a06c09..53f69011 100644 --- a/src/shared/ui/components/table/index.tsx +++ b/src/shared/ui/components/table/index.tsx @@ -1,56 +1,16 @@ -import { TableContainer, TableHead, TableCell, TableRow as MuiTableRow, TableBody, styled } from "@mui/material"; +import { + TableContainer, + TableHead, + TableCell, + TableRow as MuiTableRow, + TableBody, + useMediaQuery, + useTheme, +} from "@mui/material"; import React from "react"; -import { useBreakpoint } from "../../lib/breakpoints"; -import { TableRow, TableRowCard, TableRowDefault, TableRowProps } from "./row"; - -const StyledTableContainer = styled(TableContainer)({ - display: "table", - borderRadius: "40px", - "& .MuiTableCell-root": { - borderBottom: "none", - fontWeight: 400, - padding: "14px 20px", - "&:first-of-type": { - paddingLeft: 20, - }, - "&:last-child": { - paddingRight: 20, - }, - }, - "& table": { - width: "100%", - borderCollapse: "separate", - borderSpacing: "0 8px", - }, -}); - -const StyledTableHead = styled(TableHead)(({ theme }) => ({ - borderRadius: 8, - overflow: "hidden", - "& .MuiTableCell-root": { - fontSize: "12px", - whiteSpace: "pre", - lineHeight: "12px", - background: "rgba(255, 255, 255, 0.08)", - padding: "12px 20px 12px 0", - color: theme.palette.text.secondary, - borderBottom: "none", - "& .MuiTableSortLabel-root": { - fontWeight: 400, - fontSize: "12px!important", - color: theme.palette.text.secondary, - }, - "&:first-of-type": { - paddingLeft: 20, - borderTopLeftRadius: 8, - }, - "&:last-child": { - paddingRight: 20, - borderTopRightRadius: 8, - }, - }, -})); +import { TableRowCard, TableRowDefault, TableRowProps } from "./row"; +import "./index.scss"; export const Table = ({ header, @@ -59,12 +19,12 @@ export const Table = ({ header: TableRowProps["headerCells"]; rows?: TableRowProps["cells"][]; }) => { - const matches = useBreakpoint("md"); + const matches = useMediaQuery(useTheme().breakpoints.down("md")); return ( <> {matches ? ( - <> +
{rows.map((cells, index) => ( ))} - +
) : ( - +
- + {header.map((headerCell, index) => ( {headerCell} ))} - + {rows.map((cells, index) => ( @@ -93,7 +53,7 @@ export const Table = ({ ))}
- + )} ); diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index c8fe5a62..36401eb2 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -1,11 +1,13 @@ +@use "sass/color"; +@use "sass/size"; + .table-row-default { height: 80px; border-radius: 16px; overflow: hidden; position: relative; white-space: pre; - background: #b4ccca; - font-family: "Titillium Web"; + background: color.$light; & .MuiTableCell-root { font-size: 16px; @@ -21,36 +23,30 @@ } &:first-of-type { - border-left: 1px solid; border-color: transparent; - padding-left: 20px; border-top-left-radius: 16px; border-bottom-left-radius: 16px; } - &:last-child { - border-right: 1px solid; + &:last-of-type { border-color: transparent; - padding-right: 20px; border-top-right-radius: 16px; border-bottom-right-radius: 16px; } } &:hover { - background-color: #dcefea; + background-color: color.$lightest; } } .table-row-card { display: flex; flex-direction: column; - gap: 16px; - border: "1px solid rgba(0, 0, 0, 0.1)"; + gap: size.$gap; border-radius: 16px; padding: 16px; - width: 100%; - background-color: rgba(255, 255, 255, 0.08); + background-color: color.$light; .content { display: flex; diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index f170c2df..4f3acdb8 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -29,14 +29,18 @@ export const TableRowCard = ({ cells, headerCells }: TableRowCardProps) => ( {headerCell} - {cells && cells[headerCellIndex]} + + {cells && cells[headerCellIndex]} +
))}
diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx index 60ab3aed..2fd9699c 100644 --- a/src/shared/ui/components/tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -1,68 +1,45 @@ -import { Tabs as MuiTabs, Tab, Box } from "@mui/material"; import clsx from "clsx"; -import React, { Fragment, useCallback } from "react"; +import React, { useCallback, useState } from "react"; -interface Props { - titles: string[] | JSX.Element[]; - content: React.ReactNode[]; - fontWeight?: number; +import { TabsItemButton, TabsItemPanel } from "./item"; +import { TabsLayout, TabsLayoutProps } from "./layout"; + +interface TabsProps { + classes?: TabsLayoutProps["classes"] & {}; + items: { title: string; content: JSX.Element }[]; } -export const Tabs = ({ titles, content }: Props) => { - const [activeТаbIndex, activeTabSwitch] = React.useState(0); +export const Tabs = ({ classes, items }: TabsProps) => { + const [activeТаbIndex, activeTabSwitch] = useState(0); - const onChange = useCallback( - (_event: React.ChangeEvent, value: any) => activeTabSwitch(value), + const itemButtonClickHandler = useCallback( + (itemIndex: number) => () => activeTabSwitch(itemIndex), [activeTabSwitch] ); - return ( - - - - {titles.map((title, index) => ( - - ))} - - + const buttons = items.map(({ title }, tabIndex) => ( + + )); - {content.map( - (tabPanelContent, tabIndex) => - activeТаbIndex === tabIndex && {tabPanelContent} + return ( + + {items.map( + ({ content }, tabIndex) => + /* TODO: Render inactive tabs too */ + activeТаbIndex === tabIndex && ( + + {content} + + ) )} - + ); }; diff --git a/src/shared/ui/components/tabs/item.scss b/src/shared/ui/components/tabs/item.scss new file mode 100644 index 00000000..b87f17ce --- /dev/null +++ b/src/shared/ui/components/tabs/item.scss @@ -0,0 +1,41 @@ +@use "sass/mixin"; +@use "sass/size"; +@use "sass/color"; + +.TabsItem-button { + flex: 1; + padding: 0; + width: 30%; + height: 100%; + padding: 0 size.$gap; + font-size: size.$text; + background-color: transparent; + + &:focus, + &:hover { + background-color: rgba(color.$white, 0.1); + } + + &.is-active { + background-color: color.$white; + } +} + +.TabsItem-panel { + display: none; + width: 100%; + height: 100%; + margin: 0 auto; + + &.is-active { + @include mixin.center-items; + height: calc(100% - size.$Tab-buttons-height - 2 * size.$gap); + flex-flow: column; + gap: size.$gap; + + & > div { + height: calc(100% - size.$gap); + width: calc(100% - (2 * size.$gap)); + } + } +} diff --git a/src/shared/ui/components/tabs/item.tsx b/src/shared/ui/components/tabs/item.tsx new file mode 100644 index 00000000..26d21c87 --- /dev/null +++ b/src/shared/ui/components/tabs/item.tsx @@ -0,0 +1,26 @@ +import clsx from "clsx"; +import React from "react"; + +import "./item.scss"; + +const NAMESPACE = "TabsItem"; + +export interface TabsItemButtonProps extends React.HTMLAttributes { + title: string; + onClick: VoidFunction; +} + +export const TabsItemButton = ({ className, onClick, title }: TabsItemButtonProps) => ( + +); + +export interface TabsItemPanelProps extends React.PropsWithChildren, React.HTMLAttributes {} + +export const TabsItemPanel = ({ children, className }: TabsItemPanelProps) => ( +
{children}
+); diff --git a/src/shared/ui/components/tabs/layout.scss b/src/shared/ui/components/tabs/layout.scss new file mode 100644 index 00000000..ee7c0657 --- /dev/null +++ b/src/shared/ui/components/tabs/layout.scss @@ -0,0 +1,22 @@ +@use "sass/mixin"; +@use "sass/size"; +@use "sass/color"; + +.TabsLayout-root { + height: 100%; +} + +.TabsLayout-buttonsPanel { + @include mixin.center-items; + box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); + background-color: color.$lightest; + border-radius: size.$task-radius; + padding: 0; + height: size.$Tab-buttons-height; + overflow: hidden; + z-index: 1; +} + +.TabsLayout-contentSpace { + height: 100%; +} diff --git a/src/shared/ui/components/tabs/layout.tsx b/src/shared/ui/components/tabs/layout.tsx new file mode 100644 index 00000000..b50ac3df --- /dev/null +++ b/src/shared/ui/components/tabs/layout.tsx @@ -0,0 +1,30 @@ +import clsx from "clsx"; +import React from "react"; + +import "./layout.scss"; + +const NAMESPACE = "TabsLayout"; + +interface TabsLayoutButtonsPanelProps extends React.PropsWithChildren, React.HTMLAttributes {} + +const TabsLayoutButtonsPanel = ({ children, className }: TabsLayoutButtonsPanelProps) => ( +
{children}
+); + +interface TabsLayoutContentSpaceProps extends React.PropsWithChildren, React.HTMLAttributes {} + +const TabsLayoutContentSpace = ({ children, className }: TabsLayoutContentSpaceProps) => ( +
{children}
+); + +export interface TabsLayoutProps extends React.PropsWithChildren { + buttons: JSX.Element[]; + classes?: { root?: string; buttonsPanel?: string; contentSpace?: string }; +} + +export const TabsLayout = ({ buttons, children, classes }: TabsLayoutProps) => ( +
+ {buttons} + {children} +
+); diff --git a/src/shared/ui/components/tabs/styles.scss b/src/shared/ui/components/tabs/styles.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/shared/ui/components/token-label/token-label.scss b/src/shared/ui/components/token-label/index.scss similarity index 100% rename from src/shared/ui/components/token-label/token-label.scss rename to src/shared/ui/components/token-label/index.scss diff --git a/src/shared/ui/components/token-label/token-label.tsx b/src/shared/ui/components/token-label/index.tsx similarity index 95% rename from src/shared/ui/components/token-label/token-label.tsx rename to src/shared/ui/components/token-label/index.tsx index e8199593..a90d068e 100644 --- a/src/shared/ui/components/token-label/token-label.tsx +++ b/src/shared/ui/components/token-label/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import { NearGenericTokenIconFilled, NearIconFilled } from "../icons"; -import "./token-label.scss"; +import "./index.scss"; export const TokenLabel = ({ icon, diff --git a/src/shared/ui/lib/breakpoints.ts b/src/shared/ui/lib/breakpoints.ts deleted file mode 100644 index 8271c568..00000000 --- a/src/shared/ui/lib/breakpoints.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useMediaQuery, useTheme } from "@mui/material"; -import { Breakpoint } from "@mui/material/styles"; - -export const useBreakpoint = (breakpoint: Breakpoint = "sm") => { - const theme = useTheme(); - - return useMediaQuery(theme.breakpoints.down(breakpoint)); -}; From 2cfbd48d304790552639ec913d6100f4766cd881 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Thu, 22 Sep 2022 16:54:18 +0200 Subject: [PATCH 078/537] backend support to propose multicall config changes --- src/utils/contracts/multicall.ts | 84 ++++++++++++++++++++++++++++++ src/utils/contracts/sputnik-dao.ts | 32 ++++++++++++ 2 files changed, 116 insertions(+) diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index 9d4cb4ee..fda5715f 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -1,5 +1,8 @@ import { rpcProvider, view, tx } from "../wallet"; import { Big, toGas, dateToCron } from "../converter"; +import { Base64 } from "js-base64"; + +import type { FunctionCallAction as daoFunctionCallAction } from "./sputnik-dao"; const FACTORY_ADDRESS_SELECTOR: Record = { mainnet: "v1.multicall.near", @@ -46,6 +49,13 @@ type MulticallArgs = { calls: BatchCall[][]; }; +class MulticallConfigChanges { + removeTokens: string[] = []; + addTokens: string[] = []; + jobBond: string = ""; + croncatManager: string = ""; +} + class Multicall { static FACTORY_ADDRESS: string = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; static CONTRACT_CODE_HASHES: string[] = CONTRACT_CODE_HASHES_SELECTOR[window.NEAR_ENV]; @@ -120,6 +130,73 @@ class Multicall { return view(this.FACTORY_ADDRESS, "get_fee", {}); } + /** + * Convert a series of config changes into an "actions" object that's compatible + * with SputnikDAO (V2 & V3) function call proposal params. + * + * @param configDiff changes to current config of some multicall instance. + * @returns actions that can be passed to JSON for DAO "add_proposal". + */ + static configDiffToProposalActions(configDiff: MulticallConfigChanges): daoFunctionCallAction[] { + const { removeTokens, addTokens, jobBond, croncatManager } = configDiff; + const actions: daoFunctionCallAction[] = []; + + // action: change croncat manager address + if (croncatManager !== "") { + actions.push({ + method_name: "set_croncat_manager", + args: Base64.encode( + JSON.stringify({ + address: croncatManager, + }) + ), + deposit: "1", // 1 yocto + gas: toGas("10"), // 10 Tgas + }); + } + // action: change amount of job bond + if (jobBond !== "") { + actions.push({ + method_name: "set_job_bond", + args: Base64.encode( + JSON.stringify({ + amount: jobBond, + }) + ), + deposit: "1", // 1 yocto + gas: toGas("10"), // 10 Tgas + }); + } + // action: remove tokens from whitelist + if (removeTokens.length > 0) { + actions.push({ + method_name: "tokens_remove", + args: Base64.encode( + JSON.stringify({ + addresses: removeTokens, + }) + ), + deposit: "1", // 1 yocto + gas: toGas("20"), // 20 Tgas + }); + } + // action: add tokens to whitelist + if (addTokens.length > 0) { + actions.push({ + method_name: "tokens_add", + args: Base64.encode( + JSON.stringify({ + addresses: addTokens, + }) + ), + deposit: "1", // 1 yocto + gas: toGas("20"), // 20 Tgas + }); + } + + return actions; + } + /** * get list of admins */ @@ -134,6 +211,13 @@ class Multicall { return view(this.address, "get_tokens", {}); } + /** + * get croncat manager address that was regitered on the multicall instance. + */ + async getCroncatManager(): Promise { + return view(this.address, "get_croncat_manager", {}); + } + /** * get whitelisted tokens */ diff --git a/src/utils/contracts/sputnik-dao.ts b/src/utils/contracts/sputnik-dao.ts index 9e43ef52..762e243d 100644 --- a/src/utils/contracts/sputnik-dao.ts +++ b/src/utils/contracts/sputnik-dao.ts @@ -95,6 +95,19 @@ enum ProposalAction { MoveToHub = "MoveToHub", } +// SputnikDAO FunctionCall structure +type FunctionCall = { + receiver_id: string; + actions: FunctionCallAction[]; +}; + +type FunctionCallAction = { + method_name: string; + args: string; // (base64 encoded JSON) + deposit: string; // (u128 as a string) + gas: string; // (u64 as a string) +}; + class SputnikDAO { static FACTORY_ADDRESS: string = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; static REFERENCE_UI_BASE_URL: string = REFERENCE_UI_URL_SELECTOR[window.NEAR_ENV]; @@ -325,6 +338,24 @@ class SputnikDAO { return canDoAction; } + // propose a generic function call to DAO. + async proposeFunctionCall(desc: string, pTarget: string, pActions: FunctionCall): Promise { + const proposalArgs = { + proposal: { + description: desc, + kind: { + FunctionCall: { + receiver_id: pTarget, + actions: pActions, + }, + }, + }, + }; + + // fire the add_proposal transaction + this.addProposal(proposalArgs); + } + /** * propose a multicall using args from LAYOUT * @@ -432,3 +463,4 @@ class SputnikDAO { } export { SputnikDAO, SputnikUI, ProposalKind, ProposalAction }; +export type { FunctionCall, FunctionCallAction }; From bdc12f4bf783742476b6bac0928c26ed596138c3 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Sat, 24 Sep 2022 00:40:51 +0200 Subject: [PATCH 079/537] fix: css scaling --- src/components/dao/dao.scss | 19 ++++++------------- src/components/dao/multicall.scss | 1 + src/shared/ui/components/card/index.scss | 3 +-- src/shared/ui/components/tabs/item.scss | 21 ++++++++++++--------- src/shared/ui/components/tabs/layout.scss | 2 +- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 4ce88bb5..a1fe885b 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -12,6 +12,8 @@ .header { @include mixin.center-items(space-between); flex-flow: row nowrap; + flex-basis: calc(2 * size.$gap + 0.5 * size.$large-text); + flex-shrink: 0; max-width: 120rem; margin: 0 auto; @@ -19,12 +21,13 @@ @include mixin.center-items; flex-flow: row nowrap; width: auto; + height: 100%; .MuiTextField-root { width: calc(100% - 2 * size.$gap); max-width: 100ch; text-align: left; - margin: calc(size.$gap - 0.5 * size.$large-text) size.$gap; + margin: 0 size.$gap; .MuiInputBase-root { font-size: size.$large-text; @@ -68,7 +71,7 @@ position: fixed; top: 0; left: 0; - height: calc(2.5 * size.$gap - 0.5 * (size.$gap - size.$large-text)); + height: calc(2 * size.$gap + 0.5 * size.$large-text); min-width: 100%; background-color: color.$light; } @@ -78,7 +81,7 @@ gap: size.$gap; padding: size.$gap; max-width: 120rem; - max-height: calc(100% - (4.5 * size.$gap - 0.5 * (size.$gap - size.$large-text))); + max-height: calc(100% - 2 * size.$gap); &.error { display: flex; @@ -127,13 +130,3 @@ top: 1vmax; left: 16vw; } - -.DaoPageTabs-contentSpace { - width: 100%; - height: 100%; - margin: 0 auto; - - &.active { - display: grid; - } -} diff --git a/src/components/dao/multicall.scss b/src/components/dao/multicall.scss index 775e89d4..af589801 100644 --- a/src/components/dao/multicall.scss +++ b/src/components/dao/multicall.scss @@ -43,6 +43,7 @@ padding: 0.5 * size.$gap; font-family: font.$code; font-size: size.$small-text; + overflow: hidden; } } } diff --git a/src/shared/ui/components/card/index.scss b/src/shared/ui/components/card/index.scss index 1b7862e1..9af9ea9c 100644 --- a/src/shared/ui/components/card/index.scss +++ b/src/shared/ui/components/card/index.scss @@ -5,11 +5,10 @@ display: flex; flex-flow: column nowrap; position: relative; - padding: calc(size.$gap / 6); + padding: calc(0.25 * size.$gap); background-color: rgba(color.$lightest, 0.25); border-radius: size.$task-radius; font-size: size.$small-text; - overflow: scroll; .title { padding: 0.5 * size.$gap size.$gap; diff --git a/src/shared/ui/components/tabs/item.scss b/src/shared/ui/components/tabs/item.scss index b87f17ce..e53d5abf 100644 --- a/src/shared/ui/components/tabs/item.scss +++ b/src/shared/ui/components/tabs/item.scss @@ -5,7 +5,6 @@ .TabsItem-button { flex: 1; padding: 0; - width: 30%; height: 100%; padding: 0 size.$gap; font-size: size.$text; @@ -29,13 +28,17 @@ &.is-active { @include mixin.center-items; - height: calc(100% - size.$Tab-buttons-height - 2 * size.$gap); - flex-flow: column; - gap: size.$gap; - - & > div { - height: calc(100% - size.$gap); - width: calc(100% - (2 * size.$gap)); - } + + // Code below does not belong here, it's styling for the app menu, + // it should be applied to the tabs selector via a seperate css class + + // height: calc(100% - size.$Tab-buttons-height - 2 * size.$gap); + // flex-flow: column; + // gap: size.$gap; + + // & > div { + // height: calc(100% - size.$gap); + // width: calc(100% - (2 * size.$gap)); + // } } } diff --git a/src/shared/ui/components/tabs/layout.scss b/src/shared/ui/components/tabs/layout.scss index ee7c0657..3e61c9fa 100644 --- a/src/shared/ui/components/tabs/layout.scss +++ b/src/shared/ui/components/tabs/layout.scss @@ -3,7 +3,7 @@ @use "sass/color"; .TabsLayout-root { - height: 100%; + height: calc(100% - (2 * size.$gap + 0.5 * size.$large-text)); } .TabsLayout-buttonsPanel { From bd9ccdf3977168510f1b7026ea3878298abf35a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 24 Sep 2022 04:09:49 +0400 Subject: [PATCH 080/537] fix: Use overflow-y instead of overflow --- src/shared/ui/components/card/index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/components/card/index.scss b/src/shared/ui/components/card/index.scss index 1b7862e1..aa9fef1d 100644 --- a/src/shared/ui/components/card/index.scss +++ b/src/shared/ui/components/card/index.scss @@ -9,7 +9,7 @@ background-color: rgba(color.$lightest, 0.25); border-radius: size.$task-radius; font-size: size.$small-text; - overflow: scroll; + overflow-y: scroll; .title { padding: 0.5 * size.$gap size.$gap; From dec8720700195d237b54464b03332a10384dc5dd Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Sat, 24 Sep 2022 02:28:59 +0200 Subject: [PATCH 081/537] move tab selector --- src/components/dao/dao.scss | 31 ++++++++++++++++++++++--- src/shared/ui/components/tabs/item.scss | 2 -- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index a1fe885b..5d4e43eb 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -126,7 +126,32 @@ } .DaoPageTabs-buttonsPanel { - position: absolute; - top: 1vmax; - left: 16vw; + display: flex; + justify-content: flex-start; + max-width: 120rem; + margin: size.$gap auto 0 auto; + padding: 0 size.$gap; + background-color: transparent; + & > button { + background-color: color.$lightest; + color: color.$text; + &.is-active, + &:hover, + &:focus { + background-color: color.$darkest; + color: color.$light-text; + transition: all 400ms ease; + transition-property: background-color, color; + } + &:first-of-type { + border-radius: size.$task-radius 0 0 size.$task-radius; + } + &:last-of-type { + border-radius: 0 size.$task-radius size.$task-radius 0; + } + } +} + +.TabsLayout-contentSpace { + height: calc(100% - size.$gap - size.$Tab-buttons-height); } diff --git a/src/shared/ui/components/tabs/item.scss b/src/shared/ui/components/tabs/item.scss index e53d5abf..53109da9 100644 --- a/src/shared/ui/components/tabs/item.scss +++ b/src/shared/ui/components/tabs/item.scss @@ -3,8 +3,6 @@ @use "sass/color"; .TabsItem-button { - flex: 1; - padding: 0; height: 100%; padding: 0 size.$gap; font-size: size.$text; From d8fe079d4d0f26fa9322f76342b860549d7bd36e Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Sat, 24 Sep 2022 02:56:50 +0200 Subject: [PATCH 082/537] fix: funds list scrolling --- src/components/dao/dao.tsx | 2 +- src/components/dao/funds.scss | 2 ++ src/components/token/ui/fungible.scss | 12 ++++++++++++ src/components/token/ui/fungible.tsx | 11 +++++++---- 4 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 src/components/token/ui/fungible.scss diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index e61f1342..ed94fa58 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -488,7 +488,7 @@ export class Dao extends Component { content: (
diff --git a/src/components/dao/funds.scss b/src/components/dao/funds.scss index 756fb4bc..f9987a28 100644 --- a/src/components/dao/funds.scss +++ b/src/components/dao/funds.scss @@ -10,5 +10,7 @@ .balances { grid-area: balances; padding-bottom: size.$gap; + position: relative; + overflow: hidden; } } diff --git a/src/components/token/ui/fungible.scss b/src/components/token/ui/fungible.scss new file mode 100644 index 00000000..100045a8 --- /dev/null +++ b/src/components/token/ui/fungible.scss @@ -0,0 +1,12 @@ +@use "sass/mixin"; +@use "sass/size"; + +.scroll-wrapper { + @include mixin.no-scrollbar; + overflow-y: scroll; + position: absolute; + top: calc(size.$large-text + 1.5 * size.$gap); + bottom: 0; + left: 0; + right: 0; +} diff --git a/src/components/token/ui/fungible.tsx b/src/components/token/ui/fungible.tsx index c1b41945..83c3c93e 100644 --- a/src/components/token/ui/fungible.tsx +++ b/src/components/token/ui/fungible.tsx @@ -5,6 +5,7 @@ import { Table } from "../../../shared/ui/components/table"; import { Card } from "../../../shared/ui/components/card"; import { BalancesModel } from "../model/balances"; import { ContractsData } from "../types"; +import "./fungible.scss"; interface FungibleTokenBalancesProps extends ContractsData { className?: string; @@ -39,10 +40,12 @@ export const FungibleTokenBalances = ({ className, dao, multicall }: FungibleTok {loading ? (
) : ( - +
+
+ )} ); From ecc3a17261792cacd51d11e1e8ab8eddc776a1c8 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Sat, 24 Sep 2022 03:40:05 +0200 Subject: [PATCH 083/537] table restyling --- src/shared/ui/components/table/index.scss | 27 ++++++++++---------- src/shared/ui/components/table/row.scss | 30 ++++++++--------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/src/shared/ui/components/table/index.scss b/src/shared/ui/components/table/index.scss index de0ab843..104679e2 100644 --- a/src/shared/ui/components/table/index.scss +++ b/src/shared/ui/components/table/index.scss @@ -1,44 +1,43 @@ @use "sass/color"; @use "sass/font"; +@use "sass/size"; .table-container { display: table; - border-radius: 40px; + border-radius: size.$task-radius; font-family: font.$text; + margin-top: size.$gap; & .MuiTableCell-root { border-bottom: none; - padding: 14px 20px; - font-weight: 400; + padding: 0.5 * size.$gap; } & table { width: 100%; border-collapse: separate; - border-spacing: 0 1.6ch; + border-spacing: 0; } } .table-head { overflow: hidden; - background-color: color.$lightest; - color: color.$text; + font-family: font.$text; & .MuiTableCell-root { border-bottom: none; - padding: 12px 20px; - font-size: 12px; - line-height: 12px; - white-space: pre; + font-size: size.$text; + font-weight: 800; + color: color.$text; + text-align: right; &:first-of-type { - border-top-left-radius: 12px; - border-bottom-left-radius: 12px; + text-align: left; + padding-left: 1.25 * size.$gap; } &:last-of-type { - border-top-right-radius: 12px; - border-bottom-right-radius: 12px; + padding-right: 1.25 * size.$gap; } } } diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 36401eb2..9ca1cadb 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -1,37 +1,27 @@ @use "sass/color"; @use "sass/size"; +@use "sass/font"; .table-row-default { - height: 80px; - border-radius: 16px; overflow: hidden; position: relative; white-space: pre; - background: color.$light; + background: transparent; & .MuiTableCell-root { - font-size: 16px; - justify-content: flex-start; - padding-left: 0; - border: 1px solid; - border-color: transparent; - border-right: none; - border-left: none; - - & .MuiTypography-root { - font-size: 16px; - } + font-size: size.$text; + font-family: font.$code; + border: none; + text-align: right; &:first-of-type { - border-color: transparent; - border-top-left-radius: 16px; - border-bottom-left-radius: 16px; + text-align: left; + font-family: font.$text; + padding-left: 1.25 * size.$gap; } &:last-of-type { - border-color: transparent; - border-top-right-radius: 16px; - border-bottom-right-radius: 16px; + padding-right: 1.25 * size.$gap; } } From de75094961c252200daaacc75f11011bf78dcf9a Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Sat, 24 Sep 2022 03:46:38 +0200 Subject: [PATCH 084/537] fix: remove scroll from card --- src/shared/ui/components/card/index.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shared/ui/components/card/index.scss b/src/shared/ui/components/card/index.scss index 25884a53..9af9ea9c 100644 --- a/src/shared/ui/components/card/index.scss +++ b/src/shared/ui/components/card/index.scss @@ -9,7 +9,6 @@ background-color: rgba(color.$lightest, 0.25); border-radius: size.$task-radius; font-size: size.$small-text; - overflow-y: scroll; .title { padding: 0.5 * size.$gap size.$gap; From d646f96502151aeb654c5e694d59f5692bd7d183 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Sun, 25 Sep 2022 02:22:11 +0200 Subject: [PATCH 085/537] wip: use Tabs on menu --- src/components/dao/dao.scss | 2 +- src/components/dao/dao.tsx | 2 +- src/components/menu/menu.jsx | 62 ++++++++++++++---------------------- 3 files changed, 26 insertions(+), 40 deletions(-) diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 5d4e43eb..2a9e0335 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -152,6 +152,6 @@ } } -.TabsLayout-contentSpace { +.DaoPageTabs-contentSpace { height: calc(100% - size.$gap - size.$Tab-buttons-height); } diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index ed94fa58..a429f93e 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -439,7 +439,7 @@ export class Dao extends Component { return ( this.setState({ activeTab: newTab }); render() { - const { expanded, activeTab } = this.state; + const { expanded } = this.state; const LAYOUT = this.props.layout; // ususally global parameter return (
-
- - - - - -
- -
- -
- -
- -
- -
- -
+ + ), + }, + { + title: "Edit", + content: , + }, + { + title: "Export", + content: , + }, + ]} + />
Date: Sun, 25 Sep 2022 02:58:51 +0200 Subject: [PATCH 086/537] move FunctionCall base64 args encoding inside proposeFunctionCall --- src/components/dao/dao.js | 2 +- src/components/export/export.js | 44 ++++++++-------- src/utils/contracts/multicall.ts | 25 ++------- src/utils/contracts/sputnik-dao.ts | 82 ++++++++++++------------------ 4 files changed, 58 insertions(+), 95 deletions(-) diff --git a/src/components/dao/dao.js b/src/components/dao/dao.js index 25121c40..5b0fff38 100644 --- a/src/components/dao/dao.js +++ b/src/components/dao/dao.js @@ -304,7 +304,7 @@ export default class DaoComponent extends Component { job(job) { return ( -
+
{job.is_active ? : } diff --git a/src/components/export/export.js b/src/components/export/export.js index 1a3d0861..0f2877a1 100644 --- a/src/components/export/export.js +++ b/src/components/export/export.js @@ -144,29 +144,27 @@ export default class Export extends Component { let multicallArgs = {}; // Multicall args in text form to display for copy/pasting args let multicallArgsText = ""; - if (this.showArgs) { - // Return error message if a card has JSON errors. Faulty JSON breaks toBase64. - const hasJsonErrors = - errors.hasErrors.isBad && allErrors.some((err) => err.message === errorMsg.ERR_INVALID_ARGS); - if (hasJsonErrors) { - multicallArgsText = "Please fix invalid JSON errors"; - } else { - // toBase64 might throw on failure - try { - multicallArgs = { calls: LAYOUT.toBase64() }; - multicallArgsText = !this.attachFT - ? JSON.stringify(multicallArgs) - : JSON.stringify({ - receiver_id: STORAGE.addresses.multicall, - amount: convert(amount.value, amount.unit, amount.decimals), - msg: JSON.stringify({ - function_id: "multicall", - args: Base64.encode(JSON.stringify(multicallArgs).toString()), - }).toString(), - }); - } catch (e) { - multicallArgsText = "ERROR: something went wrong during JSON creation"; - } + // Return error message if a card has JSON errors. Faulty JSON breaks toBase64. + const hasJsonErrors = + errors.hasErrors.isBad && allErrors.some((err) => err.message === errorMsg.ERR_INVALID_ARGS); + if (hasJsonErrors) { + multicallArgsText = "Please fix invalid JSON errors"; + } else { + // toBase64 might throw on failure + try { + multicallArgs = { calls: LAYOUT.toBase64() }; + multicallArgsText = !this.attachFT + ? JSON.stringify(multicallArgs) + : JSON.stringify({ + receiver_id: STORAGE.addresses.multicall, + amount: convert(amount.value, amount.unit, amount.decimals), + msg: JSON.stringify({ + function_id: "multicall", + args: Base64.encode(JSON.stringify(multicallArgs).toString()), + }).toString(), + }); + } catch (e) { + multicallArgsText = "ERROR: something went wrong during JSON creation"; } } diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index fda5715f..39d80501 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -1,6 +1,5 @@ import { rpcProvider, view, tx } from "../wallet"; import { Big, toGas, dateToCron } from "../converter"; -import { Base64 } from "js-base64"; import type { FunctionCallAction as daoFunctionCallAction } from "./sputnik-dao"; @@ -145,11 +144,7 @@ class Multicall { if (croncatManager !== "") { actions.push({ method_name: "set_croncat_manager", - args: Base64.encode( - JSON.stringify({ - address: croncatManager, - }) - ), + args: { address: croncatManager }, deposit: "1", // 1 yocto gas: toGas("10"), // 10 Tgas }); @@ -158,11 +153,7 @@ class Multicall { if (jobBond !== "") { actions.push({ method_name: "set_job_bond", - args: Base64.encode( - JSON.stringify({ - amount: jobBond, - }) - ), + args: { amount: jobBond }, deposit: "1", // 1 yocto gas: toGas("10"), // 10 Tgas }); @@ -171,11 +162,7 @@ class Multicall { if (removeTokens.length > 0) { actions.push({ method_name: "tokens_remove", - args: Base64.encode( - JSON.stringify({ - addresses: removeTokens, - }) - ), + args: { addresses: removeTokens }, deposit: "1", // 1 yocto gas: toGas("20"), // 20 Tgas }); @@ -184,11 +171,7 @@ class Multicall { if (addTokens.length > 0) { actions.push({ method_name: "tokens_add", - args: Base64.encode( - JSON.stringify({ - addresses: addTokens, - }) - ), + args: { addresses: addTokens }, deposit: "1", // 1 yocto gas: toGas("20"), // 20 Tgas }); diff --git a/src/utils/contracts/sputnik-dao.ts b/src/utils/contracts/sputnik-dao.ts index 762e243d..f7cb3e24 100644 --- a/src/utils/contracts/sputnik-dao.ts +++ b/src/utils/contracts/sputnik-dao.ts @@ -103,7 +103,7 @@ type FunctionCall = { type FunctionCallAction = { method_name: string; - args: string; // (base64 encoded JSON) + args: object; deposit: string; // (u128 as a string) gas: string; // (u64 as a string) }; @@ -182,7 +182,7 @@ class SputnikDAO { this.address, "add_proposal", args, - toGas("25"), // 25 Tgas + toGas("50"), // 50 Tgas this.policy.proposal_bond ); } @@ -339,14 +339,18 @@ class SputnikDAO { } // propose a generic function call to DAO. - async proposeFunctionCall(desc: string, pTarget: string, pActions: FunctionCall): Promise { + async proposeFunctionCall(desc: string, pTarget: string, pActions: FunctionCallAction[]): Promise { const proposalArgs = { proposal: { description: desc, kind: { FunctionCall: { receiver_id: pTarget, - actions: pActions, + actions: pActions.map((action) => ({ + ...action, + // base64 encode supplied action args + args: Base64.encode(JSON.stringify(action.args)), + })), }, }, }, @@ -367,27 +371,17 @@ class SputnikDAO { async proposeMulticall(desc: string, multicallArgs: MulticallArgs, depo: string, gas: string): Promise { const { multicall } = STORAGE.addresses; - const proposalArgs = { - proposal: { - description: desc, - kind: { - FunctionCall: { - receiver_id: multicall, - actions: [ - { - method_name: "multicall", - args: Base64.encode(JSON.stringify(multicallArgs)), - deposit: `${depo}`, - gas: `${gas}`, - }, - ], - }, - }, + const callActions: FunctionCallAction[] = [ + { + method_name: "multicall", + args: multicallArgs, + deposit: `${depo}`, + gas: `${gas}`, }, - }; + ]; // fire the add_proposal transaction - this.addProposal(proposalArgs); + this.proposeFunctionCall(desc, multicall, callActions); } /** @@ -408,33 +402,21 @@ class SputnikDAO { ): Promise { const { multicall } = STORAGE.addresses; - const proposalArgs = { - proposal: { - description: desc, - kind: { - FunctionCall: { - receiver_id: tokenAddress, - actions: [ - { - method_name: "ft_transfer_call", - args: Base64.encode( - JSON.stringify({ - receiver_id: multicall, - amount: amount, - msg: JSON.stringify({ - function_id: "multicall", - args: Base64.encode(JSON.stringify(multicallArgs).toString()), - }).toString(), - }) - ), - deposit: "1", // nep-141: ft_transfer_call expects EXACTLY 1 yocto - gas: gas, - }, - ], - }, + const actions: FunctionCallAction[] = [ + { + method_name: "ft_transfer_call", + args: { + receiver_id: multicall, + amount: amount, + msg: JSON.stringify({ + function_id: "multicall", + args: Base64.encode(JSON.stringify(multicallArgs).toString()), + }).toString(), }, + deposit: "1", // nep-141: ft_transfer_call expects EXACTLY 1 yocto + gas: gas, }, - }; + ]; // check if multicall has enough storage on Token const [storageBalance, storageBounds] = await Promise.all([ @@ -449,16 +431,16 @@ class SputnikDAO { // if storage balance is less than minimum bound, add proposal action to pay for storage if (totalStorageBalance.lt(storageMinBound)) { // push to beginning of actions array. Has to execute before ft_transfer_call - proposalArgs.proposal.kind.FunctionCall.actions.unshift({ + actions.unshift({ method_name: "storage_deposit", - args: Base64.encode(JSON.stringify({ account_id: multicall })), + args: { account_id: multicall }, deposit: storageMinBound.sub(totalStorageBalance).toFixed(), // difference between current storage total and required minimum gas: toGas("5"), // 5 Tgas }); } // fire the add_proposal transaction - this.addProposal(proposalArgs); + this.proposeFunctionCall(desc, tokenAddress, actions); } } From c92657543c98909892236211a7e1364e3f69a19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 25 Sep 2022 09:24:51 +0400 Subject: [PATCH 087/537] fix: Make tabs lazy loading optional --- src/components/dao/dao.tsx | 1 + src/shared/ui/components/tabs/index.tsx | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index a429f93e..909bbd4d 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -484,6 +484,7 @@ export class Dao extends Component { }, { title: "Funds", + lazy: true, content: (
diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx index 2fd9699c..e88a923d 100644 --- a/src/shared/ui/components/tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -6,7 +6,7 @@ import { TabsLayout, TabsLayoutProps } from "./layout"; interface TabsProps { classes?: TabsLayoutProps["classes"] & {}; - items: { title: string; content: JSX.Element }[]; + items: { content: JSX.Element; lazy?: boolean; title: string }[]; } export const Tabs = ({ classes, items }: TabsProps) => { @@ -28,17 +28,15 @@ export const Tabs = ({ classes, items }: TabsProps) => { return ( - {items.map( - ({ content }, tabIndex) => - /* TODO: Render inactive tabs too */ - activeТаbIndex === tabIndex && ( - - {content} - - ) + {items.map(({ content, lazy = false }, tabIndex) => + activeТаbIndex === tabIndex || !lazy ? ( + + {content} + + ) : null )} ); From 25f731d3eab9bdd5c2e8405d7e3d0677c9598e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 25 Sep 2022 09:44:09 +0400 Subject: [PATCH 088/537] chore: Enable React 18 JSX features --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 1577e2c8..3f935e7e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "target": "es6", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, - "jsx": "react", + "jsx": "react-jsx", "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, From c687796f77482988b05b929fd145c4be6a1f42af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 25 Sep 2022 11:45:52 +0400 Subject: [PATCH 089/537] wip: Update shared UI components library --- src/components.js | 12 ----- src/components/dao/dao.tsx | 14 ++---- src/components/dao/multicall.scss | 34 +++++-------- src/components/index.ts | 10 ++++ src/components/menu/menu.jsx | 7 +-- src/components/sidebar/dialogs.jsx | 5 +- src/components/sidebar/sidebar.jsx | 5 +- src/components/token/ui/fungible.scss | 22 +++++---- src/components/token/ui/fungible.tsx | 38 +++++++++++---- src/components/tooltip/tooltip.jsx | 12 ----- src/families/base.jsx | 7 +-- src/pages/app-page.jsx | 2 +- src/pages/dao-page.jsx | 2 +- src/shared/ui/components/card/index.tsx | 4 +- .../ui/components/dialog/index.scss} | 0 .../ui/components/dialog/index.tsx} | 48 ++++++++++++------- src/shared/ui/components/icons/index.ts | 2 +- src/shared/ui/components/icons/near.tsx | 10 ++-- src/shared/ui/components/index.ts | 8 ++++ .../ui/components/popup-menu/index.scss} | 0 .../ui/components/popup-menu/index.tsx} | 11 ++++- .../ui/components/scrollable/index.scss | 12 +++++ src/shared/ui/components/scrollable/index.tsx | 12 +++++ src/shared/ui/components/tabs/index.tsx | 2 +- .../ui/components/token-label/index.scss | 17 ------- .../ui/components/token-label/index.tsx | 28 ----------- .../ui/components/tooltip/index.scss} | 0 src/shared/ui/components/tooltip/index.tsx | 16 +++++++ src/utils/window.ts | 2 +- 29 files changed, 184 insertions(+), 158 deletions(-) delete mode 100644 src/components.js create mode 100644 src/components/index.ts delete mode 100644 src/components/tooltip/tooltip.jsx rename src/{components/dialog/dialog.scss => shared/ui/components/dialog/index.scss} (100%) rename src/{components/dialog/dialog.jsx => shared/ui/components/dialog/index.tsx} (61%) create mode 100644 src/shared/ui/components/index.ts rename src/{components/popup-menu/popup-menu.scss => shared/ui/components/popup-menu/index.scss} (100%) rename src/{components/popup-menu/popup-menu.jsx => shared/ui/components/popup-menu/index.tsx} (66%) create mode 100644 src/shared/ui/components/scrollable/index.scss create mode 100644 src/shared/ui/components/scrollable/index.tsx delete mode 100644 src/shared/ui/components/token-label/index.scss delete mode 100644 src/shared/ui/components/token-label/index.tsx rename src/{components/tooltip/tooltip.scss => shared/ui/components/tooltip/index.scss} (100%) create mode 100644 src/shared/ui/components/tooltip/index.tsx diff --git a/src/components.js b/src/components.js deleted file mode 100644 index cbe490c5..00000000 --- a/src/components.js +++ /dev/null @@ -1,12 +0,0 @@ -export { Layout } from "./components/layout/layout.jsx"; -export { Column } from "./components/column/column.jsx"; -export { Task } from "./components/task/task.jsx"; -export { Menu } from "./components/menu/menu.jsx"; -export { Builder } from "./components/builder/builder.jsx"; -export { Editor } from "./components/editor/editor.jsx"; -export { Export } from "./components/export/export.jsx"; -export { Wallet } from "./components/wallet/wallet.jsx"; -export { Sidebar } from "./components/sidebar/sidebar.jsx"; -export { Dao } from "./components/dao/dao.tsx"; -export { Tooltip } from "./components/tooltip/tooltip.jsx"; -export { PopupMenu } from "./components/popup-menu/popup-menu.jsx"; diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index 909bbd4d..0f83345b 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -3,7 +3,7 @@ import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutli import clsx from "clsx"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; -import React, { Component } from "react"; +import { Component, ContextType } from "react"; import { ArgsAccount, ArgsError } from "../../utils/args"; import { STORAGE } from "../../utils/persistent"; @@ -12,8 +12,7 @@ import { view } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; import { Multicall } from "../../utils/contracts/multicall"; -import { Card } from "../../shared/ui/components/card"; -import { Tabs } from "../../shared/ui/components/tabs"; +import { Card, Scrollable, Tabs } from "../../shared/ui/components"; import { TextInput } from "../editor/elements"; import { FungibleTokenBalances } from "../token"; import "./dao.scss"; @@ -33,7 +32,6 @@ interface State { loading: boolean; proposed: number; proposedInfo: object; - activeTab: number; info: { admins: string[]; @@ -76,7 +74,7 @@ export class Dao extends Component { } static contextType = Ctx; - declare context: React.ContextType; + declare context: ContextType; errors = { name: new ArgsError( @@ -398,7 +396,7 @@ export class Dao extends Component { getContent() { const { selector: walletSelector } = this.context!; - const { info, loading, activeTab } = this.state; + const { info, loading } = this.state; // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) if (!walletSelector.isSignedIn()) { @@ -470,7 +468,7 @@ export class Dao extends Component {

Jobs

-
{info.jobs.map((j) => this.job(j))}
+ {info.jobs.map((j) => this.job(j))}
@@ -528,8 +526,6 @@ export class Dao extends Component { } render() { - const { activeTab } = this.state; - return (
diff --git a/src/components/dao/multicall.scss b/src/components/dao/multicall.scss index af589801..0e1687a2 100644 --- a/src/components/dao/multicall.scss +++ b/src/components/dao/multicall.scss @@ -23,28 +23,18 @@ grid-area: jobs; position: relative; - .scroll-wrapper { - @include mixin.no-scrollbar; - overflow-y: scroll; - position: absolute; - top: calc(size.$large-text + 1.5 * size.$gap); - bottom: 0; - left: 0; - right: 0; - - .job { - position: relative; - margin: size.$gap; - margin-top: 0; - border-radius: size.$task-radius; - background-color: color.$lightest; - - pre { - padding: 0.5 * size.$gap; - font-family: font.$code; - font-size: size.$small-text; - overflow: hidden; - } + .job { + position: relative; + margin: size.$gap; + margin-top: 0; + border-radius: size.$task-radius; + background-color: color.$lightest; + + pre { + padding: 0.5 * size.$gap; + font-family: font.$code; + font-size: size.$small-text; + overflow: hidden; } } } diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 00000000..9e7850fd --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,10 @@ +export { Layout } from "./layout/layout.jsx"; +export { Column } from "./column/column.jsx"; +export { Task } from "./task/task.jsx"; +export { Menu } from "./menu/menu.jsx"; +export { Builder } from "./builder/builder.jsx"; +export { Editor } from "./editor/editor.jsx"; +export { Export } from "./export/export.jsx"; +export { Wallet } from "./wallet/wallet.jsx"; +export { Sidebar } from "./sidebar/sidebar.jsx"; +export { Dao } from "./dao/dao"; diff --git a/src/components/menu/menu.jsx b/src/components/menu/menu.jsx index c355c10a..be9d77ae 100644 --- a/src/components/menu/menu.jsx +++ b/src/components/menu/menu.jsx @@ -1,11 +1,12 @@ -import React, { Component } from "react"; import Icon from "@mui/material/Icon"; +import clsx from "clsx"; +import { Component } from "react"; + +import { Tabs } from "../../shared/ui/components"; import { Builder } from "../builder/builder.jsx"; import { Editor } from "../editor/editor.jsx"; import { Export } from "../export/export.jsx"; -import { Tabs } from "../../shared/ui/components/tabs/index.tsx"; import "./menu.scss"; -import clsx from "clsx"; export class Menu extends Component { constructor(props) { diff --git a/src/components/sidebar/dialogs.jsx b/src/components/sidebar/dialogs.jsx index 53b49feb..a097b478 100644 --- a/src/components/sidebar/dialogs.jsx +++ b/src/components/sidebar/dialogs.jsx @@ -1,15 +1,14 @@ import { InfoOutlined } from "@mui/icons-material"; import { TextField } from "@mui/material"; import { Base64 } from "js-base64"; -import React, { useMemo, useReducer, useState } from "react"; +import { useMemo, useReducer, useState } from "react"; import { ArgsError, ArgsString } from "../../utils/args"; import { SputnikDAO } from "../../utils/contracts/sputnik-dao"; import { readFile, saveFile } from "../../utils/loader"; import { STORAGE } from "../../utils/persistent"; -import { Dialog } from "../dialog/dialog"; import { TextInput } from "../editor/elements"; -import { Tooltip } from "../tooltip/tooltip.jsx"; +import { Dialog, Tooltip } from "../../shared/ui/components"; import "./dialogs.scss"; const DAPP_LOGIN_INSTRUCTIONS = [ diff --git a/src/components/sidebar/sidebar.jsx b/src/components/sidebar/sidebar.jsx index b39a5dd9..2f1726e0 100644 --- a/src/components/sidebar/sidebar.jsx +++ b/src/components/sidebar/sidebar.jsx @@ -7,7 +7,7 @@ import { } from "@mui/icons-material"; import { Icon } from "@mui/material"; -import React, { Component } from "react"; +import { Component } from "react"; import { NavLink } from "react-router-dom"; import Discord from "../../assets/discord.svg"; @@ -15,8 +15,7 @@ import Github from "../../assets/github.svg"; import Twitter from "../../assets/twitter.svg"; import { Wallet } from "../wallet/wallet.jsx"; import { STORAGE } from "../../utils/persistent"; -import { PopupMenu } from "../popup-menu/popup-menu.jsx"; -import { Tooltip } from "../tooltip/tooltip"; +import { PopupMenu, Tooltip } from "../../shared/ui/components"; import { DappLoginDialog, diff --git a/src/components/token/ui/fungible.scss b/src/components/token/ui/fungible.scss index 100045a8..0f5cd043 100644 --- a/src/components/token/ui/fungible.scss +++ b/src/components/token/ui/fungible.scss @@ -1,12 +1,18 @@ @use "sass/mixin"; @use "sass/size"; -.scroll-wrapper { - @include mixin.no-scrollbar; - overflow-y: scroll; - position: absolute; - top: calc(size.$large-text + 1.5 * size.$gap); - bottom: 0; - left: 0; - right: 0; +.token-label { + display: flex; + align-items: center; + gap: 14px; + + .icon, + .icon svg { + width: 32px; + height: 32px; + } + + .symbol { + font-weight: bold; + } } diff --git a/src/components/token/ui/fungible.tsx b/src/components/token/ui/fungible.tsx index 83c3c93e..b97ddc87 100644 --- a/src/components/token/ui/fungible.tsx +++ b/src/components/token/ui/fungible.tsx @@ -1,12 +1,32 @@ -import React from "react"; - -import { TokenLabel } from "../../../shared/ui/components/token-label"; -import { Table } from "../../../shared/ui/components/table"; -import { Card } from "../../../shared/ui/components/card"; +import { Card, NearIcons, Scrollable, Table } from "../../../shared/ui/components"; import { BalancesModel } from "../model/balances"; import { ContractsData } from "../types"; import "./fungible.scss"; +interface FungibleTokenLabelProps { + icon?: string | JSX.Element | null; + native?: boolean; + symbol?: string; +} + +export const FungibleTokenLabel = ({ icon, native, symbol }: FungibleTokenLabelProps) => ( + + {!native && typeof icon === "string" ? ( + + ) : ( + + {native ? : icon || } + + )} + + {native ? "NEAR" : symbol} + +); + interface FungibleTokenBalancesProps extends ContractsData { className?: string; } @@ -18,7 +38,7 @@ export const FungibleTokenBalances = ({ className, dao, multicall }: FungibleTok const tableContent = [ nativeToken.data && [ - , + , nativeToken.data.multicall, nativeToken.data.dao, nativeToken.data.total, @@ -26,7 +46,7 @@ export const FungibleTokenBalances = ({ className, dao, multicall }: FungibleTok ].concat( customTokens.data && customTokens.data.map((customToken) => [ - , + , customToken.multicall, customToken.dao, customToken.total, @@ -40,12 +60,12 @@ export const FungibleTokenBalances = ({ className, dao, multicall }: FungibleTok {loading ? (
) : ( -
+
- + )} ); diff --git a/src/components/tooltip/tooltip.jsx b/src/components/tooltip/tooltip.jsx deleted file mode 100644 index 1fc364cf..00000000 --- a/src/components/tooltip/tooltip.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Tooltip as MuiTooltip } from "@mui/material"; - -import "./tooltip.scss"; - -export const Tooltip = ({ children, title, ...props }) => ( - {title}} - {...props} - > - {children} - -); diff --git a/src/families/base.jsx b/src/families/base.jsx index 18615416..694ad32c 100644 --- a/src/families/base.jsx +++ b/src/families/base.jsx @@ -1,13 +1,14 @@ import { DeleteOutline, MoveDown, EditOutlined } from "@mui/icons-material"; -import { Tooltip } from "../components/tooltip/tooltip"; -import React, { Component } from "react"; +import debounce from "lodash.debounce"; +import { Component } from "react"; + +import { Tooltip } from "../shared/ui/components"; import { TextInput, TextInputWithUnits } from "../components/editor/elements"; import { ArgsAccount, ArgsBig, ArgsError, ArgsJSON, ArgsString } from "../utils/args"; import Call from "../utils/call"; import { toGas, toYocto, formatTokenAmount, unitToDecimals } from "../utils/converter"; import { errorMsg } from "../utils/errors"; import { hasContract } from "../utils/contracts/generic"; -import debounce from "lodash.debounce"; import "./base.scss"; export class BaseTask extends Component { diff --git a/src/pages/app-page.jsx b/src/pages/app-page.jsx index 3867178f..77ee7952 100644 --- a/src/pages/app-page.jsx +++ b/src/pages/app-page.jsx @@ -1,5 +1,5 @@ import React from "react"; -import { Layout, Sidebar } from "../components.js"; +import { Layout, Sidebar } from "../components"; export const AppPage = () => { window.PAGE = "app"; diff --git a/src/pages/dao-page.jsx b/src/pages/dao-page.jsx index e90ba16a..e8e431d0 100644 --- a/src/pages/dao-page.jsx +++ b/src/pages/dao-page.jsx @@ -1,5 +1,5 @@ import React from "react"; -import { Dao, Sidebar } from "../components.js"; +import { Dao, Sidebar } from "../components"; export const DaoPage = () => { window.PAGE = "dao"; diff --git a/src/shared/ui/components/card/index.tsx b/src/shared/ui/components/card/index.tsx index 538a4d79..76d0261b 100644 --- a/src/shared/ui/components/card/index.tsx +++ b/src/shared/ui/components/card/index.tsx @@ -1,11 +1,11 @@ import clsx from "clsx"; -import React from "react"; +import { HTMLAttributes, PropsWithChildren } from "react"; import "./index.scss"; const NAMESPACE = "Card"; -export interface CardProps extends React.PropsWithChildren, React.HTMLAttributes {} +export interface CardProps extends PropsWithChildren, HTMLAttributes {} export const Card = ({ children, className }: CardProps) => (
{children}
diff --git a/src/components/dialog/dialog.scss b/src/shared/ui/components/dialog/index.scss similarity index 100% rename from src/components/dialog/dialog.scss rename to src/shared/ui/components/dialog/index.scss diff --git a/src/components/dialog/dialog.jsx b/src/shared/ui/components/dialog/index.tsx similarity index 61% rename from src/components/dialog/dialog.jsx rename to src/shared/ui/components/dialog/index.tsx index c5095980..ac819302 100644 --- a/src/components/dialog/dialog.jsx +++ b/src/shared/ui/components/dialog/index.tsx @@ -1,16 +1,31 @@ import { - Dialog as MUIDialog, - DialogTitle as MUIDialogTitle, - DialogContent as MUIDialogContent, - DialogActions as MUIDialogAction, + Dialog as MuiDialog, + DialogTitle as MuiDialogTitle, + DialogContent as MuiDialogContent, + DialogActions as MuiDialogAction, + DialogProps as MuiDialogProps, } from "@mui/material"; import { clsx } from "clsx"; -import React, { Component } from "react"; +import { Component } from "react"; -import "./dialog.scss"; +import "./index.scss"; -export class Dialog extends Component { - constructor(props) { +interface DialogProps extends MuiDialogProps { + cancelRename?: string; + disable: () => boolean; + doneRename?: string; + onClose: VoidFunction; + onCancel: VoidFunction; + onDone: VoidFunction; +} + +interface DialogState { + open: DialogProps["open"]; + title: DialogProps["title"]; +} + +export class Dialog extends Component { + constructor(props: DialogProps) { super(props); this.state = { @@ -29,20 +44,19 @@ export class Dialog extends Component { const { className, onClose, onDone, doneRename, onCancel, cancelRename, disable, children } = this.props; return ( - onClose()} - open={open} + - {title} - {children} - + {title} + {children} + {onCancel !== undefined ? ( ) : null} - - + + ); } } diff --git a/src/shared/ui/components/icons/index.ts b/src/shared/ui/components/icons/index.ts index f94a64a7..0ec44ea6 100644 --- a/src/shared/ui/components/icons/index.ts +++ b/src/shared/ui/components/icons/index.ts @@ -1 +1 @@ -export { NearIconFilled, NearGenericTokenIconFilled } from "./near"; +export { NearIcons } from "./near"; diff --git a/src/shared/ui/components/icons/near.tsx b/src/shared/ui/components/icons/near.tsx index 877f9634..bd61af1a 100644 --- a/src/shared/ui/components/icons/near.tsx +++ b/src/shared/ui/components/icons/near.tsx @@ -1,7 +1,6 @@ import { SvgIcon, SvgIconProps } from "@mui/material"; -import React from "react"; -export const NearIconFilled = (props: SvgIconProps) => ( +const NativeTokenFilled = (props: SvgIconProps) => ( ( ); -export const NearGenericTokenIconFilled = (props: SvgIconProps) => ( +const GenericTokenFilled = (props: SvgIconProps) => ( ( > ); + +export const NearIcons = { + GenericTokenFilled, + NativeTokenFilled, +}; diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts new file mode 100644 index 00000000..dbc06809 --- /dev/null +++ b/src/shared/ui/components/index.ts @@ -0,0 +1,8 @@ +export { Card } from "./card"; +export { Dialog } from "./dialog"; +export * from "./icons"; +export { PopupMenu } from "./popup-menu"; +export { Scrollable } from "./scrollable"; +export { Table } from "./table"; +export { Tabs } from "./tabs"; +export { Tooltip } from "./tooltip"; diff --git a/src/components/popup-menu/popup-menu.scss b/src/shared/ui/components/popup-menu/index.scss similarity index 100% rename from src/components/popup-menu/popup-menu.scss rename to src/shared/ui/components/popup-menu/index.scss diff --git a/src/components/popup-menu/popup-menu.jsx b/src/shared/ui/components/popup-menu/index.tsx similarity index 66% rename from src/components/popup-menu/popup-menu.jsx rename to src/shared/ui/components/popup-menu/index.tsx index 860358d4..3180d217 100644 --- a/src/components/popup-menu/popup-menu.jsx +++ b/src/shared/ui/components/popup-menu/index.tsx @@ -1,9 +1,16 @@ import { Chip } from "@mui/material"; import clsx from "clsx"; +import { ReactNode } from "react"; -import "./popup-menu.scss"; +import "./index.scss"; -export const PopupMenu = ({ icon, items, triggerClassName }) => ( +interface PopupMenuProps { + icon: ReactNode; + items: { label: string; onClick: VoidFunction; title: string }[]; + triggerClassName: string; +} + +export const PopupMenu = ({ icon, items, triggerClassName }: PopupMenuProps) => (
{icon} diff --git a/src/shared/ui/components/scrollable/index.scss b/src/shared/ui/components/scrollable/index.scss new file mode 100644 index 00000000..601bef82 --- /dev/null +++ b/src/shared/ui/components/scrollable/index.scss @@ -0,0 +1,12 @@ +@use "sass/mixin"; +@use "sass/size"; + +.Scrollable { + @include mixin.no-scrollbar; + overflow-y: scroll; + position: absolute; + top: calc(size.$large-text + 1.5 * size.$gap); + bottom: 0; + left: 0; + right: 0; +} diff --git a/src/shared/ui/components/scrollable/index.tsx b/src/shared/ui/components/scrollable/index.tsx new file mode 100644 index 00000000..4c0f574b --- /dev/null +++ b/src/shared/ui/components/scrollable/index.tsx @@ -0,0 +1,12 @@ +import clsx from "clsx"; +import { HTMLAttributes, PropsWithChildren } from "react"; + +import "./index.scss"; + +const NAMESPACE = "Scrollable"; + +interface ScrollableProps extends PropsWithChildren, HTMLAttributes {} + +export const Scrollable = ({ children, className }: ScrollableProps) => ( +
{children}
+); diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx index e88a923d..4ae91cd2 100644 --- a/src/shared/ui/components/tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import React, { useCallback, useState } from "react"; +import { useCallback, useState } from "react"; import { TabsItemButton, TabsItemPanel } from "./item"; import { TabsLayout, TabsLayoutProps } from "./layout"; diff --git a/src/shared/ui/components/token-label/index.scss b/src/shared/ui/components/token-label/index.scss deleted file mode 100644 index aac7cbb6..00000000 --- a/src/shared/ui/components/token-label/index.scss +++ /dev/null @@ -1,17 +0,0 @@ -@use "sass/mixin"; - -.token-label { - display: flex; - align-items: center; - gap: 14px; - - .icon, - .icon svg { - width: 32px; - height: 32px; - } - - .symbol { - font-weight: bold; - } -} diff --git a/src/shared/ui/components/token-label/index.tsx b/src/shared/ui/components/token-label/index.tsx deleted file mode 100644 index a90d068e..00000000 --- a/src/shared/ui/components/token-label/index.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; - -import { NearGenericTokenIconFilled, NearIconFilled } from "../icons"; -import "./index.scss"; - -export const TokenLabel = ({ - icon, - native, - symbol, -}: { - icon?: string | JSX.Element | null; - native?: boolean; - symbol?: string; -}) => ( - - {!native && typeof icon === "string" ? ( - - ) : ( - {native ? : icon || } - )} - - {native ? "NEAR" : symbol} - -); diff --git a/src/components/tooltip/tooltip.scss b/src/shared/ui/components/tooltip/index.scss similarity index 100% rename from src/components/tooltip/tooltip.scss rename to src/shared/ui/components/tooltip/index.scss diff --git a/src/shared/ui/components/tooltip/index.tsx b/src/shared/ui/components/tooltip/index.tsx new file mode 100644 index 00000000..c853a636 --- /dev/null +++ b/src/shared/ui/components/tooltip/index.tsx @@ -0,0 +1,16 @@ +import { Tooltip as MuiTooltip, TooltipProps as MuiTooltipProps } from "@mui/material"; + +import "./index.scss"; + +interface TooltipProps extends MuiTooltipProps { + title: string; +} + +export const Tooltip = ({ children, title, ...props }: TooltipProps) => ( + {title}} + {...props} + > + {children} + +); diff --git a/src/utils/window.ts b/src/utils/window.ts index 57e45a2d..4dc2ec35 100644 --- a/src/utils/window.ts +++ b/src/utils/window.ts @@ -2,7 +2,7 @@ import * as nearAPI from "near-api-js"; import type { NetworkId } from "@near-wallet-selector/core"; import { Component } from "react"; -import { Task, Layout } from "../components.js"; +import { Task, Layout } from "../components"; type CardInfo = { call: object; From 4b054d22e23b383299b5d2ee94361a1741bd0d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 25 Sep 2022 11:52:07 +0400 Subject: [PATCH 090/537] chore: Install `@types/react-dom` package --- package.json | 1 + yarn.lock | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/package.json b/package.json index d55ce584..4e164e9c 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@parcel/transformer-sass": "^2.4.1", "@types/big.js": "^6.1.5", "@types/lodash.debounce": "^4.0.7", + "@types/react-dom": "^18.0.6", "@typescript-eslint/parser": "^5.36.1", "babel-jest": "^28.0.2", "env-cmd": "~10.1.0", diff --git a/yarn.lock b/yarn.lock index 9a021d46..bd9a803f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2695,6 +2695,13 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== +"@types/react-dom@^18.0.6": + version "18.0.6" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.6.tgz#36652900024842b74607a17786b6662dd1e103a1" + integrity sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA== + dependencies: + "@types/react" "*" + "@types/react-is@^16.7.1 || ^17.0.0": version "17.0.3" resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.3.tgz#2d855ba575f2fc8d17ef9861f084acc4b90a137a" From 5d70ab9e80b43e3be3b8b276ea066db19faccdea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 25 Sep 2022 13:27:33 +0400 Subject: [PATCH 091/537] wip: Convert to tsx & Use nested structure for pages --- src/index.html | 2 +- src/{index.jsx => index.tsx} | 5 ++--- src/pages/{app-page.jsx => app/index.tsx} | 3 +-- src/pages/{dao-page.jsx => dao/index.tsx} | 3 +-- 4 files changed, 5 insertions(+), 8 deletions(-) rename src/{index.jsx => index.tsx} (89%) rename src/pages/{app-page.jsx => app/index.tsx} (66%) rename src/pages/{dao-page.jsx => dao/index.tsx} (73%) diff --git a/src/index.html b/src/index.html index 02ff5cfb..8df468b5 100644 --- a/src/index.html +++ b/src/index.html @@ -49,7 +49,7 @@ --> diff --git a/src/index.jsx b/src/index.tsx similarity index 89% rename from src/index.jsx rename to src/index.tsx index df93f8d8..f3421a20 100644 --- a/src/index.jsx +++ b/src/index.tsx @@ -1,8 +1,7 @@ -import React from "react"; import ReactDOM from "react-dom"; import { HashRouter, Routes, Route, Navigate } from "react-router-dom"; -import { AppPage } from "./pages/app-page"; -import { DaoPage } from "./pages/dao-page"; +import { AppPage } from "./pages/app"; +import { DaoPage } from "./pages/dao"; import { WalletSelectorContextProvider } from "./contexts/walletSelectorContext"; import "./utils/persistent"; import "@near-wallet-selector/modal-ui/styles.css"; diff --git a/src/pages/app-page.jsx b/src/pages/app/index.tsx similarity index 66% rename from src/pages/app-page.jsx rename to src/pages/app/index.tsx index 77ee7952..0081e115 100644 --- a/src/pages/app-page.jsx +++ b/src/pages/app/index.tsx @@ -1,5 +1,4 @@ -import React from "react"; -import { Layout, Sidebar } from "../components"; +import { Layout, Sidebar } from "../../components"; export const AppPage = () => { window.PAGE = "app"; diff --git a/src/pages/dao-page.jsx b/src/pages/dao/index.tsx similarity index 73% rename from src/pages/dao-page.jsx rename to src/pages/dao/index.tsx index e8e431d0..c78f1313 100644 --- a/src/pages/dao-page.jsx +++ b/src/pages/dao/index.tsx @@ -1,5 +1,4 @@ -import React from "react"; -import { Dao, Sidebar } from "../components"; +import { Dao, Sidebar } from "../../components"; export const DaoPage = () => { window.PAGE = "dao"; From 54d38c556fc431f855117aca2f58f78ad25cc142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 25 Sep 2022 18:25:51 +0400 Subject: [PATCH 092/537] wip: Fix styles --- sass/_base.scss | 3 ++ sass/_size.scss | 2 +- src/components/dao/dao.scss | 23 +------- src/components/menu/menu.jsx | 11 ++-- src/components/menu/menu.scss | 65 ++++++++--------------- src/shared/ui/components/tabs/item.scss | 39 +++++++------- src/shared/ui/components/tabs/item.tsx | 2 +- src/shared/ui/components/tabs/layout.scss | 24 ++++++--- src/shared/ui/components/tabs/layout.tsx | 2 +- 9 files changed, 73 insertions(+), 98 deletions(-) diff --git a/sass/_base.scss b/sass/_base.scss index cd5be854..a38157fd 100644 --- a/sass/_base.scss +++ b/sass/_base.scss @@ -58,11 +58,13 @@ .loader { display: flex; + flex: 1; align-self: center; align-items: center; justify-content: center; width: 100px; height: 100px; + &::after { content: " "; display: block; @@ -73,6 +75,7 @@ border-color: color.$lightish transparent color.$lightish transparent; animation: lds-dual-ring 1.2s linear infinite; } + @keyframes lds-dual-ring { 0% { transform: rotate(0deg); diff --git a/sass/_size.scss b/sass/_size.scss index 8437eed2..09405516 100644 --- a/sass/_size.scss +++ b/sass/_size.scss @@ -15,5 +15,5 @@ $task-radius: 2.4rem; $menu-width: 0rem; // 25vw; -$Tab-buttons-height: 3.2rem; +$Tabs-buttons-height: 3.2rem; $sidebar-width: 2 * $gap; diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 2a9e0335..1df55420 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -126,32 +126,11 @@ } .DaoPageTabs-buttonsPanel { - display: flex; justify-content: flex-start; max-width: 120rem; margin: size.$gap auto 0 auto; - padding: 0 size.$gap; - background-color: transparent; - & > button { - background-color: color.$lightest; - color: color.$text; - &.is-active, - &:hover, - &:focus { - background-color: color.$darkest; - color: color.$light-text; - transition: all 400ms ease; - transition-property: background-color, color; - } - &:first-of-type { - border-radius: size.$task-radius 0 0 size.$task-radius; - } - &:last-of-type { - border-radius: 0 size.$task-radius size.$task-radius 0; - } - } } .DaoPageTabs-contentSpace { - height: calc(100% - size.$gap - size.$Tab-buttons-height); + height: calc(100% - size.$gap - size.$Tabs-buttons-height); } diff --git a/src/components/menu/menu.jsx b/src/components/menu/menu.jsx index be9d77ae..f1654091 100644 --- a/src/components/menu/menu.jsx +++ b/src/components/menu/menu.jsx @@ -29,13 +29,16 @@ export class Menu extends Component { render() { const { expanded } = this.state; - const LAYOUT = this.props.layout; // ususally global parameter + const LAYOUT = this.props.layout; // usually global parameter return ( -
-
+
+
div { display: flex; @@ -79,16 +61,20 @@ top: calc(50% - 0.5 * size.$large-text); width: calc(size.$large-text + size.$gap); transition: transform animation.$menu-expand-time linear; + .icon { scale: 1.2; } + &.expand { transform: scaleX(1); + .icon { @include mixin.icon; font-size: size.$large-text; } } + &.collapse { transform: scaleX(-1); .icon { @@ -97,8 +83,3 @@ } } } - -.expanded-menu { - width: animation.$menu-expand-width; - transition: width animation.$menu-expand-time ease-out; -} diff --git a/src/shared/ui/components/tabs/item.scss b/src/shared/ui/components/tabs/item.scss index 53109da9..c8861178 100644 --- a/src/shared/ui/components/tabs/item.scss +++ b/src/shared/ui/components/tabs/item.scss @@ -2,23 +2,34 @@ @use "sass/size"; @use "sass/color"; -.TabsItem-button { +.Tabs-item-button { height: 100%; padding: 0 size.$gap; font-size: size.$text; - background-color: transparent; + background-color: color.$lightest; + color: color.$text; - &:focus, - &:hover { - background-color: rgba(color.$white, 0.1); + &--dark-bg { + background-color: transparent; + color: color.$light-text; } - &.is-active { - background-color: color.$white; + &.is-active, + &:hover, + &:focus { + background-color: color.$darkest; + color: color.$light-text; + transition: all 400ms ease; + transition-property: background-color, color; + + &--dark-bg { + background-color: color.$white; + color: color.$text; + } } } -.TabsItem-panel { +.Tabs-item-panel { display: none; width: 100%; height: 100%; @@ -26,17 +37,5 @@ &.is-active { @include mixin.center-items; - - // Code below does not belong here, it's styling for the app menu, - // it should be applied to the tabs selector via a seperate css class - - // height: calc(100% - size.$Tab-buttons-height - 2 * size.$gap); - // flex-flow: column; - // gap: size.$gap; - - // & > div { - // height: calc(100% - size.$gap); - // width: calc(100% - (2 * size.$gap)); - // } } } diff --git a/src/shared/ui/components/tabs/item.tsx b/src/shared/ui/components/tabs/item.tsx index 26d21c87..c5aab25f 100644 --- a/src/shared/ui/components/tabs/item.tsx +++ b/src/shared/ui/components/tabs/item.tsx @@ -3,7 +3,7 @@ import React from "react"; import "./item.scss"; -const NAMESPACE = "TabsItem"; +const NAMESPACE = "Tabs-item"; export interface TabsItemButtonProps extends React.HTMLAttributes { title: string; diff --git a/src/shared/ui/components/tabs/layout.scss b/src/shared/ui/components/tabs/layout.scss index 3e61c9fa..edf4a349 100644 --- a/src/shared/ui/components/tabs/layout.scss +++ b/src/shared/ui/components/tabs/layout.scss @@ -2,21 +2,31 @@ @use "sass/size"; @use "sass/color"; -.TabsLayout-root { +.Tabs-layout-root { height: calc(100% - (2 * size.$gap + 0.5 * size.$large-text)); } -.TabsLayout-buttonsPanel { +.Tabs-layout-buttonsPanel { @include mixin.center-items; - box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); - background-color: color.$lightest; + z-index: 1; border-radius: size.$task-radius; + height: size.$Tabs-buttons-height; padding: 0; - height: size.$Tab-buttons-height; overflow: hidden; - z-index: 1; + background-color: transparent; + box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); + + & > .Tabs-item-button { + &:first-of-type { + border-radius: size.$task-radius 0 0 size.$task-radius; + } + + &:last-of-type { + border-radius: 0 size.$task-radius size.$task-radius 0; + } + } } -.TabsLayout-contentSpace { +.Tabs-layout-contentSpace { height: 100%; } diff --git a/src/shared/ui/components/tabs/layout.tsx b/src/shared/ui/components/tabs/layout.tsx index b50ac3df..00a59995 100644 --- a/src/shared/ui/components/tabs/layout.tsx +++ b/src/shared/ui/components/tabs/layout.tsx @@ -3,7 +3,7 @@ import React from "react"; import "./layout.scss"; -const NAMESPACE = "TabsLayout"; +const NAMESPACE = "Tabs-layout"; interface TabsLayoutButtonsPanelProps extends React.PropsWithChildren, React.HTMLAttributes {} From 1925398fc53fb79ce7517b7632f602a624c90941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 25 Sep 2022 20:10:14 +0400 Subject: [PATCH 093/537] wip: Add inverted color scheme for tabs button --- sass/_size.scss | 2 +- src/components/dao/dao.scss | 2 +- src/components/menu/menu.jsx | 1 + src/components/menu/menu.scss | 2 +- src/shared/ui/components/tabs/index.tsx | 8 ++++---- src/shared/ui/components/tabs/item.scss | 22 +++++++++++++++------- src/shared/ui/components/tabs/item.tsx | 13 ++++++++++--- src/shared/ui/components/tabs/layout.scss | 2 +- 8 files changed, 34 insertions(+), 18 deletions(-) diff --git a/sass/_size.scss b/sass/_size.scss index 09405516..efc3ba8a 100644 --- a/sass/_size.scss +++ b/sass/_size.scss @@ -15,5 +15,5 @@ $task-radius: 2.4rem; $menu-width: 0rem; // 25vw; -$Tabs-buttons-height: 3.2rem; +$Tabs-layout-buttonsPanel-height: 3.2rem; $sidebar-width: 2 * $gap; diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 1df55420..454228e8 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -132,5 +132,5 @@ } .DaoPageTabs-contentSpace { - height: calc(100% - size.$gap - size.$Tabs-buttons-height); + height: calc(100% - size.$gap - size.$Tabs-layout-buttonsPanel-height); } diff --git a/src/components/menu/menu.jsx b/src/components/menu/menu.jsx index f1654091..0ce4d2db 100644 --- a/src/components/menu/menu.jsx +++ b/src/components/menu/menu.jsx @@ -35,6 +35,7 @@ export class Menu extends Component {
div { display: flex; diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx index 4ae91cd2..503bac05 100644 --- a/src/shared/ui/components/tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -1,15 +1,15 @@ import clsx from "clsx"; import { useCallback, useState } from "react"; -import { TabsItemButton, TabsItemPanel } from "./item"; +import { TabsItemButton, TabsItemButtonProps, TabsItemPanel } from "./item"; import { TabsLayout, TabsLayoutProps } from "./layout"; -interface TabsProps { +interface TabsProps extends Pick { classes?: TabsLayoutProps["classes"] & {}; items: { content: JSX.Element; lazy?: boolean; title: string }[]; } -export const Tabs = ({ classes, items }: TabsProps) => { +export const Tabs = ({ classes, invertedColors, items }: TabsProps) => { const [activeТаbIndex, activeTabSwitch] = useState(0); const itemButtonClickHandler = useCallback( @@ -22,7 +22,7 @@ export const Tabs = ({ classes, items }: TabsProps) => { className={clsx({ "is-active": activeТаbIndex === tabIndex })} key={tabIndex} onClick={itemButtonClickHandler(tabIndex)} - {...{ title }} + {...{ invertedColors, title }} /> )); diff --git a/src/shared/ui/components/tabs/item.scss b/src/shared/ui/components/tabs/item.scss index c8861178..3cc78123 100644 --- a/src/shared/ui/components/tabs/item.scss +++ b/src/shared/ui/components/tabs/item.scss @@ -9,11 +9,6 @@ background-color: color.$lightest; color: color.$text; - &--dark-bg { - background-color: transparent; - color: color.$light-text; - } - &.is-active, &:hover, &:focus { @@ -21,11 +16,24 @@ color: color.$light-text; transition: all 400ms ease; transition-property: background-color, color; + } - &--dark-bg { - background-color: color.$white; + &--invertedColors { + background-color: transparent; + color: color.$light-text; + + &.is-active { color: color.$text; } + + &.is-active, + &.is-active:hover { + background-color: color.$white; + } + + &:hover { + background-color: rgba(color.$white, 0.1); + } } } diff --git a/src/shared/ui/components/tabs/item.tsx b/src/shared/ui/components/tabs/item.tsx index c5aab25f..08d0a020 100644 --- a/src/shared/ui/components/tabs/item.tsx +++ b/src/shared/ui/components/tabs/item.tsx @@ -6,13 +6,20 @@ import "./item.scss"; const NAMESPACE = "Tabs-item"; export interface TabsItemButtonProps extends React.HTMLAttributes { - title: string; + invertedColors?: boolean; onClick: VoidFunction; + title: string; } -export const TabsItemButton = ({ className, onClick, title }: TabsItemButtonProps) => ( +export const TabsItemButton = ({ className, invertedColors = false, onClick, title }: TabsItemButtonProps) => (
diff --git a/src/components/menu/menu.jsx b/src/components/menu/menu.jsx index 0ce4d2db..757a182c 100644 --- a/src/components/menu/menu.jsx +++ b/src/components/menu/menu.jsx @@ -14,7 +14,7 @@ export class Menu extends Component { this.state = { expanded: false, - activeTab: 0, + activeTabIndex: 0, }; document.addEventListener("onaddressesupdated", () => this.forceUpdate()); @@ -24,18 +24,21 @@ export class Menu extends Component { window.MENU = this; } - changeTab = (newTab) => this.setState({ activeTab: newTab }); + activeTabSwitch = (newTabIndex) => this.setState({ activeTabIndex: newTabIndex }); render() { - const { expanded } = this.state; + const { activeTabIndex, expanded } = this.state; - const LAYOUT = this.props.layout; // usually global parameter + /** Usually global parameter */ + const LAYOUT = this.props.layout; return (
{ EDITOR.edit(id); - MENU.changeTab(1); + MENU.activeTabSwitch(1); }} /> diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx index 503bac05..922be278 100644 --- a/src/shared/ui/components/tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -1,38 +1,50 @@ import clsx from "clsx"; -import { useCallback, useState } from "react"; +import { Dispatch, SetStateAction, useCallback, useEffect, useState } from "react"; import { TabsItemButton, TabsItemButtonProps, TabsItemPanel } from "./item"; import { TabsLayout, TabsLayoutProps } from "./layout"; interface TabsProps extends Pick { + activeItemIndexOverride?: number; + activeItemSwitchOverride?: Dispatch>; classes?: TabsLayoutProps["classes"] & {}; items: { content: JSX.Element; lazy?: boolean; title: string }[]; } -export const Tabs = ({ classes, invertedColors, items }: TabsProps) => { - const [activeТаbIndex, activeTabSwitch] = useState(0); +export const Tabs = ({ + activeItemIndexOverride, + activeItemSwitchOverride, + classes, + invertedColors, + items, +}: TabsProps) => { + const [activeItemIndex, activeItemSwitch] = + activeItemIndexOverride === undefined || activeItemSwitchOverride === undefined + ? useState(0) + : [activeItemIndexOverride, activeItemSwitchOverride]; - const itemButtonClickHandler = useCallback( - (itemIndex: number) => () => activeTabSwitch(itemIndex), - [activeTabSwitch] + const activeItemSwitchBinding = useCallback( + (itemIndex: number) => () => activeItemSwitch(itemIndex), + [activeItemSwitch] ); - const buttons = items.map(({ title }, tabIndex) => ( - - )); - return ( - - {items.map(({ content, lazy = false }, tabIndex) => - activeТаbIndex === tabIndex || !lazy ? ( + ( + + ))} + > + {items.map(({ content, lazy = false }, itemIndex) => + activeItemIndex === itemIndex || !lazy ? ( {content} From d85d3edd33172147362e08429ce5c946f3ab15ef Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Mon, 26 Sep 2022 19:14:54 +0200 Subject: [PATCH 098/537] Fix: ci failed, ProposalAction not found. Convert proposalAlreadyExists to async --- src/components/dao/dao.tsx | 74 +++++++++++++++++++------------------- src/utils/args.ts | 2 -- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index ccfea717..f6b0935c 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -10,7 +10,7 @@ import { STORAGE } from "../../utils/persistent"; import { toNEAR, toYocto, Big } from "../../utils/converter"; import { view } from "../../utils/wallet"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; -import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; +import { SputnikDAO, SputnikUI, ProposalStatus } from "../../utils/contracts/sputnik-dao"; import { Multicall } from "../../utils/contracts/multicall"; import { Card, Scrollable, Tabs } from "../../shared/ui/components"; import { TextInput } from "../editor/elements"; @@ -33,7 +33,7 @@ interface State { multicall: Multicall; loading: boolean; proposed: number; - proposedInfo: object; + proposedInfo: ProposalOutput; info: { admins: string[]; @@ -97,47 +97,45 @@ export class Dao extends Component { * * @returns {object} ID and info of proposal to create multicall instance, */ - proposalAlreadyExists(dao: SputnikDAO) { + async proposalAlreadyExists(dao: SputnikDAO): Promise<{ proposal_id: number; proposal_info: object }> { // Date.now() returns timestamp in milliseconds, SputnikDAO uses nanoseconds const currentTime = Big(Date.now()).times("1000000"); const lastProposalId = dao.lastProposalId; const proposalPeriod = dao.policy.proposal_period; - return dao - .getProposals({ - from_index: lastProposalId < 100 ? 0 : lastProposalId - 100, - limit: 100, - }) - .then((response) => { - const proposals = response.filter((proposal) => { - // discard if not active proposal to create multicall instance - if ( - !(proposal.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) || - !(proposal.kind?.FunctionCall?.actions?.[0]?.method_name === "create") || - !(proposal.status === ProposalStatus.InProgress) - ) { - return false; - } - // calculate proposal expiration timestamp in nanoseconds - const expirationTime = Big(proposal.submission_time).add(proposalPeriod); - // check if proposal expired - return expirationTime.gt(currentTime) ? true : false; - }); - - // If there many "Create multicall" proposals, return latest. - if (proposals.length > 0) { - const lastProposal = proposals.pop(); - return { proposal_id: lastProposal?.id, proposal_info: lastProposal }; - } - // No "Create multicall" proposals found. - else return { proposal_id: -1, proposal_info: {} }; - }) - .catch((e) => {}); + // get last 100 DAO proposals + const proposals = await dao.getProposals({ + from_index: lastProposalId < 100 ? 0 : lastProposalId - 100, + limit: 100, + }); + // Look for active "Create multicall" proposals + const activeProposals = proposals.filter((proposal) => { + // discard if not active proposal to create multicall instance + if ( + !(proposal.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) || + !(proposal.kind?.FunctionCall?.actions?.[0]?.method_name === "create") || + !(proposal.status === ProposalStatus.InProgress) + ) { + return false; + } + // calculate proposal expiration timestamp in nanoseconds + const expirationTime = Big(proposal.submission_time).add(proposalPeriod); + // check if proposal expired + return expirationTime.gt(currentTime) ? true : false; + }); + + // If there many "Create multicall" proposals, return latest. + if (activeProposals.length > 0) { + const lastProposal = activeProposals.pop()!; + return { proposal_id: lastProposal.id, proposal_info: lastProposal }; + } + // No "Create multicall" proposals found. + else return { proposal_id: -1, proposal_info: {} }; } createMulticall() { const { accountId } = this.context!; - const { loading, name, dao, proposed, proposedInfo } = this.state; + const { loading, dao, proposed, proposedInfo } = this.state; const { noContract, noDao } = this.errors; if ( @@ -152,10 +150,10 @@ export class Dao extends Component { const daoSearchInput: HTMLInputElement = document.querySelector(".address-container input")!; // can user propose a FunctionCall to DAO? - const canPropose = dao.checkUserPermission(accountId!, ProposalAction.AddProposal, ProposalKind.FunctionCall); + const canPropose = dao.checkUserPermission(accountId!, "AddProposal", "FunctionCall"); // can user vote approve a FunctionCall on the DAO? - const canApprove = dao.checkUserPermission(accountId!, ProposalAction.VoteApprove, ProposalKind.FunctionCall); + const canApprove = dao.checkUserPermission(accountId!, "VoteApprove", "FunctionCall"); const args = { proposal: { @@ -259,7 +257,7 @@ export class Dao extends Component {
); - } else if (proposedInfo.votes[accountId]) { + } else if (proposedInfo.votes[accountId!]) { // user can VoteApprove and already voted return ( @@ -529,6 +527,8 @@ export class Dao extends Component { } render() { + const { name } = this.state; + return (
diff --git a/src/utils/args.ts b/src/utils/args.ts index cf5fb502..419e5c1f 100644 --- a/src/utils/args.ts +++ b/src/utils/args.ts @@ -1,8 +1,6 @@ import { useEffect, useMemo, useReducer } from "react"; import { BigSource } from "big.js"; import { Validation } from "./validation"; - -import { SputnikDAO } from "./contracts/sputnik-dao"; import { unitToDecimals, convert, Big } from "./converter"; export default abstract class Args { From 3fefc5df3fe0dca68b5d0ce9764af17edcbee9dd Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Mon, 26 Sep 2022 20:41:16 +0200 Subject: [PATCH 099/537] keep state of multicall in sync with name on DAO page --- src/components/dao/dao.tsx | 5 +++-- src/utils/contracts/sputnik-dao.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index 0f83345b..09193577 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -366,7 +366,7 @@ export class Dao extends Component { // or some error happened during DAO object init. noContract.isBad = true; noDao.isBad = true; - this.setState({ dao, loading: false }); + this.setState({ dao, multicall: new Multicall(multicallAddress), loading: false }); return; } else { // DAO correctly initialized, try to fetch multicall info @@ -384,10 +384,11 @@ export class Dao extends Component { ]).then(([admins, tokens, jobs, jobBond, proposalData]) => this.setState((prevState) => ({ dao, + multicall: new Multicall(multicallAddress), info: { admins, tokens, jobs, jobBond }, loading: false, proposed: proposalData?.proposal_id, - proposedInfo: proposalData?.proposal_info || prevState.proposedInfo, + proposedInfo: proposalData?.proposal_info || {}, })) ); } diff --git a/src/utils/contracts/sputnik-dao.ts b/src/utils/contracts/sputnik-dao.ts index c213cfe8..62bb8a9a 100644 --- a/src/utils/contracts/sputnik-dao.ts +++ b/src/utils/contracts/sputnik-dao.ts @@ -148,7 +148,7 @@ class SputnikDAO { * * @param accountId */ - static async isSputnikDAO (accountId: string): Promise { + static async isSputnikDAO(accountId: string): Promise { const accountInfo = await viewAccount(accountId); const codeHash: string = accountInfo.code_hash; return SputnikDAO.CONTRACT_CODE_HASHES.includes(codeHash); From 9703814a0a1ff439f43d9629b8609cba81466b93 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Mon, 26 Sep 2022 22:19:22 +0200 Subject: [PATCH 100/537] fix: mini css clean-up --- src/components/dao/dao.scss | 1 + src/components/token/ui/fungible.scss | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index 454228e8..ea8f3fc1 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -129,6 +129,7 @@ justify-content: flex-start; max-width: 120rem; margin: size.$gap auto 0 auto; + padding: 0 size.$gap; } .DaoPageTabs-contentSpace { diff --git a/src/components/token/ui/fungible.scss b/src/components/token/ui/fungible.scss index 0f5cd043..1bb0b89c 100644 --- a/src/components/token/ui/fungible.scss +++ b/src/components/token/ui/fungible.scss @@ -4,12 +4,12 @@ .token-label { display: flex; align-items: center; - gap: 14px; + gap: size.$gap; .icon, .icon svg { - width: 32px; - height: 32px; + width: 1.5 * size.$gap; + height: 1.5 * size.$gap; } .symbol { From ea266d3417a077ab2796a481df435b684f0fd19c Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Mon, 26 Sep 2022 22:48:25 +0200 Subject: [PATCH 101/537] fix: css cursor and add box-shadow --- src/components/token/ui/fungible.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/token/ui/fungible.scss b/src/components/token/ui/fungible.scss index 1bb0b89c..eeb6ed1c 100644 --- a/src/components/token/ui/fungible.scss +++ b/src/components/token/ui/fungible.scss @@ -10,6 +10,9 @@ .icon svg { width: 1.5 * size.$gap; height: 1.5 * size.$gap; + cursor: default !important; + border-radius: 50%; + box-shadow: 0px 5px 11px -3px rgba(0, 0, 0, 0.1); } .symbol { From 0744d2996a81be72b09b79ef37b4b93dff011cba Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Tue, 27 Sep 2022 00:37:42 +0200 Subject: [PATCH 102/537] fix cards breaking on "edit" click --- src/components/editor/elements.jsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/editor/elements.jsx b/src/components/editor/elements.jsx index d0825fa2..f8d64a60 100644 --- a/src/components/editor/elements.jsx +++ b/src/components/editor/elements.jsx @@ -20,7 +20,9 @@ class TextInput extends Component { this.forceUpdate(); }} error={errors.some((error) => error?.isBad)} - helperText={errors.find((error) => error.isBad)?.message} + helperText={errors.map((error) => { + if (error?.isBad) return error?.message; + })} InputLabelProps={{ shrink: true }} {...props} /> @@ -51,7 +53,9 @@ class TextInputWithUnits extends Component { update?.(e, this); }} error={errors.some((e) => e?.isBad)} - helperText={errors.find((error) => error.isBad)?.message} + helperText={errors.map((error) => { + if (error?.isBad) return error?.message; + })} InputLabelProps={{ shrink: true }} {...textProps} {...props} From 097439c705a6528a60381167b52d5aebc3a807d8 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Tue, 27 Sep 2022 00:55:21 +0200 Subject: [PATCH 103/537] Revert "fix cards breaking on "edit" click" This reverts commit 0744d2996a81be72b09b79ef37b4b93dff011cba. --- src/components/editor/elements.jsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/components/editor/elements.jsx b/src/components/editor/elements.jsx index f8d64a60..d0825fa2 100644 --- a/src/components/editor/elements.jsx +++ b/src/components/editor/elements.jsx @@ -20,9 +20,7 @@ class TextInput extends Component { this.forceUpdate(); }} error={errors.some((error) => error?.isBad)} - helperText={errors.map((error) => { - if (error?.isBad) return error?.message; - })} + helperText={errors.find((error) => error.isBad)?.message} InputLabelProps={{ shrink: true }} {...props} /> @@ -53,9 +51,7 @@ class TextInputWithUnits extends Component { update?.(e, this); }} error={errors.some((e) => e?.isBad)} - helperText={errors.map((error) => { - if (error?.isBad) return error?.message; - })} + helperText={errors.find((error) => error.isBad)?.message} InputLabelProps={{ shrink: true }} {...textProps} {...props} From 2ca303b8946248852b4599a3f951c9072f19e853 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Tue, 27 Sep 2022 00:57:24 +0200 Subject: [PATCH 104/537] only display one error --- src/components/editor/elements.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/editor/elements.jsx b/src/components/editor/elements.jsx index d0825fa2..253d1a18 100644 --- a/src/components/editor/elements.jsx +++ b/src/components/editor/elements.jsx @@ -20,7 +20,7 @@ class TextInput extends Component { this.forceUpdate(); }} error={errors.some((error) => error?.isBad)} - helperText={errors.find((error) => error.isBad)?.message} + helperText={errors.find((error) => error?.isBad)?.message} InputLabelProps={{ shrink: true }} {...props} /> @@ -51,7 +51,7 @@ class TextInputWithUnits extends Component { update?.(e, this); }} error={errors.some((e) => e?.isBad)} - helperText={errors.find((error) => error.isBad)?.message} + helperText={errors.find((error) => error?.isBad)?.message} InputLabelProps={{ shrink: true }} {...textProps} {...props} From 62fc4cee42725099de135804be6f3079a162a3c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 28 Sep 2022 02:05:57 +0400 Subject: [PATCH 105/537] fix: Update feature flags only once per sidebar render --- src/components/sidebar/sidebar.jsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/sidebar/sidebar.jsx b/src/components/sidebar/sidebar.jsx index 7adb10fd..043c2585 100644 --- a/src/components/sidebar/sidebar.jsx +++ b/src/components/sidebar/sidebar.jsx @@ -60,10 +60,14 @@ export class Sidebar extends Component { document.addEventListener("onaddressesupdated", () => this.forceUpdate()); } - componentDidUpdate() { - viewAccount(STORAGE.addresses.multicall) - .then(() => this.setState({ featureFlags: { ...this.state.featureFlags, multicallDappLogin: true } })) - .catch(() => this.setState({ featureFlags: { ...this.state.featureFlags, multicallDappLogin: false } })); + componentDidUpdate(_, previousState) { + if (this.state !== previousState) { + viewAccount(STORAGE.addresses.multicall) + .then(() => this.setState({ featureFlags: { ...this.state.featureFlags, multicallDappLogin: true } })) + .catch(() => + this.setState({ featureFlags: { ...this.state.featureFlags, multicallDappLogin: false } }) + ); + } } openDialog(name) { From 74d78a086d71212d6c23db468ecfbfbabd112575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 28 Sep 2022 02:20:48 +0400 Subject: [PATCH 106/537] fix: Update active tab switch callback binder deps --- src/shared/ui/components/tabs/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/index.tsx index 922be278..9d63351e 100644 --- a/src/shared/ui/components/tabs/index.tsx +++ b/src/shared/ui/components/tabs/index.tsx @@ -23,9 +23,9 @@ export const Tabs = ({ ? useState(0) : [activeItemIndexOverride, activeItemSwitchOverride]; - const activeItemSwitchBinding = useCallback( + const activeItemSwitchBond = useCallback( (itemIndex: number) => () => activeItemSwitch(itemIndex), - [activeItemSwitch] + [activeItemSwitch, items] ); return ( @@ -35,7 +35,7 @@ export const Tabs = ({ ))} From 91ad48caf8ae587cb7ae06e9098015e91e406c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 28 Sep 2022 02:29:18 +0400 Subject: [PATCH 107/537] chore: Shorten root component styles namespace --- src/components/dao/dao.scss | 2 +- src/components/dao/dao.tsx | 2 +- src/components/menu/menu.jsx | 4 ++-- src/components/menu/menu.scss | 4 ++-- src/shared/ui/components/tabs/layout.scss | 2 +- src/shared/ui/components/tabs/layout.tsx | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/dao/dao.scss b/src/components/dao/dao.scss index ea8f3fc1..aff14a6e 100644 --- a/src/components/dao/dao.scss +++ b/src/components/dao/dao.scss @@ -4,7 +4,7 @@ @use "sass/font"; @use "sass/animation"; -.DaoPage-root { +.DaoPage { @include mixin.page-wrapper; display: flex; flex-flow: column nowrap; diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index 771f6add..d4b631ae 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -531,7 +531,7 @@ export class Dao extends Component { const { name } = this.state; return ( -
+
-
+
+
( -
+
{buttons} {children}
From 352fa9047dbf470b518d3a59b1bc1f8480d7d02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 28 Sep 2022 10:09:58 +0400 Subject: [PATCH 108/537] chore: Enable full ESM support --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 4e164e9c..37c92e3c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "homepage": "http://near-multicall.github.io/ui", "name": "ui", + "type": "module", "version": "0.1.0", "license": "UNLICENSED", "scripts": { From 13bd7c2e6e6eef1a6b94b5c5c643687aa1e3b88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 28 Sep 2022 10:10:38 +0400 Subject: [PATCH 109/537] chore: Format --- src/index.html | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/index.html b/src/index.html index 8df468b5..849d9806 100644 --- a/src/index.html +++ b/src/index.html @@ -2,6 +2,7 @@ + near-multicall - near-multicall
- - + + From 055a23268871d4804aa64ae8896e60d69ff5e52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 1 Oct 2022 19:21:30 +0400 Subject: [PATCH 124/537] wip: Decompose DaoPage tabs & Add DaoJobsTab --- src/entities/fungible-token/model/balances.ts | 4 +- src/entities/fungible-token/ui/balances.tsx | 6 +- src/entities/native-token/model/balances.ts | 4 +- src/entities/native-token/ui/balances.tsx | 6 +- src/pages/dao/config/tab.scss | 26 +--- src/pages/dao/config/tab.tsx | 78 ++++++++++++ src/pages/dao/funds/tab.scss | 8 +- src/pages/dao/funds/tab.tsx | 26 ++++ src/pages/dao/index.tsx | 114 +++--------------- src/pages/dao/jobs/tab.scss | 29 +++++ src/pages/dao/jobs/tab.tsx | 51 ++++++++ src/pages/dao/page.scss | 2 +- src/widgets/tokens-balances/index.ts | 2 +- src/widgets/tokens-balances/ui/card.tsx | 14 +-- 14 files changed, 225 insertions(+), 145 deletions(-) create mode 100644 src/pages/dao/config/tab.tsx create mode 100644 src/pages/dao/funds/tab.tsx create mode 100644 src/pages/dao/jobs/tab.scss create mode 100644 src/pages/dao/jobs/tab.tsx diff --git a/src/entities/fungible-token/model/balances.ts b/src/entities/fungible-token/model/balances.ts index bc4f816c..3e5d2a5b 100644 --- a/src/entities/fungible-token/model/balances.ts +++ b/src/entities/fungible-token/model/balances.ts @@ -50,10 +50,10 @@ const fungibleTokensDataFx = async ({ dao, multicall }: DaoContracts, callback: }); }; -const useFungibleTokensData = (daoContracts: DaoContracts) => { +const useFungibleTokensData = (contracts: DaoContracts) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void fungibleTokensDataFx(daoContracts, stateUpdate), []); + useEffect(() => void fungibleTokensDataFx(contracts, stateUpdate), []); return state; }; diff --git a/src/entities/fungible-token/ui/balances.tsx b/src/entities/fungible-token/ui/balances.tsx index da64a0e2..46bf43f8 100644 --- a/src/entities/fungible-token/ui/balances.tsx +++ b/src/entities/fungible-token/ui/balances.tsx @@ -4,11 +4,11 @@ import { FungibleTokenFormat } from "../lib/format"; import { FungibleTokenBalancesModel } from "../model/balances"; interface FungibleTokensBalancesRenderProps { - daoContracts: DaoContracts; + contracts: DaoContracts; } -export const fungibleTokensBalancesRender = ({ daoContracts }: FungibleTokensBalancesRenderProps) => { - const { data } = FungibleTokenBalancesModel.useAllData(daoContracts); +export const fungibleTokensBalancesRender = ({ contracts }: FungibleTokensBalancesRenderProps) => { + const { data } = FungibleTokenBalancesModel.useAllData(contracts); return !data ? null diff --git a/src/entities/native-token/model/balances.ts b/src/entities/native-token/model/balances.ts index bf915469..8c4e4f5d 100644 --- a/src/entities/native-token/model/balances.ts +++ b/src/entities/native-token/model/balances.ts @@ -30,10 +30,10 @@ const nativeTokenDataFx = async ({ dao, multicall }: DaoContracts, callback: (da }); }; -const useNativeTokenData = (daoContracts: DaoContracts) => { +const useNativeTokenData = (contracts: DaoContracts) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void nativeTokenDataFx(daoContracts, stateUpdate), []); + useEffect(() => void nativeTokenDataFx(contracts, stateUpdate), []); return state; }; diff --git a/src/entities/native-token/ui/balances.tsx b/src/entities/native-token/ui/balances.tsx index 70c26900..85d9c96a 100644 --- a/src/entities/native-token/ui/balances.tsx +++ b/src/entities/native-token/ui/balances.tsx @@ -3,11 +3,11 @@ import type { DaoContracts } from "../../types"; import { NativeTokenBalancesModel } from "../model/balances"; interface NativeTokenBalancesRenderProps { - daoContracts: DaoContracts; + contracts: DaoContracts; } -export const nativeTokenBalancesRender = ({ daoContracts }: NativeTokenBalancesRenderProps) => { - const { data } = NativeTokenBalancesModel.useData(daoContracts); +export const nativeTokenBalancesRender = ({ contracts }: NativeTokenBalancesRenderProps) => { + const { data } = NativeTokenBalancesModel.useData(contracts); return !data ? null : [, data.multicall, data.dao, data.total]; }; diff --git a/src/pages/dao/config/tab.scss b/src/pages/dao/config/tab.scss index 8b6ecb94..faa3d5c2 100644 --- a/src/pages/dao/config/tab.scss +++ b/src/pages/dao/config/tab.scss @@ -3,12 +3,12 @@ @use "sass/mixin"; @use "sass/size"; -.ConfigTab { +.DaoConfigTab { display: grid; grid-template: - "AdminsList Jobs" 6fr - "TokenWhitelist Jobs" 5fr + "AdminsList ." 6fr + "TokenWhitelist ." 5fr "TokenWhitelist JobBond" 1fr / 1fr 1fr; .AdminsList { @@ -19,26 +19,6 @@ grid-area: TokenWhitelist; } - .JobsList { - grid-area: Jobs; - position: relative; - - &-item { - position: relative; - margin: size.$gap; - margin-top: 0; - border-radius: size.$task-radius; - background-color: color.$lightest; - - pre { - padding: 0.5 * size.$gap; - font-family: font.$code; - font-size: size.$small-text; - overflow: hidden; - } - } - } - .JobBond { grid-area: JobBond; diff --git a/src/pages/dao/config/tab.tsx b/src/pages/dao/config/tab.tsx new file mode 100644 index 00000000..e03b849e --- /dev/null +++ b/src/pages/dao/config/tab.tsx @@ -0,0 +1,78 @@ +import { AddOutlined, DeleteOutline } from "@mui/icons-material"; +import clsx from "clsx"; +import type { HTMLProps } from "react"; + +import { ArgsAccount } from "../../../shared/lib/args"; +import { Multicall } from "../../../shared/lib/contracts/multicall"; +import { toNEAR } from "../../../shared/lib/converter"; +import { Card } from "../../../shared/ui/components"; + +import "./tab.scss"; + +const Link = ({ address, deleteIcon = false }: { address: string; deleteIcon?: boolean }) => { + const addr = new ArgsAccount(address); + + return ( + + + {addr.value} + + {deleteIcon ? : null} + + ); +}; + +interface DaoConfigTabComponentProps extends HTMLProps { + contracts: { + multicall: Multicall; + }; +} + +const _DaoConfigTab = "DaoConfigTab"; + +const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfigTabComponentProps) => ( +
+ + +

Admins

+ +
    + {multicall.admins.map((admin) => ( +
  • + +
  • + ))} +
+
+ + +

Whitelisted Tokens

+ +
    + {multicall.tokensWhitelist.map((token) => ( +
  • + +
  • + ))} +
+
+ + +

+ Job Bond + {`${multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "..."} Ⓝ`} +

+
+
+); + +export const DaoConfigTab = { + connect: (props: DaoConfigTabComponentProps) => ({ + content: , + title: "Config", + }), +}; diff --git a/src/pages/dao/funds/tab.scss b/src/pages/dao/funds/tab.scss index b7bc2480..41036ca4 100644 --- a/src/pages/dao/funds/tab.scss +++ b/src/pages/dao/funds/tab.scss @@ -3,12 +3,12 @@ @use "sass/mixin"; @use "sass/size"; -.FundsTab { +.DaoFundsTab { display: grid; - grid-template: "balances" 1fr / 1fr; + grid-template: "tokenBalances" 1fr / 1fr; - .balances { - grid-area: balances; + &-tokenBalances { + grid-area: tokenBalances; padding-bottom: size.$gap; position: relative; overflow: hidden; diff --git a/src/pages/dao/funds/tab.tsx b/src/pages/dao/funds/tab.tsx new file mode 100644 index 00000000..b4a25c46 --- /dev/null +++ b/src/pages/dao/funds/tab.tsx @@ -0,0 +1,26 @@ +import clsx from "clsx"; + +import { TokensBalances, type TokensBalancesProps } from "../../../widgets/tokens-balances"; + +import "./tab.scss"; + +interface DaoFundsTabComponentProps extends TokensBalancesProps {} + +const _DaoFundsTab = "DaoFundsTab"; + +const DaoFundsTabComponent = ({ className, contracts }: DaoFundsTabComponentProps) => ( +
+ +
+); + +export const DaoFundsTab = { + connect: (props: DaoFundsTabComponentProps) => ({ + content: , + lazy: true, + title: "Funds", + }), +}; diff --git a/src/pages/dao/index.tsx b/src/pages/dao/index.tsx index b7611248..faded050 100644 --- a/src/pages/dao/index.tsx +++ b/src/pages/dao/index.tsx @@ -1,6 +1,4 @@ import { InputAdornment } from "@mui/material"; -import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; -import clsx from "clsx"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component, ContextType } from "react"; @@ -8,16 +6,17 @@ import { Component, ContextType } from "react"; import { Sidebar } from "../../widgets"; import { TextInput } from "../../widgets/editor/elements"; import { Wallet } from "../../entities"; -import { TokensBalances } from "../../widgets/tokens-balances"; import { ArgsAccount, ArgsError } from "../../shared/lib/args"; import { SputnikDAO, SputnikUI, ProposalStatus } from "../../shared/lib/contracts/sputnik-dao"; import { JobSchema, Multicall } from "../../shared/lib/contracts/multicall"; -import { toNEAR, toYocto, Big, toGas } from "../../shared/lib/converter"; +import { toYocto, Big, toGas } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import type { ProposalOutput } from "../../shared/lib/contracts/sputnik-dao"; -import { Card, Scrollable, Tabs } from "../../shared/ui/components"; -import "./funds/tab.scss"; -import "./config/tab.scss"; +import { Tabs } from "../../shared/ui/components"; + +import { DaoFundsTab } from "./funds/tab"; +import { DaoJobsTab } from "./jobs/tab"; +import { DaoConfigTab } from "./config/tab"; import "./page.scss"; // minimum balance a multicall instance needs for storage + state. @@ -36,6 +35,8 @@ interface State { jobs: JobSchema[]; } +const _DaoPage = "DaoPage"; + export class DaoPage extends Component { constructor(props: Props) { super(props); @@ -297,37 +298,6 @@ export class DaoPage extends Component { } } - toLink(address: string, deleteIcon: boolean = false) { - const addr = new ArgsAccount(address); - - return ( - - - {addr.value} - - {deleteIcon ? : null} - - ); - } - - job(job: JobSchema) { - return ( -
- - - {job.is_active ? : } -
{JSON.stringify(job, null, "  ")}
-
- ); - } - loadInfo() { const { address, noContract, noDao } = this.errors; const { name } = this.state; @@ -394,7 +364,7 @@ export class DaoPage extends Component { // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) if (!walletSelector.isSignedIn()) { - return
Please sign in to continue
; + return
Please sign in to continue
; } const displayErrorsList = ["name", "noDao", "noContract"]; @@ -414,81 +384,28 @@ export class DaoPage extends Component { if (displayErrors.length > 0) return ( <> -
+
{displayErrors}
{this.createMulticall()}
); - if (loading) return
; + if (loading) return
; // everything should be loaded if (!multicall.admins || !multicall.tokensWhitelist || !multicall.jobBond) { console.error("multicall infos incomplete", multicall); - return
Unexpected error! Multicall might be outdated.
; + return
Unexpected error! Multicall might be outdated.
; } return ( - - -

Admins

- -
    - {multicall.admins.map((admin) => ( -
  • {this.toLink(admin)}
  • - ))} -
-
- - -

Whitelisted Tokens

- -
    - {multicall.tokensWhitelist.map((token) => ( -
  • {this.toLink(token)}
  • - ))} -
-
- - - -

Jobs

- {jobs.map((job) => this.job(job))} -
- - -

- Job Bond - {`${ - multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "..." - } Ⓝ`} -

-
-
- ), - }, - { - title: "Funds", - lazy: true, - - content: ( -
- -
- ), - }, + DaoConfigTab.connect({ className: `${_DaoPage}-content`, contracts: { multicall } }), + DaoFundsTab.connect({ className: `${_DaoPage}-content`, contracts: { dao, multicall } }), + DaoJobsTab.connect({ className: `${_DaoPage}-content`, jobs }), ]} /> ); @@ -502,7 +419,6 @@ export class DaoPage extends Component { this.setState( { name: new ArgsAccount(daoAccount.deconstructAddress().name), - multicall: new Multicall(`${daoAccount.deconstructAddress().name}.${Multicall.FACTORY_ADDRESS}`), }, diff --git a/src/pages/dao/jobs/tab.scss b/src/pages/dao/jobs/tab.scss new file mode 100644 index 00000000..ee97d68c --- /dev/null +++ b/src/pages/dao/jobs/tab.scss @@ -0,0 +1,29 @@ +@use "sass/color"; +@use "sass/font"; +@use "sass/size"; + +.DaoJobsTab { + display: grid; + + grid-template: "JobsList" auto; + + .JobsList { + grid-area: JobsList; + position: relative; + + &-item { + position: relative; + margin: size.$gap; + margin-top: 0; + border-radius: size.$task-radius; + background-color: color.$lightest; + + pre { + padding: 0.5 * size.$gap; + font-family: font.$code; + font-size: size.$small-text; + overflow: hidden; + } + } + } +} diff --git a/src/pages/dao/jobs/tab.tsx b/src/pages/dao/jobs/tab.tsx new file mode 100644 index 00000000..9944f94b --- /dev/null +++ b/src/pages/dao/jobs/tab.tsx @@ -0,0 +1,51 @@ +import { AddOutlined, DeleteOutline, EditOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; +import clsx from "clsx"; +import type { HTMLProps } from "react"; + +import { JobSchema } from "../../../shared/lib/contracts/multicall"; +import { Card, Scrollable } from "../../../shared/ui/components"; + +import "./tab.scss"; + +const Job = ({ data: { croncat_hash, is_active, ...data } }: { data: JobSchema }) => ( +
+ + + {is_active ? : } +
{JSON.stringify(data, null, "  ")}
+
+); + +interface DaoJobsTabComponentProps extends HTMLProps { + jobs: JobSchema[]; +} + +const _DaoJobsTab = "DaoJobsTab"; + +const DaoJobsTabComponent = ({ className, jobs }: DaoJobsTabComponentProps) => ( +
+ + +

Jobs

+ + {jobs.map((data) => ( + + ))} + +
+
+); + +export const DaoJobsTab = { + connect: (props: DaoJobsTabComponentProps) => ({ + content: , + lazy: true, + title: "Jobs", + }), +}; diff --git a/src/pages/dao/page.scss b/src/pages/dao/page.scss index 074e0ecb..5de14d1b 100644 --- a/src/pages/dao/page.scss +++ b/src/pages/dao/page.scss @@ -76,7 +76,7 @@ background-color: color.$light; } - &-body { + &-content { @include mixin.full; gap: size.$gap; padding: size.$gap; diff --git a/src/widgets/tokens-balances/index.ts b/src/widgets/tokens-balances/index.ts index 6346b1c6..4f0fd883 100644 --- a/src/widgets/tokens-balances/index.ts +++ b/src/widgets/tokens-balances/index.ts @@ -1 +1 @@ -export { TokensBalances } from "./ui/card"; +export { TokensBalances, type TokensBalancesProps } from "./ui/card"; diff --git a/src/widgets/tokens-balances/ui/card.tsx b/src/widgets/tokens-balances/ui/card.tsx index e41d4de9..8fb9d047 100644 --- a/src/widgets/tokens-balances/ui/card.tsx +++ b/src/widgets/tokens-balances/ui/card.tsx @@ -2,26 +2,26 @@ import { Card, Scrollable, Table } from "../../../shared/ui/components"; import { type DaoContracts } from "../../../entities/types"; import { FungibleToken, NativeToken } from "../../../entities"; -interface TokensBalancesProps { +export interface TokensBalancesProps { className?: string; - daoContracts: DaoContracts; + contracts: DaoContracts; } -export const TokensBalances = ({ className, daoContracts }: TokensBalancesProps) => { - const nativeTokenBalance = NativeToken.balancesRender({ daoContracts }), - fungibleTokensBalances = FungibleToken.allBalancesRender({ daoContracts }); +export const TokensBalances = ({ className, contracts }: TokensBalancesProps) => { + const nativeTokenBalances = NativeToken.balancesRender({ contracts }), + fungibleTokensBalances = FungibleToken.allBalancesRender({ contracts }); return (

Token Balances

- {!nativeTokenBalance || !fungibleTokensBalances ? ( + {!nativeTokenBalances || !fungibleTokensBalances ? (
) : (
)} From cb37171af4257ad54f5e7564bdecec166a56b86a Mon Sep 17 00:00:00 2001 From: Dali Chelbi Date: Sun, 2 Oct 2022 01:50:09 +0200 Subject: [PATCH 125/537] remove dev scripts and unused code, Fix readme --- README.md | 4 ++-- package.json | 2 -- src/entities/wallet/ui/wallet.tsx | 2 +- src/shared/lib/validation.ts | 21 --------------------- 4 files changed, 3 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 4d88bd64..00e40328 100644 --- a/README.md +++ b/README.md @@ -27,13 +27,13 @@ yarn For **NEAR Testnet**: ```sh -yarn dev +yarn start:testnet ``` For **NEAR Mainnet**: ```sh -yarn dev:mainnet +yarn start:mainnet ``` #### Architectural specification diff --git a/package.json b/package.json index 84d01af0..2fbf131f 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,6 @@ "start": "echo 'The app is starting! It will automatically open in your browser when ready' && parcel src/index.html --open", "start:testnet": "NEAR_ENV=testnet yarn start", "start:mainnet": "NEAR_ENV=mainnet yarn start", - "dev": "nodemon --watch contract -e ts --exec \"yarn start\"", - "dev:mainnet": "nodemon --watch contract -e ts --exec \"yarn start:mainnet\"", "test": "jest test --runInBand", "prettier": "prettier --write \"./**/*.{ts,tsx,js,jsx,css,scss,html}\"", "prepare": "husky install" diff --git a/src/entities/wallet/ui/wallet.tsx b/src/entities/wallet/ui/wallet.tsx index c37abc0c..be40e73e 100644 --- a/src/entities/wallet/ui/wallet.tsx +++ b/src/entities/wallet/ui/wallet.tsx @@ -183,7 +183,7 @@ export class WalletComponent extends Component { Promise.all([ SputnikDAO.init(dao).catch(() => { // return non-initialized DAO obj as ready = false per default. - new SputnikDAO(dao); + return new SputnikDAO(dao); }), view(multicall, "get_admins", {}).catch((e) => { if ( diff --git a/src/shared/lib/validation.ts b/src/shared/lib/validation.ts index 0685606b..d01ebd89 100644 --- a/src/shared/lib/validation.ts +++ b/src/shared/lib/validation.ts @@ -1,24 +1,3 @@ -/* -const isUrl = (urlString: string) => - Boolean( - new RegExp( - // validate protocol - "^(https?:\\/\\/)?" + - // validate domain name - "((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + - // validate OR ip (v4) address - "((\\d{1,3}\\.){3}\\d{1,3}))" + - // validate port and path - "(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + - // validate query string - "(\\?[;&a-z\\d%_.~+=-]*)?" + - // validate fragment locator - "(\\#[-a-z\\d_]*)?$", - "i" - ).test(urlString) - ); - */ - const isUrl = (urlString: string): boolean => { try { return Boolean(new URL(urlString)); From 8f9fb7ac49d2347eea46523d8983de8d46ab0817 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Sun, 2 Oct 2022 02:51:04 +0200 Subject: [PATCH 126/537] chore: clean up --- .../icons => app/static}/discord.svg | 0 .../icons => app/static}/github.svg | 0 .../icons => app/static}/parallel.svg | 0 .../icons => app/static}/sequence.svg | 0 .../icons => app/static}/telegram.svg | 0 .../icons => app/static}/twitter.svg | 0 src/entities/wallet/ui/wallet.tsx | 38 +++--- src/global.scss | 2 +- src/index.tsx | 15 ++- src/pages/app/index.tsx | 3 +- src/pages/dao/index.tsx | 108 +++++++++--------- src/shared/ui/components/icons/near.scss | 2 +- src/shared/ui/components/table/index.tsx | 2 +- src/shared/ui/components/table/row.scss | 34 +++--- src/shared/ui/components/table/row.tsx | 30 +---- src/shared/ui/components/table/table.scss | 12 +- src/widgets/layout/layout.scss | 8 +- src/widgets/sidebar/sidebar.jsx | 7 +- 18 files changed, 122 insertions(+), 139 deletions(-) rename src/{shared/ui/components/icons => app/static}/discord.svg (100%) rename src/{shared/ui/components/icons => app/static}/github.svg (100%) rename src/{shared/ui/components/icons => app/static}/parallel.svg (100%) rename src/{shared/ui/components/icons => app/static}/sequence.svg (100%) rename src/{shared/ui/components/icons => app/static}/telegram.svg (100%) rename src/{shared/ui/components/icons => app/static}/twitter.svg (100%) diff --git a/src/shared/ui/components/icons/discord.svg b/src/app/static/discord.svg similarity index 100% rename from src/shared/ui/components/icons/discord.svg rename to src/app/static/discord.svg diff --git a/src/shared/ui/components/icons/github.svg b/src/app/static/github.svg similarity index 100% rename from src/shared/ui/components/icons/github.svg rename to src/app/static/github.svg diff --git a/src/shared/ui/components/icons/parallel.svg b/src/app/static/parallel.svg similarity index 100% rename from src/shared/ui/components/icons/parallel.svg rename to src/app/static/parallel.svg diff --git a/src/shared/ui/components/icons/sequence.svg b/src/app/static/sequence.svg similarity index 100% rename from src/shared/ui/components/icons/sequence.svg rename to src/app/static/sequence.svg diff --git a/src/shared/ui/components/icons/telegram.svg b/src/app/static/telegram.svg similarity index 100% rename from src/shared/ui/components/icons/telegram.svg rename to src/app/static/telegram.svg diff --git a/src/shared/ui/components/icons/twitter.svg b/src/app/static/twitter.svg similarity index 100% rename from src/shared/ui/components/icons/twitter.svg rename to src/app/static/twitter.svg diff --git a/src/entities/wallet/ui/wallet.tsx b/src/entities/wallet/ui/wallet.tsx index c37abc0c..a7221ad7 100644 --- a/src/entities/wallet/ui/wallet.tsx +++ b/src/entities/wallet/ui/wallet.tsx @@ -16,6 +16,25 @@ import "./wallet.scss"; /* TODO: Decompose code */ export class WalletComponent extends Component { + static contextType = useWalletSelector(); + + errors = { + noDao: new ArgsError(errorMsg.ERR_NO_DAO_ON_ADDR, (value) => this.errors.noDao.isBad), + noRights: new ArgsError(errorMsg.ERR_CANNOT_PROPOSE_TO_DAO, (value) => this.errors.noRights), + noContract: new ArgsError(errorMsg.ERR_DAO_HAS_NO_MTCL, (value) => this.errors.noContract.isBad), + }; + + daoList = []; + + daoSearchDebounced = debounce( + // debounced function + (newValue) => { + this.daoSearch(newValue); + }, + // debounce time + 400 + ); + constructor(props, context) { super(props, context); @@ -41,25 +60,6 @@ export class WalletComponent extends Component { } } - static contextType = useWalletSelector(); - - errors = { - noDao: new ArgsError(errorMsg.ERR_NO_DAO_ON_ADDR, (value) => this.errors.noDao.isBad), - noRights: new ArgsError(errorMsg.ERR_CANNOT_PROPOSE_TO_DAO, (value) => this.errors.noRights), - noContract: new ArgsError(errorMsg.ERR_DAO_HAS_NO_MTCL, (value) => this.errors.noContract.isBad), - }; - - daoList = []; - - daoSearchDebounced = debounce( - // debounced function - (newValue) => { - this.daoSearch(newValue); - }, - // debounce time - 400 - ); - signIn() { const { modal } = this.context; modal.show(); diff --git a/src/global.scss b/src/global.scss index 1b4d0aa8..e2532e0a 100644 --- a/src/global.scss +++ b/src/global.scss @@ -40,7 +40,7 @@ button { .disabled { background-color: color.$darkest !important; - color: rgba(232, 230, 227, 0.3); + color: rgba(color.$light-text, 0.3); cursor: not-allowed !important; } diff --git a/src/index.tsx b/src/index.tsx index b2b89ba0..2b01d8a5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,6 +5,7 @@ import { DaoPage } from "./pages/dao"; import { Wallet } from "./entities"; import "./shared/lib/persistent"; import "@near-wallet-selector/modal-ui/styles.css"; +import { Sidebar } from "./widgets"; window.PAGE = "app"; @@ -24,12 +25,22 @@ ReactDOM.render( } + element={ + <> + + + + } /> } + element={ + <> + + + + } /> diff --git a/src/pages/app/index.tsx b/src/pages/app/index.tsx index 7658ce62..a1801247 100644 --- a/src/pages/app/index.tsx +++ b/src/pages/app/index.tsx @@ -1,11 +1,10 @@ -import { Layout, Sidebar } from "../../widgets"; +import { Layout } from "../../widgets"; export const AppPage = () => { window.PAGE = "app"; return ( <> - ); diff --git a/src/pages/dao/index.tsx b/src/pages/dao/index.tsx index 197226eb..ccf1c015 100644 --- a/src/pages/dao/index.tsx +++ b/src/pages/dao/index.tsx @@ -1,24 +1,23 @@ +import { AddOutlined, DeleteOutline, EditOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; import { InputAdornment } from "@mui/material"; -import { DeleteOutline, EditOutlined, AddOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; import clsx from "clsx"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component, ContextType } from "react"; -import { Sidebar } from "../../widgets"; -import { TextInput } from "../../widgets/editor/elements"; import { Wallet } from "../../entities"; -import { TokensBalances } from "../../widgets/tokens-balances"; import { ArgsAccount, ArgsError } from "../../shared/lib/args"; -import { SputnikDAO, SputnikUI, ProposalStatus } from "../../shared/lib/contracts/sputnik-dao"; import { Multicall } from "../../shared/lib/contracts/multicall"; -import { toNEAR, toYocto, Big } from "../../shared/lib/converter"; +import type { ProposalOutput } from "../../shared/lib/contracts/sputnik-dao"; +import { ProposalStatus, SputnikDAO, SputnikUI } from "../../shared/lib/contracts/sputnik-dao"; +import { Big, toNEAR, toYocto } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { view } from "../../shared/lib/wallet"; -import type { ProposalOutput } from "../../shared/lib/contracts/sputnik-dao"; import { Card, Scrollable, Tabs } from "../../shared/ui/components"; -import "./funds/tab.scss"; +import { TextInput } from "../../widgets/editor/elements"; +import { TokensBalances } from "../../widgets/tokens-balances"; import "./config/tab.scss"; +import "./funds/tab.scss"; import "./page.scss"; // minimum balance a multicall instance needs for storage + state. @@ -44,6 +43,25 @@ interface State { } export class DaoPage extends Component { + static contextType = Ctx; + declare context: ContextType; + + errors: { [key: string]: ArgsError } = { + name: new ArgsError( + "Invalid NEAR address", + (input) => ArgsAccount.isValid(`${input.value}.${SputnikDAO.FACTORY_ADDRESS}`), + !ArgsAccount.isValid(STORAGE.addresses.dao) + ), + noDao: new ArgsError("Sputnik DAO not found on given address", (value) => this.errors.noDao.isBad), + noContract: new ArgsError("DAO has no multicall instance", (value) => this.errors.noContract.isBad), + }; + + loadInfoDebounced = debounce(() => this.loadInfo(), 400); + + lastAddr: string = ""; + // Multicall factory fee. + fee: string = ""; + constructor(props: Props) { super(props); @@ -72,25 +90,6 @@ export class DaoPage extends Component { }); } - static contextType = Ctx; - declare context: ContextType; - - errors: { [key: string]: ArgsError } = { - name: new ArgsError( - "Invalid NEAR address", - (input) => ArgsAccount.isValid(`${input.value}.${SputnikDAO.FACTORY_ADDRESS}`), - !ArgsAccount.isValid(STORAGE.addresses.dao) - ), - noDao: new ArgsError("Sputnik DAO not found on given address", (value) => this.errors.noDao.isBad), - noContract: new ArgsError("DAO has no multicall instance", (value) => this.errors.noContract.isBad), - }; - - loadInfoDebounced = debounce(() => this.loadInfo(), 400); - - lastAddr: string = ""; - // Multicall factory fee. - fee: string = ""; - /** * check if DAO has a proposal to create multicall instance. * proposal must be in progress, and not expired. @@ -523,45 +522,40 @@ export class DaoPage extends Component { } componentDidMount(): void { + window.PAGE = "dao"; document.addEventListener("onaddressesupdated", () => this.onAddressesUpdated()); } render() { - window.PAGE = "dao"; - const { name } = this.state; return ( - <> - - -
-
-
- { - const fullDaoAddr = `${name.value}.${SputnikDAO.FACTORY_ADDRESS}`; - const daoAccount = new ArgsAccount(fullDaoAddr); - if (daoAccount.isValid()) { - this.loadInfoDebounced(); - } - this.forceUpdate(); - }} - InputProps={{ - endAdornment: ( - {`.${SputnikDAO.FACTORY_ADDRESS}`} - ), - }} - /> -
+
+
+
+ { + const fullDaoAddr = `${name.value}.${SputnikDAO.FACTORY_ADDRESS}`; + const daoAccount = new ArgsAccount(fullDaoAddr); + if (daoAccount.isValid()) { + this.loadInfoDebounced(); + } + this.forceUpdate(); + }} + InputProps={{ + endAdornment: ( + {`.${SputnikDAO.FACTORY_ADDRESS}`} + ), + }} + />
- - {this.getContent()}
- + + {this.getContent()} +
); } } diff --git a/src/shared/ui/components/icons/near.scss b/src/shared/ui/components/icons/near.scss index a1307f18..332cf513 100644 --- a/src/shared/ui/components/icons/near.scss +++ b/src/shared/ui/components/icons/near.scss @@ -5,5 +5,5 @@ } .GenericTokenIcon--filled { - position: "initial !important"; + position: initial !important; } diff --git a/src/shared/ui/components/table/index.tsx b/src/shared/ui/components/table/index.tsx index 7d106626..28ab09f8 100644 --- a/src/shared/ui/components/table/index.tsx +++ b/src/shared/ui/components/table/index.tsx @@ -22,7 +22,7 @@ export const Table = ({ header, rows }: TableProps) => { return ( <> {matches ? ( -
+
{rows && rows.map((cells, index) => ( div { display: flex; justify-content: space-between; - grid-template-columns: auto 100%; - - > div:first-of-type { - white-space: nowrap; + align-items: center; + font-size: size.$text; + span:first-of-type { + font-weight: 800; } - - > div:last-child { - width: 100%; - display: flex; - justify-content: flex-end; - align-items: center; + &:first-of-type { + margin-bottom: 0.5 * size.$gap; + & > span { + &:first-of-type { + display: none; + } + &:last-child { + font-size: size.$large-text; + } + } } } } diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 7cd001c7..0f081fe2 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -19,7 +19,7 @@ export const TableRow = ({ cells, headerCells }: TableRowProps) => ( ); -const _TableRowCard = `${_TableRow}--card`; +const _TableRowCard = `${_TableRow}--mobile`; export const TableRowCard = ({ cells, headerCells }: TableRowProps) => (
@@ -28,33 +28,9 @@ export const TableRowCard = ({ cells, headerCells }: TableRowProps) => ( className={`${_TableRowCard}-content`} key={headerCellIndex} > - - {headerCell} - - - - {cells ? cells[headerCellIndex] : "No data"} - + {headerCell} + {cells ? cells[headerCellIndex] : "No data"}
))}
); - -/* -export interface TableRowProps extends TableRowDefaultProps, TableRowCardProps {} - -export const TableRow = (props: TableRowProps) => ( - <> - - - -); -*/ diff --git a/src/shared/ui/components/table/table.scss b/src/shared/ui/components/table/table.scss index 227a2288..86962f52 100644 --- a/src/shared/ui/components/table/table.scss +++ b/src/shared/ui/components/table/table.scss @@ -3,17 +3,16 @@ @use "sass/size"; .Table { - display: table; border-radius: size.$task-radius; font-family: font.$text; margin-top: size.$gap; - & .MuiTableCell-root { + .MuiTableCell-root { border-bottom: none; padding: 0.5 * size.$gap; } - & table { + table { width: 100%; border-collapse: separate; border-spacing: 0; @@ -41,8 +40,9 @@ } } - &-column { - display: grid; - gap: 1.6ch; + &--mobile { + display: flex; + flex-flow: column nowrap; + gap: size.$gap; } } diff --git a/src/widgets/layout/layout.scss b/src/widgets/layout/layout.scss index d70a0173..d0de5d3e 100644 --- a/src/widgets/layout/layout.scss +++ b/src/widgets/layout/layout.scss @@ -30,14 +30,14 @@ @include tutorial; width: 28%; left: 15%; - background-image: url("../../shared/ui/components/icons/sequence.svg"); + background-image: url("../../app/static/sequence.svg"); background-position: left; } &[tutorial="no"]::before { @include tutorial; width: 28%; left: 15%; - background-image: url("../../shared/ui/components/icons/sequence.svg"); + background-image: url("../../app/static/sequence.svg"); background-position: left; opacity: 0; filter: blur(5px); @@ -46,14 +46,14 @@ @include tutorial; width: 35%; right: 15%; - background-image: url("../../shared/ui/components/icons/parallel.svg"); + background-image: url("../../app/static/parallel.svg"); background-position: right; } &[tutorial="no"]::after { @include tutorial; width: 35%; right: 15%; - background-image: url("../../shared/ui/components/icons/parallel.svg"); + background-image: url("../../app/static/parallel.svg"); background-position: right; opacity: 0; filter: blur(5px); diff --git a/src/widgets/sidebar/sidebar.jsx b/src/widgets/sidebar/sidebar.jsx index aa3621be..e456d666 100644 --- a/src/widgets/sidebar/sidebar.jsx +++ b/src/widgets/sidebar/sidebar.jsx @@ -10,9 +10,9 @@ import { Icon } from "@mui/material"; import { Component } from "react"; import { NavLink } from "react-router-dom"; -import Discord from "../../shared/ui/components/icons/discord.svg"; -import Github from "../../shared/ui/components/icons/github.svg"; -import Twitter from "../../shared/ui/components/icons/twitter.svg"; +import Discord from "../../app/static/discord.svg"; +import Github from "../../app/static/github.svg"; +import Twitter from "../../app/static/twitter.svg"; import { Wallet } from "../../entities/wallet"; import { STORAGE } from "../../shared/lib/persistent"; import { viewAccount } from "../../shared/lib/wallet"; @@ -56,7 +56,6 @@ export class Sidebar extends Component { componentDidMount() { window.SIDEBAR = this; - document.addEventListener("onaddressesupdated", () => this.forceUpdate()); } From e3919b0cf152e27530b9aeeac447acbe6484b4cc Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Sun, 2 Oct 2022 03:23:46 +0200 Subject: [PATCH 127/537] chore: clean up naming --- src/entities/fungible-token/index.ts | 2 +- .../model/{balances.ts => fungible-token.ts} | 0 .../ui/{balances.tsx => fungible-token.tsx} | 2 +- src/entities/native-token/index.ts | 2 +- .../model/{balances.ts => native-token.ts} | 0 .../ui/{balances.tsx => native-token.tsx} | 2 +- src/entities/task/index.ts | 6 +- src/entities/task/ui/{card.jsx => task.jsx} | 4 +- src/entities/task/ui/{card.scss => task.scss} | 0 src/index.tsx | 2 +- src/pages/app/app.tsx | 11 + src/pages/app/index.tsx | 12 +- .../dao/config/{tab.scss => config.scss} | 0 src/pages/dao/{page.scss => dao.scss} | 0 src/pages/dao/dao.tsx | 561 +++++++++++++++++ src/pages/dao/funds/{tab.scss => funds.scss} | 0 src/pages/dao/index.tsx | 562 +----------------- src/shared/ui/components/card/index.tsx | 10 - .../dialog/{index.tsx => dialog.tsx} | 0 src/shared/ui/components/dialog/index.ts | 1 + .../{card/card.scss => facet/facet.scss} | 2 +- src/shared/ui/components/facet/facet.tsx | 10 + src/shared/ui/components/facet/index.ts | 1 + src/shared/ui/components/icons/index.ts | 2 +- .../ui/components/icons/{ => near}/near.scss | 0 .../ui/components/icons/{ => near}/near.tsx | 0 src/shared/ui/components/index.ts | 16 +- src/shared/ui/components/popup-menu/index.ts | 1 + .../popup-menu/{index.tsx => popup-menu.tsx} | 0 src/shared/ui/components/scrollable/index.ts | 1 + .../scrollable/{index.tsx => scrollable.tsx} | 0 src/shared/ui/components/table/index.ts | 1 + .../components/table/{index.tsx => table.tsx} | 0 src/shared/ui/components/tabs/index.ts | 1 + .../components/tabs/{index.tsx => tabs.tsx} | 0 src/shared/ui/components/token-label/index.ts | 1 + .../{index.tsx => token-label.tsx} | 0 src/shared/ui/components/tooltip/index.ts | 1 + .../tooltip/{index.tsx => tooltip.tsx} | 0 src/widgets/builder/index.ts | 1 + src/widgets/column/column.jsx | 2 +- src/widgets/column/index.ts | 1 + src/widgets/editor/index.ts | 2 + src/widgets/export/index.ts | 1 + src/widgets/layout/index.ts | 1 + src/widgets/menu/index.ts | 1 + src/widgets/sidebar/index.ts | 1 + src/widgets/tokens-balances/index.ts | 2 +- .../ui/{card.tsx => token-balances.tsx} | 6 +- 49 files changed, 623 insertions(+), 609 deletions(-) rename src/entities/fungible-token/model/{balances.ts => fungible-token.ts} (100%) rename src/entities/fungible-token/ui/{balances.tsx => fungible-token.tsx} (92%) rename src/entities/native-token/model/{balances.ts => native-token.ts} (100%) rename src/entities/native-token/ui/{balances.tsx => native-token.tsx} (87%) rename src/entities/task/ui/{card.jsx => task.jsx} (98%) rename src/entities/task/ui/{card.scss => task.scss} (100%) create mode 100644 src/pages/app/app.tsx rename src/pages/dao/config/{tab.scss => config.scss} (100%) rename src/pages/dao/{page.scss => dao.scss} (100%) create mode 100644 src/pages/dao/dao.tsx rename src/pages/dao/funds/{tab.scss => funds.scss} (100%) delete mode 100644 src/shared/ui/components/card/index.tsx rename src/shared/ui/components/dialog/{index.tsx => dialog.tsx} (100%) create mode 100644 src/shared/ui/components/dialog/index.ts rename src/shared/ui/components/{card/card.scss => facet/facet.scss} (99%) create mode 100644 src/shared/ui/components/facet/facet.tsx create mode 100644 src/shared/ui/components/facet/index.ts rename src/shared/ui/components/icons/{ => near}/near.scss (100%) rename src/shared/ui/components/icons/{ => near}/near.tsx (100%) create mode 100644 src/shared/ui/components/popup-menu/index.ts rename src/shared/ui/components/popup-menu/{index.tsx => popup-menu.tsx} (100%) create mode 100644 src/shared/ui/components/scrollable/index.ts rename src/shared/ui/components/scrollable/{index.tsx => scrollable.tsx} (100%) create mode 100644 src/shared/ui/components/table/index.ts rename src/shared/ui/components/table/{index.tsx => table.tsx} (100%) create mode 100644 src/shared/ui/components/tabs/index.ts rename src/shared/ui/components/tabs/{index.tsx => tabs.tsx} (100%) create mode 100644 src/shared/ui/components/token-label/index.ts rename src/shared/ui/components/token-label/{index.tsx => token-label.tsx} (100%) create mode 100644 src/shared/ui/components/tooltip/index.ts rename src/shared/ui/components/tooltip/{index.tsx => tooltip.tsx} (100%) create mode 100644 src/widgets/builder/index.ts create mode 100644 src/widgets/column/index.ts create mode 100644 src/widgets/editor/index.ts create mode 100644 src/widgets/export/index.ts create mode 100644 src/widgets/layout/index.ts create mode 100644 src/widgets/menu/index.ts create mode 100644 src/widgets/sidebar/index.ts rename src/widgets/tokens-balances/ui/{card.tsx => token-balances.tsx} (88%) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 0a9700da..e45f614d 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,4 +1,4 @@ -import { fungibleTokensBalancesRender } from "./ui/balances"; +import { fungibleTokensBalancesRender } from "./ui/fungible-token"; export class FungibleToken { static allBalancesRender = fungibleTokensBalancesRender; diff --git a/src/entities/fungible-token/model/balances.ts b/src/entities/fungible-token/model/fungible-token.ts similarity index 100% rename from src/entities/fungible-token/model/balances.ts rename to src/entities/fungible-token/model/fungible-token.ts diff --git a/src/entities/fungible-token/ui/balances.tsx b/src/entities/fungible-token/ui/fungible-token.tsx similarity index 92% rename from src/entities/fungible-token/ui/balances.tsx rename to src/entities/fungible-token/ui/fungible-token.tsx index da64a0e2..a0d6addd 100644 --- a/src/entities/fungible-token/ui/balances.tsx +++ b/src/entities/fungible-token/ui/fungible-token.tsx @@ -1,7 +1,7 @@ import { TokenLabel } from "../../../shared/ui/components"; import type { DaoContracts } from "../../types"; import { FungibleTokenFormat } from "../lib/format"; -import { FungibleTokenBalancesModel } from "../model/balances"; +import { FungibleTokenBalancesModel } from "../model/fungible-token"; interface FungibleTokensBalancesRenderProps { daoContracts: DaoContracts; diff --git a/src/entities/native-token/index.ts b/src/entities/native-token/index.ts index c80a4940..6430194e 100644 --- a/src/entities/native-token/index.ts +++ b/src/entities/native-token/index.ts @@ -1,4 +1,4 @@ -import { nativeTokenBalancesRender } from "./ui/balances"; +import { nativeTokenBalancesRender } from "./ui/native-token"; export class NativeToken { static balancesRender = nativeTokenBalancesRender; diff --git a/src/entities/native-token/model/balances.ts b/src/entities/native-token/model/native-token.ts similarity index 100% rename from src/entities/native-token/model/balances.ts rename to src/entities/native-token/model/native-token.ts diff --git a/src/entities/native-token/ui/balances.tsx b/src/entities/native-token/ui/native-token.tsx similarity index 87% rename from src/entities/native-token/ui/balances.tsx rename to src/entities/native-token/ui/native-token.tsx index 70c26900..089ec38f 100644 --- a/src/entities/native-token/ui/balances.tsx +++ b/src/entities/native-token/ui/native-token.tsx @@ -1,6 +1,6 @@ import { TokenLabel } from "../../../shared/ui/components"; import type { DaoContracts } from "../../types"; -import { NativeTokenBalancesModel } from "../model/balances"; +import { NativeTokenBalancesModel } from "../model/native-token"; interface NativeTokenBalancesRenderProps { daoContracts: DaoContracts; diff --git a/src/entities/task/index.ts b/src/entities/task/index.ts index ae54f41f..87b7ede5 100644 --- a/src/entities/task/index.ts +++ b/src/entities/task/index.ts @@ -1,5 +1 @@ -import { TaskCard } from "./ui/card"; - -export const Task = { - Card: TaskCard, -}; +export { Task } from "./ui/task"; diff --git a/src/entities/task/ui/card.jsx b/src/entities/task/ui/task.jsx similarity index 98% rename from src/entities/task/ui/card.jsx rename to src/entities/task/ui/task.jsx index 54f85108..a6b45afe 100644 --- a/src/entities/task/ui/card.jsx +++ b/src/entities/task/ui/task.jsx @@ -2,10 +2,10 @@ import React, { Component } from "react"; import { Draggable } from "react-beautiful-dnd"; import { Family } from "../../../families/index.js"; -import "./card.scss"; +import "./task.scss"; /* TODO: Decompose model and view */ -export class TaskCard extends Component { +export class Task extends Component { id; constructor(props) { diff --git a/src/entities/task/ui/card.scss b/src/entities/task/ui/task.scss similarity index 100% rename from src/entities/task/ui/card.scss rename to src/entities/task/ui/task.scss diff --git a/src/index.tsx b/src/index.tsx index 2b01d8a5..9e017715 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,7 @@ import ReactDOM from "react-dom"; import { HashRouter, Routes, Route, Navigate } from "react-router-dom"; import { AppPage } from "./pages/app"; -import { DaoPage } from "./pages/dao"; +import { DaoPage } from "./pages/dao/dao"; import { Wallet } from "./entities"; import "./shared/lib/persistent"; import "@near-wallet-selector/modal-ui/styles.css"; diff --git a/src/pages/app/app.tsx b/src/pages/app/app.tsx new file mode 100644 index 00000000..a1801247 --- /dev/null +++ b/src/pages/app/app.tsx @@ -0,0 +1,11 @@ +import { Layout } from "../../widgets"; + +export const AppPage = () => { + window.PAGE = "app"; + + return ( + <> + + + ); +}; diff --git a/src/pages/app/index.tsx b/src/pages/app/index.tsx index a1801247..5e083cf8 100644 --- a/src/pages/app/index.tsx +++ b/src/pages/app/index.tsx @@ -1,11 +1 @@ -import { Layout } from "../../widgets"; - -export const AppPage = () => { - window.PAGE = "app"; - - return ( - <> - - - ); -}; +export { AppPage } from "./app"; diff --git a/src/pages/dao/config/tab.scss b/src/pages/dao/config/config.scss similarity index 100% rename from src/pages/dao/config/tab.scss rename to src/pages/dao/config/config.scss diff --git a/src/pages/dao/page.scss b/src/pages/dao/dao.scss similarity index 100% rename from src/pages/dao/page.scss rename to src/pages/dao/dao.scss diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx new file mode 100644 index 00000000..4c081e7f --- /dev/null +++ b/src/pages/dao/dao.tsx @@ -0,0 +1,561 @@ +import { AddOutlined, DeleteOutline, EditOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; +import { InputAdornment } from "@mui/material"; +import clsx from "clsx"; +import { Base64 } from "js-base64"; +import debounce from "lodash.debounce"; +import { Component, ContextType } from "react"; + +import { Wallet } from "../../entities"; +import { ArgsAccount, ArgsError } from "../../shared/lib/args"; +import { Multicall } from "../../shared/lib/contracts/multicall"; +import type { ProposalOutput } from "../../shared/lib/contracts/sputnik-dao"; +import { ProposalStatus, SputnikDAO, SputnikUI } from "../../shared/lib/contracts/sputnik-dao"; +import { Big, toNEAR, toYocto } from "../../shared/lib/converter"; +import { STORAGE } from "../../shared/lib/persistent"; +import { view } from "../../shared/lib/wallet"; +import { Facet, Scrollable, Tabs } from "../../shared/ui/components"; +import { TextInput } from "../../widgets/editor/elements"; +import { TokensBalances } from "../../widgets/tokens-balances"; +import "./config/config.scss"; +import "./funds/funds.scss"; +import "./dao.scss"; + +// minimum balance a multicall instance needs for storage + state. +const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR +const Ctx = Wallet.useSelector(); + +interface Props {} + +interface State { + name: ArgsAccount; + dao: SputnikDAO; + multicall: Multicall; + loading: boolean; + proposed: number; + proposedInfo: ProposalOutput; + + info: { + admins: string[]; + tokens: string[]; + jobs: any[]; + jobBond: string; + }; +} + +export class DaoPage extends Component { + static contextType = Ctx; + declare context: ContextType; + + errors: { [key: string]: ArgsError } = { + name: new ArgsError( + "Invalid NEAR address", + (input) => ArgsAccount.isValid(`${input.value}.${SputnikDAO.FACTORY_ADDRESS}`), + !ArgsAccount.isValid(STORAGE.addresses.dao) + ), + noDao: new ArgsError("Sputnik DAO not found on given address", (value) => this.errors.noDao.isBad), + noContract: new ArgsError("DAO has no multicall instance", (value) => this.errors.noContract.isBad), + }; + + loadInfoDebounced = debounce(() => this.loadInfo(), 400); + + lastAddr: string = ""; + // Multicall factory fee. + fee: string = ""; + + constructor(props: Props) { + super(props); + + // split DAO address into parent address and rest (name). + const deconstructedDaoAddress = ArgsAccount.deconstructAddress(STORAGE.addresses.dao); + + this.state = { + name: new ArgsAccount(deconstructedDaoAddress.name), + dao: new SputnikDAO(STORAGE.addresses.dao), + multicall: new Multicall(`${deconstructedDaoAddress.name}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`), + loading: false, + proposed: -1, + proposedInfo: {}, + + info: { + admins: [], + tokens: [], + jobs: [], + jobBond: "...", + }, + }; + + view(window.nearConfig.MULTICALL_FACTORY_ADDRESS, "get_fee", {}).then((createMulticallFee) => { + this.fee = createMulticallFee; + this.loadInfo(); + }); + } + + /** + * check if DAO has a proposal to create multicall instance. + * proposal must be in progress, and not expired. + * + * @returns {object} ID and info of proposal to create multicall instance, + */ + async proposalAlreadyExists(dao: SputnikDAO): Promise<{ proposal_id: number; proposal_info: object }> { + // Date.now() returns timestamp in milliseconds, SputnikDAO uses nanoseconds + const currentTime = Big(Date.now()).times("1000000"); + const lastProposalId = dao.lastProposalId; + const proposalPeriod = dao.policy.proposal_period; + + // get last 100 DAO proposals + const proposals = await dao.getProposals({ + from_index: lastProposalId < 100 ? 0 : lastProposalId - 100, + limit: 100, + }); + // Look for active "Create multicall" proposals + const activeProposals = proposals.filter((proposal) => { + // discard if not active proposal to create multicall instance + if ( + !(proposal.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) || + !(proposal.kind?.FunctionCall?.actions?.[0]?.method_name === "create") || + !(proposal.status === ProposalStatus.InProgress) + ) { + return false; + } + // calculate proposal expiration timestamp in nanoseconds + const expirationTime = Big(proposal.submission_time).add(proposalPeriod); + // check if proposal expired + return expirationTime.gt(currentTime) ? true : false; + }); + + // If there many "Create multicall" proposals, return latest. + if (activeProposals.length > 0) { + const lastProposal = activeProposals.pop()!; + return { proposal_id: lastProposal.id, proposal_info: lastProposal }; + } + // No "Create multicall" proposals found. + else return { proposal_id: -1, proposal_info: {} }; + } + + createMulticall() { + const { accountId } = this.context!; + const { loading, dao, proposed, proposedInfo } = this.state; + const { noContract, noDao } = this.errors; + + if ( + this.fee === "" || + // wallet not logged in or DAO object not initialized yet + dao?.ready !== true + ) { + return null; + } + + const depo = Big(this.fee).plus(MIN_INSTANCE_BALANCE); + const daoSearchInput: HTMLInputElement = document.querySelector(".DaoSearch input")!; + + // can user propose a FunctionCall to DAO? + const canPropose = dao.checkUserPermission(accountId!, "AddProposal", "FunctionCall"); + + // can user vote approve a FunctionCall on the DAO? + const canApprove = dao.checkUserPermission(accountId!, "VoteApprove", "FunctionCall"); + + const args = { + proposal: { + description: `create multicall instance for this DAO at ${this.state.multicall.address}`, + + kind: { + FunctionCall: { + receiver_id: window.nearConfig.MULTICALL_FACTORY_ADDRESS, + + actions: [ + { + method_name: "create", + args: Base64.encode( + JSON.stringify({ + multicall_init_args: { + admin_accounts: [dao.address], + croncat_manager: window.nearConfig.CRONCAT_MANAGER_ADDRESS, + job_bond: dao.policy.proposal_bond, + }, + + public_key: "HdJuXFRBKMEXuzEsXVscdd3aoBvEGGXDKQ3JoNhqJ4uU", + }) + ), + + deposit: depo.toFixed(), + gas: "150000000000000", + }, + ], + }, + }, + }, + }; + + if ( + noContract.isBad && + // base.sputnik-dao.near does not exist + !noDao.isBad && + !loading && + // disappear while debouncing + this.lastAddr === daoSearchInput.value + ) { + if (proposed === -1) { + // no create multicall proposal exists + + if (canPropose) { + // ... and user can propose FunctionCall + + return ( + <> +
+ {/* hint: you can use "genesis" or "test" as DAO to get to this message */} + {`A multicall instance can only be created for `} + + + {dao.address} + + + {` by making a proposal.`} +
+ + + + ); + } else { + // ... and user cannot propose FunctionCall + + return ( +
+ {/* hint: you can use "ref-community-board-testnet" as DAO to get to this message */} + {`This DAO has no multicall instance. A DAO member with proposing permissions should make a proposal.`} +
+ ); + } + } else if (proposed !== -1) { + // create multicall proposal exists + + if (!canApprove) { + // user does not have rights to VoteApprove + + return ( +
+ {`Proposal to create a multicall exists (#${proposed}), but you have no voting permissions on this DAO.`} +
+ + Proposal on Astro + +
+ ); + } else if (proposedInfo.votes[accountId!]) { + // user can VoteApprove and already voted + + return ( +
+ {`You have voted on creating a multicall instance for this DAO. It will be created as soon as the proposal passes voting.`} +
+ + Proposal on Astro + +
+ ); + } else { + // user can VoteApprove and did NOT vote yet. + + return ( + <> +
+ {/* hint: you can use "genesis" or "test" as DAO to get to this message */} + {`There exists a proposal (#${proposed}) to create a multicall instance for this DAO. `} + + + Open on AstroDAO + +
+ + + + ); + } + } + } + } + + toLink(address: string, deleteIcon: boolean = false) { + const addr = new ArgsAccount(address); + + return ( + + + {addr.value} + + {deleteIcon ? : null} + + ); + } + + job(job: any) { + return ( +
+ + + {job.is_active ? : } +
{JSON.stringify(job, null, "  ")}
+
+ ); + } + + loadInfo() { + const { name: nameError, noContract, noDao } = this.errors; + const { name } = this.state; + + const multicallAddress = `${name.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; + const daoAddress = `${name.value}.${SputnikDAO.FACTORY_ADDRESS}`; + + if (this.lastAddr === name.value) return; + + this.lastAddr = name.value; + noContract.isBad = false; + noDao.isBad = false; + + // chosen address violates NEAR AccountId rules. + if (nameError.isBad) { + noContract.isBad = true; + noDao.isBad = true; + this.setState({ proposed: -1, proposedInfo: {} }); + return; + } + + this.setState({ loading: true }); + + // initialize DAO object + SputnikDAO.init(daoAddress) + // on error, return non-initialized DAO object, as ready = false per default + .catch((e) => new SputnikDAO(daoAddress)) + .then((dao) => { + if (!dao.ready) { + // DAO not ready => either no SputnikDAO contract on the chosen address + // or some error happened during DAO object init. + noContract.isBad = true; + noDao.isBad = true; + this.setState({ dao, multicall: new Multicall(multicallAddress), loading: false }); + return; + } else { + // DAO correctly initialized, try to fetch multicall info + Promise.all([ + view(multicallAddress, "get_admins", {}).catch((e) => { + if (e.type === "AccountDoesNotExist" && e.toString().includes(` ${multicallAddress} `)) { + noContract.isBad = true; + } + }), + + view(multicallAddress, "get_tokens", {}).catch((e) => {}), + view(multicallAddress, "get_jobs", {}).catch((e) => {}), + view(multicallAddress, "get_job_bond", {}).catch((e) => {}), + this.proposalAlreadyExists(dao).catch((e) => {}), + ]).then(([admins, tokens, jobs, jobBond, proposalData]) => + this.setState((prevState) => ({ + dao, + multicall: new Multicall(multicallAddress), + info: { admins, tokens, jobs, jobBond }, + loading: false, + proposed: proposalData?.proposal_id, + proposedInfo: proposalData?.proposal_info || {}, + })) + ); + } + }); + } + + getContent() { + const { selector: walletSelector } = this.context!; + const { dao, info, loading, multicall } = this.state; + + // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) + if (!walletSelector.isSignedIn()) { + return
Please sign in to continue
; + } + + const displayErrorsList = ["name", "noDao", "noContract"]; + + const displayErrors = Object.keys(this.errors) + .filter((e) => this.errors[e].isBad && displayErrorsList.includes(e)) + .map((e) => ( +

+ {this.errors[e].isBad ? "\u2717" : "\u2714"} + {this.errors[e].message} +

+ )); + + if (displayErrors.length > 0) + return ( + <> +
+
{displayErrors}
+ {this.createMulticall()} +
+ + ); + + if (loading) return
; + + // everything should be loaded + if (!info.admins || !info.tokens || !info.jobBond) { + console.error("info incomplete", info); + return
Unexpected error! Multicall might be outdated.
; + } + + return ( + + + +

Admins

+ +
    + {info.admins.map((admin) => ( +
  • {this.toLink(admin)}
  • + ))} +
+
+ + +

Whitelisted Tokens

+ +
    + {info.tokens.map((token) => ( +
  • {this.toLink(token)}
  • + ))} +
+
+ + + +

Jobs

+ {info.jobs.map((j) => this.job(j))} +
+ + +

+ Job Bond + {`${info.jobBond !== "..." ? toNEAR(info.jobBond) : "..."} Ⓝ`} +

+
+
+ ), + }, + { + title: "Funds", + lazy: true, + + content: ( +
+ +
+ ), + }, + ]} + /> + ); + } + + onAddressesUpdated() { + const { name } = this.state; + const daoAccount = new ArgsAccount(STORAGE.addresses.dao); + if (!(name.value === daoAccount.deconstructAddress().name)) { + this.setState( + { + name: new ArgsAccount(daoAccount.deconstructAddress().name), + + multicall: new Multicall( + `${daoAccount.deconstructAddress().name}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}` + ), + }, + + () => { + this.errors.name.validOrNull(daoAccount); + this.loadInfo(); + this.forceUpdate(); + } + ); + } + } + + componentDidMount(): void { + window.PAGE = "dao"; + document.addEventListener("onaddressesupdated", () => this.onAddressesUpdated()); + } + + render() { + const { name } = this.state; + + return ( +
+
+
+ { + const fullDaoAddr = `${name.value}.${SputnikDAO.FACTORY_ADDRESS}`; + const daoAccount = new ArgsAccount(fullDaoAddr); + if (daoAccount.isValid()) { + this.loadInfoDebounced(); + } + this.forceUpdate(); + }} + InputProps={{ + endAdornment: ( + {`.${SputnikDAO.FACTORY_ADDRESS}`} + ), + }} + /> +
+
+ + {this.getContent()} +
+ ); + } +} diff --git a/src/pages/dao/funds/tab.scss b/src/pages/dao/funds/funds.scss similarity index 100% rename from src/pages/dao/funds/tab.scss rename to src/pages/dao/funds/funds.scss diff --git a/src/pages/dao/index.tsx b/src/pages/dao/index.tsx index ccf1c015..4c676b91 100644 --- a/src/pages/dao/index.tsx +++ b/src/pages/dao/index.tsx @@ -1,561 +1 @@ -import { AddOutlined, DeleteOutline, EditOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; -import { InputAdornment } from "@mui/material"; -import clsx from "clsx"; -import { Base64 } from "js-base64"; -import debounce from "lodash.debounce"; -import { Component, ContextType } from "react"; - -import { Wallet } from "../../entities"; -import { ArgsAccount, ArgsError } from "../../shared/lib/args"; -import { Multicall } from "../../shared/lib/contracts/multicall"; -import type { ProposalOutput } from "../../shared/lib/contracts/sputnik-dao"; -import { ProposalStatus, SputnikDAO, SputnikUI } from "../../shared/lib/contracts/sputnik-dao"; -import { Big, toNEAR, toYocto } from "../../shared/lib/converter"; -import { STORAGE } from "../../shared/lib/persistent"; -import { view } from "../../shared/lib/wallet"; -import { Card, Scrollable, Tabs } from "../../shared/ui/components"; -import { TextInput } from "../../widgets/editor/elements"; -import { TokensBalances } from "../../widgets/tokens-balances"; -import "./config/tab.scss"; -import "./funds/tab.scss"; -import "./page.scss"; - -// minimum balance a multicall instance needs for storage + state. -const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR -const Ctx = Wallet.useSelector(); - -interface Props {} - -interface State { - name: ArgsAccount; - dao: SputnikDAO; - multicall: Multicall; - loading: boolean; - proposed: number; - proposedInfo: ProposalOutput; - - info: { - admins: string[]; - tokens: string[]; - jobs: any[]; - jobBond: string; - }; -} - -export class DaoPage extends Component { - static contextType = Ctx; - declare context: ContextType; - - errors: { [key: string]: ArgsError } = { - name: new ArgsError( - "Invalid NEAR address", - (input) => ArgsAccount.isValid(`${input.value}.${SputnikDAO.FACTORY_ADDRESS}`), - !ArgsAccount.isValid(STORAGE.addresses.dao) - ), - noDao: new ArgsError("Sputnik DAO not found on given address", (value) => this.errors.noDao.isBad), - noContract: new ArgsError("DAO has no multicall instance", (value) => this.errors.noContract.isBad), - }; - - loadInfoDebounced = debounce(() => this.loadInfo(), 400); - - lastAddr: string = ""; - // Multicall factory fee. - fee: string = ""; - - constructor(props: Props) { - super(props); - - // split DAO address into parent address and rest (name). - const deconstructedDaoAddress = ArgsAccount.deconstructAddress(STORAGE.addresses.dao); - - this.state = { - name: new ArgsAccount(deconstructedDaoAddress.name), - dao: new SputnikDAO(STORAGE.addresses.dao), - multicall: new Multicall(`${deconstructedDaoAddress.name}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`), - loading: false, - proposed: -1, - proposedInfo: {}, - - info: { - admins: [], - tokens: [], - jobs: [], - jobBond: "...", - }, - }; - - view(window.nearConfig.MULTICALL_FACTORY_ADDRESS, "get_fee", {}).then((createMulticallFee) => { - this.fee = createMulticallFee; - this.loadInfo(); - }); - } - - /** - * check if DAO has a proposal to create multicall instance. - * proposal must be in progress, and not expired. - * - * @returns {object} ID and info of proposal to create multicall instance, - */ - async proposalAlreadyExists(dao: SputnikDAO): Promise<{ proposal_id: number; proposal_info: object }> { - // Date.now() returns timestamp in milliseconds, SputnikDAO uses nanoseconds - const currentTime = Big(Date.now()).times("1000000"); - const lastProposalId = dao.lastProposalId; - const proposalPeriod = dao.policy.proposal_period; - - // get last 100 DAO proposals - const proposals = await dao.getProposals({ - from_index: lastProposalId < 100 ? 0 : lastProposalId - 100, - limit: 100, - }); - // Look for active "Create multicall" proposals - const activeProposals = proposals.filter((proposal) => { - // discard if not active proposal to create multicall instance - if ( - !(proposal.kind?.FunctionCall?.receiver_id === window.nearConfig.MULTICALL_FACTORY_ADDRESS) || - !(proposal.kind?.FunctionCall?.actions?.[0]?.method_name === "create") || - !(proposal.status === ProposalStatus.InProgress) - ) { - return false; - } - // calculate proposal expiration timestamp in nanoseconds - const expirationTime = Big(proposal.submission_time).add(proposalPeriod); - // check if proposal expired - return expirationTime.gt(currentTime) ? true : false; - }); - - // If there many "Create multicall" proposals, return latest. - if (activeProposals.length > 0) { - const lastProposal = activeProposals.pop()!; - return { proposal_id: lastProposal.id, proposal_info: lastProposal }; - } - // No "Create multicall" proposals found. - else return { proposal_id: -1, proposal_info: {} }; - } - - createMulticall() { - const { accountId } = this.context!; - const { loading, dao, proposed, proposedInfo } = this.state; - const { noContract, noDao } = this.errors; - - if ( - this.fee === "" || - // wallet not logged in or DAO object not initialized yet - dao?.ready !== true - ) { - return null; - } - - const depo = Big(this.fee).plus(MIN_INSTANCE_BALANCE); - const daoSearchInput: HTMLInputElement = document.querySelector(".DaoSearch input")!; - - // can user propose a FunctionCall to DAO? - const canPropose = dao.checkUserPermission(accountId!, "AddProposal", "FunctionCall"); - - // can user vote approve a FunctionCall on the DAO? - const canApprove = dao.checkUserPermission(accountId!, "VoteApprove", "FunctionCall"); - - const args = { - proposal: { - description: `create multicall instance for this DAO at ${this.state.multicall.address}`, - - kind: { - FunctionCall: { - receiver_id: window.nearConfig.MULTICALL_FACTORY_ADDRESS, - - actions: [ - { - method_name: "create", - args: Base64.encode( - JSON.stringify({ - multicall_init_args: { - admin_accounts: [dao.address], - croncat_manager: window.nearConfig.CRONCAT_MANAGER_ADDRESS, - job_bond: dao.policy.proposal_bond, - }, - - public_key: "HdJuXFRBKMEXuzEsXVscdd3aoBvEGGXDKQ3JoNhqJ4uU", - }) - ), - - deposit: depo.toFixed(), - gas: "150000000000000", - }, - ], - }, - }, - }, - }; - - if ( - noContract.isBad && - // base.sputnik-dao.near does not exist - !noDao.isBad && - !loading && - // disappear while debouncing - this.lastAddr === daoSearchInput.value - ) { - if (proposed === -1) { - // no create multicall proposal exists - - if (canPropose) { - // ... and user can propose FunctionCall - - return ( - <> -
- {/* hint: you can use "genesis" or "test" as DAO to get to this message */} - {`A multicall instance can only be created for `} - - - {dao.address} - - - {` by making a proposal.`} -
- - - - ); - } else { - // ... and user cannot propose FunctionCall - - return ( -
- {/* hint: you can use "ref-community-board-testnet" as DAO to get to this message */} - {`This DAO has no multicall instance. A DAO member with proposing permissions should make a proposal.`} -
- ); - } - } else if (proposed !== -1) { - // create multicall proposal exists - - if (!canApprove) { - // user does not have rights to VoteApprove - - return ( -
- {`Proposal to create a multicall exists (#${proposed}), but you have no voting permissions on this DAO.`} -
- - Proposal on Astro - -
- ); - } else if (proposedInfo.votes[accountId!]) { - // user can VoteApprove and already voted - - return ( -
- {`You have voted on creating a multicall instance for this DAO. It will be created as soon as the proposal passes voting.`} -
- - Proposal on Astro - -
- ); - } else { - // user can VoteApprove and did NOT vote yet. - - return ( - <> -
- {/* hint: you can use "genesis" or "test" as DAO to get to this message */} - {`There exists a proposal (#${proposed}) to create a multicall instance for this DAO. `} - - - Open on AstroDAO - -
- - - - ); - } - } - } - } - - toLink(address: string, deleteIcon: boolean = false) { - const addr = new ArgsAccount(address); - - return ( - - - {addr.value} - - {deleteIcon ? : null} - - ); - } - - job(job: any) { - return ( -
- - - {job.is_active ? : } -
{JSON.stringify(job, null, "  ")}
-
- ); - } - - loadInfo() { - const { name: nameError, noContract, noDao } = this.errors; - const { name } = this.state; - - const multicallAddress = `${name.value}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}`; - const daoAddress = `${name.value}.${SputnikDAO.FACTORY_ADDRESS}`; - - if (this.lastAddr === name.value) return; - - this.lastAddr = name.value; - noContract.isBad = false; - noDao.isBad = false; - - // chosen address violates NEAR AccountId rules. - if (nameError.isBad) { - noContract.isBad = true; - noDao.isBad = true; - this.setState({ proposed: -1, proposedInfo: {} }); - return; - } - - this.setState({ loading: true }); - - // initialize DAO object - SputnikDAO.init(daoAddress) - // on error, return non-initialized DAO object, as ready = false per default - .catch((e) => new SputnikDAO(daoAddress)) - .then((dao) => { - if (!dao.ready) { - // DAO not ready => either no SputnikDAO contract on the chosen address - // or some error happened during DAO object init. - noContract.isBad = true; - noDao.isBad = true; - this.setState({ dao, multicall: new Multicall(multicallAddress), loading: false }); - return; - } else { - // DAO correctly initialized, try to fetch multicall info - Promise.all([ - view(multicallAddress, "get_admins", {}).catch((e) => { - if (e.type === "AccountDoesNotExist" && e.toString().includes(` ${multicallAddress} `)) { - noContract.isBad = true; - } - }), - - view(multicallAddress, "get_tokens", {}).catch((e) => {}), - view(multicallAddress, "get_jobs", {}).catch((e) => {}), - view(multicallAddress, "get_job_bond", {}).catch((e) => {}), - this.proposalAlreadyExists(dao).catch((e) => {}), - ]).then(([admins, tokens, jobs, jobBond, proposalData]) => - this.setState((prevState) => ({ - dao, - multicall: new Multicall(multicallAddress), - info: { admins, tokens, jobs, jobBond }, - loading: false, - proposed: proposalData?.proposal_id, - proposedInfo: proposalData?.proposal_info || {}, - })) - ); - } - }); - } - - getContent() { - const { selector: walletSelector } = this.context!; - const { dao, info, loading, multicall } = this.state; - - // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) - if (!walletSelector.isSignedIn()) { - return
Please sign in to continue
; - } - - const displayErrorsList = ["name", "noDao", "noContract"]; - - const displayErrors = Object.keys(this.errors) - .filter((e) => this.errors[e].isBad && displayErrorsList.includes(e)) - .map((e) => ( -

- {this.errors[e].isBad ? "\u2717" : "\u2714"} - {this.errors[e].message} -

- )); - - if (displayErrors.length > 0) - return ( - <> -
-
{displayErrors}
- {this.createMulticall()} -
- - ); - - if (loading) return
; - - // everything should be loaded - if (!info.admins || !info.tokens || !info.jobBond) { - console.error("info incomplete", info); - return
Unexpected error! Multicall might be outdated.
; - } - - return ( - - - -

Admins

- -
    - {info.admins.map((admin) => ( -
  • {this.toLink(admin)}
  • - ))} -
-
- - -

Whitelisted Tokens

- -
    - {info.tokens.map((token) => ( -
  • {this.toLink(token)}
  • - ))} -
-
- - - -

Jobs

- {info.jobs.map((j) => this.job(j))} -
- - -

- Job Bond - {`${info.jobBond !== "..." ? toNEAR(info.jobBond) : "..."} Ⓝ`} -

-
-
- ), - }, - { - title: "Funds", - lazy: true, - - content: ( -
- -
- ), - }, - ]} - /> - ); - } - - onAddressesUpdated() { - const { name } = this.state; - const daoAccount = new ArgsAccount(STORAGE.addresses.dao); - if (!(name.value === daoAccount.deconstructAddress().name)) { - this.setState( - { - name: new ArgsAccount(daoAccount.deconstructAddress().name), - - multicall: new Multicall( - `${daoAccount.deconstructAddress().name}.${window.nearConfig.MULTICALL_FACTORY_ADDRESS}` - ), - }, - - () => { - this.errors.name.validOrNull(daoAccount); - this.loadInfo(); - this.forceUpdate(); - } - ); - } - } - - componentDidMount(): void { - window.PAGE = "dao"; - document.addEventListener("onaddressesupdated", () => this.onAddressesUpdated()); - } - - render() { - const { name } = this.state; - - return ( -
-
-
- { - const fullDaoAddr = `${name.value}.${SputnikDAO.FACTORY_ADDRESS}`; - const daoAccount = new ArgsAccount(fullDaoAddr); - if (daoAccount.isValid()) { - this.loadInfoDebounced(); - } - this.forceUpdate(); - }} - InputProps={{ - endAdornment: ( - {`.${SputnikDAO.FACTORY_ADDRESS}`} - ), - }} - /> -
-
- - {this.getContent()} -
- ); - } -} +export { DaoPage } from "./dao"; diff --git a/src/shared/ui/components/card/index.tsx b/src/shared/ui/components/card/index.tsx deleted file mode 100644 index a0b201fc..00000000 --- a/src/shared/ui/components/card/index.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import clsx from "clsx"; -import { HTMLAttributes, PropsWithChildren } from "react"; - -import "./card.scss"; - -const _Card = "Card"; - -export interface CardProps extends PropsWithChildren, HTMLAttributes {} - -export const Card = ({ children, className }: CardProps) =>
{children}
; diff --git a/src/shared/ui/components/dialog/index.tsx b/src/shared/ui/components/dialog/dialog.tsx similarity index 100% rename from src/shared/ui/components/dialog/index.tsx rename to src/shared/ui/components/dialog/dialog.tsx diff --git a/src/shared/ui/components/dialog/index.ts b/src/shared/ui/components/dialog/index.ts new file mode 100644 index 00000000..bca0c2f7 --- /dev/null +++ b/src/shared/ui/components/dialog/index.ts @@ -0,0 +1 @@ +export { Dialog } from "./dialog"; diff --git a/src/shared/ui/components/card/card.scss b/src/shared/ui/components/facet/facet.scss similarity index 99% rename from src/shared/ui/components/card/card.scss rename to src/shared/ui/components/facet/facet.scss index 9af9ea9c..d4297eef 100644 --- a/src/shared/ui/components/card/card.scss +++ b/src/shared/ui/components/facet/facet.scss @@ -1,7 +1,7 @@ @use "sass/size"; @use "sass/color"; -.Card { +.Facet { display: flex; flex-flow: column nowrap; position: relative; diff --git a/src/shared/ui/components/facet/facet.tsx b/src/shared/ui/components/facet/facet.tsx new file mode 100644 index 00000000..c4ccb68a --- /dev/null +++ b/src/shared/ui/components/facet/facet.tsx @@ -0,0 +1,10 @@ +import clsx from "clsx"; +import { HTMLAttributes, PropsWithChildren } from "react"; + +import "./facet.scss"; + +const _Facet = "Facet"; + +export interface FacetProps extends PropsWithChildren, HTMLAttributes {} + +export const Facet = ({ children, className }: FacetProps) =>
{children}
; diff --git a/src/shared/ui/components/facet/index.ts b/src/shared/ui/components/facet/index.ts new file mode 100644 index 00000000..84f0c3bc --- /dev/null +++ b/src/shared/ui/components/facet/index.ts @@ -0,0 +1 @@ +export { Facet } from "./facet"; diff --git a/src/shared/ui/components/icons/index.ts b/src/shared/ui/components/icons/index.ts index 0ec44ea6..1ce1b82d 100644 --- a/src/shared/ui/components/icons/index.ts +++ b/src/shared/ui/components/icons/index.ts @@ -1 +1 @@ -export { NearIcons } from "./near"; +export { NearIcons } from "./near/near"; diff --git a/src/shared/ui/components/icons/near.scss b/src/shared/ui/components/icons/near/near.scss similarity index 100% rename from src/shared/ui/components/icons/near.scss rename to src/shared/ui/components/icons/near/near.scss diff --git a/src/shared/ui/components/icons/near.tsx b/src/shared/ui/components/icons/near/near.tsx similarity index 100% rename from src/shared/ui/components/icons/near.tsx rename to src/shared/ui/components/icons/near/near.tsx diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 232cc929..5b3d64d2 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,9 +1,9 @@ -export { Card } from "./card"; -export { Dialog } from "./dialog"; +export { Facet } from "./facet/facet"; +export { Dialog } from "./dialog/dialog"; export * from "./icons"; -export { PopupMenu } from "./popup-menu"; -export { Scrollable } from "./scrollable"; -export { Table } from "./table"; -export { Tabs } from "./tabs"; -export { TokenLabel } from "./token-label"; -export { Tooltip } from "./tooltip"; +export { PopupMenu } from "./popup-menu/popup-menu"; +export { Scrollable } from "./scrollable/scrollable"; +export { Table } from "./table/table"; +export { Tabs } from "./tabs/tabs"; +export { TokenLabel } from "./token-label/token-label"; +export { Tooltip } from "./tooltip/tooltip"; diff --git a/src/shared/ui/components/popup-menu/index.ts b/src/shared/ui/components/popup-menu/index.ts new file mode 100644 index 00000000..f46d5fcd --- /dev/null +++ b/src/shared/ui/components/popup-menu/index.ts @@ -0,0 +1 @@ +export { PopupMenu } from "./popup-menu"; diff --git a/src/shared/ui/components/popup-menu/index.tsx b/src/shared/ui/components/popup-menu/popup-menu.tsx similarity index 100% rename from src/shared/ui/components/popup-menu/index.tsx rename to src/shared/ui/components/popup-menu/popup-menu.tsx diff --git a/src/shared/ui/components/scrollable/index.ts b/src/shared/ui/components/scrollable/index.ts new file mode 100644 index 00000000..03604bdb --- /dev/null +++ b/src/shared/ui/components/scrollable/index.ts @@ -0,0 +1 @@ +export { Scrollable } from "./scrollable"; diff --git a/src/shared/ui/components/scrollable/index.tsx b/src/shared/ui/components/scrollable/scrollable.tsx similarity index 100% rename from src/shared/ui/components/scrollable/index.tsx rename to src/shared/ui/components/scrollable/scrollable.tsx diff --git a/src/shared/ui/components/table/index.ts b/src/shared/ui/components/table/index.ts new file mode 100644 index 00000000..8efc4312 --- /dev/null +++ b/src/shared/ui/components/table/index.ts @@ -0,0 +1 @@ +export { Table } from "./table"; diff --git a/src/shared/ui/components/table/index.tsx b/src/shared/ui/components/table/table.tsx similarity index 100% rename from src/shared/ui/components/table/index.tsx rename to src/shared/ui/components/table/table.tsx diff --git a/src/shared/ui/components/tabs/index.ts b/src/shared/ui/components/tabs/index.ts new file mode 100644 index 00000000..aee02207 --- /dev/null +++ b/src/shared/ui/components/tabs/index.ts @@ -0,0 +1 @@ +export { Tabs } from "./tabs"; diff --git a/src/shared/ui/components/tabs/index.tsx b/src/shared/ui/components/tabs/tabs.tsx similarity index 100% rename from src/shared/ui/components/tabs/index.tsx rename to src/shared/ui/components/tabs/tabs.tsx diff --git a/src/shared/ui/components/token-label/index.ts b/src/shared/ui/components/token-label/index.ts new file mode 100644 index 00000000..fe3c7ada --- /dev/null +++ b/src/shared/ui/components/token-label/index.ts @@ -0,0 +1 @@ +export { TokenLabel } from "./token-label"; diff --git a/src/shared/ui/components/token-label/index.tsx b/src/shared/ui/components/token-label/token-label.tsx similarity index 100% rename from src/shared/ui/components/token-label/index.tsx rename to src/shared/ui/components/token-label/token-label.tsx diff --git a/src/shared/ui/components/tooltip/index.ts b/src/shared/ui/components/tooltip/index.ts new file mode 100644 index 00000000..8402f319 --- /dev/null +++ b/src/shared/ui/components/tooltip/index.ts @@ -0,0 +1 @@ +export { Tooltip } from "./tooltip"; diff --git a/src/shared/ui/components/tooltip/index.tsx b/src/shared/ui/components/tooltip/tooltip.tsx similarity index 100% rename from src/shared/ui/components/tooltip/index.tsx rename to src/shared/ui/components/tooltip/tooltip.tsx diff --git a/src/widgets/builder/index.ts b/src/widgets/builder/index.ts new file mode 100644 index 00000000..74fe9466 --- /dev/null +++ b/src/widgets/builder/index.ts @@ -0,0 +1 @@ +export { Builder } from "./builder"; diff --git a/src/widgets/column/column.jsx b/src/widgets/column/column.jsx index ec328670..f31f5468 100644 --- a/src/widgets/column/column.jsx +++ b/src/widgets/column/column.jsx @@ -55,7 +55,7 @@ export class Column extends Component { {...provided.droppableProps} > {this.props.tasks.map((task, index) => ( - +

Token Balances

{!nativeTokenBalance || !fungibleTokensBalances ? ( @@ -25,6 +25,6 @@ export const TokensBalances = ({ className, daoContracts }: TokensBalancesProps) /> )} - +
); }; From a6a2424e72837bbfe6fd83bf51c506fa923b30a4 Mon Sep 17 00:00:00 2001 From: Dali Chelbi Date: Sun, 2 Oct 2022 03:38:53 +0200 Subject: [PATCH 128/537] remove event listeners on component unmount --- src/families/base.jsx | 6 +++++- src/pages/dao/dao.tsx | 6 +++++- src/widgets/export/export.jsx | 6 +++++- src/widgets/layout/layout.jsx | 6 +++++- src/widgets/menu/menu.jsx | 6 +++++- src/widgets/sidebar/sidebar.jsx | 6 +++++- 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/families/base.jsx b/src/families/base.jsx index da7830a8..9b5d0229 100644 --- a/src/families/base.jsx +++ b/src/families/base.jsx @@ -59,7 +59,7 @@ export class BaseTask extends Component { this.updateCard = this.updateCard.bind(this); - document.addEventListener("onaddressesupdated", (e) => this.onAddressesUpdated(e)); + document.addEventListener("onaddressesupdated", this.onAddressesUpdated); this.updateContract(); } @@ -127,6 +127,10 @@ export class BaseTask extends Component { this.forceUpdate(); } + componentWillUnmount() { + document.removeEventListener("onaddressesupdated", this.onAddressesUpdated); + } + onAddressesUpdated() {} onEditFocus(taskID) { diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 4c081e7f..80c3112a 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -523,7 +523,11 @@ export class DaoPage extends Component { componentDidMount(): void { window.PAGE = "dao"; - document.addEventListener("onaddressesupdated", () => this.onAddressesUpdated()); + document.addEventListener("onaddressesupdated", this.onAddressesUpdated); + } + + componentWillUnmount() { + document.removeEventListener("onaddressesupdated", this.onAddressesUpdated); } render() { diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index f6371f8c..221e2b7c 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -58,13 +58,17 @@ export class Export extends Component { this.update = this.update.bind(this); - document.addEventListener("onaddressesupdated", (e) => this.onAddressesUpdated(e)); + document.addEventListener("onaddressesupdated", this.onAddressesUpdated); } componentDidMount() { window.EXPORT = this; } + componentWillUnmount() { + document.removeEventListener("onaddressesupdated", this.onAddressesUpdated); + } + onAddressesUpdated() { this.updateFT(); } diff --git a/src/widgets/layout/layout.jsx b/src/widgets/layout/layout.jsx index d7a52784..e0f08f2f 100644 --- a/src/widgets/layout/layout.jsx +++ b/src/widgets/layout/layout.jsx @@ -18,7 +18,7 @@ export class Layout extends Component { this.clear(); - document.addEventListener("onlayoutupdated", () => this.forceUpdate()); + document.addEventListener("onlayoutupdated", this.forceUpdate); } componentDidMount() { @@ -26,6 +26,10 @@ export class Layout extends Component { STORAGE.load(); } + componentWillUnmount() { + document.removeEventListener("onlayoutupdated", this.forceUpdate); + } + getTaskID = () => this.taskID; getColumnID = () => this.columnID; diff --git a/src/widgets/menu/menu.jsx b/src/widgets/menu/menu.jsx index af959a14..0a476488 100644 --- a/src/widgets/menu/menu.jsx +++ b/src/widgets/menu/menu.jsx @@ -17,13 +17,17 @@ export class Menu extends Component { activeTabIndex: 0, }; - document.addEventListener("onaddressesupdated", () => this.forceUpdate()); + document.addEventListener("onaddressesupdated", this.forceUpdate); } componentDidMount() { window.MENU = this; } + componentWillUnmount() { + document.removeEventListener("onaddressesupdated", this.forceUpdate); + } + activeTabSwitch = (newTabIndex) => this.setState({ activeTabIndex: newTabIndex }); render() { diff --git a/src/widgets/sidebar/sidebar.jsx b/src/widgets/sidebar/sidebar.jsx index e456d666..e5340e9e 100644 --- a/src/widgets/sidebar/sidebar.jsx +++ b/src/widgets/sidebar/sidebar.jsx @@ -56,7 +56,11 @@ export class Sidebar extends Component { componentDidMount() { window.SIDEBAR = this; - document.addEventListener("onaddressesupdated", () => this.forceUpdate()); + document.addEventListener("onaddressesupdated", this.forceUpdate); + } + + componentWillUnmount() { + document.removeEventListener("onaddressesupdated", this.forceUpdate); } componentDidUpdate(_, previousState) { From d7a2674f0d97dbefd086c533c2ed9c71bcdd12d4 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sun, 2 Oct 2022 03:50:49 +0200 Subject: [PATCH 129/537] split actions generation and TX signing. Add basic jobs export example --- src/components/dao/dao.tsx | 5 +- src/components/export/export.jsx | 177 ++++++++++++++++------- src/components/wallet/wallet.jsx | 2 +- src/utils/contracts/multicall.ts | 44 +++--- src/utils/contracts/sputnik-dao.ts | 79 ++++++---- src/utils/standards/storageManagement.ts | 35 +++-- src/utils/wallet.ts | 31 +--- 7 files changed, 231 insertions(+), 142 deletions(-) diff --git a/src/components/dao/dao.tsx b/src/components/dao/dao.tsx index 1319c180..0ef592a8 100644 --- a/src/components/dao/dao.tsx +++ b/src/components/dao/dao.tsx @@ -9,6 +9,7 @@ import { ArgsAccount, ArgsError } from "../../utils/args"; import { STORAGE } from "../../utils/persistent"; import { toNEAR, toYocto, toGas, Big } from "../../utils/converter"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; +import { signAndSendTxs } from "../../utils/wallet"; import { SputnikDAO, SputnikUI, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; import { Multicall } from "../../utils/contracts/multicall"; import { Card, Scrollable, Tabs } from "../../shared/ui/components"; @@ -199,7 +200,7 @@ export class Dao extends Component {

or

- {this.attachNEAR ? ( + {attachNEAR ? ( ) : null} - {this.attachFT ? ( + {attachFT ? ( <> ) : null} + + Execution: + { + if (value === "immediate") this.setState({ useJobs: false }); + else if (value === "scheduled") this.setState({ useJobs: true }); + }} + > + } + label="Immediate" + /> + } + label="Scheduled" + /> + +
{/* Display cards' errors */} {allErrors.length > 0 && ( @@ -361,12 +436,12 @@ export class Export extends Component { this.toggleShowArgs()} - collapsed={this.showArgs ? "no" : "yes"} + collapsed={showArgs ? "no" : "yes"} > expand_more

this.toggleShowArgs()}>Multicall args

- {this.showArgs ? ( + {showArgs ? ( { @@ -380,7 +455,7 @@ export class Export extends Component { <> )}
- {this.showArgs ? ( + {showArgs ? (
{multicallArgsText}
diff --git a/src/components/wallet/wallet.jsx b/src/components/wallet/wallet.jsx index 24838684..1c2584db 100644 --- a/src/components/wallet/wallet.jsx +++ b/src/components/wallet/wallet.jsx @@ -1,6 +1,6 @@ // TODO: use Multical helper class to fetch & store infos, like admins, tokens etc... -import React, { Component } from "react"; +import { Component } from "react"; import { STORAGE } from "../../utils/persistent"; import { useWalletSelector } from "../../contexts/walletSelectorContext"; import { SputnikDAO, ProposalKind, ProposalAction } from "../../utils/contracts/sputnik-dao"; diff --git a/src/utils/contracts/multicall.ts b/src/utils/contracts/multicall.ts index 8d234f48..385ccbd1 100644 --- a/src/utils/contracts/multicall.ts +++ b/src/utils/contracts/multicall.ts @@ -1,7 +1,8 @@ -import { viewAccount, viewState, view, tx } from "../wallet"; +import { viewAccount, viewState, view } from "../wallet"; import { Big, toGas, dateToCron } from "../converter"; import type { FunctionCallAction as daoFunctionCallAction } from "./sputnik-dao"; +import type { Tx } from "../wallet"; const FACTORY_ADDRESS_SELECTOR: Record = { mainnet: "v1.multicall.near", @@ -18,6 +19,7 @@ const CONTRACT_CODE_HASHES_SELECTOR: Record = { ], }; +// Storage key of job count used by the contract const KEY_JOB_COUNT: string = "g"; // Schema for Multicall jobs @@ -232,29 +234,31 @@ class Multicall { * @param totalBudget Total fee to be paid to Croncat agents. * @returns */ - async addJob( - multicalls: MulticallArgs[], - triggerDate: Date, - triggerGas: string, - totalBudget: string - ): Promise { + async addJob(multicalls: MulticallArgs[], triggerDate: Date, triggerGas: string, totalBudget: string): Promise { // crontab in CronCat format. See: https://github.com/CronCats/Schedule const cadence: string = dateToCron(triggerDate); // timestamp as required by NEAR chain (UTC, in nanoseconds) const startAt: string = Big(triggerDate.getTime()).times("1000000").toFixed(); - return tx( - this.address, - "job_add", - { - job_multicalls: multicalls, - job_cadence: cadence, - job_trigger_gas: triggerGas, - job_total_budget: totalBudget, - job_start_at: startAt, - }, - toGas("25"), - this.jobBond - ); + return { + receiverId: this.address, + actions: [ + { + type: "FunctionCall", + params: { + methodName: "job_add", + args: { + job_multicalls: multicalls, + job_cadence: cadence, + job_trigger_gas: triggerGas, + job_total_budget: totalBudget, + job_start_at: startAt, + }, + gas: toGas("25"), + deposit: this.jobBond, + }, + }, + ], + }; } } diff --git a/src/utils/contracts/sputnik-dao.ts b/src/utils/contracts/sputnik-dao.ts index 311dcfbf..abd872cb 100644 --- a/src/utils/contracts/sputnik-dao.ts +++ b/src/utils/contracts/sputnik-dao.ts @@ -1,6 +1,6 @@ // TODO: use token functions in proposeMulticallFT -import { tx, view, viewAccount } from "../wallet"; +import { signAndSendTxs, view, viewAccount } from "../wallet"; import { toGas, Big } from "../converter"; import { ArgsAccount } from "../args"; import { STORAGE } from "../../utils/persistent"; @@ -8,6 +8,7 @@ import { Base64 } from "js-base64"; import { FungibleToken } from "../standards/fungibleToken"; import type { MulticallArgs } from "./multicall"; +import type { Tx } from "../wallet"; const FACTORY_ADDRESS_SELECTOR: Record = { mainnet: "sputnik-dao.near", @@ -174,24 +175,38 @@ class SputnikDAO { return SputnikDAO.CONTRACT_CODE_HASHES.includes(codeHash); } - async addProposal(args: object | Uint8Array) { - return tx( - this.address, - "add_proposal", - args, - toGas("50"), // 50 Tgas - this.policy.proposal_bond - ); + async addProposal(args: object | Uint8Array): Promise { + return { + receiverId: this.address, + actions: [ + { + type: "FunctionCall", + params: { + methodName: "add_proposal", + args, + gas: toGas("50"), // 50 Tgas + deposit: this.policy.proposal_bond, + }, + }, + ], + }; } - async actProposal(proposal_id: number, proposal_action: string) { - return tx( - this.address, - "act_proposal", - { id: proposal_id, action: proposal_action }, - toGas("200"), // 200 Tgas - "0" - ); + async actProposal(proposal_id: number, proposal_action: string): Promise { + return { + receiverId: this.address, + actions: [ + { + type: "FunctionCall", + params: { + methodName: "act_proposal", + args: { id: proposal_id, action: proposal_action }, + gas: toGas("200"), // 200 Tgas, + deposit: "0", + }, + }, + ], + }; } async getProposals(args: { from_index: number; limit: number }): Promise { @@ -336,7 +351,7 @@ class SputnikDAO { } // propose a generic function call to DAO. - async proposeFunctionCall(desc: string, pTarget: string, pActions: FunctionCallAction[]): Promise { + async proposeFunctionCall(desc: string, pTarget: string, pActions: FunctionCallAction[]): Promise { const proposalArgs = { proposal: { description: desc, @@ -353,8 +368,8 @@ class SputnikDAO { }, }; - // fire the add_proposal transaction - this.addProposal(proposalArgs); + // return the add_proposal transaction + return this.addProposal(proposalArgs); } /** @@ -365,7 +380,7 @@ class SputnikDAO { * @param {string} depo NEAR amount to be attached to multicall * @param {string} gas Gas amount dedicated to multicall execution */ - async proposeMulticall(desc: string, multicallArgs: MulticallArgs, depo: string, gas: string): Promise { + async proposeMulticall(desc: string, multicallArgs: MulticallArgs, depo: string, gas: string): Promise { const { multicall } = STORAGE.addresses; const callActions: FunctionCallAction[] = [ @@ -377,8 +392,8 @@ class SputnikDAO { }, ]; - // fire the add_proposal transaction - this.proposeFunctionCall(desc, multicall, callActions); + // return the add_proposal transaction + return this.proposeFunctionCall(desc, multicall, callActions); } /** @@ -388,7 +403,7 @@ class SputnikDAO { * @param {number} jobId ID of job to be activated * @param {string} depo NEAR amount to be attached to job activation */ - async proposeJobActivation(desc: string, jobId: number, depo: string): Promise { + async proposeJobActivation(desc: string, jobId: number, depo: string): Promise { const { multicall } = STORAGE.addresses; const callActions: FunctionCallAction[] = [ @@ -400,8 +415,8 @@ class SputnikDAO { }, ]; - // fire the add_proposal transaction - this.proposeFunctionCall(desc, multicall, callActions); + // return the add_proposal transaction + return this.proposeFunctionCall(desc, multicall, callActions); } /** @@ -419,7 +434,7 @@ class SputnikDAO { gas: string, tokenAddress: string, amount: string - ): Promise { + ): Promise { const { multicall } = STORAGE.addresses; const token = new FungibleToken(tokenAddress); @@ -460,8 +475,8 @@ class SputnikDAO { }); } - // fire the add_proposal transaction - this.proposeFunctionCall(desc, tokenAddress, actions); + // return the add_proposal transaction + return this.proposeFunctionCall(desc, tokenAddress, actions); } /** @@ -472,7 +487,7 @@ class SputnikDAO { * @param {string} tokenAddress attached FT address * @param {string} amount attached FT amount */ - async proposeJobActivationFT(desc: string, jobId: number, tokenAddress: string, amount: string): Promise { + async proposeJobActivationFT(desc: string, jobId: number, tokenAddress: string, amount: string): Promise { const { multicall } = STORAGE.addresses; const token = new FungibleToken(tokenAddress); @@ -513,8 +528,8 @@ class SputnikDAO { }); } - // fire the add_proposal transaction - this.proposeFunctionCall(desc, tokenAddress, actions); + // return the add_proposal transaction + return this.proposeFunctionCall(desc, tokenAddress, actions); } } diff --git a/src/utils/standards/storageManagement.ts b/src/utils/standards/storageManagement.ts index 30f49cf0..91858d0d 100644 --- a/src/utils/standards/storageManagement.ts +++ b/src/utils/standards/storageManagement.ts @@ -1,5 +1,7 @@ -import { tx, view } from "../wallet"; -import { toGas, toYocto } from "../converter"; +import { view } from "../wallet"; +import { toGas } from "../converter"; + +import type { Tx } from "../wallet"; // Storage management standard follow NEP-145. See: https://nomicon.io/Standards/StorageManagement class StorageManagement { @@ -47,17 +49,24 @@ class StorageManagement { // // Returns the StorageBalance structure showing updated balances. // IMPORTANT!!! This method has an extra parameter "amount" to control the amount in attached deposit - async storageDeposit(accountId: string, registrationOnly: boolean, amount: string): Promise { - return tx( - this.address, - "storage_deposit", - { - account_id: accountId, - registration_only: registrationOnly, - }, - toGas("5"), // 5 Tgas - amount - ); + async storageDeposit(accountId: string, registrationOnly: boolean, amount: string): Promise { + return { + receiverId: this.address, + actions: [ + { + type: "FunctionCall", + params: { + methodName: "storage_deposit", + args: { + account_id: accountId, + registration_only: registrationOnly, + }, + gas: toGas("5"), // 5 Tgas; + deposit: amount, + }, + }, + ], + }; } // Withdraw specified amount of available Ⓝ for predecessor account. diff --git a/src/utils/wallet.ts b/src/utils/wallet.ts index 28997da4..64bdc2d6 100644 --- a/src/utils/wallet.ts +++ b/src/utils/wallet.ts @@ -1,10 +1,10 @@ // TODO: de-deprecate near-wallet on wallet selector. Use patch import { providers } from "near-api-js"; -import type { NetworkId } from "@near-wallet-selector/core"; import { getConfig } from "../near-config"; import { Base64 } from "js-base64"; import type { AccountView, ViewStateResult } from "near-api-js/lib/providers/provider"; +import type { NetworkId, Transaction } from "@near-wallet-selector/core"; declare global { interface Window { @@ -13,6 +13,8 @@ declare global { } } +type Tx = Omit; + window.NEAR_ENV = process.env.NEAR_ENV ?? "testnet"; window.nearConfig = getConfig(window.NEAR_ENV); // create RPC Provider object. @@ -20,13 +22,8 @@ const rpcProvider = new providers.JsonRpcProvider({ url: window.nearConfig.nodeUrl, }); -async function tx( - addr: string, - func: string, - args: object | Uint8Array, - gas: string, - depo: string = "0" -): Promise { +async function signAndSendTxs(txs: Tx[]): Promise { + if (txs.length < 1) return; // is user logged in? if (!window.selector.isSignedIn()) { console.error("Wallet not connected"); @@ -36,20 +33,7 @@ async function tx( // get wallet from wallet selector const wallet = await window.selector.wallet(); - return wallet.signAndSendTransaction({ - receiverId: addr, - actions: [ - { - type: "FunctionCall", - params: { - methodName: func, - args: args, - gas: gas, - deposit: depo, - }, - }, - ], - }); + return wallet.signAndSendTransactions({ transactions: txs }); } /** @@ -118,4 +102,5 @@ async function viewState( })); } -export { tx, view, viewAccount, viewState, rpcProvider }; +export { signAndSendTxs, view, viewAccount, viewState, rpcProvider }; +export type { Tx }; From 7f93789beb296976782e202fc4dec543762d774c Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sun, 2 Oct 2022 21:11:27 +0200 Subject: [PATCH 130/537] Revert "remove event listeners on component unmount" This reverts commit a6a2424e72837bbfe6fd83bf51c506fa923b30a4. --- src/families/base.jsx | 6 +----- src/pages/dao/dao.tsx | 6 +----- src/widgets/export/export.jsx | 6 +----- src/widgets/layout/layout.jsx | 6 +----- src/widgets/menu/menu.jsx | 6 +----- src/widgets/sidebar/sidebar.jsx | 6 +----- 6 files changed, 6 insertions(+), 30 deletions(-) diff --git a/src/families/base.jsx b/src/families/base.jsx index 9b5d0229..da7830a8 100644 --- a/src/families/base.jsx +++ b/src/families/base.jsx @@ -59,7 +59,7 @@ export class BaseTask extends Component { this.updateCard = this.updateCard.bind(this); - document.addEventListener("onaddressesupdated", this.onAddressesUpdated); + document.addEventListener("onaddressesupdated", (e) => this.onAddressesUpdated(e)); this.updateContract(); } @@ -127,10 +127,6 @@ export class BaseTask extends Component { this.forceUpdate(); } - componentWillUnmount() { - document.removeEventListener("onaddressesupdated", this.onAddressesUpdated); - } - onAddressesUpdated() {} onEditFocus(taskID) { diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 80c3112a..4c081e7f 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -523,11 +523,7 @@ export class DaoPage extends Component { componentDidMount(): void { window.PAGE = "dao"; - document.addEventListener("onaddressesupdated", this.onAddressesUpdated); - } - - componentWillUnmount() { - document.removeEventListener("onaddressesupdated", this.onAddressesUpdated); + document.addEventListener("onaddressesupdated", () => this.onAddressesUpdated()); } render() { diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index 221e2b7c..f6371f8c 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -58,17 +58,13 @@ export class Export extends Component { this.update = this.update.bind(this); - document.addEventListener("onaddressesupdated", this.onAddressesUpdated); + document.addEventListener("onaddressesupdated", (e) => this.onAddressesUpdated(e)); } componentDidMount() { window.EXPORT = this; } - componentWillUnmount() { - document.removeEventListener("onaddressesupdated", this.onAddressesUpdated); - } - onAddressesUpdated() { this.updateFT(); } diff --git a/src/widgets/layout/layout.jsx b/src/widgets/layout/layout.jsx index e0f08f2f..d7a52784 100644 --- a/src/widgets/layout/layout.jsx +++ b/src/widgets/layout/layout.jsx @@ -18,7 +18,7 @@ export class Layout extends Component { this.clear(); - document.addEventListener("onlayoutupdated", this.forceUpdate); + document.addEventListener("onlayoutupdated", () => this.forceUpdate()); } componentDidMount() { @@ -26,10 +26,6 @@ export class Layout extends Component { STORAGE.load(); } - componentWillUnmount() { - document.removeEventListener("onlayoutupdated", this.forceUpdate); - } - getTaskID = () => this.taskID; getColumnID = () => this.columnID; diff --git a/src/widgets/menu/menu.jsx b/src/widgets/menu/menu.jsx index 0a476488..af959a14 100644 --- a/src/widgets/menu/menu.jsx +++ b/src/widgets/menu/menu.jsx @@ -17,17 +17,13 @@ export class Menu extends Component { activeTabIndex: 0, }; - document.addEventListener("onaddressesupdated", this.forceUpdate); + document.addEventListener("onaddressesupdated", () => this.forceUpdate()); } componentDidMount() { window.MENU = this; } - componentWillUnmount() { - document.removeEventListener("onaddressesupdated", this.forceUpdate); - } - activeTabSwitch = (newTabIndex) => this.setState({ activeTabIndex: newTabIndex }); render() { diff --git a/src/widgets/sidebar/sidebar.jsx b/src/widgets/sidebar/sidebar.jsx index e5340e9e..e456d666 100644 --- a/src/widgets/sidebar/sidebar.jsx +++ b/src/widgets/sidebar/sidebar.jsx @@ -56,11 +56,7 @@ export class Sidebar extends Component { componentDidMount() { window.SIDEBAR = this; - document.addEventListener("onaddressesupdated", this.forceUpdate); - } - - componentWillUnmount() { - document.removeEventListener("onaddressesupdated", this.forceUpdate); + document.addEventListener("onaddressesupdated", () => this.forceUpdate()); } componentDidUpdate(_, previousState) { From b9cc78f3ba639636b677482578ad04a57dd39058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 08:39:37 +0400 Subject: [PATCH 131/537] chore: Change file extension --- src/pages/dao/{index.tsx => index.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/pages/dao/{index.tsx => index.ts} (100%) diff --git a/src/pages/dao/index.tsx b/src/pages/dao/index.ts similarity index 100% rename from src/pages/dao/index.tsx rename to src/pages/dao/index.ts From 010eea38c66d3fad222bf984d62ba82d11d88188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 08:55:58 +0400 Subject: [PATCH 132/537] fix: Add workaround to solve issues with Parcel cache --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2fbf131f..dfc3d635 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "build:mainnet": "NEAR_ENV=mainnet yarn build", "deploy:pages": "echo 'testnet.multicall.app' > ./dist/CNAME && gh-pages -d dist/", "deploy": "yarn build && yarn deploy:pages", - "start": "echo 'The app is starting! It will automatically open in your browser when ready' && parcel src/index.html --open", + "start": "rm -rf .parcel-cache && echo 'The app is starting! It will automatically open in your browser when ready' && parcel src/index.html --open", "start:testnet": "NEAR_ENV=testnet yarn start", "start:mainnet": "NEAR_ENV=mainnet yarn start", "test": "jest test --runInBand", From 26805c9a3bcfc62518b0618cd7cba035f9a0494b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 09:01:02 +0400 Subject: [PATCH 133/537] chore: Use separation of concerns --- src/entities/fungible-token/index.ts | 2 +- .../model/{fungible-token.ts => fungible-token-balances.ts} | 0 .../ui/{fungible-token.tsx => fungible-token-balances.tsx} | 2 +- src/entities/native-token/index.ts | 2 +- .../model/{native-token.ts => native-token-balances.ts} | 0 .../ui/{native-token.tsx => native-token-balances.tsx} | 2 +- 6 files changed, 4 insertions(+), 4 deletions(-) rename src/entities/fungible-token/model/{fungible-token.ts => fungible-token-balances.ts} (100%) rename src/entities/fungible-token/ui/{fungible-token.tsx => fungible-token-balances.tsx} (98%) rename src/entities/native-token/model/{native-token.ts => native-token-balances.ts} (100%) rename src/entities/native-token/ui/{native-token.tsx => native-token-balances.tsx} (85%) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index e45f614d..a8a841b7 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,4 +1,4 @@ -import { fungibleTokensBalancesRender } from "./ui/fungible-token"; +import { fungibleTokensBalancesRender } from "./ui/fungible-token-balances"; export class FungibleToken { static allBalancesRender = fungibleTokensBalancesRender; diff --git a/src/entities/fungible-token/model/fungible-token.ts b/src/entities/fungible-token/model/fungible-token-balances.ts similarity index 100% rename from src/entities/fungible-token/model/fungible-token.ts rename to src/entities/fungible-token/model/fungible-token-balances.ts diff --git a/src/entities/fungible-token/ui/fungible-token.tsx b/src/entities/fungible-token/ui/fungible-token-balances.tsx similarity index 98% rename from src/entities/fungible-token/ui/fungible-token.tsx rename to src/entities/fungible-token/ui/fungible-token-balances.tsx index a0d6addd..9099d5ad 100644 --- a/src/entities/fungible-token/ui/fungible-token.tsx +++ b/src/entities/fungible-token/ui/fungible-token-balances.tsx @@ -1,7 +1,7 @@ import { TokenLabel } from "../../../shared/ui/components"; import type { DaoContracts } from "../../types"; import { FungibleTokenFormat } from "../lib/format"; -import { FungibleTokenBalancesModel } from "../model/fungible-token"; +import { FungibleTokenBalancesModel } from "../model/fungible-token-balances"; interface FungibleTokensBalancesRenderProps { daoContracts: DaoContracts; diff --git a/src/entities/native-token/index.ts b/src/entities/native-token/index.ts index 6430194e..f066a47b 100644 --- a/src/entities/native-token/index.ts +++ b/src/entities/native-token/index.ts @@ -1,4 +1,4 @@ -import { nativeTokenBalancesRender } from "./ui/native-token"; +import { nativeTokenBalancesRender } from "./ui/native-token-balances"; export class NativeToken { static balancesRender = nativeTokenBalancesRender; diff --git a/src/entities/native-token/model/native-token.ts b/src/entities/native-token/model/native-token-balances.ts similarity index 100% rename from src/entities/native-token/model/native-token.ts rename to src/entities/native-token/model/native-token-balances.ts diff --git a/src/entities/native-token/ui/native-token.tsx b/src/entities/native-token/ui/native-token-balances.tsx similarity index 85% rename from src/entities/native-token/ui/native-token.tsx rename to src/entities/native-token/ui/native-token-balances.tsx index 089ec38f..52d0f2e4 100644 --- a/src/entities/native-token/ui/native-token.tsx +++ b/src/entities/native-token/ui/native-token-balances.tsx @@ -1,6 +1,6 @@ import { TokenLabel } from "../../../shared/ui/components"; import type { DaoContracts } from "../../types"; -import { NativeTokenBalancesModel } from "../model/native-token"; +import { NativeTokenBalancesModel } from "../model/native-token-balances"; interface NativeTokenBalancesRenderProps { daoContracts: DaoContracts; From ca616511c27429d0155c8b5786c087b961bfe82a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 09:08:03 +0400 Subject: [PATCH 134/537] fix: Use nullish coalescing operator --- src/shared/ui/components/dialog/dialog.tsx | 4 ++-- src/shared/ui/components/table/row.tsx | 2 +- src/shared/ui/components/table/table.tsx | 2 +- src/widgets/tokens-balances/ui/token-balances.tsx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/shared/ui/components/dialog/dialog.tsx b/src/shared/ui/components/dialog/dialog.tsx index 8a11d27a..8bdcde5c 100644 --- a/src/shared/ui/components/dialog/dialog.tsx +++ b/src/shared/ui/components/dialog/dialog.tsx @@ -53,7 +53,7 @@ export const Dialog = ({ onClose?.(); }} > - {cancelRename || "Cancel"} + {cancelRename ?? "Cancel"} ) : null} @@ -65,7 +65,7 @@ export const Dialog = ({ onClose?.(); }} > - {doneRename || "Done"} + {doneRename ?? "Done"} diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 0f081fe2..887f9da0 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -12,7 +12,7 @@ export interface TableRowProps { export const TableRow = ({ cells, headerCells }: TableRowProps) => ( <> - {(cells || headerCells).map((cell, index) => ( + {(cells ?? headerCells).map((cell, index) => ( {cells ? cell : "No data"} ))} diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 28ab09f8..500184be 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -44,7 +44,7 @@ export const Table = ({ header, rows }: TableProps) => { - {(rows || header).map((cells, index) => ( + {(rows ?? header).map((cells, index) => (

Token Balances

- {!nativeTokenBalance || !fungibleTokensBalances ? ( + {!nativeTokenBalance ?? !fungibleTokensBalances ? (
) : ( From 2854735bcb6f50b4bcb32d4c11656f76eb3bddbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 09:11:15 +0400 Subject: [PATCH 135/537] Fix typo --- src/widgets/tokens-balances/ui/token-balances.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/tokens-balances/ui/token-balances.tsx b/src/widgets/tokens-balances/ui/token-balances.tsx index e70d1ec6..b01eeacf 100644 --- a/src/widgets/tokens-balances/ui/token-balances.tsx +++ b/src/widgets/tokens-balances/ui/token-balances.tsx @@ -13,7 +13,7 @@ export const TokensBalances = ({ className, daoContracts }: TokensBalancesProps) return ( -

Token Balances

+

Tokens balances

{!nativeTokenBalance ?? !fungibleTokensBalances ? (
From fa59b4e3c3e0287d9dd045d64853b4eef4f94195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 09:12:30 +0400 Subject: [PATCH 136/537] fix: Add missing pluralization --- src/widgets/tokens-balances/ui/token-balances.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/tokens-balances/ui/token-balances.tsx b/src/widgets/tokens-balances/ui/token-balances.tsx index b01eeacf..e151bdbd 100644 --- a/src/widgets/tokens-balances/ui/token-balances.tsx +++ b/src/widgets/tokens-balances/ui/token-balances.tsx @@ -8,20 +8,20 @@ interface TokensBalancesProps { } export const TokensBalances = ({ className, daoContracts }: TokensBalancesProps) => { - const nativeTokenBalance = NativeToken.balancesRender({ daoContracts }), + const nativeTokenBalances = NativeToken.balancesRender({ daoContracts }), fungibleTokensBalances = FungibleToken.allBalancesRender({ daoContracts }); return (

Tokens balances

- {!nativeTokenBalance ?? !fungibleTokensBalances ? ( + {!nativeTokenBalances ?? !fungibleTokensBalances ? (
) : (
)} From c75b959d1006ac5e72e968e5b411837171e913ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 09:40:09 +0400 Subject: [PATCH 137/537] feat: Use `.ts` everywhere --- src/entities/task/ui/task.jsx | 2 +- src/families/{families.js => families.ts} | 0 src/families/index.js | 1 - src/families/index.ts | 1 + src/families/multicall/{family.js => family.ts} | 0 src/families/near/{family.js => family.ts} | 0 src/families/ref-finance/{family.js => family.ts} | 0 src/families/ref-finance/{withdraw.js => withdraw.ts} | 0 src/{initial-data.js => initial-data.ts} | 0 src/{near-config.js => near-config.ts} | 2 +- src/shared/lib/persistent.ts | 2 +- src/widgets/layout/layout.jsx | 2 +- 12 files changed, 5 insertions(+), 5 deletions(-) rename src/families/{families.js => families.ts} (100%) delete mode 100644 src/families/index.js create mode 100644 src/families/index.ts rename src/families/multicall/{family.js => family.ts} (100%) rename src/families/near/{family.js => family.ts} (100%) rename src/families/ref-finance/{family.js => family.ts} (100%) rename src/families/ref-finance/{withdraw.js => withdraw.ts} (100%) rename src/{initial-data.js => initial-data.ts} (100%) rename src/{near-config.js => near-config.ts} (98%) diff --git a/src/entities/task/ui/task.jsx b/src/entities/task/ui/task.jsx index a6b45afe..18acc106 100644 --- a/src/entities/task/ui/task.jsx +++ b/src/entities/task/ui/task.jsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { Draggable } from "react-beautiful-dnd"; -import { Family } from "../../../families/index.js"; +import { Family } from "../../../families"; import "./task.scss"; /* TODO: Decompose model and view */ diff --git a/src/families/families.js b/src/families/families.ts similarity index 100% rename from src/families/families.js rename to src/families/families.ts diff --git a/src/families/index.js b/src/families/index.js deleted file mode 100644 index d7b03aa2..00000000 --- a/src/families/index.js +++ /dev/null @@ -1 +0,0 @@ -export * as Family from "./families.js"; diff --git a/src/families/index.ts b/src/families/index.ts new file mode 100644 index 00000000..8ad59d3c --- /dev/null +++ b/src/families/index.ts @@ -0,0 +1 @@ +export * as Family from "./families"; diff --git a/src/families/multicall/family.js b/src/families/multicall/family.ts similarity index 100% rename from src/families/multicall/family.js rename to src/families/multicall/family.ts diff --git a/src/families/near/family.js b/src/families/near/family.ts similarity index 100% rename from src/families/near/family.js rename to src/families/near/family.ts diff --git a/src/families/ref-finance/family.js b/src/families/ref-finance/family.ts similarity index 100% rename from src/families/ref-finance/family.js rename to src/families/ref-finance/family.ts diff --git a/src/families/ref-finance/withdraw.js b/src/families/ref-finance/withdraw.ts similarity index 100% rename from src/families/ref-finance/withdraw.js rename to src/families/ref-finance/withdraw.ts diff --git a/src/initial-data.js b/src/initial-data.ts similarity index 100% rename from src/initial-data.js rename to src/initial-data.ts diff --git a/src/near-config.js b/src/near-config.ts similarity index 98% rename from src/near-config.js rename to src/near-config.ts index 0f3d2b9a..b43e8aab 100644 --- a/src/near-config.js +++ b/src/near-config.ts @@ -1,4 +1,4 @@ -function getConfig(env) { +function getConfig(env: string) { switch (env) { case "production": case "mainnet": diff --git a/src/shared/lib/persistent.ts b/src/shared/lib/persistent.ts index 4c650c9c..bb09aa8d 100644 --- a/src/shared/lib/persistent.ts +++ b/src/shared/lib/persistent.ts @@ -1,4 +1,4 @@ -import { initialData } from "../../initial-data.js"; +import { initialData } from "../../initial-data"; import debounce from "lodash.debounce"; const STORAGE_KEY_ADDRESSES = "multicall_addresses"; diff --git a/src/widgets/layout/layout.jsx b/src/widgets/layout/layout.jsx index d7a52784..ede5b4f3 100644 --- a/src/widgets/layout/layout.jsx +++ b/src/widgets/layout/layout.jsx @@ -2,7 +2,7 @@ import React, { Component } from "react"; import { DragDropContext, Droppable } from "react-beautiful-dnd"; import { Column } from "../column/column.jsx"; import { Menu } from "../menu/menu.jsx"; -import { initialData } from "../../initial-data.js"; +import { initialData } from "../../initial-data"; import { Base64 } from "js-base64"; import { STORAGE } from "../../shared/lib/persistent"; import "./layout.scss"; From f5c3def45242e50ce5fb4a37c0a8797f4430ab4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 12:17:45 +0400 Subject: [PATCH 138/537] Move app page to `pages` --- .../layout/layout.jsx => pages/app/app.jsx} | 25 +++++++++++-------- .../layout/layout.scss => pages/app/app.scss} | 0 src/pages/app/app.tsx | 11 -------- src/pages/app/{index.tsx => index.ts} | 0 src/widgets/index.ts | 1 - src/widgets/layout/index.ts | 1 - src/widgets/tokens-balances/index.ts | 2 +- ...token-balances.tsx => tokens-balances.tsx} | 0 8 files changed, 15 insertions(+), 25 deletions(-) rename src/{widgets/layout/layout.jsx => pages/app/app.jsx} (98%) rename src/{widgets/layout/layout.scss => pages/app/app.scss} (100%) delete mode 100644 src/pages/app/app.tsx rename src/pages/app/{index.tsx => index.ts} (100%) delete mode 100644 src/widgets/layout/index.ts rename src/widgets/tokens-balances/ui/{token-balances.tsx => tokens-balances.tsx} (100%) diff --git a/src/widgets/layout/layout.jsx b/src/pages/app/app.jsx similarity index 98% rename from src/widgets/layout/layout.jsx rename to src/pages/app/app.jsx index ede5b4f3..62b9f558 100644 --- a/src/widgets/layout/layout.jsx +++ b/src/pages/app/app.jsx @@ -1,13 +1,15 @@ -import React, { Component } from "react"; +import { Base64 } from "js-base64"; +import { Component } from "react"; import { DragDropContext, Droppable } from "react-beautiful-dnd"; -import { Column } from "../column/column.jsx"; -import { Menu } from "../menu/menu.jsx"; + +import { Column } from "../../widgets/column/column.jsx"; +import { Menu } from "../../widgets/menu/menu.jsx"; import { initialData } from "../../initial-data"; -import { Base64 } from "js-base64"; import { STORAGE } from "../../shared/lib/persistent"; -import "./layout.scss"; -export class Layout extends Component { +import "./app.scss"; + +export class AppPage extends Component { taskID = 0; columnID = 1; @@ -21,11 +23,6 @@ export class Layout extends Component { document.addEventListener("onlayoutupdated", () => this.forceUpdate()); } - componentDidMount() { - window.LAYOUT = this; - STORAGE.load(); - } - getTaskID = () => this.taskID; getColumnID = () => this.columnID; @@ -476,6 +473,12 @@ export class Layout extends Component { SIDEBAR.forceUpdate(); } + componentDidMount() { + window.PAGE = "app"; + window.LAYOUT = this; + STORAGE.load(); + } + render() { const layout = STORAGE.layout; diff --git a/src/widgets/layout/layout.scss b/src/pages/app/app.scss similarity index 100% rename from src/widgets/layout/layout.scss rename to src/pages/app/app.scss diff --git a/src/pages/app/app.tsx b/src/pages/app/app.tsx deleted file mode 100644 index a1801247..00000000 --- a/src/pages/app/app.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Layout } from "../../widgets"; - -export const AppPage = () => { - window.PAGE = "app"; - - return ( - <> - - - ); -}; diff --git a/src/pages/app/index.tsx b/src/pages/app/index.ts similarity index 100% rename from src/pages/app/index.tsx rename to src/pages/app/index.ts diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 16ff70f0..27f1c541 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -1,4 +1,3 @@ -export { Layout } from "./layout/layout.jsx"; export { Column } from "./column/column.jsx"; export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; diff --git a/src/widgets/layout/index.ts b/src/widgets/layout/index.ts deleted file mode 100644 index eccd125c..00000000 --- a/src/widgets/layout/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { Layout } from "./layout"; diff --git a/src/widgets/tokens-balances/index.ts b/src/widgets/tokens-balances/index.ts index f4ec7d4f..9161054c 100644 --- a/src/widgets/tokens-balances/index.ts +++ b/src/widgets/tokens-balances/index.ts @@ -1 +1 @@ -export { TokensBalances } from "./ui/token-balances"; +export { TokensBalances } from "./ui/tokens-balances"; diff --git a/src/widgets/tokens-balances/ui/token-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx similarity index 100% rename from src/widgets/tokens-balances/ui/token-balances.tsx rename to src/widgets/tokens-balances/ui/tokens-balances.tsx From 7e1b9eb20962289de2e143314248e01e189d49e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 12:28:38 +0400 Subject: [PATCH 139/537] chore: Use shorter names for segments' content --- src/entities/fungible-token/index.ts | 2 +- src/entities/fungible-token/lib/{format.ts => ft-format.ts} | 0 .../model/{fungible-token-balances.ts => ft-balances.ts} | 0 .../ui/{fungible-token-balances.tsx => ft-balances.tsx} | 4 ++-- src/entities/native-token/index.ts | 2 +- .../model/{native-token-balances.ts => nt-balances.ts} | 0 .../ui/{native-token-balances.tsx => nt-balances.tsx} | 2 +- 7 files changed, 5 insertions(+), 5 deletions(-) rename src/entities/fungible-token/lib/{format.ts => ft-format.ts} (100%) rename src/entities/fungible-token/model/{fungible-token-balances.ts => ft-balances.ts} (100%) rename src/entities/fungible-token/ui/{fungible-token-balances.tsx => ft-balances.tsx} (85%) rename src/entities/native-token/model/{native-token-balances.ts => nt-balances.ts} (100%) rename src/entities/native-token/ui/{native-token-balances.tsx => nt-balances.tsx} (85%) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index a8a841b7..76f09041 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,4 +1,4 @@ -import { fungibleTokensBalancesRender } from "./ui/fungible-token-balances"; +import { fungibleTokensBalancesRender } from "./ui/ft-balances"; export class FungibleToken { static allBalancesRender = fungibleTokensBalancesRender; diff --git a/src/entities/fungible-token/lib/format.ts b/src/entities/fungible-token/lib/ft-format.ts similarity index 100% rename from src/entities/fungible-token/lib/format.ts rename to src/entities/fungible-token/lib/ft-format.ts diff --git a/src/entities/fungible-token/model/fungible-token-balances.ts b/src/entities/fungible-token/model/ft-balances.ts similarity index 100% rename from src/entities/fungible-token/model/fungible-token-balances.ts rename to src/entities/fungible-token/model/ft-balances.ts diff --git a/src/entities/fungible-token/ui/fungible-token-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx similarity index 85% rename from src/entities/fungible-token/ui/fungible-token-balances.tsx rename to src/entities/fungible-token/ui/ft-balances.tsx index 9099d5ad..eb62a3e0 100644 --- a/src/entities/fungible-token/ui/fungible-token-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -1,7 +1,7 @@ import { TokenLabel } from "../../../shared/ui/components"; import type { DaoContracts } from "../../types"; -import { FungibleTokenFormat } from "../lib/format"; -import { FungibleTokenBalancesModel } from "../model/fungible-token-balances"; +import { FungibleTokenFormat } from "../lib/ft-format"; +import { FungibleTokenBalancesModel } from "../model/ft-balances"; interface FungibleTokensBalancesRenderProps { daoContracts: DaoContracts; diff --git a/src/entities/native-token/index.ts b/src/entities/native-token/index.ts index f066a47b..325d3d30 100644 --- a/src/entities/native-token/index.ts +++ b/src/entities/native-token/index.ts @@ -1,4 +1,4 @@ -import { nativeTokenBalancesRender } from "./ui/native-token-balances"; +import { nativeTokenBalancesRender } from "./ui/nt-balances"; export class NativeToken { static balancesRender = nativeTokenBalancesRender; diff --git a/src/entities/native-token/model/native-token-balances.ts b/src/entities/native-token/model/nt-balances.ts similarity index 100% rename from src/entities/native-token/model/native-token-balances.ts rename to src/entities/native-token/model/nt-balances.ts diff --git a/src/entities/native-token/ui/native-token-balances.tsx b/src/entities/native-token/ui/nt-balances.tsx similarity index 85% rename from src/entities/native-token/ui/native-token-balances.tsx rename to src/entities/native-token/ui/nt-balances.tsx index 52d0f2e4..beccecc1 100644 --- a/src/entities/native-token/ui/native-token-balances.tsx +++ b/src/entities/native-token/ui/nt-balances.tsx @@ -1,6 +1,6 @@ import { TokenLabel } from "../../../shared/ui/components"; import type { DaoContracts } from "../../types"; -import { NativeTokenBalancesModel } from "../model/native-token-balances"; +import { NativeTokenBalancesModel } from "../model/nt-balances"; interface NativeTokenBalancesRenderProps { daoContracts: DaoContracts; From 90c8d210a8636cc25a187c06dc6151ae86d7e566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 12:34:37 +0400 Subject: [PATCH 140/537] chore: Use explicit naming for NEAR native token entity --- src/entities/index.ts | 2 +- src/entities/native-token/index.ts | 5 ----- src/entities/native-token/ui/nt-balances.tsx | 13 ------------- .../{native-token => near-token}/config.ts | 0 src/entities/near-token/index.ts | 5 +++++ .../model/near-balances.ts} | 14 +++++++------- src/entities/near-token/ui/near-balances.tsx | 13 +++++++++++++ src/widgets/tokens-balances/ui/tokens-balances.tsx | 8 ++++---- 8 files changed, 30 insertions(+), 30 deletions(-) delete mode 100644 src/entities/native-token/index.ts delete mode 100644 src/entities/native-token/ui/nt-balances.tsx rename src/entities/{native-token => near-token}/config.ts (100%) create mode 100644 src/entities/near-token/index.ts rename src/entities/{native-token/model/nt-balances.ts => near-token/model/near-balances.ts} (69%) create mode 100644 src/entities/near-token/ui/near-balances.tsx diff --git a/src/entities/index.ts b/src/entities/index.ts index 7afd1f85..98abd373 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,4 +1,4 @@ export { Task } from "./task"; export { FungibleToken } from "./fungible-token"; -export { NativeToken } from "./native-token"; +export { NearToken } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/native-token/index.ts b/src/entities/native-token/index.ts deleted file mode 100644 index 325d3d30..00000000 --- a/src/entities/native-token/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { nativeTokenBalancesRender } from "./ui/nt-balances"; - -export class NativeToken { - static balancesRender = nativeTokenBalancesRender; -} diff --git a/src/entities/native-token/ui/nt-balances.tsx b/src/entities/native-token/ui/nt-balances.tsx deleted file mode 100644 index beccecc1..00000000 --- a/src/entities/native-token/ui/nt-balances.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { TokenLabel } from "../../../shared/ui/components"; -import type { DaoContracts } from "../../types"; -import { NativeTokenBalancesModel } from "../model/nt-balances"; - -interface NativeTokenBalancesRenderProps { - daoContracts: DaoContracts; -} - -export const nativeTokenBalancesRender = ({ daoContracts }: NativeTokenBalancesRenderProps) => { - const { data } = NativeTokenBalancesModel.useData(daoContracts); - - return !data ? null : [, data.multicall, data.dao, data.total]; -}; diff --git a/src/entities/native-token/config.ts b/src/entities/near-token/config.ts similarity index 100% rename from src/entities/native-token/config.ts rename to src/entities/near-token/config.ts diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts new file mode 100644 index 00000000..1feb9a3e --- /dev/null +++ b/src/entities/near-token/index.ts @@ -0,0 +1,5 @@ +import { nearTokenBalancesRender } from "./ui/near-balances"; + +export class NearToken { + static balancesRender = nearTokenBalancesRender; +} diff --git a/src/entities/native-token/model/nt-balances.ts b/src/entities/near-token/model/near-balances.ts similarity index 69% rename from src/entities/native-token/model/nt-balances.ts rename to src/entities/near-token/model/near-balances.ts index bf915469..625770da 100644 --- a/src/entities/native-token/model/nt-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -5,12 +5,12 @@ import { viewAccount } from "../../../shared/lib/wallet"; import { DaoContracts } from "../../types"; import { FRACTIONAL_PART_LENGTH } from "../config"; -type NativeTokenData = { +type NearTokenData = { data: { dao: string; multicall: string; total: string } | null; loading: boolean; }; -const nativeTokenDataFx = async ({ dao, multicall }: DaoContracts, callback: (data: NativeTokenData) => void) => { +const nearTokenDataFx = async ({ dao, multicall }: DaoContracts, callback: (data: NearTokenData) => void) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ viewAccount(dao.address), viewAccount(multicall.address), @@ -30,14 +30,14 @@ const nativeTokenDataFx = async ({ dao, multicall }: DaoContracts, callback: (da }); }; -const useNativeTokenData = (daoContracts: DaoContracts) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); +const useNearTokenData = (daoContracts: DaoContracts) => { + const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void nativeTokenDataFx(daoContracts, stateUpdate), []); + useEffect(() => void nearTokenDataFx(daoContracts, stateUpdate), []); return state; }; -export class NativeTokenBalancesModel { - static useData = useNativeTokenData; +export class NearTokenBalancesModel { + static useData = useNearTokenData; } diff --git a/src/entities/near-token/ui/near-balances.tsx b/src/entities/near-token/ui/near-balances.tsx new file mode 100644 index 00000000..8a4538aa --- /dev/null +++ b/src/entities/near-token/ui/near-balances.tsx @@ -0,0 +1,13 @@ +import { TokenLabel } from "../../../shared/ui/components"; +import type { DaoContracts } from "../../types"; +import { NearTokenBalancesModel } from "../model/near-balances"; + +interface NearTokenBalancesRenderProps { + daoContracts: DaoContracts; +} + +export const nearTokenBalancesRender = ({ daoContracts }: NearTokenBalancesRenderProps) => { + const { data } = NearTokenBalancesModel.useData(daoContracts); + + return !data ? null : [, data.multicall, data.dao, data.total]; +}; diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index e151bdbd..816cf8c0 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -1,6 +1,6 @@ import { Facet, Scrollable, Table } from "../../../shared/ui/components"; import { type DaoContracts } from "../../../entities/types"; -import { FungibleToken, NativeToken } from "../../../entities"; +import { FungibleToken, NearToken } from "../../../entities"; interface TokensBalancesProps { className?: string; @@ -8,20 +8,20 @@ interface TokensBalancesProps { } export const TokensBalances = ({ className, daoContracts }: TokensBalancesProps) => { - const nativeTokenBalances = NativeToken.balancesRender({ daoContracts }), + const nearTokenBalances = NearToken.balancesRender({ daoContracts }), fungibleTokensBalances = FungibleToken.allBalancesRender({ daoContracts }); return (

Tokens balances

- {!nativeTokenBalances ?? !fungibleTokensBalances ? ( + {!nearTokenBalances ?? !fungibleTokensBalances ? (
) : (
)} From 0a1c4fb3f1125fe7b7e12aa939ab59a07fa68a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 13:07:25 +0400 Subject: [PATCH 141/537] fix: Use correct method reference --- src/pages/app/app.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/app/app.jsx b/src/pages/app/app.jsx index 62b9f558..681f4191 100644 --- a/src/pages/app/app.jsx +++ b/src/pages/app/app.jsx @@ -52,7 +52,7 @@ export class AppPage extends Component { deleteTask = (taskId) => { const layout = STORAGE.layout; - const { columnId, taskIndex } = Layout.findTaskCoordinates(taskId); + const { columnId, taskIndex } = AppPage.findTaskCoordinates(taskId); if (columnId == undefined || taskIndex == undefined) { console.error("Task not found"); @@ -80,7 +80,7 @@ export class AppPage extends Component { duplicateTask = (taskId) => { const layout = STORAGE.layout; - const { columnId, taskIndex } = Layout.findTaskCoordinates(taskId); + const { columnId, taskIndex } = AppPage.findTaskCoordinates(taskId); if (columnId == undefined || taskIndex == undefined) { console.error("Task not found"); From 3f89c3f56884202ac539bcc97e83ee7334c9212c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 17:33:51 +0400 Subject: [PATCH 142/537] dev: Add Better Comments extension to workspace recommendations --- .vscode/extensions.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index aec05715..3710a13b 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,8 @@ { - "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "Gruntfuggly.todo-tree"] + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "gruntfuggly.todo-tree", + "aaron-bond.better-comments" + ] } From 6825c860548dabd5696b43b9e4fdd4e7ec8f138e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 23:00:01 +0400 Subject: [PATCH 143/537] Fix dApp login feature flags & Extract dApp login feature --- src/families/base.jsx | 3 +- src/families/multicall/transfer.jsx | 7 +- src/families/near/transfer.jsx | 7 +- src/families/ref-finance/swap.jsx | 5 +- src/features/dapp-login/config.ts | 31 +++++++ src/features/dapp-login/index.ts | 8 ++ .../dapp-login/model/dapp-login-dialogs.ts | 57 ++++++++++++ .../dapp-login/ui/dapp-login-dialog.scss | 27 ++++++ .../dapp-login/ui/dapp-login-dialogs.tsx | 91 +++++++++++++++++++ .../dapp-login/ui/dapp-login-menu.tsx | 24 +++++ src/features/index.ts | 1 + src/index.tsx | 7 +- src/pages/dao/dao.tsx | 6 +- src/shared/lib/args.ts | 2 +- src/shared/ui/components/dialog/dialog.scss | 1 + src/shared/ui/components/dialog/dialog.tsx | 6 +- src/shared/ui/components/dialog/index.ts | 2 +- src/shared/ui/components/index.ts | 7 +- src/shared/ui/components/popup-menu/index.ts | 2 +- .../ui/components/popup-menu/popup-menu.tsx | 4 +- src/shared/ui/components/text-input/index.ts | 1 + .../ui/components/text-input/text-input.tsx} | 22 +++-- src/widgets/dialogs-layer/index.ts | 1 + .../dialogs-layer/ui/dialogs-layer.tsx | 7 ++ src/widgets/editor/index.ts | 1 - src/widgets/export/export.jsx | 2 +- src/widgets/index.ts | 1 + src/widgets/sidebar/dialogs.jsx | 91 +------------------ src/widgets/sidebar/dialogs.scss | 29 ------ src/widgets/sidebar/sidebar.jsx | 89 +++++++++--------- 30 files changed, 346 insertions(+), 196 deletions(-) create mode 100644 src/features/dapp-login/config.ts create mode 100644 src/features/dapp-login/index.ts create mode 100644 src/features/dapp-login/model/dapp-login-dialogs.ts create mode 100644 src/features/dapp-login/ui/dapp-login-dialog.scss create mode 100644 src/features/dapp-login/ui/dapp-login-dialogs.tsx create mode 100644 src/features/dapp-login/ui/dapp-login-menu.tsx create mode 100644 src/features/index.ts create mode 100644 src/shared/ui/components/text-input/index.ts rename src/{widgets/editor/elements.jsx => shared/ui/components/text-input/text-input.tsx} (81%) create mode 100644 src/widgets/dialogs-layer/index.ts create mode 100644 src/widgets/dialogs-layer/ui/dialogs-layer.tsx delete mode 100644 src/widgets/sidebar/dialogs.scss diff --git a/src/families/base.jsx b/src/families/base.jsx index da7830a8..0ef3e5bd 100644 --- a/src/families/base.jsx +++ b/src/families/base.jsx @@ -2,8 +2,7 @@ import { DeleteOutline, MoveDown, EditOutlined } from "@mui/icons-material"; import debounce from "lodash.debounce"; import { Component } from "react"; -import { Tooltip } from "../shared/ui/components"; -import { TextInput, TextInputWithUnits } from "../widgets/editor/elements"; +import { TextInput, TextInputWithUnits, Tooltip } from "../shared/ui/components"; import { ArgsAccount, ArgsBig, ArgsError, ArgsJSON, ArgsString } from "../shared/lib/args"; import Call from "../shared/lib/call"; import { toGas, toYocto, formatTokenAmount, unitToDecimals } from "../shared/lib/converter"; diff --git a/src/families/multicall/transfer.jsx b/src/families/multicall/transfer.jsx index b0d1ae13..3fd7ddb2 100644 --- a/src/families/multicall/transfer.jsx +++ b/src/families/multicall/transfer.jsx @@ -1,14 +1,15 @@ import Checkbox from "@mui/material/Checkbox"; -import React from "react"; + import { ArgsAccount, ArgsBig, ArgsString, ArgsObject, ArgsError } from "../../shared/lib/args"; import Call from "../../shared/lib/call"; import { errorMsg } from "../../shared/lib/errors"; import { STORAGE } from "../../shared/lib/persistent"; import { toGas, toYocto, formatTokenAmount, unitToDecimals } from "../../shared/lib/converter"; -import { BaseTask } from "../base"; import { Multicall } from "../../shared/lib/contracts/multicall"; +import { TextInput, TextInputWithUnits } from "../../shared/ui/components"; +import { BaseTask } from "../base"; + import "./multicall.scss"; -import { TextInput, TextInputWithUnits } from "../../widgets/editor/elements"; export class Transfer extends BaseTask { uniqueClassName = "multicall-transfer-task"; diff --git a/src/families/near/transfer.jsx b/src/families/near/transfer.jsx index 987d8648..c9d35912 100644 --- a/src/families/near/transfer.jsx +++ b/src/families/near/transfer.jsx @@ -1,13 +1,14 @@ import { InputAdornment } from "@mui/material"; -import React from "react"; -import { TextInput, TextInputWithUnits } from "../../widgets/editor/elements"; +import debounce from "lodash.debounce"; + +import { TextInput, TextInputWithUnits } from "../../shared/ui/components"; import { ArgsAccount, ArgsBig, ArgsError, ArgsObject, ArgsString } from "../../shared/lib/args"; import Call from "../../shared/lib/call"; import { toGas, formatTokenAmount, unitToDecimals } from "../../shared/lib/converter"; import { view } from "../../shared/lib/wallet"; import { errorMsg } from "../../shared/lib/errors"; import { BaseTask } from "../base"; -import debounce from "lodash.debounce"; + import "./near.scss"; export class Transfer extends BaseTask { diff --git a/src/families/ref-finance/swap.jsx b/src/families/ref-finance/swap.jsx index 8ac11e47..e92806b6 100644 --- a/src/families/ref-finance/swap.jsx +++ b/src/families/ref-finance/swap.jsx @@ -1,11 +1,12 @@ import { TextField } from "@mui/material"; -import React from "react"; -import { TextInput, TextInputWithUnits } from "../../widgets/editor/elements"; + +import { TextInput, TextInputWithUnits } from "../../shared/ui/components"; import { ArgsAccount, ArgsBig, ArgsError, ArgsNumber, ArgsString, ArgsObject, ArgsArray } from "../../shared/lib/args"; import Call from "../../shared/lib/call"; import { errorMsg } from "../../shared/lib/errors"; import { toGas } from "../../shared/lib/converter"; import { BaseTask } from "../base"; + import "./ref-finance.scss"; export class Swap extends BaseTask { diff --git a/src/features/dapp-login/config.ts b/src/features/dapp-login/config.ts new file mode 100644 index 00000000..e475a3ac --- /dev/null +++ b/src/features/dapp-login/config.ts @@ -0,0 +1,31 @@ +export class DappLoginConfig { + static KEYS = { + all: "ed25519%3A9jeqkc8ybv7aYSA7uLNFUEn8cgKo759yue4771bBWsSr", + public: "ed25519%3ADEaoD65LomNHAMzhNZva15LC85ntwBHdcTbCnZRXciZH", + }; + + static METHODS: Record<"dao" | "multicall", { title: string; type: keyof typeof DappLoginConfig.METHODS }> = { + dao: { title: "Login in dApps as DAO", type: "dao" }, + multicall: { title: "Login in dApps as Multicall", type: "multicall" }, + }; + + static STEP_BY_STEP_GUIDE = [ + { + text: "Open the dApp in another browser tab", + }, + { + text: "Log out your account on the dApp", + hint: "You should not be logged in with any wallet on the other dApp, otherwise this won't work.", + }, + { + text: "Copy the dApp's URL", + }, + { + text: "Paste the URL in the input field below", + }, + { + text: 'Click "Proceed"', + hint: 'This opens the dApp in a new tab, with a "watch-only" mode. Meaning you cannot sign transactions with it', + }, + ]; +} diff --git a/src/features/dapp-login/index.ts b/src/features/dapp-login/index.ts new file mode 100644 index 00000000..81b36280 --- /dev/null +++ b/src/features/dapp-login/index.ts @@ -0,0 +1,8 @@ +import { DappLoginConfig } from "./config"; +import { DappLoginDialogs } from "./ui/dapp-login-dialogs"; +import { DappLoginMenu } from "./ui/dapp-login-menu"; + +export class DappLogin extends DappLoginConfig { + static Dialogs = DappLoginDialogs; + static Menu = DappLoginMenu; +} diff --git a/src/features/dapp-login/model/dapp-login-dialogs.ts b/src/features/dapp-login/model/dapp-login-dialogs.ts new file mode 100644 index 00000000..4fa7a766 --- /dev/null +++ b/src/features/dapp-login/model/dapp-login-dialogs.ts @@ -0,0 +1,57 @@ +import { useCallback, useEffect, useState } from "react"; + +import { DappLoginConfig as Config } from "../config"; + +/** + * !TODO: Use 3rd party solution for dialogs management + */ + +const _dialogOpenRequested = "dialogopenrequested"; + +const dialogOpenRequested = { + dispatch: (dialogKey: keyof typeof Config.METHODS) => + document.dispatchEvent(new CustomEvent(_dialogOpenRequested, { detail: { dialogKey } })), + + subscribe: (callback: EventListener) => { + document.addEventListener(_dialogOpenRequested, callback); + + return () => document.removeEventListener(_dialogOpenRequested, callback); + }, +}; + +const useDappLoginDialogsVisibilityState = () => { + const [dialogsVisibility, dialogVisibilitySwitch] = useState | {}>( + Object.values(Config.METHODS).reduce((visibilityState, { type }) => ({ ...visibilityState, [type]: false }), {}) + ); + + useEffect( + () => + dialogOpenRequested.subscribe(({ detail }) => + dialogVisibilitySwitch( + Object.keys(dialogsVisibility).reduce( + (visibilityState, someDialogKey) => ({ + ...visibilityState, + [someDialogKey]: someDialogKey === detail.dialogKey ? true : false, + }), + + dialogsVisibility + ) + ) + ), + [] + ); + + return { + dialogsVisibility, + + closeHandlerBinding: useCallback( + (dialogKey: string) => () => dialogVisibilitySwitch({ ...dialogsVisibility, [dialogKey]: false }), + [dialogVisibilitySwitch] + ), + }; +}; + +export class DappLoginDialogsModel { + static dialogOpenRequested = dialogOpenRequested.dispatch; + static useVisibilityState = useDappLoginDialogsVisibilityState; +} diff --git a/src/features/dapp-login/ui/dapp-login-dialog.scss b/src/features/dapp-login/ui/dapp-login-dialog.scss new file mode 100644 index 00000000..7178993c --- /dev/null +++ b/src/features/dapp-login/ui/dapp-login-dialog.scss @@ -0,0 +1,27 @@ +@use "sass/size"; +@use "sass/mixin"; + +.DappLoginDialog { + &-stepByStepGuide { + padding: 0 size.$gap; + list-style-type: decimal; + font-size: size.$text; + + li { + span { + @include mixin.center-items(flex-start, center); + flex-flow: row nowrap; + gap: 0.5ch; + padding-left: 0.25 * size.$gap; + + .MuiSvgIcon-root { + @include mixin.light-icon; + } + } + + &::marker { + font-weight: 800; + } + } + } +} diff --git a/src/features/dapp-login/ui/dapp-login-dialogs.tsx b/src/features/dapp-login/ui/dapp-login-dialogs.tsx new file mode 100644 index 00000000..7bfa4d4f --- /dev/null +++ b/src/features/dapp-login/ui/dapp-login-dialogs.tsx @@ -0,0 +1,91 @@ +import { InfoOutlined } from "@mui/icons-material"; +import clsx from "clsx"; +import { useCallback, useMemo, useReducer, useState } from "react"; + +import { ArgsError, ArgsString } from "../../../shared/lib/args"; +import { STORAGE } from "../../../shared/lib/persistent"; +import { Validation } from "../../../shared/lib/validation"; +import { Dialog, type DialogProps, TextInput, Tooltip } from "../../../shared/ui/components"; +import { DappLoginConfig as Config } from "../config"; +import { DappLoginDialogsModel } from "../model/dapp-login-dialogs"; + +import "./dapp-login-dialog.scss"; + +interface DappLoginDialogProps extends Pick { + method: "dao" | "multicall"; +} + +const _DappLoginDialog = "DappLoginDialog"; + +const DappLoginDialog = ({ className, method, onClose, open, title }: DappLoginDialogProps) => { + const dAppURL = useMemo(() => new ArgsString(""), []); + + const URLInvalid = ArgsError.useInstance("Invalid URL", Validation.isUrl, true); + + const [requestURL, requestURLUpdate] = useReducer<(currentValue: string, input: string) => string>( + (currentValue, value) => { + if (URLInvalid.$detected) { + return currentValue; + } else { + const url = new URL(value); + url.searchParams.set("account_id", STORAGE.addresses[method]); + url.searchParams.set("public_key", Config.KEYS.public); + url.searchParams.set("all_keys", Config.KEYS.all); + return url.toString(); + } + }, + "" + ); + + return ( + window.open(requestURL, "_blank")} + {...{ onClose, open, title }} + > +
    + {Config.STEP_BY_STEP_GUIDE.map((step) => ( +
  • + + {step.text} + + {step.hint && ( + + + + )} + +
  • + ))} +
+ + requestURLUpdate(target.value)} + value={dAppURL} + variant="filled" + /> +
+ ); +}; + +export const DappLoginDialogs = () => { + const { dialogsVisibility, closeHandlerBinding } = DappLoginDialogsModel.useVisibilityState(); + + return Object.values(Config.METHODS).map((loginMethod) => ( + + )); +}; diff --git a/src/features/dapp-login/ui/dapp-login-menu.tsx b/src/features/dapp-login/ui/dapp-login-menu.tsx new file mode 100644 index 00000000..78b3724a --- /dev/null +++ b/src/features/dapp-login/ui/dapp-login-menu.tsx @@ -0,0 +1,24 @@ +import { PreviewOutlined } from "@mui/icons-material"; + +import { PopupMenu, PopupMenuProps } from "../../../shared/ui/components"; +import { DappLoginConfig as Config } from "../config"; +import { DappLoginDialogsModel } from "../model/dapp-login-dialogs"; + +interface DappLoginMenuProps extends Pick { + FeatureFlags: { + DappLogin: Record; + }; +} + +export const DappLoginMenu = ({ FeatureFlags, triggerClassName }: DappLoginMenuProps) => ( + } + items={Object.values(Config.METHODS).map(({ title, type }) => ({ + disabled: !FeatureFlags.DappLogin[type], + key: type, + onClick: () => DappLoginDialogsModel.dialogOpenRequested(type), + title, + }))} + {...{ triggerClassName }} + /> +); diff --git a/src/features/index.ts b/src/features/index.ts new file mode 100644 index 00000000..e31ff1f7 --- /dev/null +++ b/src/features/index.ts @@ -0,0 +1 @@ +export { DappLogin } from "./dapp-login"; diff --git a/src/index.tsx b/src/index.tsx index 9e017715..729caab1 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,11 +1,12 @@ +import "@near-wallet-selector/modal-ui/styles.css"; import ReactDOM from "react-dom"; import { HashRouter, Routes, Route, Navigate } from "react-router-dom"; + import { AppPage } from "./pages/app"; import { DaoPage } from "./pages/dao/dao"; import { Wallet } from "./entities"; +import { DialogsLayer, Sidebar } from "./widgets"; import "./shared/lib/persistent"; -import "@near-wallet-selector/modal-ui/styles.css"; -import { Sidebar } from "./widgets"; window.PAGE = "app"; @@ -29,6 +30,7 @@ ReactDOM.render( <> + } /> @@ -39,6 +41,7 @@ ReactDOM.render( <> + } /> diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 4c081e7f..e2fc649c 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -13,9 +13,9 @@ import { ProposalStatus, SputnikDAO, SputnikUI } from "../../shared/lib/contract import { Big, toNEAR, toYocto } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { view } from "../../shared/lib/wallet"; -import { Facet, Scrollable, Tabs } from "../../shared/ui/components"; -import { TextInput } from "../../widgets/editor/elements"; +import { Facet, Scrollable, Tabs, TextInput } from "../../shared/ui/components"; import { TokensBalances } from "../../widgets/tokens-balances"; + import "./config/config.scss"; import "./funds/funds.scss"; import "./dao.scss"; @@ -489,7 +489,7 @@ export class DaoPage extends Component {
), diff --git a/src/shared/lib/args.ts b/src/shared/lib/args.ts index 419e5c1f..15d4adef 100644 --- a/src/shared/lib/args.ts +++ b/src/shared/lib/args.ts @@ -277,7 +277,7 @@ class ArgsError { return valid ? value : null; } - static useInstance = (message: string, validator?: (value: unknown) => boolean, isBad: boolean = true) => { + static useInstance = (message: string, validator?: (value: Args["value"]) => boolean, isBad: boolean = true) => { const [$detected, detected] = useReducer( (_currentValue: boolean, value: Error | boolean): boolean => Boolean(value), isBad diff --git a/src/shared/ui/components/dialog/dialog.scss b/src/shared/ui/components/dialog/dialog.scss index eb605df3..956b1811 100644 --- a/src/shared/ui/components/dialog/dialog.scss +++ b/src/shared/ui/components/dialog/dialog.scss @@ -5,6 +5,7 @@ .Dialog { .MuiPaper-root { + min-width: size.$task-width; background-color: color.$black; color: color.$light-text; border-radius: size.$task-radius; diff --git a/src/shared/ui/components/dialog/dialog.tsx b/src/shared/ui/components/dialog/dialog.tsx index 8bdcde5c..ac295f18 100644 --- a/src/shared/ui/components/dialog/dialog.tsx +++ b/src/shared/ui/components/dialog/dialog.tsx @@ -9,9 +9,7 @@ import { PropsWithChildren } from "react"; import "./dialog.scss"; -const _Dialog = "Dialog"; - -interface DialogProps extends PropsWithChildren { +export interface DialogProps extends PropsWithChildren { cancelRename?: string; className?: string; doneRename?: string; @@ -24,6 +22,8 @@ interface DialogProps extends PropsWithChildren { title: string; } +const _Dialog = "Dialog"; + export const Dialog = ({ cancelRename, children, diff --git a/src/shared/ui/components/dialog/index.ts b/src/shared/ui/components/dialog/index.ts index bca0c2f7..04f7b3d1 100644 --- a/src/shared/ui/components/dialog/index.ts +++ b/src/shared/ui/components/dialog/index.ts @@ -1 +1 @@ -export { Dialog } from "./dialog"; +export { Dialog, type DialogProps } from "./dialog"; diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 5b3d64d2..16373f92 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,9 +1,10 @@ export { Facet } from "./facet/facet"; -export { Dialog } from "./dialog/dialog"; -export * from "./icons"; -export { PopupMenu } from "./popup-menu/popup-menu"; +export { Dialog, type DialogProps } from "./dialog/dialog"; +export { NearIcons } from "./icons"; +export { PopupMenu, type PopupMenuProps } from "./popup-menu/popup-menu"; export { Scrollable } from "./scrollable/scrollable"; export { Table } from "./table/table"; export { Tabs } from "./tabs/tabs"; +export { TextInput, type TextInputProps, TextInputWithUnits, type TextInputWithUnitsProps } from "./text-input"; export { TokenLabel } from "./token-label/token-label"; export { Tooltip } from "./tooltip/tooltip"; diff --git a/src/shared/ui/components/popup-menu/index.ts b/src/shared/ui/components/popup-menu/index.ts index f46d5fcd..9b6d72e2 100644 --- a/src/shared/ui/components/popup-menu/index.ts +++ b/src/shared/ui/components/popup-menu/index.ts @@ -1 +1 @@ -export { PopupMenu } from "./popup-menu"; +export { PopupMenu, type PopupMenuProps } from "./popup-menu"; diff --git a/src/shared/ui/components/popup-menu/popup-menu.tsx b/src/shared/ui/components/popup-menu/popup-menu.tsx index d6aa0bef..3cb4b4bc 100644 --- a/src/shared/ui/components/popup-menu/popup-menu.tsx +++ b/src/shared/ui/components/popup-menu/popup-menu.tsx @@ -4,9 +4,9 @@ import { ReactNode } from "react"; import "./popup-menu.scss"; -interface PopupMenuProps { +export interface PopupMenuProps { icon: ReactNode; - items: { disabled?: boolean; label: string; onClick?: VoidFunction; title: string }[]; + items: { disabled?: boolean; label?: string; onClick?: VoidFunction; title: string }[]; triggerClassName: string; } diff --git a/src/shared/ui/components/text-input/index.ts b/src/shared/ui/components/text-input/index.ts new file mode 100644 index 00000000..8eafe224 --- /dev/null +++ b/src/shared/ui/components/text-input/index.ts @@ -0,0 +1 @@ +export { TextInput, type TextInputProps, TextInputWithUnits, type TextInputWithUnitsProps } from "./text-input"; diff --git a/src/widgets/editor/elements.jsx b/src/shared/ui/components/text-input/text-input.tsx similarity index 81% rename from src/widgets/editor/elements.jsx rename to src/shared/ui/components/text-input/text-input.tsx index 253d1a18..352524fe 100644 --- a/src/widgets/editor/elements.jsx +++ b/src/shared/ui/components/text-input/text-input.tsx @@ -1,7 +1,15 @@ -import React, { Component } from "react"; -import { MenuItem, TextField } from "@mui/material"; +import { ChangeEvent, Component } from "react"; +import { MenuItem, TextField, TextFieldProps } from "@mui/material"; -class TextInput extends Component { +import { ArgsError, ArgsString } from "../../../lib/args"; + +export interface TextInputProps extends Pick { + error: ArgsError; + update: (event: ChangeEvent, component: Component) => void; + value: ArgsString; +} + +export class TextInput extends Component { render() { const { label, value, error, update, ...props } = this.props; @@ -28,7 +36,11 @@ class TextInput extends Component { } } -class TextInputWithUnits extends Component { +export interface TextInputWithUnitsProps extends TextInputProps { + // TODO!: Extend the interface +} + +export class TextInputWithUnits extends Component { render() { const { label, value, error, options, update, textProps, unitProps, ...props } = this.props; @@ -85,5 +97,3 @@ class TextInputWithUnits extends Component { ); } } - -export { TextInput, TextInputWithUnits }; diff --git a/src/widgets/dialogs-layer/index.ts b/src/widgets/dialogs-layer/index.ts new file mode 100644 index 00000000..62bc5a04 --- /dev/null +++ b/src/widgets/dialogs-layer/index.ts @@ -0,0 +1 @@ +export { DialogsLayer } from "./ui/dialogs-layer"; diff --git a/src/widgets/dialogs-layer/ui/dialogs-layer.tsx b/src/widgets/dialogs-layer/ui/dialogs-layer.tsx new file mode 100644 index 00000000..294cae0f --- /dev/null +++ b/src/widgets/dialogs-layer/ui/dialogs-layer.tsx @@ -0,0 +1,7 @@ +import { DappLogin } from "../../../features/dapp-login"; + +export const DialogsLayer = () => ( + <> + + +); diff --git a/src/widgets/editor/index.ts b/src/widgets/editor/index.ts index 8a46bc0a..f1298df8 100644 --- a/src/widgets/editor/index.ts +++ b/src/widgets/editor/index.ts @@ -1,2 +1 @@ export { Editor } from "./editor"; -export { TextInput, TextInputWithUnits } from "./elements"; // gone soon diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index f6371f8c..a6dcca43 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -13,7 +13,7 @@ import { STORAGE } from "../../shared/lib/persistent"; import { convert, toGas, toNEAR } from "../../shared/lib/converter"; import { view } from "../../shared/lib/wallet"; import { Wallet } from "../../entities"; -import { TextInput, TextInputWithUnits } from "../editor/elements"; +import { TextInput, TextInputWithUnits } from "../../shared/ui/components"; import "./export.scss"; export class Export extends Component { diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 27f1c541..7c000370 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -1,4 +1,5 @@ export { Column } from "./column/column.jsx"; +export { DialogsLayer } from "./dialogs-layer"; export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; diff --git a/src/widgets/sidebar/dialogs.jsx b/src/widgets/sidebar/dialogs.jsx index 9795efe8..5ea7a508 100644 --- a/src/widgets/sidebar/dialogs.jsx +++ b/src/widgets/sidebar/dialogs.jsx @@ -1,102 +1,18 @@ -import { InfoOutlined } from "@mui/icons-material"; import { TextField } from "@mui/material"; import { Base64 } from "js-base64"; -import { useMemo, useReducer, useState } from "react"; +import { useMemo, useState } from "react"; import { ArgsError, ArgsString } from "../../shared/lib/args"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; import { readFile, saveFile } from "../../shared/lib/loader"; -import { STORAGE } from "../../shared/lib/persistent"; import { Validation } from "../../shared/lib/validation"; -import { TextInput } from "../editor/elements"; -import { Dialog, Tooltip } from "../../shared/ui/components"; -import "./dialogs.scss"; - -const DAPP_LOGIN_INSTRUCTIONS = [ - { - text: "Open the dApp in another browser tab", - }, - { - text: "Log out your account on the dApp", - hint: "You should not be logged in with any wallet on the other dApp, otherwise this won't work.", - }, - { - text: "Copy the dApp's URL", - }, - { - text: "Paste the URL in the input field below", - }, - { - text: 'Click "Proceed"', - hint: 'This opens the dApp in a new tab, with a "watch-only" mode. Meaning you cannot sign transactions with it', - }, -]; - -export const DappLoginDialog = ({ actorType, onClose, open, title }) => { - const dAppURL = useMemo(() => new ArgsString(""), []); - - const URLInvalid = ArgsError.useInstance("Invalid URL", Validation.isUrl, true); - - const [requestURL, requestURLUpdate] = useReducer((currentValue, value) => { - if (URLInvalid.$detected) { - return currentValue; - } else { - const url = new URL(value); - url.searchParams.set("account_id", STORAGE.addresses[actorType]); - url.searchParams.set("public_key", "ed25519%3ADEaoD65LomNHAMzhNZva15LC85ntwBHdcTbCnZRXciZH"); - url.searchParams.set("all_keys", "ed25519%3A9jeqkc8ybv7aYSA7uLNFUEn8cgKo759yue4771bBWsSr"); - return url.toString(); - } - }); - - return ( - window.open(requestURL, "_blank")} - {...{ onClose, open, title }} - > -
    - {DAPP_LOGIN_INSTRUCTIONS.map(({ text, hint }) => ( -
  • - - {text} - - {hint && ( - - - - )} - -
  • - ))} -
- - requestURLUpdate(target.value)} - value={dAppURL} - variant="filled" - /> -
- ); -}; +import { Dialog, TextInput } from "../../shared/ui/components"; export const SaveAsJsonDialog = ({ onClose, open }) => { const [fileName, fileNameUpdate] = useState("my-multicall"); return ( saveFile(`${fileName}.json`, [JSON.stringify(LAYOUT.toBase64(), null, 2)])} title="Save As JSON" @@ -124,7 +40,6 @@ export const LoadFromJsonDialog = ({ open, ...props }) => { return ( readFile(uploadedFile, (json) => LAYOUT.fromBase64(json))} @@ -193,7 +108,6 @@ export const LoadFromProposalDialog = ({ onClose, open }) => { return ( window.LAYOUT.fromBase64(argsFromProposal)} noSubmit={URLInvalid.$detected || proposalURLInvalid.$detected || proposalNonCompatible.$detected} @@ -218,7 +132,6 @@ export const LoadFromProposalDialog = ({ onClose, open }) => { export const ClearAllDialog = ({ onClose, open }) => ( LAYOUT.clear()} title="Clear All" diff --git a/src/widgets/sidebar/dialogs.scss b/src/widgets/sidebar/dialogs.scss deleted file mode 100644 index b7b24d8d..00000000 --- a/src/widgets/sidebar/dialogs.scss +++ /dev/null @@ -1,29 +0,0 @@ -@use "sass/size"; -@use "sass/mixin"; - -.modal-dialog .MuiPaper-root { - min-width: size.$task-width; -} - -.dapp-login-steps { - padding: 0 size.$gap; - list-style-type: decimal; - font-size: size.$text; - - .item { - .content { - @include mixin.center-items(flex-start, center); - flex-flow: row nowrap; - gap: 0.5ch; - padding-left: 0.25 * size.$gap; - - .icon { - @include mixin.light-icon; - } - } - - &::marker { - font-weight: 800; - } - } -} diff --git a/src/widgets/sidebar/sidebar.jsx b/src/widgets/sidebar/sidebar.jsx index e456d666..c345fef8 100644 --- a/src/widgets/sidebar/sidebar.jsx +++ b/src/widgets/sidebar/sidebar.jsx @@ -14,33 +14,27 @@ import Discord from "../../app/static/discord.svg"; import Github from "../../app/static/github.svg"; import Twitter from "../../app/static/twitter.svg"; import { Wallet } from "../../entities/wallet"; +import { DappLogin } from "../../features"; import { STORAGE } from "../../shared/lib/persistent"; import { viewAccount } from "../../shared/lib/wallet"; import { PopupMenu, Tooltip } from "../../shared/ui/components"; -import { - DappLoginDialog, - LoadFromJsonDialog, - LoadFromProposalDialog, - SaveAsJsonDialog, - ClearAllDialog, -} from "./dialogs.jsx"; +import { LoadFromJsonDialog, LoadFromProposalDialog, SaveAsJsonDialog, ClearAllDialog } from "./dialogs.jsx"; import "./sidebar.scss"; -const DAPP_LOGIN_METHODS = { - dao: { actorType: "dao", key: "daoDappLogin", title: "Login in dApps as DAO" }, - multicall: { actorType: "multicall", key: "multicallDappLogin", title: "Login in dApps as Multicall" }, -}; - export class Sidebar extends Component { constructor(props) { super(props); this.state = { - featureFlags: { - daoDappLogin: true, - multicallDappLogin: false, + FeatureFlags: { + initialized: false, + + DappLogin: { + [DappLogin.METHODS.dao.type]: true, + [DappLogin.METHODS.multicall.type]: false, + }, }, dialogs: { @@ -48,25 +42,45 @@ export class Sidebar extends Component { loadFromJSON: false, loadFromProposal: false, clearAll: false, - daoDappLogin: false, - multicallDappLogin: false, }, }; } - componentDidMount() { - window.SIDEBAR = this; - document.addEventListener("onaddressesupdated", () => this.forceUpdate()); + static walletContext = Wallet.useSelector(); + + featureFlagsCalc() { + viewAccount(STORAGE.addresses.multicall) + .then(() => + this.setState({ + FeatureFlags: { + ...this.state.FeatureFlags, + initialized: true, + + DappLogin: { + ...this.state.FeatureFlags.DappLogin, + [DappLogin.METHODS.multicall.type]: true, + }, + }, + }) + ) + .catch(() => + this.setState({ + FeatureFlags: { + ...this.state.FeatureFlags, + initialized: true, + + DappLogin: { + ...this.state.FeatureFlags.DappLogin, + [DappLogin.METHODS.multicall.type]: false, + }, + }, + }) + ); } - componentDidUpdate(_, previousState) { - if (this.state !== previousState) { - viewAccount(STORAGE.addresses.multicall) - .then(() => this.setState({ featureFlags: { ...this.state.featureFlags, multicallDappLogin: true } })) - .catch(() => - this.setState({ featureFlags: { ...this.state.featureFlags, multicallDappLogin: false } }) - ); - } + componentDidMount() { + window.SIDEBAR = this; + document.addEventListener("onaddressesupdated", () => this.featureFlagsCalc()); } openDialog(name) { @@ -82,14 +96,6 @@ export class Sidebar extends Component { const { dialogs } = this.state; return [ - ...Object.values(DAPP_LOGIN_METHODS).map((props) => ( - this.closeDialog(props.key)} - open={dialogs[props.key]} - {...props} - /> - )), - this.closeDialog("saveAsJSON")} @@ -149,14 +155,8 @@ export class Sidebar extends Component {
- } - items={Object.values(DAPP_LOGIN_METHODS).map(({ key, title }) => ({ - disabled: !this.state.featureFlags[key], - key, - onClick: () => this.openDialog(key), - title, - }))} +
@@ -171,6 +171,7 @@ export class Sidebar extends Component { title: "Save as JSON", }, { + disabled: true, title: "Share as Link", label: "coming soon!", }, From 307e6509c44183a23b8598c0d813e11ad6d778bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 3 Oct 2022 23:05:33 +0400 Subject: [PATCH 144/537] fix: Use correct property name --- src/entities/fungible-token/model/ft-balances.ts | 4 ++-- src/entities/fungible-token/ui/ft-balances.tsx | 6 +++--- src/entities/near-token/model/near-balances.ts | 4 ++-- src/entities/near-token/ui/near-balances.tsx | 6 +++--- src/widgets/sidebar/sidebar.jsx | 9 +-------- src/widgets/tokens-balances/ui/tokens-balances.tsx | 8 ++++---- 6 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/entities/fungible-token/model/ft-balances.ts b/src/entities/fungible-token/model/ft-balances.ts index bc4f816c..3e5d2a5b 100644 --- a/src/entities/fungible-token/model/ft-balances.ts +++ b/src/entities/fungible-token/model/ft-balances.ts @@ -50,10 +50,10 @@ const fungibleTokensDataFx = async ({ dao, multicall }: DaoContracts, callback: }); }; -const useFungibleTokensData = (daoContracts: DaoContracts) => { +const useFungibleTokensData = (contracts: DaoContracts) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void fungibleTokensDataFx(daoContracts, stateUpdate), []); + useEffect(() => void fungibleTokensDataFx(contracts, stateUpdate), []); return state; }; diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index eb62a3e0..54be9789 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -4,11 +4,11 @@ import { FungibleTokenFormat } from "../lib/ft-format"; import { FungibleTokenBalancesModel } from "../model/ft-balances"; interface FungibleTokensBalancesRenderProps { - daoContracts: DaoContracts; + contracts: DaoContracts; } -export const fungibleTokensBalancesRender = ({ daoContracts }: FungibleTokensBalancesRenderProps) => { - const { data } = FungibleTokenBalancesModel.useAllData(daoContracts); +export const fungibleTokensBalancesRender = ({ contracts }: FungibleTokensBalancesRenderProps) => { + const { data } = FungibleTokenBalancesModel.useAllData(contracts); return !data ? null diff --git a/src/entities/near-token/model/near-balances.ts b/src/entities/near-token/model/near-balances.ts index 625770da..ed3b9c50 100644 --- a/src/entities/near-token/model/near-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -30,10 +30,10 @@ const nearTokenDataFx = async ({ dao, multicall }: DaoContracts, callback: (data }); }; -const useNearTokenData = (daoContracts: DaoContracts) => { +const useNearTokenData = (contracts: DaoContracts) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void nearTokenDataFx(daoContracts, stateUpdate), []); + useEffect(() => void nearTokenDataFx(contracts, stateUpdate), []); return state; }; diff --git a/src/entities/near-token/ui/near-balances.tsx b/src/entities/near-token/ui/near-balances.tsx index 8a4538aa..205fbfc2 100644 --- a/src/entities/near-token/ui/near-balances.tsx +++ b/src/entities/near-token/ui/near-balances.tsx @@ -3,11 +3,11 @@ import type { DaoContracts } from "../../types"; import { NearTokenBalancesModel } from "../model/near-balances"; interface NearTokenBalancesRenderProps { - daoContracts: DaoContracts; + contracts: DaoContracts; } -export const nearTokenBalancesRender = ({ daoContracts }: NearTokenBalancesRenderProps) => { - const { data } = NearTokenBalancesModel.useData(daoContracts); +export const nearTokenBalancesRender = ({ contracts }: NearTokenBalancesRenderProps) => { + const { data } = NearTokenBalancesModel.useData(contracts); return !data ? null : [, data.multicall, data.dao, data.total]; }; diff --git a/src/widgets/sidebar/sidebar.jsx b/src/widgets/sidebar/sidebar.jsx index c345fef8..035b713e 100644 --- a/src/widgets/sidebar/sidebar.jsx +++ b/src/widgets/sidebar/sidebar.jsx @@ -1,11 +1,4 @@ -import { - DeleteForeverOutlined, - FileDownloadOutlined, - FileUploadOutlined, - PreviewOutlined, - ScienceOutlined, -} from "@mui/icons-material"; - +import { DeleteForeverOutlined, FileDownloadOutlined, FileUploadOutlined, ScienceOutlined } from "@mui/icons-material"; import { Icon } from "@mui/material"; import { Component } from "react"; import { NavLink } from "react-router-dom"; diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index 816cf8c0..620803e4 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -4,12 +4,12 @@ import { FungibleToken, NearToken } from "../../../entities"; interface TokensBalancesProps { className?: string; - daoContracts: DaoContracts; + contracts: DaoContracts; } -export const TokensBalances = ({ className, daoContracts }: TokensBalancesProps) => { - const nearTokenBalances = NearToken.balancesRender({ daoContracts }), - fungibleTokensBalances = FungibleToken.allBalancesRender({ daoContracts }); +export const TokensBalances = ({ className, contracts }: TokensBalancesProps) => { + const nearTokenBalances = NearToken.balancesRender({ contracts }), + fungibleTokensBalances = FungibleToken.allBalancesRender({ contracts }); return ( From 917ac2246b5d78e5bbccf92da056ce2b03af98fa Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Mon, 3 Oct 2022 23:40:13 +0200 Subject: [PATCH 145/537] fix: hide app page buttons on dao page --- src/index.tsx | 2 -- src/pages/app/app.jsx | 2 +- src/pages/dao/dao.tsx | 2 +- src/shared/lib/persistent.ts | 2 +- src/shared/lib/window.ts | 7 ++----- src/widgets/sidebar/sidebar.jsx | 11 ++++++++++- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 729caab1..0c83cb4a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,8 +8,6 @@ import { Wallet } from "./entities"; import { DialogsLayer, Sidebar } from "./widgets"; import "./shared/lib/persistent"; -window.PAGE = "app"; - ReactDOM.render( diff --git a/src/pages/app/app.jsx b/src/pages/app/app.jsx index 681f4191..89697977 100644 --- a/src/pages/app/app.jsx +++ b/src/pages/app/app.jsx @@ -474,7 +474,7 @@ export class AppPage extends Component { } componentDidMount() { - window.PAGE = "app"; + window.SIDEBAR.switchPage("app"); window.LAYOUT = this; STORAGE.load(); } diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index e2fc649c..d61885c4 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -522,7 +522,7 @@ export class DaoPage extends Component { } componentDidMount(): void { - window.PAGE = "dao"; + window.SIDEBAR.switchPage("dao"); document.addEventListener("onaddressesupdated", () => this.onAddressesUpdated()); } diff --git a/src/shared/lib/persistent.ts b/src/shared/lib/persistent.ts index bb09aa8d..62cd55c3 100644 --- a/src/shared/lib/persistent.ts +++ b/src/shared/lib/persistent.ts @@ -53,7 +53,7 @@ class Persistent { } save() { - if (window.PAGE !== "app") return; + if (window.SIDEBAR.getPage() !== "app") return; localStorage.setItem(STORAGE_KEY_ADDRESSES, JSON.stringify(this.addresses)); localStorage.setItem(STORAGE_KEY_JSON, JSON.stringify(window.LAYOUT.toBase64())); diff --git a/src/shared/lib/window.ts b/src/shared/lib/window.ts index 68097609..73d14db5 100644 --- a/src/shared/lib/window.ts +++ b/src/shared/lib/window.ts @@ -2,7 +2,7 @@ import * as nearAPI from "near-api-js"; import type { NetworkId } from "@near-wallet-selector/core"; import { Component } from "react"; -import { Task, Layout } from "../../widgets"; +import { Task, Layout, Sidebar } from "../../widgets"; type CardInfo = { call: object; @@ -27,14 +27,11 @@ declare global { EXPORT: Component; LAYOUT: Layout; - SIDEBAR: Component; + SIDEBAR: Sidebar; // List of all mounted tasks TASKS: Array; - // Indicates what page is opened - PAGE: "app" | "dao"; - // Temporary storage for moving and cloning cards TEMP: CardInfo | null; COPY: CardCopy | null; diff --git a/src/widgets/sidebar/sidebar.jsx b/src/widgets/sidebar/sidebar.jsx index 035b713e..a884bcfd 100644 --- a/src/widgets/sidebar/sidebar.jsx +++ b/src/widgets/sidebar/sidebar.jsx @@ -36,6 +36,7 @@ export class Sidebar extends Component { loadFromProposal: false, clearAll: false, }, + page: "app", }; } @@ -76,6 +77,14 @@ export class Sidebar extends Component { document.addEventListener("onaddressesupdated", () => this.featureFlagsCalc()); } + switchPage(to) { + this.setState({ page: to }); + } + + getPage() { + return this.state.page; + } + openDialog(name) { this.setState({ dialogs: { ...this.state.dialogs, [name]: true } }); } @@ -154,7 +163,7 @@ export class Sidebar extends Component { />
- {window.PAGE === "app" ? ( + {this.state.page === "app" ? ( <> } From 25799ed3fc89bd81da63d2dd46241d081ba5cfb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 4 Oct 2022 04:35:44 +0400 Subject: [PATCH 146/537] chore: Recheck deps on devserver start for smoother branches switching --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da63c3ab..d67f15b0 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "build:mainnet": "NEAR_ENV=mainnet yarn build", "deploy:pages": "echo 'testnet.multicall.app' > ./dist/CNAME && gh-pages -d dist/", "deploy": "yarn build && yarn deploy:pages", - "start": "rm -rf .parcel-cache && echo 'The app is starting! It will automatically open in your browser when ready' && parcel src/index.html --open", + "start": "rm -rf .parcel-cache && yarn && echo 'The app is starting! It will automatically open in your browser when ready' && parcel src/index.html --open", "start:testnet": "NEAR_ENV=testnet yarn start", "start:mainnet": "NEAR_ENV=mainnet yarn start", "test": "jest test --runInBand", From e32ef49dc752d43332cceb69586dabe8f4730728 Mon Sep 17 00:00:00 2001 From: Dali Chelbi Date: Tue, 4 Oct 2022 02:58:01 +0200 Subject: [PATCH 147/537] revert "chore: Recheck deps on devserver start for smoother branches switching" --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d67f15b0..da63c3ab 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "build:mainnet": "NEAR_ENV=mainnet yarn build", "deploy:pages": "echo 'testnet.multicall.app' > ./dist/CNAME && gh-pages -d dist/", "deploy": "yarn build && yarn deploy:pages", - "start": "rm -rf .parcel-cache && yarn && echo 'The app is starting! It will automatically open in your browser when ready' && parcel src/index.html --open", + "start": "rm -rf .parcel-cache && echo 'The app is starting! It will automatically open in your browser when ready' && parcel src/index.html --open", "start:testnet": "NEAR_ENV=testnet yarn start", "start:mainnet": "NEAR_ENV=mainnet yarn start", "test": "jest test --runInBand", From ff9740c46ab608b3bb34d37b6000a97cbbc56eb0 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Tue, 4 Oct 2022 03:23:43 +0200 Subject: [PATCH 148/537] fix: better visualize loading tokens --- src/widgets/tokens-balances/ui/tokens-balances.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index 620803e4..b788b3bd 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -15,16 +15,16 @@ export const TokensBalances = ({ className, contracts }: TokensBalancesProps) =>

Tokens balances

- {!nearTokenBalances ?? !fungibleTokensBalances ? ( -
- ) : ( + {(nearTokenBalances ?? fungibleTokensBalances) && (
)} + + {(!nearTokenBalances || !fungibleTokensBalances) &&
} ); }; From 3d52d48c59b71f6f54ca129e910eefc796eab0ca Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Tue, 4 Oct 2022 03:25:15 +0200 Subject: [PATCH 149/537] chore: rename mobile -> compact --- src/shared/ui/components/table/row.scss | 2 +- src/shared/ui/components/table/row.tsx | 2 +- src/shared/ui/components/table/table.scss | 2 +- src/shared/ui/components/table/table.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index c71aa272..8506df86 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -29,7 +29,7 @@ background-color: color.$lightest; } - &--mobile { + &--compact { display: flex; flex-direction: column; gap: 0.25 * size.$gap; diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 887f9da0..46381f3e 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -19,7 +19,7 @@ export const TableRow = ({ cells, headerCells }: TableRowProps) => ( ); -const _TableRowCard = `${_TableRow}--mobile`; +const _TableRowCard = `${_TableRow}--compact`; export const TableRowCard = ({ cells, headerCells }: TableRowProps) => (
diff --git a/src/shared/ui/components/table/table.scss b/src/shared/ui/components/table/table.scss index 86962f52..ad19eea8 100644 --- a/src/shared/ui/components/table/table.scss +++ b/src/shared/ui/components/table/table.scss @@ -40,7 +40,7 @@ } } - &--mobile { + &--compact { display: flex; flex-flow: column nowrap; gap: size.$gap; diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 500184be..9fed179c 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -22,7 +22,7 @@ export const Table = ({ header, rows }: TableProps) => { return ( <> {matches ? ( -
+
{rows && rows.map((cells, index) => ( Date: Tue, 4 Oct 2022 03:28:11 +0200 Subject: [PATCH 150/537] chore: rename Facet -> Tile --- src/pages/dao/dao.tsx | 18 +++++++++--------- src/shared/ui/components/facet/facet.scss | 2 +- src/shared/ui/components/facet/facet.tsx | 6 +++--- src/shared/ui/components/facet/index.ts | 2 +- src/shared/ui/components/index.ts | 2 +- .../tokens-balances/ui/tokens-balances.tsx | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index d61885c4..15c10f0c 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -13,7 +13,7 @@ import { ProposalStatus, SputnikDAO, SputnikUI } from "../../shared/lib/contract import { Big, toNEAR, toYocto } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { view } from "../../shared/lib/wallet"; -import { Facet, Scrollable, Tabs, TextInput } from "../../shared/ui/components"; +import { Tile, Scrollable, Tabs, TextInput } from "../../shared/ui/components"; import { TokensBalances } from "../../widgets/tokens-balances"; import "./config/config.scss"; @@ -445,7 +445,7 @@ export class DaoPage extends Component { content: (
- +

Admins

@@ -454,9 +454,9 @@ export class DaoPage extends Component {
  • {this.toLink(admin)}
  • ))} -
    + - +

    Whitelisted Tokens

      @@ -464,20 +464,20 @@ export class DaoPage extends Component {
    • {this.toLink(token)}
    • ))}
    -
    + - +

    Jobs

    {info.jobs.map((j) => this.job(j))} -
    + - +

    Job Bond {`${info.jobBond !== "..." ? toNEAR(info.jobBond) : "..."} Ⓝ`}

    -
    +
    ), }, diff --git a/src/shared/ui/components/facet/facet.scss b/src/shared/ui/components/facet/facet.scss index d4297eef..5ee231ab 100644 --- a/src/shared/ui/components/facet/facet.scss +++ b/src/shared/ui/components/facet/facet.scss @@ -1,7 +1,7 @@ @use "sass/size"; @use "sass/color"; -.Facet { +.Tile { display: flex; flex-flow: column nowrap; position: relative; diff --git a/src/shared/ui/components/facet/facet.tsx b/src/shared/ui/components/facet/facet.tsx index c4ccb68a..5f6b29d6 100644 --- a/src/shared/ui/components/facet/facet.tsx +++ b/src/shared/ui/components/facet/facet.tsx @@ -3,8 +3,8 @@ import { HTMLAttributes, PropsWithChildren } from "react"; import "./facet.scss"; -const _Facet = "Facet"; +const _Tile = "Tile"; -export interface FacetProps extends PropsWithChildren, HTMLAttributes {} +export interface TileProps extends PropsWithChildren, HTMLAttributes {} -export const Facet = ({ children, className }: FacetProps) =>
    {children}
    ; +export const Tile = ({ children, className }: TileProps) =>
    {children}
    ; diff --git a/src/shared/ui/components/facet/index.ts b/src/shared/ui/components/facet/index.ts index 84f0c3bc..a20e508d 100644 --- a/src/shared/ui/components/facet/index.ts +++ b/src/shared/ui/components/facet/index.ts @@ -1 +1 @@ -export { Facet } from "./facet"; +export { Tile } from "./facet"; diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 16373f92..c5514c60 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,4 +1,4 @@ -export { Facet } from "./facet/facet"; +export { Tile } from "./facet/facet"; export { Dialog, type DialogProps } from "./dialog/dialog"; export { NearIcons } from "./icons"; export { PopupMenu, type PopupMenuProps } from "./popup-menu/popup-menu"; diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index b788b3bd..57e34c84 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -1,4 +1,4 @@ -import { Facet, Scrollable, Table } from "../../../shared/ui/components"; +import { Tile, Scrollable, Table } from "../../../shared/ui/components"; import { type DaoContracts } from "../../../entities/types"; import { FungibleToken, NearToken } from "../../../entities"; @@ -12,7 +12,7 @@ export const TokensBalances = ({ className, contracts }: TokensBalancesProps) => fungibleTokensBalances = FungibleToken.allBalancesRender({ contracts }); return ( - +

    Tokens balances

    {(nearTokenBalances ?? fungibleTokensBalances) && ( @@ -25,6 +25,6 @@ export const TokensBalances = ({ className, contracts }: TokensBalancesProps) => )} {(!nearTokenBalances || !fungibleTokensBalances) &&
    } - + ); }; From 1a1da1754189587eb5db002c414bc85c0d7b4a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 4 Oct 2022 06:39:36 +0400 Subject: [PATCH 151/537] feat: Introduce display mode selection for table --- src/pages/dao/dao.tsx | 1 - src/shared/ui/components/table/row.scss | 20 +++++---- src/shared/ui/components/table/row.tsx | 6 +-- src/shared/ui/components/table/table.scss | 9 ++-- src/shared/ui/components/table/table.tsx | 50 +++++++++++++++-------- 5 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 6085b773..5148c26f 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -15,7 +15,6 @@ import { Tabs, TextInput } from "../../shared/ui/components"; import { DaoFundsTab } from "./funds/funds"; import { DaoJobsTab } from "./jobs/jobs"; import { DaoConfigTab } from "./config/config"; - import "./dao.scss"; // minimum balance a multicall instance needs for storage + state. diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index c71aa272..23031799 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -17,11 +17,11 @@ &:first-of-type { text-align: left; font-family: font.$text; - padding-left: 1.25 * size.$gap; + padding-left: calc(1.25 * size.$gap); } &:last-of-type { - padding-right: 1.25 * size.$gap; + padding-right: calc(1.25 * size.$gap); } } @@ -29,28 +29,34 @@ background-color: color.$lightest; } - &--mobile { + &--compact { display: flex; flex-direction: column; - gap: 0.25 * size.$gap; + gap: calc(0.5 * size.$gap); border-radius: size.$task-radius; padding: size.$gap; background-color: color.$light; + } - & > div { + &-content { + &--compact { display: flex; justify-content: space-between; align-items: center; - font-size: size.$text; + font-size: calc(1.1 * size.$text); + span:first-of-type { font-weight: 800; } + &:first-of-type { - margin-bottom: 0.5 * size.$gap; + margin-bottom: calc(0.5 * size.$gap); + & > span { &:first-of-type { display: none; } + &:last-child { font-size: size.$large-text; } diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 887f9da0..e06d41e7 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -19,13 +19,11 @@ export const TableRow = ({ cells, headerCells }: TableRowProps) => ( ); -const _TableRowCard = `${_TableRow}--mobile`; - export const TableRowCard = ({ cells, headerCells }: TableRowProps) => ( -
    +
    {headerCells.map((headerCell, headerCellIndex) => (
    {headerCell} diff --git a/src/shared/ui/components/table/table.scss b/src/shared/ui/components/table/table.scss index 86962f52..9d553f77 100644 --- a/src/shared/ui/components/table/table.scss +++ b/src/shared/ui/components/table/table.scss @@ -9,7 +9,7 @@ .MuiTableCell-root { border-bottom: none; - padding: 0.5 * size.$gap; + padding: calc(0.5 * size.$gap); } table { @@ -31,18 +31,19 @@ &:first-of-type { text-align: left; - padding-left: 1.25 * size.$gap; + padding-left: calc(1.25 * size.$gap); } &:last-of-type { - padding-right: 1.25 * size.$gap; + padding-right: calc(1.25 * size.$gap); } } } - &--mobile { + &--compact { display: flex; flex-flow: column nowrap; + padding: calc(1.25 * size.$gap); gap: size.$gap; } } diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 500184be..ff900540 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -12,30 +12,35 @@ import { TableRowCard, TableRow, type TableRowProps } from "./row"; import "./table.scss"; interface TableProps { + /** + * `"classic"` mode is a classic table view. + * + * In `"compact"` mode, the table is being rendered as a single column with `rows` rendered as cards, + * where every card is entitled by corresponding element from `header`. + * + * In `"default"` mode, the table is being rendered according to the screen size: + * `"classic"` mode is meant for wide screens, while `"compact"` is meant for medium and small ones. + * + * Whether `"compact"` or `"classic"` mode is selected, it's being applied regardless of the screen size. + */ + displayMode?: "default" | "compact" | "classic"; header: TableRowProps["headerCells"]; rows?: TableRowProps["cells"][]; } -export const Table = ({ header, rows }: TableProps) => { - const matches = useMediaQuery(useTheme().breakpoints.down("md")); +const _Table = "Table"; + +export const Table = ({ displayMode = "default", header, rows }: TableProps) => { + const mediumOrSmallScreen = useMediaQuery(useTheme().breakpoints.down("md")), + classicModeRequired = (!mediumOrSmallScreen && displayMode === "default") || displayMode === "classic", + compactModeRequired = (mediumOrSmallScreen && displayMode === "default") || displayMode === "compact"; return ( <> - {matches ? ( -
    - {rows && - rows.map((cells, index) => ( - - ))} -
    - ) : ( - + {classicModeRequired && ( +
    - + {header.map((headerCell, index) => ( {headerCell} @@ -55,6 +60,19 @@ export const Table = ({ header, rows }: TableProps) => {
    )} + + {compactModeRequired && ( +
    + {rows && + rows.map((cells, index) => ( + + ))} +
    + )} ); }; From ec0218395d0be7c63ba88cf7229cf639d47a25fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 4 Oct 2022 07:15:00 +0400 Subject: [PATCH 152/537] Fix merging artifacts --- src/pages/dao/config/config.tsx | 14 +++++++------- src/pages/dao/jobs/jobs.tsx | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 4cfe0763..832e5516 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -5,7 +5,7 @@ import type { HTMLProps } from "react"; import { ArgsAccount } from "../../../shared/lib/args"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { toNEAR } from "../../../shared/lib/converter"; -import { Facet } from "../../../shared/ui/components"; +import { Tile } from "../../../shared/ui/components"; import "./config.scss"; @@ -36,7 +36,7 @@ const _DaoConfigTab = "DaoConfigTab"; const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfigTabComponentProps) => (
    - +

    Admins

    @@ -47,9 +47,9 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi ))} -
    + - +

    Whitelisted Tokens

      @@ -59,14 +59,14 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi ))}
    -
    + - +

    Job Bond {`${multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "..."} Ⓝ`}

    -
    +
    ); diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index aa3173b2..ab6b346d 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -3,7 +3,7 @@ import clsx from "clsx"; import type { HTMLProps } from "react"; import { JobSchema } from "../../../shared/lib/contracts/multicall"; -import { Facet, Scrollable } from "../../../shared/ui/components"; +import { Tile, Scrollable } from "../../../shared/ui/components"; import "./jobs.scss"; @@ -27,7 +27,7 @@ const _DaoJobsTab = "DaoJobsTab"; const DaoJobsTabComponent = ({ className, jobs }: DaoJobsTabComponentProps) => (
    - +

    Jobs

    @@ -38,7 +38,7 @@ const DaoJobsTabComponent = ({ className, jobs }: DaoJobsTabComponentProps) => ( /> ))} -
    +
    ); From 0e64ecdcc0eb6de09ca64659cb3dd6dbb143db3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 20:16:20 +0400 Subject: [PATCH 153/537] wip: Update types and models --- src/entities/fungible-token/config.ts | 10 ++++++ src/entities/fungible-token/index.ts | 2 ++ .../fungible-token/model/ft-balances.ts | 15 +++++---- .../fungible-token/ui/ft-balances.tsx | 8 ++--- src/entities/index.ts | 5 +-- src/entities/near-token/config.ts | 10 ++++++ src/entities/near-token/index.ts | 2 ++ .../near-token/model/near-balances.ts | 16 +++++----- src/entities/near-token/ui/near-balances.tsx | 6 ++-- src/entities/types.d.ts | 8 ----- src/pages/dao/funds/funds.tsx | 4 +-- src/shared/lib/contracts/multicall.ts | 31 ++++++++++--------- src/widgets/index.ts | 1 + src/widgets/tokens-balances/config.ts | 6 ++++ src/widgets/tokens-balances/index.ts | 3 +- .../tokens-balances/ui/tokens-balances.tsx | 8 ++--- 16 files changed, 81 insertions(+), 54 deletions(-) delete mode 100644 src/entities/types.d.ts create mode 100644 src/widgets/tokens-balances/config.ts diff --git a/src/entities/fungible-token/config.ts b/src/entities/fungible-token/config.ts index 1b9d6ccd..a49d50e7 100644 --- a/src/entities/fungible-token/config.ts +++ b/src/entities/fungible-token/config.ts @@ -1 +1,11 @@ +import { Multicall } from "../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; + +export interface Dependencies { + contracts: { + dao: SputnikDAO; + multicall: Multicall; + }; +} + export const FRACTIONAL_PART_LENGTH = 5; diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 76f09041..dfa2be31 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -3,3 +3,5 @@ import { fungibleTokensBalancesRender } from "./ui/ft-balances"; export class FungibleToken { static allBalancesRender = fungibleTokensBalancesRender; } + +export { type Dependencies as FungibleTokensDependencies } from "./config"; diff --git a/src/entities/fungible-token/model/ft-balances.ts b/src/entities/fungible-token/model/ft-balances.ts index 3e5d2a5b..cd6a74bc 100644 --- a/src/entities/fungible-token/model/ft-balances.ts +++ b/src/entities/fungible-token/model/ft-balances.ts @@ -2,14 +2,17 @@ import { useEffect, useState } from "react"; import { Big } from "../../../shared/lib/converter"; import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; -import { DaoContracts } from "../../types"; +import { Dependencies } from "../config"; -type FungibleTokensData = { +type FungibleTokensDataFxResponse = { data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; loading: boolean; }; -const fungibleTokensDataFx = async ({ dao, multicall }: DaoContracts, callback: (data: FungibleTokensData) => void) => { +const fungibleTokensDataFx = async ( + { dao, multicall }: Dependencies["contracts"], + callback: (result: FungibleTokensDataFxResponse) => void +) => { /* Get LikelyTokens list on DAO and its Multicall instance */ const [daoLikelyTokensList, multicallLikelyTokensList] = await Promise.all([ FungibleToken.getLikelyTokenContracts(multicall.address), @@ -50,8 +53,8 @@ const fungibleTokensDataFx = async ({ dao, multicall }: DaoContracts, callback: }); }; -const useFungibleTokensData = (contracts: DaoContracts) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); +const useAllFungibleTokensData = (contracts: Dependencies["contracts"]) => { + const [state, stateUpdate] = useState({ data: null, loading: true }); useEffect(() => void fungibleTokensDataFx(contracts, stateUpdate), []); @@ -59,5 +62,5 @@ const useFungibleTokensData = (contracts: DaoContracts) => { }; export class FungibleTokenBalancesModel { - static useAllData = useFungibleTokensData; + static useAllTokensFrom = useAllFungibleTokensData; } diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index 54be9789..b7347d92 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -1,14 +1,12 @@ import { TokenLabel } from "../../../shared/ui/components"; -import type { DaoContracts } from "../../types"; import { FungibleTokenFormat } from "../lib/ft-format"; import { FungibleTokenBalancesModel } from "../model/ft-balances"; +import { Dependencies } from "../config"; -interface FungibleTokensBalancesRenderProps { - contracts: DaoContracts; -} +interface FungibleTokensBalancesRenderProps extends Dependencies {} export const fungibleTokensBalancesRender = ({ contracts }: FungibleTokensBalancesRenderProps) => { - const { data } = FungibleTokenBalancesModel.useAllData(contracts); + const { data } = FungibleTokenBalancesModel.useAllTokensFrom(contracts); return !data ? null diff --git a/src/entities/index.ts b/src/entities/index.ts index 98abd373..b08244f7 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,4 +1,5 @@ export { Task } from "./task"; -export { FungibleToken } from "./fungible-token"; -export { NearToken } from "./near-token"; +export { Job, type JobDependencies } from "./job"; +export { FungibleToken, type FungibleTokensDependencies } from "./fungible-token"; +export { NearToken, type NearTokenDependencies } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/near-token/config.ts b/src/entities/near-token/config.ts index 1b9d6ccd..a49d50e7 100644 --- a/src/entities/near-token/config.ts +++ b/src/entities/near-token/config.ts @@ -1 +1,11 @@ +import { Multicall } from "../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; + +export interface Dependencies { + contracts: { + dao: SputnikDAO; + multicall: Multicall; + }; +} + export const FRACTIONAL_PART_LENGTH = 5; diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts index 1feb9a3e..04f9366d 100644 --- a/src/entities/near-token/index.ts +++ b/src/entities/near-token/index.ts @@ -3,3 +3,5 @@ import { nearTokenBalancesRender } from "./ui/near-balances"; export class NearToken { static balancesRender = nearTokenBalancesRender; } + +export { type Dependencies as NearTokenDependencies } from "./config"; diff --git a/src/entities/near-token/model/near-balances.ts b/src/entities/near-token/model/near-balances.ts index ed3b9c50..2d36c0fc 100644 --- a/src/entities/near-token/model/near-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -2,15 +2,17 @@ import { useEffect, useState } from "react"; import { Big, formatTokenAmount } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; -import { DaoContracts } from "../../types"; -import { FRACTIONAL_PART_LENGTH } from "../config"; +import { FRACTIONAL_PART_LENGTH, type Dependencies } from "../config"; -type NearTokenData = { +type NearTokenDataFxResponse = { data: { dao: string; multicall: string; total: string } | null; loading: boolean; }; -const nearTokenDataFx = async ({ dao, multicall }: DaoContracts, callback: (data: NearTokenData) => void) => { +const nearTokenDataFx = async ( + { dao, multicall }: Dependencies["contracts"], + callback: (result: NearTokenDataFxResponse) => void +) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ viewAccount(dao.address), viewAccount(multicall.address), @@ -30,8 +32,8 @@ const nearTokenDataFx = async ({ dao, multicall }: DaoContracts, callback: (data }); }; -const useNearTokenData = (contracts: DaoContracts) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); +const useNearTokenData = (contracts: Dependencies["contracts"]) => { + const [state, stateUpdate] = useState({ data: null, loading: true }); useEffect(() => void nearTokenDataFx(contracts, stateUpdate), []); @@ -39,5 +41,5 @@ const useNearTokenData = (contracts: DaoContracts) => { }; export class NearTokenBalancesModel { - static useData = useNearTokenData; + static useTokenFrom = useNearTokenData; } diff --git a/src/entities/near-token/ui/near-balances.tsx b/src/entities/near-token/ui/near-balances.tsx index 205fbfc2..7142a21f 100644 --- a/src/entities/near-token/ui/near-balances.tsx +++ b/src/entities/near-token/ui/near-balances.tsx @@ -1,13 +1,13 @@ import { TokenLabel } from "../../../shared/ui/components"; -import type { DaoContracts } from "../../types"; import { NearTokenBalancesModel } from "../model/near-balances"; +import { type Dependencies } from "../config"; interface NearTokenBalancesRenderProps { - contracts: DaoContracts; + contracts: Dependencies["contracts"]; } export const nearTokenBalancesRender = ({ contracts }: NearTokenBalancesRenderProps) => { - const { data } = NearTokenBalancesModel.useData(contracts); + const { data } = NearTokenBalancesModel.useTokenFrom(contracts); return !data ? null : [, data.multicall, data.dao, data.total]; }; diff --git a/src/entities/types.d.ts b/src/entities/types.d.ts deleted file mode 100644 index 18cafea5..00000000 --- a/src/entities/types.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { SputnikDAO } from "../shared/lib/contracts/sputnik-dao"; -import { FungibleToken } from "../shared/lib/standards/fungibleToken"; -import { Multicall } from "../shared/lib/contracts/multicall"; - -export interface DaoContracts { - dao: SputnikDAO; - multicall: Multicall; -} diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index 452c9b4a..70411e24 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -1,10 +1,10 @@ import clsx from "clsx"; -import { TokensBalances, type TokensBalancesProps } from "../../../widgets/tokens-balances"; +import { TokensBalances, type TokensBalancesDependencies } from "../../../widgets"; import "./funds.scss"; -interface DaoFundsTabComponentProps extends TokensBalancesProps {} +interface DaoFundsTabComponentProps extends TokensBalancesDependencies {} const _DaoFundsTab = "DaoFundsTab"; diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index d60cc6c5..bab0e525 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -20,18 +20,21 @@ const CONTRACT_CODE_HASHES_SELECTOR: Record = { const KEY_JOB_COUNT: string = "g"; -// Schema for Multicall jobs -type JobSchema = { - croncat_hash: string; - creator: string; - bond: string; // string encoded number (u128) - cadence: string; - trigger_gas: string; // string encoded number (u64) - croncat_budget: string; // string encoded number (u128) - start_at: string; // string encoded number (u64) - run_count: number; - is_active: boolean; - multicalls: MulticallArgs[]; +type JobData = { + id: number; + + job: { + croncat_hash: string; + creator: string; + bond: string; // string encoded number (u128) + cadence: string; + trigger_gas: string; // string encoded number (u64) + croncat_budget: string; // string encoded number (u128) + start_at: string; // string encoded number (u64) + run_count: number; + is_active: boolean; + multicalls: MulticallArgs[]; + }; }; type FunctionCall = { @@ -209,7 +212,7 @@ class Multicall { /** * list all currently registered jobs */ - async getJobs(): Promise<{ id: number; job: JobSchema }[]> { + async getJobs(): Promise { return view(this.address, "get_jobs", {}); } @@ -259,4 +262,4 @@ class Multicall { } export { Multicall }; -export type { JobSchema, MulticallArgs }; +export type { JobData, MulticallArgs }; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 7c000370..a23ad260 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -5,3 +5,4 @@ export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export/export.jsx"; export { Sidebar } from "./sidebar/sidebar.jsx"; +export { TokensBalances, type TokensBalancesDependencies } from "./tokens-balances"; diff --git a/src/widgets/tokens-balances/config.ts b/src/widgets/tokens-balances/config.ts new file mode 100644 index 00000000..67ffa8e0 --- /dev/null +++ b/src/widgets/tokens-balances/config.ts @@ -0,0 +1,6 @@ +import { NearTokenDependencies } from "../../entities"; +import { FungibleTokensDependencies } from "../../entities"; + +export interface Dependencies extends FungibleTokensDependencies, NearTokenDependencies { + className?: string; +} diff --git a/src/widgets/tokens-balances/index.ts b/src/widgets/tokens-balances/index.ts index 678d5c73..e478a8b8 100644 --- a/src/widgets/tokens-balances/index.ts +++ b/src/widgets/tokens-balances/index.ts @@ -1 +1,2 @@ -export { TokensBalances, type TokensBalancesProps } from "./ui/tokens-balances"; +export { TokensBalances } from "./ui/tokens-balances"; +export { type Dependencies as TokensBalancesDependencies } from "./config"; diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index 19072610..18f95c59 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -1,13 +1,9 @@ import { Tile, Scrollable, Table } from "../../../shared/ui/components"; -import { type DaoContracts } from "../../../entities/types"; import { FungibleToken, NearToken } from "../../../entities"; -export interface TokensBalancesProps { - className?: string; - contracts: DaoContracts; -} +import { Dependencies } from "../config"; -export const TokensBalances = ({ className, contracts }: TokensBalancesProps) => { +export const TokensBalances = ({ className, contracts }: Dependencies) => { const nearTokenBalances = NearToken.balancesRender({ contracts }), fungibleTokensBalances = FungibleToken.allBalancesRender({ contracts }); From 93b1d4feaafdc4b4062b3458940abf603f0539b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 21:39:52 +0400 Subject: [PATCH 154/537] wip: Implement `Job` entity --- src/entities/job/config.ts | 6 ++++ src/entities/job/index.ts | 7 +++++ src/entities/job/model/job-data.ts | 30 ++++++++++++++++++++ src/entities/job/ui/jobs-list.scss | 2 ++ src/entities/job/ui/jobs-list.tsx | 44 ++++++++++++++++++++++++++++++ src/pages/dao/jobs/jobs.tsx | 39 +++++--------------------- 6 files changed, 96 insertions(+), 32 deletions(-) create mode 100644 src/entities/job/config.ts create mode 100644 src/entities/job/index.ts create mode 100644 src/entities/job/model/job-data.ts create mode 100644 src/entities/job/ui/jobs-list.scss create mode 100644 src/entities/job/ui/jobs-list.tsx diff --git a/src/entities/job/config.ts b/src/entities/job/config.ts new file mode 100644 index 00000000..994af6fb --- /dev/null +++ b/src/entities/job/config.ts @@ -0,0 +1,6 @@ +import { Multicall } from "../../shared/lib/contracts/multicall"; + +export interface Dependencies { + className: string; + contracts: { multicall: Multicall }; +} diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts new file mode 100644 index 00000000..c49dd73f --- /dev/null +++ b/src/entities/job/index.ts @@ -0,0 +1,7 @@ +import { JobsList } from "./ui/jobs-list"; + +export class Job { + static ListOfAll = JobsList; +} + +export { type Dependencies as JobDependencies } from "./config"; diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts new file mode 100644 index 00000000..cce982b8 --- /dev/null +++ b/src/entities/job/model/job-data.ts @@ -0,0 +1,30 @@ +import { useEffect, useState } from "react"; +import { JobData } from "../../../shared/lib/contracts/multicall"; + +import { Dependencies } from "../config"; + +type JobsDataFxResponse = { + data: JobData[] | null; + error?: Error | null; + loading: boolean; +}; + +const jobsDataFx = async ({ multicall }: Dependencies["contracts"], callback: (result: JobsDataFxResponse) => void) => + callback( + await multicall + .getJobs() + .then((data) => ({ data, loading: false })) + .catch((error) => ({ data: null, error: new Error(error), loading: false })) + ); + +const useJobsData = (contracts: Dependencies["contracts"]) => { + const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); + + useEffect(() => void jobsDataFx(contracts, stateUpdate), []); + + return state; +}; + +export class JobDataModel { + static useAllJobsFrom = useJobsData; +} diff --git a/src/entities/job/ui/jobs-list.scss b/src/entities/job/ui/jobs-list.scss new file mode 100644 index 00000000..0dca0631 --- /dev/null +++ b/src/entities/job/ui/jobs-list.scss @@ -0,0 +1,2 @@ +.JobsList { +} diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx new file mode 100644 index 00000000..9b815919 --- /dev/null +++ b/src/entities/job/ui/jobs-list.tsx @@ -0,0 +1,44 @@ +import { Tile, Scrollable, Table } from "../../../shared/ui/components"; +import { Dependencies } from "../config"; +import { JobDataModel } from "../model/job-data"; + +const _Job = ({ data: { croncat_hash, is_active, ...data } }: { data: JobData }) => ( +
    + {is_active ? : } +
    {JSON.stringify(data, null, "  ")}
    +
    +); + +interface JobsListProps extends Dependencies {} + +export const JobsList = ({ className, contracts }: JobsListProps) => { + const { data, loading } = JobDataModel.useAllJobsFrom(contracts); + + return ( + +

    Jobs

    + + {data && ( + + [ + job.is_active ? "Active" : "Inactive", + job.croncat_hash, + job.creator, + job.trigger_gas, + job.run_count, + JSON.stringify(job.multicalls, null, " "), + ])} + /> + + )} + + {loading &&
    } + + ); +}; diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index ab6b346d..45ee8ae2 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -1,44 +1,19 @@ -import { AddOutlined, DeleteOutline, EditOutlined, PauseOutlined, PlayArrowOutlined } from "@mui/icons-material"; import clsx from "clsx"; -import type { HTMLProps } from "react"; -import { JobSchema } from "../../../shared/lib/contracts/multicall"; -import { Tile, Scrollable } from "../../../shared/ui/components"; +import { Job, type JobDependencies } from "../../../entities"; import "./jobs.scss"; -const Job = ({ data: { croncat_hash, is_active, ...data } }: { data: JobSchema }) => ( -
    - - - {is_active ? : } -
    {JSON.stringify(data, null, "  ")}
    -
    -); - -interface DaoJobsTabComponentProps extends HTMLProps { - jobs: JobSchema[]; -} +interface DaoJobsTabComponentProps extends JobDependencies {} const _DaoJobsTab = "DaoJobsTab"; -const DaoJobsTabComponent = ({ className, jobs }: DaoJobsTabComponentProps) => ( +const DaoJobsTabComponent = ({ className, contracts }: DaoJobsTabComponentProps) => (
    - - -

    Jobs

    - - {jobs.map((data) => ( - - ))} - -
    +
    ); From c74716f197b3419fb898e4e7551a677660ec8f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 21:40:20 +0400 Subject: [PATCH 155/537] wip: Render list of all jobs on DAO jobs tab --- src/pages/dao/dao.tsx | 14 ++++---------- src/pages/dao/jobs/jobs.scss | 24 +++++------------------- 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 5148c26f..c3a5b36d 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -6,7 +6,7 @@ import { Component, ContextType } from "react"; import { Wallet } from "../../entities"; import { ArgsAccount, ArgsError } from "../../shared/lib/args"; import { SputnikDAO, SputnikUI, ProposalStatus } from "../../shared/lib/contracts/sputnik-dao"; -import { JobSchema, Multicall } from "../../shared/lib/contracts/multicall"; +import { Multicall } from "../../shared/lib/contracts/multicall"; import { toYocto, Big, toGas } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import type { ProposalOutput } from "../../shared/lib/contracts/sputnik-dao"; @@ -30,7 +30,6 @@ interface State { loading: boolean; proposed: number; proposedInfo: ProposalOutput | null; - jobs: JobSchema[]; } const _DaoPage = "DaoPage"; @@ -49,7 +48,6 @@ export class DaoPage extends Component { loading: false, proposed: -1, proposedInfo: null, - jobs: [], }; this.fee = ""; @@ -340,14 +338,10 @@ export class DaoPage extends Component { return; } else { // DAO correctly initialized, try to fetch multicall info - Promise.all([ - multicall.getJobs().catch(console.error), - this.proposalAlreadyExists(dao).catch(console.error), - ]).then(([jobs, proposalData]) => + Promise.all([this.proposalAlreadyExists(dao).catch(console.error)]).then(([proposalData]) => this.setState(({ proposed }) => ({ dao, multicall, - jobs: jobs || [], loading: false, proposed: proposalData?.proposal_id || proposed, proposedInfo: proposalData?.proposal_info || null, @@ -359,7 +353,7 @@ export class DaoPage extends Component { getContent() { const { selector: walletSelector } = this.context!; - const { dao, jobs, loading, multicall } = this.state; + const { dao, loading, multicall } = this.state; // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) if (!walletSelector.isSignedIn()) { @@ -404,7 +398,7 @@ export class DaoPage extends Component { items={[ DaoConfigTab.connect({ className: `${_DaoPage}-content`, contracts: { multicall } }), DaoFundsTab.connect({ className: `${_DaoPage}-content`, contracts: { dao, multicall } }), - DaoJobsTab.connect({ className: `${_DaoPage}-content`, jobs }), + DaoJobsTab.connect({ className: `${_DaoPage}-content`, contracts: { multicall } }), ]} /> ); diff --git a/src/pages/dao/jobs/jobs.scss b/src/pages/dao/jobs/jobs.scss index ee97d68c..21d1bb5f 100644 --- a/src/pages/dao/jobs/jobs.scss +++ b/src/pages/dao/jobs/jobs.scss @@ -4,26 +4,12 @@ .DaoJobsTab { display: grid; + grid-template: "jobsList" auto; - grid-template: "JobsList" auto; - - .JobsList { - grid-area: JobsList; + &-jobsList { + grid-area: jobsList; + padding-bottom: size.$gap; position: relative; - - &-item { - position: relative; - margin: size.$gap; - margin-top: 0; - border-radius: size.$task-radius; - background-color: color.$lightest; - - pre { - padding: 0.5 * size.$gap; - font-family: font.$code; - font-size: size.$small-text; - overflow: hidden; - } - } + overflow: hidden; } } From 84df4fc2fb2f4dc41f064554eb97a6b3218ee32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 21:41:46 +0400 Subject: [PATCH 156/537] wip: Remove unused code & Wrap job multicalls JSON --- src/entities/job/ui/jobs-list.tsx | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 9b815919..8d1642a3 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -2,16 +2,6 @@ import { Tile, Scrollable, Table } from "../../../shared/ui/components"; import { Dependencies } from "../config"; import { JobDataModel } from "../model/job-data"; -const _Job = ({ data: { croncat_hash, is_active, ...data } }: { data: JobData }) => ( -
    - {is_active ? : } -
    {JSON.stringify(data, null, "  ")}
    -
    -); - interface JobsListProps extends Dependencies {} export const JobsList = ({ className, contracts }: JobsListProps) => { @@ -32,7 +22,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { job.creator, job.trigger_gas, job.run_count, - JSON.stringify(job.multicalls, null, " "), +
    {JSON.stringify(job.multicalls, null, " ")}
    , ])} /> From d46e948bf8c01d241fdddaf5d011264bacb1532b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 22:09:32 +0400 Subject: [PATCH 157/537] wip: Display "Start at" job value --- src/entities/job/ui/jobs-list.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 8d1642a3..c68f8ed1 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,6 +1,7 @@ +import { cronToDate } from "../../../shared/lib/converter"; import { Tile, Scrollable, Table } from "../../../shared/ui/components"; -import { Dependencies } from "../config"; import { JobDataModel } from "../model/job-data"; +import { Dependencies } from "../config"; interface JobsListProps extends Dependencies {} @@ -15,9 +16,18 @@ export const JobsList = ({ className, contracts }: JobsListProps) => {
    [ + header={[ + "Active status", + "Start at", + "Croncat hash", + "Creator", + "Trigger gas", + "Run count", + "Multicalls", + ]} + rows={data.map(({ job }) => [ job.is_active ? "Active" : "Inactive", + cronToDate(job.cadence).toLocaleString(), job.croncat_hash, job.creator, job.trigger_gas, From 22eee9c28f04e1ba9c25c9270953aa81b878f759 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Thu, 6 Oct 2022 21:08:41 +0200 Subject: [PATCH 158/537] display trigger gas in Tgas --- src/entities/job/ui/jobs-list.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index c68f8ed1..35ec1231 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,4 +1,4 @@ -import { cronToDate } from "../../../shared/lib/converter"; +import { cronToDate, toTGas } from "../../../shared/lib/converter"; import { Tile, Scrollable, Table } from "../../../shared/ui/components"; import { JobDataModel } from "../model/job-data"; import { Dependencies } from "../config"; @@ -30,7 +30,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { cronToDate(job.cadence).toLocaleString(), job.croncat_hash, job.creator, - job.trigger_gas, + `${toTGas(job.trigger_gas)} Tgas`, job.run_count,
    {JSON.stringify(job.multicalls, null, " ")}
    , ])} From 3ec6b4cd272be8403c24cd7469a04ef38d7241c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 23:29:52 +0400 Subject: [PATCH 159/537] wip: Create tile for selected job information --- src/entities/job/index.ts | 2 ++ src/entities/job/model/job-data.ts | 7 +++++-- src/entities/job/ui/job-info.tsx | 19 +++++++++++++++++++ src/entities/job/ui/jobs-list.tsx | 12 ++++++++---- src/pages/dao/jobs/jobs.scss | 9 ++++++++- src/pages/dao/jobs/jobs.tsx | 29 +++++++++++++++++++++-------- 6 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 src/entities/job/ui/job-info.tsx diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index c49dd73f..c9278b00 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,6 +1,8 @@ +import { JobInfo } from "./ui/job-info"; import { JobsList } from "./ui/jobs-list"; export class Job { + static Info = JobInfo; static ListOfAll = JobsList; } diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index cce982b8..884246b7 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -4,7 +4,7 @@ import { JobData } from "../../../shared/lib/contracts/multicall"; import { Dependencies } from "../config"; type JobsDataFxResponse = { - data: JobData[] | null; + data: Record | null; error?: Error | null; loading: boolean; }; @@ -13,7 +13,10 @@ const jobsDataFx = async ({ multicall }: Dependencies["contracts"], callback: (r callback( await multicall .getJobs() - .then((data) => ({ data, loading: false })) + .then((data) => ({ + data: data.reduce((jobsRegistry, { id, job }) => ({ ...jobsRegistry, [id]: { id, job } }), {}), + loading: false, + })) .catch((error) => ({ data: null, error: new Error(error), loading: false })) ); diff --git a/src/entities/job/ui/job-info.tsx b/src/entities/job/ui/job-info.tsx new file mode 100644 index 00000000..07c4a006 --- /dev/null +++ b/src/entities/job/ui/job-info.tsx @@ -0,0 +1,19 @@ +import clsx from "clsx"; + +import { JobData } from "../../../shared/lib/contracts/multicall"; +import { Tile } from "../../../shared/ui/components"; +import { Dependencies } from "../config"; + +interface JobInfoProps extends Pick { + id: JobData["id"] | null; +} + +const _JobInfo = "JobInfo"; + +export const JobInfo = ({ className, id }: JobInfoProps) => { + return ( + +

    Job info

    +
    + ); +}; diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index c68f8ed1..2c1a746c 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -3,14 +3,16 @@ import { Tile, Scrollable, Table } from "../../../shared/ui/components"; import { JobDataModel } from "../model/job-data"; import { Dependencies } from "../config"; -interface JobsListProps extends Dependencies {} +interface JobsListProps extends Dependencies { + elementClickHandler: (id: number) => void; +} -export const JobsList = ({ className, contracts }: JobsListProps) => { +export const JobsList = ({ className, contracts, elementClickHandler }: JobsListProps) => { const { data, loading } = JobDataModel.useAllJobsFrom(contracts); return ( -

    Jobs

    +

    All jobs

    {data && ( @@ -18,6 +20,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { displayMode="compact" header={[ "Active status", + "ID", "Start at", "Croncat hash", "Creator", @@ -25,8 +28,9 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { "Run count", "Multicalls", ]} - rows={data.map(({ job }) => [ + rows={Object.values(data).map(({ id, job }) => [ job.is_active ? "Active" : "Inactive", + id, cronToDate(job.cadence).toLocaleString(), job.croncat_hash, job.creator, diff --git a/src/pages/dao/jobs/jobs.scss b/src/pages/dao/jobs/jobs.scss index 21d1bb5f..0ba97bdb 100644 --- a/src/pages/dao/jobs/jobs.scss +++ b/src/pages/dao/jobs/jobs.scss @@ -4,7 +4,14 @@ .DaoJobsTab { display: grid; - grid-template: "jobsList" auto; + grid-template: "jobsList jobInfo" auto / 50%; + + &-jobInfo { + grid-area: jobInfo; + padding-bottom: size.$gap; + position: relative; + overflow: hidden; + } &-jobsList { grid-area: jobsList; diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 45ee8ae2..b4bafbd5 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; +import { useMemo, useState } from "react"; import { Job, type JobDependencies } from "../../../entities"; @@ -8,14 +9,26 @@ interface DaoJobsTabComponentProps extends JobDependencies {} const _DaoJobsTab = "DaoJobsTab"; -const DaoJobsTabComponent = ({ className, contracts }: DaoJobsTabComponentProps) => ( -
    - -
    -); +const DaoJobsTabComponent = ({ className, contracts }: DaoJobsTabComponentProps) => { + const [selectedJobId, selectedJobIdSwitch] = useState(null); + + const jobSelect = useMemo((id: number) => () => selectedJobIdSwitch(id), [selectedJobIdSwitch]); + + return ( +
    + + + +
    + ); +}; export const DaoJobsTab = { connect: (props: DaoJobsTabComponentProps) => ({ From 056c4d608413290f3552cf9585e45d086bf3b1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 23:37:26 +0400 Subject: [PATCH 160/537] wip: Update detailed job view title --- src/entities/job/ui/job-info.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/job/ui/job-info.tsx b/src/entities/job/ui/job-info.tsx index 07c4a006..bf46cd53 100644 --- a/src/entities/job/ui/job-info.tsx +++ b/src/entities/job/ui/job-info.tsx @@ -13,7 +13,7 @@ const _JobInfo = "JobInfo"; export const JobInfo = ({ className, id }: JobInfoProps) => { return ( -

    Job info

    +

    Job details

    ); }; From 0274fac480e4d87395092d355d25e4ebccf1e1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 23:39:52 +0400 Subject: [PATCH 161/537] wip: Update detailed job view naming --- src/entities/job/index.ts | 4 ++-- src/entities/job/ui/{job-info.tsx => job-details.tsx} | 8 ++++---- src/pages/dao/jobs/jobs.scss | 6 +++--- src/pages/dao/jobs/jobs.tsx | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) rename src/entities/job/ui/{job-info.tsx => job-details.tsx} (58%) diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index c9278b00..bb59fc95 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,8 +1,8 @@ -import { JobInfo } from "./ui/job-info"; +import { JobDetails } from "./ui/job-details"; import { JobsList } from "./ui/jobs-list"; export class Job { - static Info = JobInfo; + static Details = JobDetails; static ListOfAll = JobsList; } diff --git a/src/entities/job/ui/job-info.tsx b/src/entities/job/ui/job-details.tsx similarity index 58% rename from src/entities/job/ui/job-info.tsx rename to src/entities/job/ui/job-details.tsx index bf46cd53..e9aae7ba 100644 --- a/src/entities/job/ui/job-info.tsx +++ b/src/entities/job/ui/job-details.tsx @@ -4,15 +4,15 @@ import { JobData } from "../../../shared/lib/contracts/multicall"; import { Tile } from "../../../shared/ui/components"; import { Dependencies } from "../config"; -interface JobInfoProps extends Pick { +interface JobDetailsProps extends Pick { id: JobData["id"] | null; } -const _JobInfo = "JobInfo"; +const _JobDetails = "JobDetails"; -export const JobInfo = ({ className, id }: JobInfoProps) => { +export const JobDetails = ({ className, id }: JobDetailsProps) => { return ( - +

    Job details

    ); diff --git a/src/pages/dao/jobs/jobs.scss b/src/pages/dao/jobs/jobs.scss index 0ba97bdb..f9a0f3cf 100644 --- a/src/pages/dao/jobs/jobs.scss +++ b/src/pages/dao/jobs/jobs.scss @@ -4,10 +4,10 @@ .DaoJobsTab { display: grid; - grid-template: "jobsList jobInfo" auto / 50%; + grid-template: "jobsList jobDetails" auto / 50%; - &-jobInfo { - grid-area: jobInfo; + &-jobDetails { + grid-area: jobDetails; padding-bottom: size.$gap; position: relative; overflow: hidden; diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index b4bafbd5..9a9186fb 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -22,8 +22,8 @@ const DaoJobsTabComponent = ({ className, contracts }: DaoJobsTabComponentProps) {...{ contracts }} /> - From 312413636f55afbe07155064a1bc8ba00b0b0605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 6 Oct 2022 23:56:51 +0400 Subject: [PATCH 162/537] wip: Remove detailed job view --- src/entities/job/index.ts | 2 -- src/entities/job/ui/job-details.tsx | 19 ------------------- src/entities/job/ui/jobs-list.tsx | 6 ++---- src/pages/dao/jobs/jobs.scss | 9 +-------- src/pages/dao/jobs/jobs.tsx | 28 ++++++++-------------------- 5 files changed, 11 insertions(+), 53 deletions(-) delete mode 100644 src/entities/job/ui/job-details.tsx diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index bb59fc95..c49dd73f 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,8 +1,6 @@ -import { JobDetails } from "./ui/job-details"; import { JobsList } from "./ui/jobs-list"; export class Job { - static Details = JobDetails; static ListOfAll = JobsList; } diff --git a/src/entities/job/ui/job-details.tsx b/src/entities/job/ui/job-details.tsx deleted file mode 100644 index e9aae7ba..00000000 --- a/src/entities/job/ui/job-details.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import clsx from "clsx"; - -import { JobData } from "../../../shared/lib/contracts/multicall"; -import { Tile } from "../../../shared/ui/components"; -import { Dependencies } from "../config"; - -interface JobDetailsProps extends Pick { - id: JobData["id"] | null; -} - -const _JobDetails = "JobDetails"; - -export const JobDetails = ({ className, id }: JobDetailsProps) => { - return ( - -

    Job details

    -
    - ); -}; diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 63f6ba8b..8a8751ea 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -3,11 +3,9 @@ import { Tile, Scrollable, Table } from "../../../shared/ui/components"; import { JobDataModel } from "../model/job-data"; import { Dependencies } from "../config"; -interface JobsListProps extends Dependencies { - elementClickHandler: (id: number) => void; -} +interface JobsListProps extends Dependencies {} -export const JobsList = ({ className, contracts, elementClickHandler }: JobsListProps) => { +export const JobsList = ({ className, contracts }: JobsListProps) => { const { data, loading } = JobDataModel.useAllJobsFrom(contracts); return ( diff --git a/src/pages/dao/jobs/jobs.scss b/src/pages/dao/jobs/jobs.scss index f9a0f3cf..f9d1d4a1 100644 --- a/src/pages/dao/jobs/jobs.scss +++ b/src/pages/dao/jobs/jobs.scss @@ -4,14 +4,7 @@ .DaoJobsTab { display: grid; - grid-template: "jobsList jobDetails" auto / 50%; - - &-jobDetails { - grid-area: jobDetails; - padding-bottom: size.$gap; - position: relative; - overflow: hidden; - } + grid-template: "jobsList " auto / 100%; &-jobsList { grid-area: jobsList; diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 9a9186fb..51f04ce7 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -9,26 +9,14 @@ interface DaoJobsTabComponentProps extends JobDependencies {} const _DaoJobsTab = "DaoJobsTab"; -const DaoJobsTabComponent = ({ className, contracts }: DaoJobsTabComponentProps) => { - const [selectedJobId, selectedJobIdSwitch] = useState(null); - - const jobSelect = useMemo((id: number) => () => selectedJobIdSwitch(id), [selectedJobIdSwitch]); - - return ( -
    - - - -
    - ); -}; +const DaoJobsTabComponent = ({ className, contracts }: DaoJobsTabComponentProps) => ( +
    + +
    +); export const DaoJobsTab = { connect: (props: DaoJobsTabComponentProps) => ({ From ee02728e645c213785cd03d612a629f94eeda0c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 7 Oct 2022 00:15:13 +0400 Subject: [PATCH 163/537] wip: Add classname prop for `Table` --- src/shared/ui/components/table/table.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index ff900540..e4be25b6 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -7,11 +7,13 @@ import { useMediaQuery, useTheme, } from "@mui/material"; +import clsx from "clsx"; +import { HTMLAttributes } from "react"; import { TableRowCard, TableRow, type TableRowProps } from "./row"; import "./table.scss"; -interface TableProps { +interface TableProps extends HTMLAttributes { /** * `"classic"` mode is a classic table view. * @@ -30,7 +32,7 @@ interface TableProps { const _Table = "Table"; -export const Table = ({ displayMode = "default", header, rows }: TableProps) => { +export const Table = ({ className, displayMode = "default", header, rows }: TableProps) => { const mediumOrSmallScreen = useMediaQuery(useTheme().breakpoints.down("md")), classicModeRequired = (!mediumOrSmallScreen && displayMode === "default") || displayMode === "classic", compactModeRequired = (mediumOrSmallScreen && displayMode === "default") || displayMode === "compact"; @@ -38,7 +40,7 @@ export const Table = ({ displayMode = "default", header, rows }: TableProps) => return ( <> {classicModeRequired && ( - +
    @@ -62,7 +64,7 @@ export const Table = ({ displayMode = "default", header, rows }: TableProps) => )} {compactModeRequired && ( -
    +
    {rows && rows.map((cells, index) => ( Date: Fri, 7 Oct 2022 00:16:39 +0400 Subject: [PATCH 164/537] wip: Wrap job multicalls with spoiler --- src/entities/job/ui/jobs-list.scss | 7 +++++++ src/entities/job/ui/jobs-list.tsx | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/entities/job/ui/jobs-list.scss b/src/entities/job/ui/jobs-list.scss index 0dca0631..96499323 100644 --- a/src/entities/job/ui/jobs-list.scss +++ b/src/entities/job/ui/jobs-list.scss @@ -1,2 +1,9 @@ .JobsList { + .Table-row-content--compact:last-of-type { + & > span { + &:first-of-type { + display: none; + } + } + } } diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 8a8751ea..7723f409 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -3,8 +3,12 @@ import { Tile, Scrollable, Table } from "../../../shared/ui/components"; import { JobDataModel } from "../model/job-data"; import { Dependencies } from "../config"; +import "./jobs-list.scss"; + interface JobsListProps extends Dependencies {} +const _JobsList = "JobsList"; + export const JobsList = ({ className, contracts }: JobsListProps) => { const { data, loading } = JobDataModel.useAllJobsFrom(contracts); @@ -15,6 +19,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { {data && (
    { job.creator, `${toTGas(job.trigger_gas)} Tgas`, job.run_count, -
    {JSON.stringify(job.multicalls, null, " ")}
    , + +
    + Multicalls +
    {JSON.stringify(job.multicalls, null, " ")}
    +
    , ])} /> From 459877b5afbc1574df7c9aa614ad5432864474e6 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Thu, 6 Oct 2022 22:22:07 +0200 Subject: [PATCH 165/537] add dateTimePicker component --- package.json | 5 +- .../date-time-picker/date-time-picker.tsx | 27 +++++++ .../ui/components/date-time-picker/index.ts | 1 + src/widgets/export/export.jsx | 9 ++- yarn.lock | 81 ++++++++++++++++++- 5 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 src/shared/ui/components/date-time-picker/date-time-picker.tsx create mode 100644 src/shared/ui/components/date-time-picker/index.ts diff --git a/package.json b/package.json index da63c3ab..48c578b7 100644 --- a/package.json +++ b/package.json @@ -65,18 +65,21 @@ "@mui/icons-material": "^5.2.0", "@mui/lab": "^5.0.0-alpha.58", "@mui/material": "^5.0.0", + "@mui/x-date-pickers": "^5.0.4", "@near-wallet-selector/core": "^5.0.0", "@near-wallet-selector/math-wallet": "^5.0.0", "@near-wallet-selector/modal-ui": "^5.0.0", "@near-wallet-selector/my-near-wallet": "^5.0.0", "@near-wallet-selector/near-wallet": "^5.0.0", "@near-wallet-selector/sender": "^5.0.0", + "@types/luxon": "^3.0.1", "@types/react": "^18.0.0", "big.js": "^6.2.1", - "cron-parser": "^4.6.0", "clsx": "^1.2.1", + "cron-parser": "^4.6.0", "js-base64": "^3.7.2", "lodash.debounce": "^4.0.8", + "luxon": "^3.0.4", "near-api-js": "^0.45.1", "object-hash": "^3.0.0", "parcel": "^2.4.0", diff --git a/src/shared/ui/components/date-time-picker/date-time-picker.tsx b/src/shared/ui/components/date-time-picker/date-time-picker.tsx new file mode 100644 index 00000000..83ebd455 --- /dev/null +++ b/src/shared/ui/components/date-time-picker/date-time-picker.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { DateTime } from "luxon"; +import TextField from "@mui/material/TextField"; +import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; +import { AdapterLuxon } from "@mui/x-date-pickers/AdapterLuxon"; +import { DateTimePicker as MaterialUIPicker } from "@mui/x-date-pickers/DateTimePicker"; + +function DateTimePicker() { + const [value, setValue] = React.useState(DateTime.local()); + + const handleChange = (newValue: DateTime | null) => { + setValue(newValue); + }; + + return ( + + } + /> + + ); +} + +export { DateTimePicker }; diff --git a/src/shared/ui/components/date-time-picker/index.ts b/src/shared/ui/components/date-time-picker/index.ts new file mode 100644 index 00000000..6eb58e4a --- /dev/null +++ b/src/shared/ui/components/date-time-picker/index.ts @@ -0,0 +1 @@ +export { DateTimePicker } from "./date-time-picker"; diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index 3184cdbf..c3f6beba 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -233,7 +233,14 @@ export class Export extends Component { Multicall.init(STORAGE.addresses.multicall), ]); const [addJobTx, proposeJobTx] = await Promise.all([ - multicall.addJob([], new Date(), toGas("100"), toYocto("1")), + multicall.addJob( + // TODO: support jobs with multiple multicalls + [multicallArgs], + // trigger date + new Date(), + convert(gas.value, gas.unit), + toYocto("1") + ), dao.proposeJobActivation("test job activation", jobCount, toYocto("1")), ]); signAndSendTxs([addJobTx, proposeJobTx]); diff --git a/yarn.lock b/yarn.lock index 222c5bd2..ed728c82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -971,6 +971,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.18.9", "@babel/runtime@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" + integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.18.10", "@babel/template@^7.18.6", "@babel/template@^7.3.3": version "7.18.10" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" @@ -1010,6 +1017,39 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@date-io/core@^2.15.0", "@date-io/core@^2.16.0": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.16.0.tgz#7871bfc1d9bca9aa35ad444a239505589d0f22f6" + integrity sha512-DYmSzkr+jToahwWrsiRA2/pzMEtz9Bq1euJwoOuYwuwIYXnZFtHajY2E6a1VNVDc9jP8YUXK1BvnZH9mmT19Zg== + +"@date-io/date-fns@^2.15.0": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-2.16.0.tgz#bd5e09b6ecb47ee55e593fc3a87e7b2caaa3da40" + integrity sha512-bfm5FJjucqlrnQcXDVU5RD+nlGmL3iWgkHTq3uAZWVIuBu6dDmGa3m8a6zo2VQQpu8ambq9H22UyUpn7590joA== + dependencies: + "@date-io/core" "^2.16.0" + +"@date-io/dayjs@^2.15.0": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@date-io/dayjs/-/dayjs-2.16.0.tgz#0d2c254ad8db1306fdc4b8eda197cb53c9af89dc" + integrity sha512-y5qKyX2j/HG3zMvIxTobYZRGnd1FUW2olZLS0vTj7bEkBQkjd2RO7/FEwDY03Z1geVGlXKnzIATEVBVaGzV4Iw== + dependencies: + "@date-io/core" "^2.16.0" + +"@date-io/luxon@^2.15.0": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@date-io/luxon/-/luxon-2.16.0.tgz#97773d56532706c1a68113a1de07eecd0d41bebb" + integrity sha512-L8UXHa/9VbfRqP4KB7JUZwFgOVxo22rONVod1o7GMN2Oku4PzJ0k1kXc+nLP9lRlF1UAA28oQsQqn85Y/PdBZw== + dependencies: + "@date-io/core" "^2.16.0" + +"@date-io/moment@^2.15.0": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-2.16.0.tgz#a6658c05e14e7fcc57adeda675462e0b6750542d" + integrity sha512-wvu/40k128kF6P0jPbiyZcPR14VjJAgYEs+mYtsXz/AyWpC2DEJKly7ub+dpevUywbTzzpZysyCxCdzLzxD/uw== + dependencies: + "@date-io/core" "^2.16.0" + "@emotion/babel-plugin@^11.10.0": version "11.10.0" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.0.tgz#ae545b8faa6b42d3a50ec86b70b758296f3c4467" @@ -1723,6 +1763,17 @@ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.1.5.tgz#5e5cc49d719bc86522983359bc1f90eddcff0624" integrity sha512-HnRXrxgHJYJcT8ZDdDCQIlqk0s0skOKD7eWs9mJgBUu70hyW4iA6Kiv3yspJR474RFH8hysKR65VVSzUSzkuwA== +"@mui/utils@^5.10.3": + version "5.10.6" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.10.6.tgz#98d432d2b05544c46efe356cf095cea3a37c2e59" + integrity sha512-g0Qs8xN/MW2M3fLL8197h5J2VB9U+49fLlnKKqC6zy/yus5cZwdT+Gwec+wUMxgwQoxMDn+J8oDWAn28kEOR/Q== + dependencies: + "@babel/runtime" "^7.19.0" + "@types/prop-types" "^15.7.5" + "@types/react-is" "^16.7.1 || ^17.0.0" + prop-types "^15.8.1" + react-is "^18.2.0" + "@mui/utils@^5.9.3": version "5.9.3" resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.9.3.tgz#a11e0824f00b7ea40257b390060ce167fe861d02" @@ -1734,6 +1785,24 @@ prop-types "^15.8.1" react-is "^18.2.0" +"@mui/x-date-pickers@^5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-5.0.4.tgz#79a509354eea4bedaa955ee52f37d80256d7e415" + integrity sha512-Co4tbwqXSdHfR8UoZSHQpDZqnFdikzQr0lQPG2AjGh9BdB4EdY3YE2+sZyAltjk/AXxp5JzIWDZ2Kj83ClzjwA== + dependencies: + "@babel/runtime" "^7.18.9" + "@date-io/core" "^2.15.0" + "@date-io/date-fns" "^2.15.0" + "@date-io/dayjs" "^2.15.0" + "@date-io/luxon" "^2.15.0" + "@date-io/moment" "^2.15.0" + "@mui/utils" "^5.10.3" + "@types/react-transition-group" "^4.4.5" + clsx "^1.2.1" + prop-types "^15.7.2" + react-transition-group "^4.4.5" + rifm "^0.12.1" + "@near-wallet-selector/core@5.0.2", "@near-wallet-selector/core@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@near-wallet-selector/core/-/core-5.0.2.tgz#c0a18bfa5607d99b9055ec524c7cbd35d19e233c" @@ -2670,6 +2739,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== +"@types/luxon@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.0.1.tgz#2b1657096473e24b049bdedf3710f99645f3a17f" + integrity sha512-/LAvk1cMOJt0ghzMFrZEvByUhsiEfeeT2IF53Le+Ki3A538yEL9pRZ7a6MuCxdrYK+YNqNIDmrKU/r2nnw04zQ== + "@types/node@*": version "18.6.4" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.4.tgz#fd26723a8a3f8f46729812a7f9b4fc2d1608ed39" @@ -6147,7 +6221,7 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== -luxon@^3.0.1: +luxon@^3.0.1, luxon@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.0.4.tgz#d179e4e9f05e092241e7044f64aaa54796b03929" integrity sha512-aV48rGUwP/Vydn8HT+5cdr26YYQiUZ42NM6ToMoaGKwYfWbfLeRkEu1wXWMHBZT6+KyLfcbbtVcoQFCbbPjKlw== @@ -7439,6 +7513,11 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== +rifm@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.12.1.tgz#8fa77f45b7f1cda2a0068787ac821f0593967ac4" + integrity sha512-OGA1Bitg/dSJtI/c4dh90svzaUPt228kzFsUkJbtA2c964IqEAwWXeL9ZJi86xWv3j5SMqRvGULl7bA6cK0Bvg== + rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" From 8e6310319135ee5d5ba715dd23c09d82a48f6415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 7 Oct 2022 17:51:57 +0400 Subject: [PATCH 166/537] wip: Update Job data model --- src/entities/job/model/job-data.ts | 26 ++++++++++++++++++++++++-- src/entities/job/ui/jobs-list.tsx | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 884246b7..067f2803 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -3,8 +3,16 @@ import { JobData } from "../../../shared/lib/contracts/multicall"; import { Dependencies } from "../config"; +type JobDataWithStats = { + id: JobData["id"]; + + job: JobData["job"] & { + status: "Active" | "Expired" | "Inactive" | "Running"; + }; +}; + type JobsDataFxResponse = { - data: Record | null; + data: Record | null; error?: Error | null; loading: boolean; }; @@ -14,7 +22,21 @@ const jobsDataFx = async ({ multicall }: Dependencies["contracts"], callback: (r await multicall .getJobs() .then((data) => ({ - data: data.reduce((jobsRegistry, { id, job }) => ({ ...jobsRegistry, [id]: { id, job } }), {}), + /** Jobs indexed by ID for easy access to each particular job */ + data: data.reduce( + (jobsRegistry, { id, job }) => ({ + ...jobsRegistry, + [id]: { + id, + job: { + ...job, + /** Calculation from `job.is_active` and `job_run_count` goes here */ + status: "Inactive", + }, + }, + }), + {} + ), loading: false, })) .catch((error) => ({ data: null, error: new Error(error), loading: false })) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 7723f409..9d8f143e 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -32,7 +32,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { "Multicalls", ]} rows={Object.values(data).map(({ id, job }) => [ - job.is_active ? "Active" : "Inactive", + job.status, id, cronToDate(job.cadence).toLocaleString(), job.croncat_hash, From 903c9a3ffbb85beec0636919c875631b959919e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 08:47:06 +0400 Subject: [PATCH 167/537] wip: Implement data inspector component --- package.json | 3 +- src/shared/ui/components/config.ts | 8 +++++ .../data-inspector/data-inspector.scss | 14 +++++++++ .../data-inspector/data-inspector.tsx | 29 +++++++++++++++++++ .../ui/components/data-inspector/index.ts | 1 + src/shared/ui/components/index.ts | 3 +- yarn.lock | 5 ++++ 7 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/shared/ui/components/config.ts create mode 100644 src/shared/ui/components/data-inspector/data-inspector.scss create mode 100644 src/shared/ui/components/data-inspector/data-inspector.tsx create mode 100644 src/shared/ui/components/data-inspector/index.ts diff --git a/package.json b/package.json index da63c3ab..045d72d8 100644 --- a/package.json +++ b/package.json @@ -73,8 +73,8 @@ "@near-wallet-selector/sender": "^5.0.0", "@types/react": "^18.0.0", "big.js": "^6.2.1", - "cron-parser": "^4.6.0", "clsx": "^1.2.1", + "cron-parser": "^4.6.0", "js-base64": "^3.7.2", "lodash.debounce": "^4.0.8", "near-api-js": "^0.45.1", @@ -83,6 +83,7 @@ "react": "^18.0.0", "react-beautiful-dnd": "^13.1.0", "react-dom": "^18.0.0", + "react-inspector": "^6.0.1", "react-router-dom": "6", "regenerator-runtime": "^0.13.9", "rxjs": "^7.5.6" diff --git a/src/shared/ui/components/config.ts b/src/shared/ui/components/config.ts new file mode 100644 index 00000000..51be1901 --- /dev/null +++ b/src/shared/ui/components/config.ts @@ -0,0 +1,8 @@ +import { chromeLight } from "react-inspector"; + +export const UiKitConfig = { + OBJECT_INSPECTOR_THEME: { + ...chromeLight, + BASE_BACKGROUND_COLOR: "transparent", + }, +}; diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss new file mode 100644 index 00000000..d7e82243 --- /dev/null +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -0,0 +1,14 @@ +@use "sass/color"; +@use "sass/size"; + +.DataInspector { + &-body { + border-radius: size.$task-radius; + padding: calc(size.$gap / 2); + background-color: color.$lightest; + + & * { + font-size: size.$text; + } + } +} diff --git a/src/shared/ui/components/data-inspector/data-inspector.tsx b/src/shared/ui/components/data-inspector/data-inspector.tsx new file mode 100644 index 00000000..602b2cf9 --- /dev/null +++ b/src/shared/ui/components/data-inspector/data-inspector.tsx @@ -0,0 +1,29 @@ +import clsx from "clsx"; +import { type ComponentProps } from "react"; +import { ObjectInspector } from "react-inspector"; + +import { UiKitConfig } from "../config"; + +import "./data-inspector.scss"; + +interface DataInspectorProps extends ComponentProps { + classes?: { root?: string; body?: string; label?: string }; + label: string; +} + +const _DataInspector = "DataInspector"; + +export const DataInspector = ({ classes, expandLevel = 1, label, ...props }: DataInspectorProps) => ( +
    + {label} + +
    + +
    +
    +); diff --git a/src/shared/ui/components/data-inspector/index.ts b/src/shared/ui/components/data-inspector/index.ts new file mode 100644 index 00000000..ebcdab4c --- /dev/null +++ b/src/shared/ui/components/data-inspector/index.ts @@ -0,0 +1 @@ +export { DataInspector } from "./data-inspector"; diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index d1d042f9..b1eea815 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,4 +1,4 @@ -export { Tile } from "./tile/tile"; +export { DataInspector } from "./data-inspector"; export { Dialog, type DialogProps } from "./dialog/dialog"; export { NearIcons } from "./icons"; export { PopupMenu, type PopupMenuProps } from "./popup-menu/popup-menu"; @@ -6,5 +6,6 @@ export { Scrollable } from "./scrollable/scrollable"; export { Table } from "./table/table"; export { Tabs } from "./tabs/tabs"; export { TextInput, type TextInputProps, TextInputWithUnits, type TextInputWithUnitsProps } from "./text-input"; +export { Tile } from "./tile/tile"; export { TokenLabel } from "./token-label/token-label"; export { Tooltip } from "./tooltip/tooltip"; diff --git a/yarn.lock b/yarn.lock index 222c5bd2..85b3c05e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7160,6 +7160,11 @@ react-error-overlay@6.0.9: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== +react-inspector@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-6.0.1.tgz#1a37f0165d9df81ee804d63259eaaeabe841287d" + integrity sha512-cxKSeFTf7jpSSVddm66sKdolG90qURAX3g1roTeaN6x0YEbtWc8JpmFN9+yIqLNH2uEkYerWLtJZIXRIFuBKrg== + "react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" From 0e5928822ca1872fa18e99bd17a9bd707581e36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 08:48:09 +0400 Subject: [PATCH 168/537] wip: Use data inspector component for job multicalls --- src/entities/job/model/job-data.ts | 2 +- src/entities/job/ui/jobs-list.scss | 15 ++++++++++++++- src/entities/job/ui/jobs-list.tsx | 12 +++++++----- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 067f2803..54d0aef0 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import { JobData } from "../../../shared/lib/contracts/multicall"; +import { JobData } from "../../../shared/lib/contracts/multicall"; import { Dependencies } from "../config"; type JobDataWithStats = { diff --git a/src/entities/job/ui/jobs-list.scss b/src/entities/job/ui/jobs-list.scss index 96499323..1c73447b 100644 --- a/src/entities/job/ui/jobs-list.scss +++ b/src/entities/job/ui/jobs-list.scss @@ -1,8 +1,21 @@ .JobsList { + &-dataInspector { + &-label { + text-align: right; + font-weight: 800; + } + } + .Table-row-content--compact:last-of-type { + align-items: flex-start; + & > span { &:first-of-type { - display: none; + position: absolute; + } + + &:last-of-type { + width: 100%; } } } diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 9d8f143e..206c9b9c 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,5 +1,5 @@ import { cronToDate, toTGas } from "../../../shared/lib/converter"; -import { Tile, Scrollable, Table } from "../../../shared/ui/components"; +import { DataInspector, Scrollable, Table, Tile } from "../../../shared/ui/components"; import { JobDataModel } from "../model/job-data"; import { Dependencies } from "../config"; @@ -40,10 +40,12 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { `${toTGas(job.trigger_gas)} Tgas`, job.run_count, -
    - Multicalls -
    {JSON.stringify(job.multicalls, null, " ")}
    -
    , + , ])} /> From cdd910a266a3fdf0edbce5f664fa0617d90f025e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 09:41:06 +0400 Subject: [PATCH 169/537] wip: Customize data inspector spoiler appearance --- src/entities/job/ui/jobs-list.scss | 1 - src/entities/job/ui/jobs-list.tsx | 1 - .../data-inspector/data-inspector.scss | 4 ++ .../data-inspector/data-inspector.tsx | 53 +++++++++++++------ 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/entities/job/ui/jobs-list.scss b/src/entities/job/ui/jobs-list.scss index 1c73447b..2bc535e7 100644 --- a/src/entities/job/ui/jobs-list.scss +++ b/src/entities/job/ui/jobs-list.scss @@ -2,7 +2,6 @@ &-dataInspector { &-label { text-align: right; - font-weight: 800; } } diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 206c9b9c..2582871b 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -44,7 +44,6 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { classes={{ label: `${_JobsList}-dataInspector-label` }} data={job.multicalls} expandLevel={1} - label="details" />, ])} /> diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss index d7e82243..fbaa2d18 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.scss +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -2,6 +2,10 @@ @use "sass/size"; .DataInspector { + &-label { + color: darken(color.$blue, 30%); + } + &-body { border-radius: size.$task-radius; padding: calc(size.$gap / 2); diff --git a/src/shared/ui/components/data-inspector/data-inspector.tsx b/src/shared/ui/components/data-inspector/data-inspector.tsx index 602b2cf9..3c5931a5 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.tsx +++ b/src/shared/ui/components/data-inspector/data-inspector.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import { type ComponentProps } from "react"; +import { MouseEvent, useCallback, useState, type ComponentProps } from "react"; import { ObjectInspector } from "react-inspector"; import { UiKitConfig } from "../config"; @@ -8,22 +8,43 @@ import "./data-inspector.scss"; interface DataInspectorProps extends ComponentProps { classes?: { root?: string; body?: string; label?: string }; - label: string; + expanded?: boolean; + label?: string; } const _DataInspector = "DataInspector"; -export const DataInspector = ({ classes, expandLevel = 1, label, ...props }: DataInspectorProps) => ( -
    - {label} - -
    - -
    -
    -); +export const DataInspector = ({ classes, expanded = false, expandLevel = 1, label, ...props }: DataInspectorProps) => { + // TODO: Extract custom `
    ` element to separate component. + + const [rootExpanded, rootExpandedUpdate] = useState(expanded), + dynamicLabel = rootExpanded ? "hide" : "show"; + + const rootExpansionToggle = useCallback( + (event: MouseEvent) => { + event.preventDefault(); + rootExpandedUpdate(!rootExpanded); + }, + + [rootExpanded, rootExpandedUpdate] + ); + + return ( +
    + {label ?? dynamicLabel} + +
    + +
    +
    + ); +}; From ce4abaac4f722611ccc3200a0ccba0e4d28b3a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 09:46:16 +0400 Subject: [PATCH 170/537] chore: Remove unused imports --- src/pages/dao/jobs/jobs.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 51f04ce7..45ee8ae2 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -1,5 +1,4 @@ import clsx from "clsx"; -import { useMemo, useState } from "react"; import { Job, type JobDependencies } from "../../../entities"; From 97305a223f1063df8653e10d089928d821a47ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 10:46:28 +0400 Subject: [PATCH 171/537] wip: Fix data inspector behavior & appearance --- src/shared/ui/components/data-inspector/data-inspector.scss | 4 ++++ src/shared/ui/components/data-inspector/data-inspector.tsx | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss index fbaa2d18..9adb7640 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.scss +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -4,6 +4,10 @@ .DataInspector { &-label { color: darken(color.$blue, 30%); + + & > span { + cursor: pointer; + } } &-body { diff --git a/src/shared/ui/components/data-inspector/data-inspector.tsx b/src/shared/ui/components/data-inspector/data-inspector.tsx index 3c5931a5..f8d8f20e 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.tsx +++ b/src/shared/ui/components/data-inspector/data-inspector.tsx @@ -32,10 +32,11 @@ export const DataInspector = ({ classes, expanded = false, expandLevel = 1, labe return (
    - {label ?? dynamicLabel} + + {label ?? dynamicLabel} +
    Date: Sun, 9 Oct 2022 12:00:22 +0400 Subject: [PATCH 172/537] wip: Revamp styles for tables and tiles --- .../data-inspector/data-inspector.scss | 6 ++-- src/shared/ui/components/table/row.scss | 31 ++++++++++++++----- src/shared/ui/components/table/row.tsx | 16 +++++----- src/shared/ui/components/tile/tile.scss | 2 +- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss index 9adb7640..7ef5f2e0 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.scss +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -11,12 +11,12 @@ } &-body { - border-radius: size.$task-radius; + margin-top: calc(size.$gap / 2); + border-radius: calc(size.$task-radius / 2); padding: calc(size.$gap / 2); - background-color: color.$lightest; & * { - font-size: size.$text; + font-size: size.$large-text; } } } diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 23031799..60664ed9 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -32,10 +32,10 @@ &--compact { display: flex; flex-direction: column; - gap: calc(0.5 * size.$gap); + gap: calc(size.$gap / 2); border-radius: size.$task-radius; - padding: size.$gap; - background-color: color.$light; + padding: calc(size.$gap / 2); + background-color: color.$white; } &-content { @@ -45,12 +45,8 @@ align-items: center; font-size: calc(1.1 * size.$text); - span:first-of-type { - font-weight: 800; - } - &:first-of-type { - margin-bottom: calc(0.5 * size.$gap); + padding: calc(size.$gap / 2); & > span { &:first-of-type { @@ -62,6 +58,25 @@ } } } + + &:not(:first-of-type) { + padding: calc(size.$gap / 1.5) size.$gap; + background-color: rgba(color.$lightest, 0.7); + } + + &:nth-of-type(2) { + border-top-left-radius: calc(size.$task-radius / 1.2); + border-top-right-radius: calc(size.$task-radius / 1.2); + } + + &:last-of-type { + border-bottom-left-radius: calc(size.$task-radius / 1.2); + border-bottom-right-radius: calc(size.$task-radius / 1.2); + } + + span:first-of-type { + font-weight: 800; + } } } } diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index e06d41e7..9007793d 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -22,13 +22,15 @@ export const TableRow = ({ cells, headerCells }: TableRowProps) => ( export const TableRowCard = ({ cells, headerCells }: TableRowProps) => (
    {headerCells.map((headerCell, headerCellIndex) => ( -
    - {headerCell} - {cells ? cells[headerCellIndex] : "No data"} -
    + <> +
    + {headerCell} + {cells ? cells[headerCellIndex] : "No data"} +
    + ))}
    ); diff --git a/src/shared/ui/components/tile/tile.scss b/src/shared/ui/components/tile/tile.scss index 5ee231ab..bf9b3d50 100644 --- a/src/shared/ui/components/tile/tile.scss +++ b/src/shared/ui/components/tile/tile.scss @@ -6,8 +6,8 @@ flex-flow: column nowrap; position: relative; padding: calc(0.25 * size.$gap); - background-color: rgba(color.$lightest, 0.25); border-radius: size.$task-radius; + background-color: color.$lightest; font-size: size.$small-text; .title { From 1b43768879d49d65e95b333e9ef060b0477fa7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 12:36:01 +0400 Subject: [PATCH 173/537] wip: Display "none" when there's no croncat hash --- src/entities/job/ui/jobs-list.tsx | 2 +- src/shared/ui/components/table/row.tsx | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 2582871b..6e28fe4e 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -35,7 +35,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { job.status, id, cronToDate(job.cadence).toLocaleString(), - job.croncat_hash, + job.croncat_hash.length === 0 ? none : job.croncat_hash, job.creator, `${toTGas(job.trigger_gas)} Tgas`, job.run_count, diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 9007793d..e06d41e7 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -22,15 +22,13 @@ export const TableRow = ({ cells, headerCells }: TableRowProps) => ( export const TableRowCard = ({ cells, headerCells }: TableRowProps) => (
    {headerCells.map((headerCell, headerCellIndex) => ( - <> -
    - {headerCell} - {cells ? cells[headerCellIndex] : "No data"} -
    - +
    + {headerCell} + {cells ? cells[headerCellIndex] : "No data"} +
    ))}
    ); From 543afb7a8ef0448f54a479b5f3c691e9d4ac806d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 16:41:17 +0400 Subject: [PATCH 174/537] fix: Decrease content overlapping by wallet labels --- src/entities/wallet/ui/wallet.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/wallet/ui/wallet.scss b/src/entities/wallet/ui/wallet.scss index 16ff3fd6..9a0da83f 100644 --- a/src/entities/wallet/ui/wallet.scss +++ b/src/entities/wallet/ui/wallet.scss @@ -38,7 +38,7 @@ position: absolute; left: calc(0.7 * size.$sidebar-width + 2px); top: calc(-0.125 * size.$gap - 1px); - padding: 0.25 * size.$gap size.$gap; + padding: calc(0.25 * size.$gap) 0 calc(0.25 * size.$gap) size.$gap; color: rgba(color.$text, 0.25); font-size: size.$text; white-space: nowrap; From 5124b88c8d5594796bcb7b5ac6e50fe883b71624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 16:46:57 +0400 Subject: [PATCH 175/537] wip: Implement job status calculation --- src/entities/index.ts | 2 +- src/entities/job/config.ts | 20 +++++++++-- src/entities/job/index.ts | 5 +-- src/entities/job/lib/job-extended.ts | 52 +++++++++++++++++++++++++++ src/entities/job/model/job-data.ts | 33 +++++++---------- src/entities/job/ui/jobs-list.tsx | 4 +-- src/pages/dao/jobs/jobs.tsx | 4 +-- src/shared/lib/contracts/multicall.ts | 3 ++ 8 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 src/entities/job/lib/job-extended.ts diff --git a/src/entities/index.ts b/src/entities/index.ts index b08244f7..67f6b162 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,5 +1,5 @@ export { Task } from "./task"; -export { Job, type JobDependencies } from "./job"; +export { Job, type JobEntity } from "./job"; export { FungibleToken, type FungibleTokensDependencies } from "./fungible-token"; export { NearToken, type NearTokenDependencies } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/config.ts b/src/entities/job/config.ts index 994af6fb..bb828c1d 100644 --- a/src/entities/job/config.ts +++ b/src/entities/job/config.ts @@ -1,6 +1,20 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; -export interface Dependencies { - className: string; - contracts: { multicall: Multicall }; +export namespace JobEntity { + export interface dependencies { + className: string; + contracts: { multicall: Multicall }; + } + + export enum Status { + Inactive = "Inactive", + Expired = "Expired", + Active = "Active", + Running = "Running", + Unknown = "Unknown", + } +} + +export class JobConfig { + static readonly Status = JobEntity.Status; } diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index c49dd73f..639605c5 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,7 +1,8 @@ +import { JobConfig } from "./config"; import { JobsList } from "./ui/jobs-list"; -export class Job { +export class Job extends JobConfig { static ListOfAll = JobsList; } -export { type Dependencies as JobDependencies } from "./config"; +export { type JobEntity } from "./config"; diff --git a/src/entities/job/lib/job-extended.ts b/src/entities/job/lib/job-extended.ts new file mode 100644 index 00000000..5fde7607 --- /dev/null +++ b/src/entities/job/lib/job-extended.ts @@ -0,0 +1,52 @@ +import { JobData } from "../../../shared/lib/contracts/multicall"; +import { cronToDate } from "../../../shared/lib/converter"; +import { JobConfig as Config } from "../config"; + +/** + * Checking if job is either active or running and provides a human-readable status string + * only if one of these conditions is satisfied. + * + * Job is being considered as running if it's still presented in pool, + * and it had been started at least once. + * + * @returns Either `"Active"` or `"Running"` if one of these statuses is actual, otherwise `false`. + */ +const activeOrRunning = ({ job }: JobData) => + job.is_active && job.run_count > -1 ? Config.Status.Running : job.is_active && Config.Status.Active; + +/** + * Checking if job is either inactive or expired and provides a human-readable status string + * only if one of these conditions is satisfied. + * + * Job is being considered as inactive if it's not presented in pool, + * and its execution start moment is still in the future. + * + * Job is being considered as inactive if it's not presented in pool, + * and its execution start moment is in the past. + * + * @returns Either `"Inactive"` or `"Expired"` if one of these statuses is actual, otherwise `false`. + */ +const inactiveOrExpired = ({ job }: JobData) => + (!job.is_active && cronToDate(job.cadence).getTime() > new Date().getTime() && Config.Status.Inactive) || + (!job.is_active && cronToDate(job.cadence).getTime() < new Date().getTime() && Config.Status.Expired); + +/** + * Calculates the actual job status from the given data + * and adds it as an additional property to the new data structure. + * + * If a calculation error has ocurred, the `"Unknown"` status is being presented. + * + * @returns Extended job data structure. + */ +const jobExtendedWithStatus = (job: JobData) => ({ + ...job, + + job: { + ...job.job, + status: activeOrRunning(job) || inactiveOrExpired(job), + }, +}); + +export const JobExtended = { + withStatus: jobExtendedWithStatus, +}; diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 54d0aef0..7d6b90fc 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -1,48 +1,41 @@ import { useEffect, useState } from "react"; import { JobData } from "../../../shared/lib/contracts/multicall"; -import { Dependencies } from "../config"; - -type JobDataWithStats = { - id: JobData["id"]; +import { type JobEntity } from "../config"; +import { JobExtended } from "../lib/job-extended"; +type JobDataWithStatus = Omit & { job: JobData["job"] & { - status: "Active" | "Expired" | "Inactive" | "Running"; + status: JobEntity.Status; }; }; type JobsDataFxResponse = { - data: Record | null; + data: Record | null; error?: Error | null; loading: boolean; }; -const jobsDataFx = async ({ multicall }: Dependencies["contracts"], callback: (result: JobsDataFxResponse) => void) => +const jobsDataFx = async ( + { multicall }: JobEntity.dependencies["contracts"], + callback: (result: JobsDataFxResponse) => void +) => callback( await multicall .getJobs() .then((data) => ({ - /** Jobs indexed by ID for easy access to each particular job */ data: data.reduce( - (jobsRegistry, { id, job }) => ({ - ...jobsRegistry, - [id]: { - id, - job: { - ...job, - /** Calculation from `job.is_active` and `job_run_count` goes here */ - status: "Inactive", - }, - }, - }), + /** Jobs indexed by ID for easy access to each particular job */ + (jobsIndexedById, job) => ({ ...jobsIndexedById, [job.id]: JobExtended.withStatus(job) }), {} ), + loading: false, })) .catch((error) => ({ data: null, error: new Error(error), loading: false })) ); -const useJobsData = (contracts: Dependencies["contracts"]) => { +const useJobsData = (contracts: JobEntity.dependencies["contracts"]) => { const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); useEffect(() => void jobsDataFx(contracts, stateUpdate), []); diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 6e28fe4e..bc7ad98b 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,11 +1,11 @@ import { cronToDate, toTGas } from "../../../shared/lib/converter"; import { DataInspector, Scrollable, Table, Tile } from "../../../shared/ui/components"; import { JobDataModel } from "../model/job-data"; -import { Dependencies } from "../config"; +import { JobEntity } from "../config"; import "./jobs-list.scss"; -interface JobsListProps extends Dependencies {} +interface JobsListProps extends JobEntity.dependencies {} const _JobsList = "JobsList"; diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 45ee8ae2..2aef13a8 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -1,10 +1,10 @@ import clsx from "clsx"; -import { Job, type JobDependencies } from "../../../entities"; +import { Job, type JobEntity } from "../../../entities"; import "./jobs.scss"; -interface DaoJobsTabComponentProps extends JobDependencies {} +interface DaoJobsTabComponentProps extends JobEntity.dependencies {} const _DaoJobsTab = "DaoJobsTab"; diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 6a4fd2b5..741f0189 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -25,6 +25,9 @@ const KEY_JOB_COUNT: string = "g"; type JobData = { id: number; + /** + * Job properties + */ job: { croncat_hash: string; creator: string; From 42cde6e3caee2855176068e809328a126db5d3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 16:59:19 +0400 Subject: [PATCH 176/537] fix: Return `"Unknown"` status on calculation error --- src/entities/job/lib/job-extended.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/job/lib/job-extended.ts b/src/entities/job/lib/job-extended.ts index 5fde7607..7ae7f716 100644 --- a/src/entities/job/lib/job-extended.ts +++ b/src/entities/job/lib/job-extended.ts @@ -43,7 +43,7 @@ const jobExtendedWithStatus = (job: JobData) => ({ job: { ...job.job, - status: activeOrRunning(job) || inactiveOrExpired(job), + status: activeOrRunning(job) || inactiveOrExpired(job) || Config.Status.Unknown, }, }); From b7b6ea42815aac469490eaf1faae8363a74a369d Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sun, 9 Oct 2022 15:22:23 +0200 Subject: [PATCH 177/537] add datetime picker, replace placeholders in addJob --- src/shared/lib/contracts/multicall.ts | 10 ++--- src/shared/lib/converter.ts | 13 +++--- .../date-time-picker/date-time-picker.tsx | 27 +++++++----- src/widgets/export/export.jsx | 42 +++++++++++++------ 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 6a4fd2b5..1059a658 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -1,5 +1,5 @@ import { viewAccount, viewState, view } from "../wallet"; -import { Big, toGas, dateToCron } from "../converter"; +import { Big, toGas, dateToCron, toYocto } from "../converter"; import type { FunctionCallAction as daoFunctionCallAction } from "./sputnik-dao"; import type { Tx } from "../wallet"; @@ -65,6 +65,8 @@ class MulticallConfigChanges { class Multicall { static FACTORY_ADDRESS: string = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; static CONTRACT_CODE_HASHES: string[] = CONTRACT_CODE_HASHES_SELECTOR[window.NEAR_ENV]; + // 0.025 NEAR is the min required by croncat for a non-recurring task. Assume trigger of 270 Tgas and 0 NEAR. + static CRONCAT_FEE: string = toYocto("0.0275"); address: string; admins: string[] = []; @@ -229,15 +231,13 @@ class Multicall { /** * Register a new job. Has to pay job bond. - * TODO: Add logic for estimating totalBudget. * * @param multicalls Multicalls to execute. 1 multicall per tx. * @param triggerDate Execution date, in user's local time. * @param triggerGas Gas amount. Will be allocated for every tx in this job. - * @param totalBudget Total fee to be paid to Croncat agents. * @returns */ - async addJob(multicalls: MulticallArgs[], triggerDate: Date, triggerGas: string, totalBudget: string): Promise { + async addJob(multicalls: MulticallArgs[], triggerDate: Date, triggerGas: string): Promise { // crontab in CronCat format. See: https://github.com/CronCats/Schedule const cadence: string = dateToCron(triggerDate); // timestamp as required by NEAR chain (UTC, in nanoseconds) @@ -253,7 +253,7 @@ class Multicall { job_multicalls: multicalls, job_cadence: cadence, job_trigger_gas: triggerGas, - job_total_budget: totalBudget, + job_total_budget: Multicall.CRONCAT_FEE, job_start_at: startAt, }, gas: toGas("25"), diff --git a/src/shared/lib/converter.ts b/src/shared/lib/converter.ts index 6a269e66..ff1668ac 100644 --- a/src/shared/lib/converter.ts +++ b/src/shared/lib/converter.ts @@ -50,7 +50,8 @@ const dateToCron = (date: Date): string => { const months = date.getUTCMonth() + 1; // JS months are 0-11. Cron needs 1-12 const year = date.getUTCFullYear(); - return `0 ${minutes} ${hours} ${days} ${months} * ${year}`; + // TODO: use year when the time is right. + return `0 ${minutes} ${hours} ${days} ${months} * *`; }; // Cron expression to JS Date. const cronToDate = (cronStr: string): Date => { @@ -58,10 +59,12 @@ const cronToDate = (cronStr: string): Date => { const options: ParserOptions = { utc: true }; if (fields.length === 7) { // remove and save the 7th field (years). - const year = fields.pop()!; - // restrict cron-parser to chosen year. Format follows ISO 8601. - options.currentDate = `${year}-01-01T00:00:00`; // first moment of "year" - options.endDate = `${year}-12-31T23:59:59`; // last moment of "year" + const year = Number(fields.pop()!); + if (Number.isInteger(year)) { + // restrict cron-parser to chosen year. Format follows ISO 8601. + options.currentDate = `${year}-01-01T00:00:00`; // first moment of "year" + options.endDate = `${year}-12-31T23:59:59`; // last moment of "year" + } } const interval = parseExpression(fields.join(" "), options); // TODO: check timezone of returned Date (unlcear whether UTC or client time) diff --git a/src/shared/ui/components/date-time-picker/date-time-picker.tsx b/src/shared/ui/components/date-time-picker/date-time-picker.tsx index 83ebd455..e56782f9 100644 --- a/src/shared/ui/components/date-time-picker/date-time-picker.tsx +++ b/src/shared/ui/components/date-time-picker/date-time-picker.tsx @@ -1,22 +1,29 @@ -import * as React from "react"; import { DateTime } from "luxon"; import TextField from "@mui/material/TextField"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterLuxon } from "@mui/x-date-pickers/AdapterLuxon"; import { DateTimePicker as MaterialUIPicker } from "@mui/x-date-pickers/DateTimePicker"; -function DateTimePicker() { - const [value, setValue] = React.useState(DateTime.local()); - - const handleChange = (newValue: DateTime | null) => { - setValue(newValue); - }; - +function DateTimePicker({ + label, + value, + minDateTime, + maxDateTime, + handleChange, +}: { + label: string; + value: Date; + minDateTime: Date; + maxDateTime: Date; + handleChange: (value: DateTime | null, keyboardInputValue: string | undefined) => void; +}) { return ( } /> diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index c3f6beba..6b3709d8 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -15,11 +15,12 @@ import { Link } from "react-router-dom"; import { ArgsAccount, ArgsBig, ArgsError, ArgsString } from "../../shared/lib/args"; import { errorMsg } from "../../shared/lib/errors"; import { STORAGE } from "../../shared/lib/persistent"; -import { convert, toGas, toNEAR, toYocto } from "../../shared/lib/converter"; +import { Big, convert, toGas, toNEAR, toYocto } from "../../shared/lib/converter"; import { Multicall } from "../../shared/lib/contracts/multicall"; import { signAndSendTxs, view } from "../../shared/lib/wallet"; import { Wallet } from "../../entities"; import { TextInput, TextInputWithUnits } from "../../shared/ui/components"; +import { DateTimePicker } from "../../shared/ui/components/date-time-picker"; import "./export.scss"; export class Export extends Component { @@ -64,7 +65,8 @@ export class Export extends Component { attachNEAR: false, attachFT: false, showArgs: false, - useJobs: false, + isJob: false, + jobDateTime: new Date(), }; this.update = this.update.bind(this); @@ -161,7 +163,7 @@ export class Export extends Component { } // normal propose multicall to DAO functionality else { - const { attachNEAR, attachFT, useJobs } = this.state; + const { attachNEAR, attachFT, isJob, jobDateTime } = this.state; const { gas, depo, desc } = this.total; const { token, amount } = this.ft; const errors = this.errors; @@ -186,7 +188,7 @@ export class Export extends Component { onClick={async () => { const { currentDAO: dao } = WALLET_COMPONENT.state; // case 1: immediate execution => basic multicall - if (!useJobs) { + if (!isJob) { // multicall with attached FT if (attachFT) { const tx = await dao.proposeMulticallFT( @@ -227,6 +229,9 @@ export class Export extends Component { // ); // multicall with attached NEAR else { + const jobCost = attachNEAR + ? Big(convert(depo.value, depo.unit)).add(Multicall.CRONCAT_FEE).toFixed() + : Multicall.CRONCAT_FEE; console.log("multicall job with attached NEAR"); const [jobCount, multicall] = await Promise.all([ temporary.getJobCount(), @@ -236,12 +241,10 @@ export class Export extends Component { multicall.addJob( // TODO: support jobs with multiple multicalls [multicallArgs], - // trigger date - new Date(), - convert(gas.value, gas.unit), - toYocto("1") + jobDateTime, + convert(gas.value, gas.unit) ), - dao.proposeJobActivation("test job activation", jobCount, toYocto("1")), + dao.proposeJobActivation(desc.value, jobCount, jobCost), ]); signAndSendTxs([addJobTx, proposeJobTx]); } @@ -264,9 +267,13 @@ export class Export extends Component { render() { const LAYOUT = this.props.layout; // ususally global parameter - const { attachNEAR, attachFT, showArgs } = this.state; + const { attachNEAR, attachFT, showArgs, isJob, jobDateTime } = this.state; const { gas, depo, desc } = this.total; const { amount, token } = this.ft; + // do not schedule jobs in the past + const currentDate = new Date(); + // limit job scheduling to one year from now + const maxDate = new Date(new Date().setFullYear(currentDate.getFullYear() + 1)); const allErrors = LAYOUT.toErrors(); const errors = this.errors; @@ -396,8 +403,8 @@ export class Export extends Component { defaultValue="immediate" name="radio-buttons-group" onChange={(event, value) => { - if (value === "immediate") this.setState({ useJobs: false }); - else if (value === "scheduled") this.setState({ useJobs: true }); + if (value === "immediate") this.setState({ isJob: false }); + else if (value === "scheduled") this.setState({ isJob: true }); }} > + {isJob ? ( + { + this.setState({ jobDateTime: value.toJSDate() }); + }} + /> + ) : null}
    {/* Display cards' errors */} {allErrors.length > 0 && ( From 5463b6e14a4cbf9c93cb21bb41fe7d19c08e99ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 9 Oct 2022 17:31:47 +0400 Subject: [PATCH 178/537] wip: Add reactive error handling --- src/entities/job/model/job-data.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 7d6b90fc..e4b7bfb7 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -40,6 +40,10 @@ const useJobsData = (contracts: JobEntity.dependencies["contracts"]) => { useEffect(() => void jobsDataFx(contracts, stateUpdate), []); + useEffect(() => { + state.error !== null && void console.error(state.error); + }, [state]); + return state; }; From cbe74d3c09a99ee71cc665a755f201e6643c68ce Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sun, 9 Oct 2022 15:51:22 +0200 Subject: [PATCH 179/537] merge job run_count into status property --- src/entities/job/lib/job-extended.ts | 41 ++++++++++------------------ src/entities/job/ui/jobs-list.tsx | 2 -- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/src/entities/job/lib/job-extended.ts b/src/entities/job/lib/job-extended.ts index 7ae7f716..129a1133 100644 --- a/src/entities/job/lib/job-extended.ts +++ b/src/entities/job/lib/job-extended.ts @@ -3,32 +3,21 @@ import { cronToDate } from "../../../shared/lib/converter"; import { JobConfig as Config } from "../config"; /** - * Checking if job is either active or running and provides a human-readable status string - * only if one of these conditions is satisfied. - * - * Job is being considered as running if it's still presented in pool, - * and it had been started at least once. - * - * @returns Either `"Active"` or `"Running"` if one of these statuses is actual, otherwise `false`. + * Job status is: + * - running: job is active, and was triggered at least once. + * - active: job is active, but not triggered yet. + * - Expired: job not active, and execution moment is in the past. + * - Inactive: job not active, but execution moment in the future. */ -const activeOrRunning = ({ job }: JobData) => - job.is_active && job.run_count > -1 ? Config.Status.Running : job.is_active && Config.Status.Active; - -/** - * Checking if job is either inactive or expired and provides a human-readable status string - * only if one of these conditions is satisfied. - * - * Job is being considered as inactive if it's not presented in pool, - * and its execution start moment is still in the future. - * - * Job is being considered as inactive if it's not presented in pool, - * and its execution start moment is in the past. - * - * @returns Either `"Inactive"` or `"Expired"` if one of these statuses is actual, otherwise `false`. - */ -const inactiveOrExpired = ({ job }: JobData) => - (!job.is_active && cronToDate(job.cadence).getTime() > new Date().getTime() && Config.Status.Inactive) || - (!job.is_active && cronToDate(job.cadence).getTime() < new Date().getTime() && Config.Status.Expired); +const getDisplayStatus = ({ job }: JobData): string => { + if (job.is_active) { + if (job.run_count > -1) return `Running: ${job.run_count + 1}/${job.multicalls.length}`; + else return Config.Status.Active; + } else { + if (cronToDate(job.cadence).getTime() < new Date().getTime()) return Config.Status.Expired; + else return Config.Status.Inactive; + } +}; /** * Calculates the actual job status from the given data @@ -43,7 +32,7 @@ const jobExtendedWithStatus = (job: JobData) => ({ job: { ...job.job, - status: activeOrRunning(job) || inactiveOrExpired(job) || Config.Status.Unknown, + status: getDisplayStatus(job), }, }); diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index bc7ad98b..ad9fc3e7 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -28,7 +28,6 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { "Croncat hash", "Creator", "Trigger gas", - "Run count", "Multicalls", ]} rows={Object.values(data).map(({ id, job }) => [ @@ -38,7 +37,6 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { job.croncat_hash.length === 0 ? none : job.croncat_hash, job.creator, `${toTGas(job.trigger_gas)} Tgas`, - job.run_count, Date: Sun, 9 Oct 2022 18:13:32 +0400 Subject: [PATCH 180/537] wip: Use proper field title --- src/entities/job/ui/jobs-list.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index ad9fc3e7..bb8622cc 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -21,15 +21,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => {
    [ job.status, id, From fecbb3f42af606a45a58af9db7b29a7405bccc7b Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Mon, 10 Oct 2022 00:56:01 +0200 Subject: [PATCH 181/537] base64 decode multicall args in jobs display --- src/entities/job/lib/job-extended.ts | 3 +-- src/entities/job/model/job-data.ts | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/entities/job/lib/job-extended.ts b/src/entities/job/lib/job-extended.ts index 129a1133..429b8218 100644 --- a/src/entities/job/lib/job-extended.ts +++ b/src/entities/job/lib/job-extended.ts @@ -28,8 +28,7 @@ const getDisplayStatus = ({ job }: JobData): string => { * @returns Extended job data structure. */ const jobExtendedWithStatus = (job: JobData) => ({ - ...job, - + id: job.id, job: { ...job.job, status: getDisplayStatus(job), diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index e4b7bfb7..4a3fc274 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { Base64 } from "js-base64"; import { JobData } from "../../../shared/lib/contracts/multicall"; import { type JobEntity } from "../config"; @@ -26,7 +27,20 @@ const jobsDataFx = async ( .then((data) => ({ data: data.reduce( /** Jobs indexed by ID for easy access to each particular job */ - (jobsIndexedById, job) => ({ ...jobsIndexedById, [job.id]: JobExtended.withStatus(job) }), + (jobsIndexedById, job) => { + const jobWithStatus = JobExtended.withStatus(job); + // base64 decode FunctionCall args + jobWithStatus.job.multicalls.forEach((mtclArgs) => + mtclArgs.calls.forEach((callArray) => + callArray.forEach((batchCall) => + batchCall.actions.forEach( + (action) => (action.args = JSON.parse(Base64.decode(action.args))) + ) + ) + ) + ); + return { ...jobsIndexedById, [job.id]: jobWithStatus }; + }, {} ), From 5c59d2b44a0d8019a34c937e9ee35a068add1fa6 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Mon, 10 Oct 2022 02:27:03 +0200 Subject: [PATCH 182/537] fix: cursor pointer on label and body elements, sync show/hide with marker --- .../components/data-inspector/data-inspector.scss | 14 +++++++------- .../components/data-inspector/data-inspector.tsx | 5 ++++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss index 7ef5f2e0..c9451690 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.scss +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -4,19 +4,19 @@ .DataInspector { &-label { color: darken(color.$blue, 30%); - - & > span { - cursor: pointer; - } + cursor: pointer; } &-body { - margin-top: calc(size.$gap / 2); - border-radius: calc(size.$task-radius / 2); - padding: calc(size.$gap / 2); + margin-top: 0.5 * size.$gap; + padding: 0.5 * size.$gap; & * { font-size: size.$large-text; } + + div > span { + cursor: pointer; + } } } diff --git a/src/shared/ui/components/data-inspector/data-inspector.tsx b/src/shared/ui/components/data-inspector/data-inspector.tsx index f8d8f20e..09770e5e 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.tsx +++ b/src/shared/ui/components/data-inspector/data-inspector.tsx @@ -34,7 +34,10 @@ export const DataInspector = ({ classes, expanded = false, expandLevel = 1, labe className={clsx(_DataInspector, classes?.root)} open={rootExpanded} > - + {label ?? dynamicLabel} From 998f7468690a0f62e95a889ed6d6034f491a7fde Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Mon, 10 Oct 2022 02:34:09 +0200 Subject: [PATCH 183/537] fix: remove redundant onClick prop --- src/shared/ui/components/data-inspector/data-inspector.scss | 2 ++ src/shared/ui/components/data-inspector/data-inspector.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss index c9451690..f474211e 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.scss +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -3,6 +3,8 @@ .DataInspector { &-label { + width: fit-content; + margin-left: auto; color: darken(color.$blue, 30%); cursor: pointer; } diff --git a/src/shared/ui/components/data-inspector/data-inspector.tsx b/src/shared/ui/components/data-inspector/data-inspector.tsx index 09770e5e..059f722d 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.tsx +++ b/src/shared/ui/components/data-inspector/data-inspector.tsx @@ -38,7 +38,7 @@ export const DataInspector = ({ classes, expanded = false, expandLevel = 1, labe className={clsx(`${_DataInspector}-label`, classes?.label)} onClick={rootExpansionToggle} > - {label ?? dynamicLabel} + {label ?? dynamicLabel}
    From 633e81c34dc18a5f67881d6ee2872572220b6633 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Mon, 10 Oct 2022 02:43:45 +0200 Subject: [PATCH 184/537] chore: set expandLevel to 5, move css styles to entity --- src/entities/job/ui/jobs-list.scss | 3 ++- src/entities/job/ui/jobs-list.tsx | 2 +- src/shared/ui/components/data-inspector/data-inspector.scss | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/entities/job/ui/jobs-list.scss b/src/entities/job/ui/jobs-list.scss index 2bc535e7..93f1863e 100644 --- a/src/entities/job/ui/jobs-list.scss +++ b/src/entities/job/ui/jobs-list.scss @@ -1,7 +1,8 @@ .JobsList { &-dataInspector { &-label { - text-align: right; + width: fit-content; + margin-left: auto; } } diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index bb8622cc..fa6022f8 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -33,7 +33,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { , ])} /> diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss index f474211e..c9451690 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.scss +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -3,8 +3,6 @@ .DataInspector { &-label { - width: fit-content; - margin-left: auto; color: darken(color.$blue, 30%); cursor: pointer; } From 755336cdbde4a039db4319c93748fef6bfd4622b Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Mon, 10 Oct 2022 03:30:31 +0200 Subject: [PATCH 185/537] feat: added view in editor button to jobs multicall display --- src/entities/job/ui/jobs-list.scss | 18 ++++++++++++++++++ src/entities/job/ui/jobs-list.tsx | 20 +++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/entities/job/ui/jobs-list.scss b/src/entities/job/ui/jobs-list.scss index 93f1863e..f595356b 100644 --- a/src/entities/job/ui/jobs-list.scss +++ b/src/entities/job/ui/jobs-list.scss @@ -1,3 +1,6 @@ +@use "sass/color"; +@use "sass/size"; + .JobsList { &-dataInspector { &-label { @@ -6,6 +9,21 @@ } } + &-viewInEditor { + margin-top: 0.5 * size.$gap; + padding: 0 1em; + border-radius: size.$task-radius; + border: 2px solid color.$blue; + font-size: size.$text; + font-weight: 800; + color: darken(color.$blue, 30%) !important; + background-color: rgba(color.$blue, 0.2); + float: right; + &:hover { + background-color: color.$blue; + } + } + .Table-row-content--compact:last-of-type { align-items: flex-start; diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index fa6022f8..4634697c 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -2,6 +2,7 @@ import { cronToDate, toTGas } from "../../../shared/lib/converter"; import { DataInspector, Scrollable, Table, Tile } from "../../../shared/ui/components"; import { JobDataModel } from "../model/job-data"; import { JobEntity } from "../config"; +import { NavLink } from "react-router-dom"; import "./jobs-list.scss"; @@ -30,11 +31,20 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { job.creator, `${toTGas(job.trigger_gas)} Tgas`, - , + <> + + setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0)} + > + View in Editor + + , ])} /> From d5801dba643d212a6a29c4a96c38547604f362d7 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Mon, 10 Oct 2022 03:55:03 +0200 Subject: [PATCH 186/537] add jobs with attached FT, resolve type errors on wallet component --- src/entities/wallet/ui/wallet.tsx | 63 +++++++++++++++---------- src/shared/lib/contracts/multicall.ts | 1 + src/shared/lib/contracts/sputnik-dao.ts | 26 ++++++++++ src/widgets/export/export.jsx | 42 +++++++++-------- 4 files changed, 86 insertions(+), 46 deletions(-) diff --git a/src/entities/wallet/ui/wallet.tsx b/src/entities/wallet/ui/wallet.tsx index 9cdc2856..d1d50d85 100644 --- a/src/entities/wallet/ui/wallet.tsx +++ b/src/entities/wallet/ui/wallet.tsx @@ -4,7 +4,7 @@ import Autocomplete from "@mui/material/Autocomplete"; import TextField from "@mui/material/TextField"; import { Icon } from "@mui/material"; import debounce from "lodash.debounce"; -import { Component } from "react"; +import { Component, ContextType } from "react"; import { ArgsAccount, ArgsError } from "../../../shared/lib/args"; import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; @@ -14,17 +14,29 @@ import { errorMsg } from "../../../shared/lib/errors"; import { useWalletSelector } from "./providers"; import "./wallet.scss"; +const Ctx = useWalletSelector(); + +interface Props {} + +interface State { + currentDAO: SputnikDAO; + currentMulticall: Multicall; + expanded: { user: boolean; dao: boolean }; + color: string; +} + /* TODO: Decompose code */ -export class WalletComponent extends Component { - static contextType = useWalletSelector(); +export class WalletComponent extends Component { + static contextType = Ctx; + declare context: ContextType; - errors = { + errors: { [key: string]: ArgsError } = { noDao: new ArgsError(errorMsg.ERR_NO_DAO_ON_ADDR, (value) => this.errors.noDao.isBad), - noRights: new ArgsError(errorMsg.ERR_CANNOT_PROPOSE_TO_DAO, (value) => this.errors.noRights), + noRights: new ArgsError(errorMsg.ERR_CANNOT_PROPOSE_TO_DAO, (value) => this.errors.noRights.isBad), noContract: new ArgsError(errorMsg.ERR_DAO_HAS_NO_MTCL, (value) => this.errors.noContract.isBad), }; - daoList = []; + daoList: string[] = []; daoSearchDebounced = debounce( // debounced function @@ -35,38 +47,36 @@ export class WalletComponent extends Component { 400 ); - constructor(props, context) { + constructor(props: Props, context: ContextType) { super(props, context); this.state = { currentDAO: new SputnikDAO(STORAGE.addresses.dao), + currentMulticall: new Multicall(STORAGE.addresses.multicall), expanded: { user: false, dao: false || STORAGE.addresses.dao === "", }, + color: "", }; - const { accountId } = context; - STORAGE.setAddresses({ user: accountId }); + const { accountId } = context!; + STORAGE.setAddresses({ user: accountId! }); window.WALLET_COMPONENT = this; if (accountId) { - const URL = `https://api.${ - window.NEAR_ENV === "mainnet" ? "" : "testnet." - }app.astrodao.com/api/v1/daos/account-daos/${accountId}`; - fetch(URL) - .then((response) => response.json()) + SputnikDAO.getUserDaosInfo(accountId) .then((data) => (this.daoList = data.map((dao) => dao.id))) .then(() => this.forceUpdate()); } } signIn() { - const { modal } = this.context; + const { modal } = this.context!; modal.show(); } async signOut() { - const { selector } = this.context; + const { selector } = this.context!; const wallet = await selector.wallet(); wallet.signOut().catch((err) => { @@ -76,7 +86,7 @@ export class WalletComponent extends Component { } connectDao(daoAddress: SputnikDAO["address"]) { - const { accountId } = this.context; + const { accountId } = this.context!; const { noDao, noRights, noContract } = this.errors; @@ -89,22 +99,23 @@ export class WalletComponent extends Component { Promise.all([ // on failure return non-initialized DAO instance (per default: ready = false) SputnikDAO.init(daoAddress).catch((e) => new SputnikDAO(daoAddress)), - Multicall.isMulticall(multicallAddress).catch((e) => false), + Multicall.init(multicallAddress).catch((e) => new Multicall(multicallAddress)), ]) - .then(([initializedDAO, hasMulticall]) => { - if (!initializedDAO.ready || !hasMulticall) { - noDao.isBad = !initializedDAO.ready; - noContract.isBad = !hasMulticall; + .then(([daoInstance, multicallInstance]) => { + if (!daoInstance.ready || !multicallInstance.ready) { + noDao.isBad = !daoInstance.ready; + noContract.isBad = !multicallInstance.ready; window.MENU?.forceUpdate(); return; } this.setState({ - currentDAO: initializedDAO, + currentDAO: daoInstance, + currentMulticall: multicallInstance, }); // can user propose FunctionCall to DAO? - const canPropose = initializedDAO.checkUserPermission(accountId, "AddProposal", "FunctionCall"); + const canPropose = daoInstance.checkUserPermission(accountId!, "AddProposal", "FunctionCall"); if (!canPropose) noRights.isBad = true; // no add proposal rights @@ -143,7 +154,7 @@ export class WalletComponent extends Component { }); } - daoSearch(newValue) { + daoSearch(newValue: string) { STORAGE.setAddresses({}); // hack: empty setAddresses call to invoke callbacks if (newValue !== undefined && ArgsAccount.isValid(newValue)) { this.connectDao(newValue); @@ -153,7 +164,7 @@ export class WalletComponent extends Component { } render() { - const { selector: walletSelector, accountId } = this.context; + const { selector: walletSelector, accountId } = this.context!; const { expanded, color } = this.state; if (!walletSelector) return null; diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index b316036d..2a637126 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -240,6 +240,7 @@ class Multicall { * @param triggerGas Gas amount. Will be allocated for every tx in this job. * @returns */ + // TODO: currenty budget is hard-coded for jobs with 1 multicall async addJob(multicalls: MulticallArgs[], triggerDate: Date, triggerGas: string): Promise { // crontab in CronCat format. See: https://github.com/CronCats/Schedule const cadence: string = dateToCron(triggerDate); diff --git a/src/shared/lib/contracts/sputnik-dao.ts b/src/shared/lib/contracts/sputnik-dao.ts index de049380..2ba88021 100644 --- a/src/shared/lib/contracts/sputnik-dao.ts +++ b/src/shared/lib/contracts/sputnik-dao.ts @@ -43,6 +43,22 @@ const CONTRACT_CODE_HASHES_SELECTOR: Record = { ], }; +type AstroApiDaoInfo = { + createdAt: string; + transactionHash: string; + id: string; + config: object; + numberOfMembers: number; + numberOfGroups: number; + council: string[]; + accountIds: string[]; + status: string; + activeProposalCount: number; + totalProposalCount: number; + totalDaoFunds: number; + isCouncil: boolean; +}; + // Define structure of a SputnikDAO policy type Policy = { // List of roles and permissions for them in the current policy. @@ -232,6 +248,16 @@ class SputnikDAO { return SputnikDAO.CONTRACT_CODE_HASHES.includes(codeHash); } + static async getUserDaosInfo(accountId: string): Promise { + const apiURL = `https://api.${ + window.NEAR_ENV === "mainnet" ? "" : "testnet." + }app.astrodao.com/api/v1/daos/account-daos/${accountId}`; + const response = await fetch(apiURL); + const data: AstroApiDaoInfo[] = await response.json(); + + return data; + } + async addProposal(args: object | Uint8Array): Promise { return { receiverId: this.address, diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index 6b3709d8..cbd65ec0 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -186,8 +186,8 @@ export class Export extends Component { className="propose button" disabled={isProposeDisabled} onClick={async () => { - const { currentDAO: dao } = WALLET_COMPONENT.state; - // case 1: immediate execution => basic multicall + const { currentDAO: dao, currentMulticall: multicall } = WALLET_COMPONENT.state; + // Case 1: immediate execution => basic multicall if (!isJob) { // multicall with attached FT if (attachFT) { @@ -212,31 +212,33 @@ export class Export extends Component { signAndSendTxs([tx]); } } - // case2: scheduled execution => use jobs + // Case2: scheduled execution => use jobs else { - const multicallAddress = STORAGE.addresses.multicall; - const temporary = new Multicall(multicallAddress); - // multicall with attached FT + // Job with attached FT if (attachFT) { - console.log("multicall job with attached FT"); + const jobCount = await multicall.getJobCount(); + const [addJobTx, proposeJobTx] = await Promise.all([ + multicall.addJob( + // TODO: support jobs with multiple multicalls + [multicallArgs], + jobDateTime, + convert(gas.value, gas.unit) + ), + dao.proposeJobActivationFT( + desc.value, + jobCount, + token.value, + convert(amount.value, amount.unit, amount.decimals) + ), + ]); + signAndSendTxs([addJobTx, proposeJobTx]); } - // WALLET_COMPONENT.state.currentDAO.proposeMulticallFT( - // desc.value, - // multicallArgs, - // convert(gas.value, gas.unit), - // token.value, - // convert(amount.value, amount.unit, amount.decimals) - // ); - // multicall with attached NEAR + // Job with attached NEAR else { const jobCost = attachNEAR ? Big(convert(depo.value, depo.unit)).add(Multicall.CRONCAT_FEE).toFixed() : Multicall.CRONCAT_FEE; - console.log("multicall job with attached NEAR"); - const [jobCount, multicall] = await Promise.all([ - temporary.getJobCount(), - Multicall.init(STORAGE.addresses.multicall), - ]); + const jobCount = await multicall.getJobCount(); const [addJobTx, proposeJobTx] = await Promise.all([ multicall.addJob( // TODO: support jobs with multiple multicalls From 765b3cc33b5e9c81685762796cdc7a688a2c70c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 11 Oct 2022 10:55:45 +0400 Subject: [PATCH 187/537] chore: Format --- src/entities/job/model/job-data.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 4a3fc274..c65bab28 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -30,9 +30,9 @@ const jobsDataFx = async ( (jobsIndexedById, job) => { const jobWithStatus = JobExtended.withStatus(job); // base64 decode FunctionCall args - jobWithStatus.job.multicalls.forEach((mtclArgs) => - mtclArgs.calls.forEach((callArray) => - callArray.forEach((batchCall) => + jobWithStatus.job.multicalls.forEach((multicallArgs) => + multicallArgs.calls.forEach((call) => + call.forEach((batchCall) => batchCall.actions.forEach( (action) => (action.args = JSON.parse(Base64.decode(action.args))) ) From 410822176537563fb66cae0030a05acf98cfe4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 11 Oct 2022 10:59:55 +0400 Subject: [PATCH 188/537] fix: Show real errors only --- src/entities/job/model/job-data.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index c65bab28..3bcf9dc2 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -44,6 +44,7 @@ const jobsDataFx = async ( {} ), + error: null, loading: false, })) .catch((error) => ({ data: null, error: new Error(error), loading: false })) @@ -55,7 +56,7 @@ const useJobsData = (contracts: JobEntity.dependencies["contracts"]) => { useEffect(() => void jobsDataFx(contracts, stateUpdate), []); useEffect(() => { - state.error !== null && void console.error(state.error); + state.error instanceof Error && void console.error(state.error); }, [state]); return state; From c46fa82aa7b39d9eb43dbcb8f2fef7a98faef949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 11 Oct 2022 11:07:08 +0400 Subject: [PATCH 189/537] fix: Show "View in editor" only if job have multicalls --- src/entities/job/ui/jobs-list.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 4634697c..f675ebc6 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -37,13 +37,18 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { data={job.multicalls} expandLevel={5} /> - setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0)} - > - View in Editor - + + {job.multicalls.length > 0 && ( + + setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0) + } + > + View in Editor + + )} , ])} /> From fa7dc6c6acf5d3cd6ea0fcaa49a93531f2efff0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 11 Oct 2022 18:20:41 +0400 Subject: [PATCH 190/537] wip: Cure OCD --- src/entities/fungible-token/config.ts | 18 ++++++++---- src/entities/fungible-token/index.ts | 5 ++-- src/entities/fungible-token/lib/ft-format.ts | 7 +++-- .../fungible-token/model/ft-balances.ts | 7 +++-- .../fungible-token/ui/ft-balances.tsx | 13 ++++++--- src/entities/index.ts | 4 +-- src/entities/job/index.ts | 6 ++-- src/entities/near-token/config.ts | 18 ++++++++---- src/entities/near-token/index.ts | 5 ++-- .../near-token/model/near-balances.ts | 18 ++++++++---- src/entities/near-token/ui/near-balances.tsx | 22 +++++++++++---- .../dapp-login/ui/dapp-login-dialogs.tsx | 6 ++-- .../dapp-login/ui/dapp-login-menu.tsx | 5 ++-- src/pages/dao/funds/funds.tsx | 5 ++-- src/pages/dao/jobs/jobs.tsx | 5 ++-- src/shared/ui/components/dialog/dialog.tsx | 2 +- src/shared/ui/components/dialog/index.ts | 2 +- .../icon-label.scss} | 9 ++++-- .../ui/components/icon-label/icon-label.tsx | 25 +++++++++++++++++ src/shared/ui/components/icon-label/index.ts | 1 + src/shared/ui/components/index.ts | 18 ++++++------ src/shared/ui/components/popup-menu/index.ts | 2 +- .../ui/components/popup-menu/popup-menu.tsx | 2 +- src/shared/ui/components/text-input/index.ts | 2 +- .../ui/components/text-input/text-input.tsx | 4 +-- src/shared/ui/components/token-label/index.ts | 1 - .../ui/components/token-label/token-label.tsx | 28 ------------------- src/widgets/dialogs-layer/index.ts | 4 ++- src/widgets/index.ts | 2 +- src/widgets/tokens-balances/config.ts | 9 +++--- src/widgets/tokens-balances/index.ts | 6 ++-- 31 files changed, 154 insertions(+), 107 deletions(-) rename src/shared/ui/components/{token-label/token-label.scss => icon-label/icon-label.scss} (75%) create mode 100644 src/shared/ui/components/icon-label/icon-label.tsx create mode 100644 src/shared/ui/components/icon-label/index.ts delete mode 100644 src/shared/ui/components/token-label/index.ts delete mode 100644 src/shared/ui/components/token-label/token-label.tsx diff --git a/src/entities/fungible-token/config.ts b/src/entities/fungible-token/config.ts index a49d50e7..6f57a2ff 100644 --- a/src/entities/fungible-token/config.ts +++ b/src/entities/fungible-token/config.ts @@ -1,11 +1,17 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -export interface Dependencies { - contracts: { - dao: SputnikDAO; - multicall: Multicall; - }; +namespace FungibleTokenEntity { + export interface Dependencies { + contracts: { + dao: SputnikDAO; + multicall: Multicall; + }; + } } -export const FRACTIONAL_PART_LENGTH = 5; +class FungibleTokenConfig { + static FRACTIONAL_PART_LENGTH = 5; +} + +export { FungibleTokenConfig, type FungibleTokenEntity }; diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index dfa2be31..d369e95f 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,7 +1,8 @@ +import { FungibleTokenConfig, type FungibleTokenEntity } from "./config"; import { fungibleTokensBalancesRender } from "./ui/ft-balances"; -export class FungibleToken { +class FungibleToken extends FungibleTokenConfig { static allBalancesRender = fungibleTokensBalancesRender; } -export { type Dependencies as FungibleTokensDependencies } from "./config"; +export { FungibleToken, FungibleTokenEntity }; diff --git a/src/entities/fungible-token/lib/ft-format.ts b/src/entities/fungible-token/lib/ft-format.ts index 5d545ad0..0985b636 100644 --- a/src/entities/fungible-token/lib/ft-format.ts +++ b/src/entities/fungible-token/lib/ft-format.ts @@ -1,13 +1,14 @@ import { Big, formatTokenAmount } from "../../../shared/lib/converter"; -import { FRACTIONAL_PART_LENGTH } from "../config"; + +import { FungibleTokenConfig } from "../config"; const amountToDisplayAmount = (amount: string, decimals: number): string => { const formattedAmount = formatTokenAmount(amount, decimals), - minimalDisplayAmount = Big("10").pow(-FRACTIONAL_PART_LENGTH).toFixed(); + minimalDisplayAmount = Big("10").pow(-FungibleTokenConfig.FRACTIONAL_PART_LENGTH).toFixed(); return Big(formattedAmount).gt("0") && Big(formattedAmount).lt(minimalDisplayAmount) ? "< " + minimalDisplayAmount - : formatTokenAmount(amount, decimals, FRACTIONAL_PART_LENGTH); + : formatTokenAmount(amount, decimals, FungibleTokenConfig.FRACTIONAL_PART_LENGTH); }; export const FungibleTokenFormat = { diff --git a/src/entities/fungible-token/model/ft-balances.ts b/src/entities/fungible-token/model/ft-balances.ts index 48409948..d0a37b50 100644 --- a/src/entities/fungible-token/model/ft-balances.ts +++ b/src/entities/fungible-token/model/ft-balances.ts @@ -2,7 +2,8 @@ import { useEffect, useState } from "react"; import { Big } from "../../../shared/lib/converter"; import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; -import { Dependencies } from "../config"; + +import { type FungibleTokenEntity } from "../config"; type FungibleTokensDataFxResponse = { data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; @@ -10,7 +11,7 @@ type FungibleTokensDataFxResponse = { }; const fungibleTokensDataFx = async ( - { dao, multicall }: Dependencies["contracts"], + { dao, multicall }: FungibleTokenEntity.Dependencies["contracts"], callback: (result: FungibleTokensDataFxResponse) => void ) => { /* Get LikelyTokens list on DAO and its Multicall instance */ @@ -53,7 +54,7 @@ const fungibleTokensDataFx = async ( }); }; -const useAllFungibleTokensData = (contracts: Dependencies["contracts"]) => { +const useAllFungibleTokensData = (contracts: FungibleTokenEntity.Dependencies["contracts"]) => { const [state, stateUpdate] = useState({ data: null, loading: true }); useEffect(() => void fungibleTokensDataFx(contracts, stateUpdate), []); diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index 8a1bc16b..eab01a33 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -1,9 +1,10 @@ -import { TokenLabel } from "../../../shared/ui/components"; +import { IconLabel, NearIcons } from "../../../shared/ui/components"; + import { FungibleTokenFormat } from "../lib/ft-format"; import { FungibleTokenBalancesModel } from "../model/ft-balances"; -import { Dependencies } from "../config"; +import { type FungibleTokenEntity } from "../config"; -interface FungibleTokensBalancesRenderProps extends Dependencies {} +interface FungibleTokensBalancesRenderProps extends FungibleTokenEntity.Dependencies {} export const fungibleTokensBalancesRender = ({ contracts }: FungibleTokensBalancesRenderProps) => { const { data } = FungibleTokenBalancesModel.useAllTokensFrom(contracts); @@ -11,7 +12,11 @@ export const fungibleTokensBalancesRender = ({ contracts }: FungibleTokensBalanc return !data ? null : data.map(({ dao, metadata, multicall, total }) => [ - , + } + label={metadata.symbol} + />, + FungibleTokenFormat.amountToDisplayAmount(multicall, metadata.decimals), FungibleTokenFormat.amountToDisplayAmount(dao, metadata.decimals), FungibleTokenFormat.amountToDisplayAmount(total, metadata.decimals), diff --git a/src/entities/index.ts b/src/entities/index.ts index 67f6b162..ef6c0dcd 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,5 +1,5 @@ export { Task } from "./task"; export { Job, type JobEntity } from "./job"; -export { FungibleToken, type FungibleTokensDependencies } from "./fungible-token"; -export { NearToken, type NearTokenDependencies } from "./near-token"; +export { FungibleToken, type FungibleTokenEntity } from "./fungible-token"; +export { NearToken, type NearTokenEntity } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index 639605c5..d4ba9a0b 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,8 +1,8 @@ -import { JobConfig } from "./config"; +import { JobConfig, type JobEntity } from "./config"; import { JobsList } from "./ui/jobs-list"; -export class Job extends JobConfig { +class Job extends JobConfig { static ListOfAll = JobsList; } -export { type JobEntity } from "./config"; +export { Job, type JobEntity }; diff --git a/src/entities/near-token/config.ts b/src/entities/near-token/config.ts index a49d50e7..20f47808 100644 --- a/src/entities/near-token/config.ts +++ b/src/entities/near-token/config.ts @@ -1,11 +1,17 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -export interface Dependencies { - contracts: { - dao: SputnikDAO; - multicall: Multicall; - }; +namespace NearTokenEntity { + export interface Dependencies { + contracts: { + dao: SputnikDAO; + multicall: Multicall; + }; + } } -export const FRACTIONAL_PART_LENGTH = 5; +class NearTokenConfig { + static FRACTIONAL_PART_LENGTH = 5; +} + +export { NearTokenConfig, type NearTokenEntity }; diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts index 04f9366d..b6aeb9d5 100644 --- a/src/entities/near-token/index.ts +++ b/src/entities/near-token/index.ts @@ -1,7 +1,8 @@ +import { NearTokenConfig, type NearTokenEntity } from "./config"; import { nearTokenBalancesRender } from "./ui/near-balances"; -export class NearToken { +class NearToken extends NearTokenConfig { static balancesRender = nearTokenBalancesRender; } -export { type Dependencies as NearTokenDependencies } from "./config"; +export { NearToken, type NearTokenEntity }; diff --git a/src/entities/near-token/model/near-balances.ts b/src/entities/near-token/model/near-balances.ts index 2d36c0fc..7fd7fb1c 100644 --- a/src/entities/near-token/model/near-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -2,7 +2,8 @@ import { useEffect, useState } from "react"; import { Big, formatTokenAmount } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; -import { FRACTIONAL_PART_LENGTH, type Dependencies } from "../config"; + +import { NearTokenConfig, type NearTokenEntity } from "../config"; type NearTokenDataFxResponse = { data: { dao: string; multicall: string; total: string } | null; @@ -10,7 +11,7 @@ type NearTokenDataFxResponse = { }; const nearTokenDataFx = async ( - { dao, multicall }: Dependencies["contracts"], + { dao, multicall }: NearTokenEntity.Dependencies["contracts"], callback: (result: NearTokenDataFxResponse) => void ) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ @@ -23,16 +24,21 @@ const nearTokenDataFx = async ( return callback({ data: { - dao: formatTokenAmount(daoRawBalance, 24, FRACTIONAL_PART_LENGTH), - multicall: formatTokenAmount(multicallRawBalance, 24, FRACTIONAL_PART_LENGTH), - total: formatTokenAmount(Big(daoRawBalance).add(multicallRawBalance).toFixed(), 24, FRACTIONAL_PART_LENGTH), + dao: formatTokenAmount(daoRawBalance, 24, NearTokenConfig.FRACTIONAL_PART_LENGTH), + multicall: formatTokenAmount(multicallRawBalance, 24, NearTokenConfig.FRACTIONAL_PART_LENGTH), + + total: formatTokenAmount( + Big(daoRawBalance).add(multicallRawBalance).toFixed(), + 24, + NearTokenConfig.FRACTIONAL_PART_LENGTH + ), }, loading: false, }); }; -const useNearTokenData = (contracts: Dependencies["contracts"]) => { +const useNearTokenData = (contracts: NearTokenEntity.Dependencies["contracts"]) => { const [state, stateUpdate] = useState({ data: null, loading: true }); useEffect(() => void nearTokenDataFx(contracts, stateUpdate), []); diff --git a/src/entities/near-token/ui/near-balances.tsx b/src/entities/near-token/ui/near-balances.tsx index 7142a21f..954d8e20 100644 --- a/src/entities/near-token/ui/near-balances.tsx +++ b/src/entities/near-token/ui/near-balances.tsx @@ -1,13 +1,23 @@ -import { TokenLabel } from "../../../shared/ui/components"; +import { IconLabel, NearIcons } from "../../../shared/ui/components"; + import { NearTokenBalancesModel } from "../model/near-balances"; -import { type Dependencies } from "../config"; +import { type NearTokenEntity } from "../config"; -interface NearTokenBalancesRenderProps { - contracts: Dependencies["contracts"]; -} +interface NearTokenBalancesRenderProps extends NearTokenEntity.Dependencies {} export const nearTokenBalancesRender = ({ contracts }: NearTokenBalancesRenderProps) => { const { data } = NearTokenBalancesModel.useTokenFrom(contracts); - return !data ? null : [, data.multicall, data.dao, data.total]; + return !data + ? null + : [ + } + label="NEAR" + />, + + data.multicall, + data.dao, + data.total, + ]; }; diff --git a/src/features/dapp-login/ui/dapp-login-dialogs.tsx b/src/features/dapp-login/ui/dapp-login-dialogs.tsx index 7bfa4d4f..97173635 100644 --- a/src/features/dapp-login/ui/dapp-login-dialogs.tsx +++ b/src/features/dapp-login/ui/dapp-login-dialogs.tsx @@ -1,17 +1,17 @@ import { InfoOutlined } from "@mui/icons-material"; import clsx from "clsx"; -import { useCallback, useMemo, useReducer, useState } from "react"; +import { ComponentProps, useCallback, useMemo, useReducer, useState } from "react"; import { ArgsError, ArgsString } from "../../../shared/lib/args"; import { STORAGE } from "../../../shared/lib/persistent"; import { Validation } from "../../../shared/lib/validation"; -import { Dialog, type DialogProps, TextInput, Tooltip } from "../../../shared/ui/components"; +import { Dialog, TextInput, Tooltip } from "../../../shared/ui/components"; import { DappLoginConfig as Config } from "../config"; import { DappLoginDialogsModel } from "../model/dapp-login-dialogs"; import "./dapp-login-dialog.scss"; -interface DappLoginDialogProps extends Pick { +interface DappLoginDialogProps extends Pick, "className" | "onClose" | "open" | "title"> { method: "dao" | "multicall"; } diff --git a/src/features/dapp-login/ui/dapp-login-menu.tsx b/src/features/dapp-login/ui/dapp-login-menu.tsx index 78b3724a..37724332 100644 --- a/src/features/dapp-login/ui/dapp-login-menu.tsx +++ b/src/features/dapp-login/ui/dapp-login-menu.tsx @@ -1,10 +1,11 @@ import { PreviewOutlined } from "@mui/icons-material"; +import { ComponentProps } from "react"; -import { PopupMenu, PopupMenuProps } from "../../../shared/ui/components"; +import { PopupMenu } from "../../../shared/ui/components"; import { DappLoginConfig as Config } from "../config"; import { DappLoginDialogsModel } from "../model/dapp-login-dialogs"; -interface DappLoginMenuProps extends Pick { +interface DappLoginMenuProps extends Pick, "triggerClassName"> { FeatureFlags: { DappLogin: Record; }; diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index 70411e24..4b4aeddf 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -1,10 +1,11 @@ import clsx from "clsx"; +import { ComponentProps, HTMLProps } from "react"; -import { TokensBalances, type TokensBalancesDependencies } from "../../../widgets"; +import { TokensBalances } from "../../../widgets"; import "./funds.scss"; -interface DaoFundsTabComponentProps extends TokensBalancesDependencies {} +interface DaoFundsTabComponentProps extends HTMLProps, ComponentProps {} const _DaoFundsTab = "DaoFundsTab"; diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 2aef13a8..e7fbe4c8 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -1,10 +1,11 @@ import clsx from "clsx"; +import { ComponentProps, HTMLProps } from "react"; -import { Job, type JobEntity } from "../../../entities"; +import { Job } from "../../../entities"; import "./jobs.scss"; -interface DaoJobsTabComponentProps extends JobEntity.dependencies {} +interface DaoJobsTabComponentProps extends HTMLProps, ComponentProps {} const _DaoJobsTab = "DaoJobsTab"; diff --git a/src/shared/ui/components/dialog/dialog.tsx b/src/shared/ui/components/dialog/dialog.tsx index ac295f18..28a78a01 100644 --- a/src/shared/ui/components/dialog/dialog.tsx +++ b/src/shared/ui/components/dialog/dialog.tsx @@ -9,7 +9,7 @@ import { PropsWithChildren } from "react"; import "./dialog.scss"; -export interface DialogProps extends PropsWithChildren { +interface DialogProps extends PropsWithChildren { cancelRename?: string; className?: string; doneRename?: string; diff --git a/src/shared/ui/components/dialog/index.ts b/src/shared/ui/components/dialog/index.ts index 04f7b3d1..bca0c2f7 100644 --- a/src/shared/ui/components/dialog/index.ts +++ b/src/shared/ui/components/dialog/index.ts @@ -1 +1 @@ -export { Dialog, type DialogProps } from "./dialog"; +export { Dialog } from "./dialog"; diff --git a/src/shared/ui/components/token-label/token-label.scss b/src/shared/ui/components/icon-label/icon-label.scss similarity index 75% rename from src/shared/ui/components/token-label/token-label.scss rename to src/shared/ui/components/icon-label/icon-label.scss index 9e4d4459..32bb2912 100644 --- a/src/shared/ui/components/token-label/token-label.scss +++ b/src/shared/ui/components/icon-label/icon-label.scss @@ -1,7 +1,7 @@ @use "sass/mixin"; @use "sass/size"; -.TokenLabel { +.IconLabel { display: flex; align-items: center; gap: size.$gap; @@ -12,9 +12,14 @@ cursor: default !important; border-radius: 50%; box-shadow: 0px 5px 11px -3px rgba(0, 0, 0, 0.1); + + & > * { + width: inherit; + height: inherit; + } } - &-symbol { + &-label { font-weight: bold; } } diff --git a/src/shared/ui/components/icon-label/icon-label.tsx b/src/shared/ui/components/icon-label/icon-label.tsx new file mode 100644 index 00000000..94ab58ee --- /dev/null +++ b/src/shared/ui/components/icon-label/icon-label.tsx @@ -0,0 +1,25 @@ +import "./icon-label.scss"; + +const _IconLabel = "IconLabel"; + +interface IconLabelProps { + icon: string | JSX.Element; + label: string; +} + +export const IconLabel = ({ icon, label }: IconLabelProps) => ( + + + {typeof icon === "string" ? ( + + ) : ( + icon + )} + + + {label} + +); diff --git a/src/shared/ui/components/icon-label/index.ts b/src/shared/ui/components/icon-label/index.ts new file mode 100644 index 00000000..fc839a6a --- /dev/null +++ b/src/shared/ui/components/icon-label/index.ts @@ -0,0 +1 @@ +export { IconLabel } from "./icon-label"; diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index b1eea815..97a98d0a 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,11 +1,11 @@ export { DataInspector } from "./data-inspector"; -export { Dialog, type DialogProps } from "./dialog/dialog"; +export { Dialog } from "./dialog"; export { NearIcons } from "./icons"; -export { PopupMenu, type PopupMenuProps } from "./popup-menu/popup-menu"; -export { Scrollable } from "./scrollable/scrollable"; -export { Table } from "./table/table"; -export { Tabs } from "./tabs/tabs"; -export { TextInput, type TextInputProps, TextInputWithUnits, type TextInputWithUnitsProps } from "./text-input"; -export { Tile } from "./tile/tile"; -export { TokenLabel } from "./token-label/token-label"; -export { Tooltip } from "./tooltip/tooltip"; +export { PopupMenu } from "./popup-menu"; +export { Scrollable } from "./scrollable"; +export { Table } from "./table"; +export { Tabs } from "./tabs"; +export { TextInput, TextInputWithUnits } from "./text-input"; +export { Tile } from "./tile"; +export { IconLabel } from "./icon-label"; +export { Tooltip } from "./tooltip"; diff --git a/src/shared/ui/components/popup-menu/index.ts b/src/shared/ui/components/popup-menu/index.ts index 9b6d72e2..f46d5fcd 100644 --- a/src/shared/ui/components/popup-menu/index.ts +++ b/src/shared/ui/components/popup-menu/index.ts @@ -1 +1 @@ -export { PopupMenu, type PopupMenuProps } from "./popup-menu"; +export { PopupMenu } from "./popup-menu"; diff --git a/src/shared/ui/components/popup-menu/popup-menu.tsx b/src/shared/ui/components/popup-menu/popup-menu.tsx index 3cb4b4bc..0ddbc19e 100644 --- a/src/shared/ui/components/popup-menu/popup-menu.tsx +++ b/src/shared/ui/components/popup-menu/popup-menu.tsx @@ -4,7 +4,7 @@ import { ReactNode } from "react"; import "./popup-menu.scss"; -export interface PopupMenuProps { +interface PopupMenuProps { icon: ReactNode; items: { disabled?: boolean; label?: string; onClick?: VoidFunction; title: string }[]; triggerClassName: string; diff --git a/src/shared/ui/components/text-input/index.ts b/src/shared/ui/components/text-input/index.ts index 8eafe224..95be585a 100644 --- a/src/shared/ui/components/text-input/index.ts +++ b/src/shared/ui/components/text-input/index.ts @@ -1 +1 @@ -export { TextInput, type TextInputProps, TextInputWithUnits, type TextInputWithUnitsProps } from "./text-input"; +export { TextInput, TextInputWithUnits } from "./text-input"; diff --git a/src/shared/ui/components/text-input/text-input.tsx b/src/shared/ui/components/text-input/text-input.tsx index 352524fe..27067528 100644 --- a/src/shared/ui/components/text-input/text-input.tsx +++ b/src/shared/ui/components/text-input/text-input.tsx @@ -3,7 +3,7 @@ import { MenuItem, TextField, TextFieldProps } from "@mui/material"; import { ArgsError, ArgsString } from "../../../lib/args"; -export interface TextInputProps extends Pick { +interface TextInputProps extends Pick { error: ArgsError; update: (event: ChangeEvent, component: Component) => void; value: ArgsString; @@ -36,7 +36,7 @@ export class TextInput extends Component { } } -export interface TextInputWithUnitsProps extends TextInputProps { +interface TextInputWithUnitsProps extends TextInputProps { // TODO!: Extend the interface } diff --git a/src/shared/ui/components/token-label/index.ts b/src/shared/ui/components/token-label/index.ts deleted file mode 100644 index fe3c7ada..00000000 --- a/src/shared/ui/components/token-label/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { TokenLabel } from "./token-label"; diff --git a/src/shared/ui/components/token-label/token-label.tsx b/src/shared/ui/components/token-label/token-label.tsx deleted file mode 100644 index 13294f91..00000000 --- a/src/shared/ui/components/token-label/token-label.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { NearIcons } from "../icons"; -import "./token-label.scss"; - -const _TokenLabel = "TokenLabel"; - -interface TokenLabelProps { - icon?: string | null; - native?: boolean; - symbol?: string; -} - -export const TokenLabel = ({ icon, native, symbol }: TokenLabelProps) => ( - - {!native && typeof icon === "string" ? ( - - ) : native ? ( - - ) : ( - - )} - - {native ? "NEAR" : symbol} - -); diff --git a/src/widgets/dialogs-layer/index.ts b/src/widgets/dialogs-layer/index.ts index 62bc5a04..36a365a8 100644 --- a/src/widgets/dialogs-layer/index.ts +++ b/src/widgets/dialogs-layer/index.ts @@ -1 +1,3 @@ -export { DialogsLayer } from "./ui/dialogs-layer"; +import { DialogsLayer } from "./ui/dialogs-layer"; + +export { DialogsLayer }; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index a23ad260..f115ff00 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -5,4 +5,4 @@ export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export/export.jsx"; export { Sidebar } from "./sidebar/sidebar.jsx"; -export { TokensBalances, type TokensBalancesDependencies } from "./tokens-balances"; +export { TokensBalances, type TokensBalancesWidget } from "./tokens-balances"; diff --git a/src/widgets/tokens-balances/config.ts b/src/widgets/tokens-balances/config.ts index 67ffa8e0..28708793 100644 --- a/src/widgets/tokens-balances/config.ts +++ b/src/widgets/tokens-balances/config.ts @@ -1,6 +1,7 @@ -import { NearTokenDependencies } from "../../entities"; -import { FungibleTokensDependencies } from "../../entities"; +import { NearTokenEntity, FungibleTokenEntity } from "../../entities"; -export interface Dependencies extends FungibleTokensDependencies, NearTokenDependencies { - className?: string; +export namespace TokensBalancesWidget { + export interface Dependencies extends NearTokenEntity.dependencies, FungibleTokenEntity.dependencies { + className?: string; + } } diff --git a/src/widgets/tokens-balances/index.ts b/src/widgets/tokens-balances/index.ts index e478a8b8..6a67baf8 100644 --- a/src/widgets/tokens-balances/index.ts +++ b/src/widgets/tokens-balances/index.ts @@ -1,2 +1,4 @@ -export { TokensBalances } from "./ui/tokens-balances"; -export { type Dependencies as TokensBalancesDependencies } from "./config"; +import { TokensBalances } from "./ui/tokens-balances"; +import { type TokensBalancesWidget } from "./config"; + +export { TokensBalances, type TokensBalancesWidget }; From 9f2c2ea0de2402a1397c75df0dede2eed6b959ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 11 Oct 2022 18:22:31 +0400 Subject: [PATCH 191/537] wip: Add icon to job status --- src/entities/job/config.ts | 20 +++++++++-- src/entities/job/lib/job-extended.ts | 15 ++++---- src/entities/job/model/job-data.ts | 30 +++++++--------- src/entities/job/ui/job-details.scss | 26 ++++++++++++++ src/entities/job/ui/job-details.tsx | 51 ++++++++++++++++++++++++++++ src/entities/job/ui/jobs-list.scss | 40 ++++++---------------- src/entities/job/ui/jobs-list.tsx | 45 +++++------------------- 7 files changed, 133 insertions(+), 94 deletions(-) create mode 100644 src/entities/job/ui/job-details.scss create mode 100644 src/entities/job/ui/job-details.tsx diff --git a/src/entities/job/config.ts b/src/entities/job/config.ts index bb828c1d..6e54533f 100644 --- a/src/entities/job/config.ts +++ b/src/entities/job/config.ts @@ -1,11 +1,13 @@ -import { Multicall } from "../../shared/lib/contracts/multicall"; +import { type JobData, type Multicall } from "../../shared/lib/contracts/multicall"; export namespace JobEntity { - export interface dependencies { - className: string; + export interface Dependencies { + className?: string; contracts: { multicall: Multicall }; } + export type Data = JobData; + export enum Status { Inactive = "Inactive", Expired = "Expired", @@ -13,8 +15,20 @@ export namespace JobEntity { Running = "Running", Unknown = "Unknown", } + + export type DataWithStatus = Omit & { + job: Data["job"] & { status: Status }; + }; } export class JobConfig { static readonly Status = JobEntity.Status; + + static StatusIcons = { + [JobEntity.Status.Inactive]: "🟡", + [JobEntity.Status.Expired]: "🔴", + [JobEntity.Status.Active]: "🟢", + [JobEntity.Status.Running]: "🟣", + [JobEntity.Status.Unknown]: "❔", + }; } diff --git a/src/entities/job/lib/job-extended.ts b/src/entities/job/lib/job-extended.ts index 429b8218..19793029 100644 --- a/src/entities/job/lib/job-extended.ts +++ b/src/entities/job/lib/job-extended.ts @@ -1,6 +1,7 @@ import { JobData } from "../../../shared/lib/contracts/multicall"; import { cronToDate } from "../../../shared/lib/converter"; -import { JobConfig as Config } from "../config"; + +import { JobConfig } from "../config"; /** * Job status is: @@ -9,13 +10,13 @@ import { JobConfig as Config } from "../config"; * - Expired: job not active, and execution moment is in the past. * - Inactive: job not active, but execution moment in the future. */ -const getDisplayStatus = ({ job }: JobData): string => { +const jobToStatus = ({ job }: JobData): string => { if (job.is_active) { - if (job.run_count > -1) return `Running: ${job.run_count + 1}/${job.multicalls.length}`; - else return Config.Status.Active; + if (job.run_count > -1) return JobConfig.Status.Running; + else return JobConfig.Status.Active; } else { - if (cronToDate(job.cadence).getTime() < new Date().getTime()) return Config.Status.Expired; - else return Config.Status.Inactive; + if (cronToDate(job.cadence).getTime() < new Date().getTime()) return JobConfig.Status.Expired; + else return JobConfig.Status.Inactive; } }; @@ -31,7 +32,7 @@ const jobExtendedWithStatus = (job: JobData) => ({ id: job.id, job: { ...job.job, - status: getDisplayStatus(job), + status: jobToStatus(job), }, }); diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 3bcf9dc2..4c5f92b8 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -1,24 +1,18 @@ import { useEffect, useState } from "react"; import { Base64 } from "js-base64"; -import { JobData } from "../../../shared/lib/contracts/multicall"; import { type JobEntity } from "../config"; import { JobExtended } from "../lib/job-extended"; -type JobDataWithStatus = Omit & { - job: JobData["job"] & { - status: JobEntity.Status; - }; -}; - type JobsDataFxResponse = { - data: Record | null; + /** Jobs indexed by ID for easy access to each particular job */ + data: Record | null; error?: Error | null; loading: boolean; }; const jobsDataFx = async ( - { multicall }: JobEntity.dependencies["contracts"], + { multicall }: JobEntity.Dependencies["contracts"], callback: (result: JobsDataFxResponse) => void ) => callback( @@ -26,21 +20,21 @@ const jobsDataFx = async ( .getJobs() .then((data) => ({ data: data.reduce( - /** Jobs indexed by ID for easy access to each particular job */ - (jobsIndexedById, job) => { - const jobWithStatus = JobExtended.withStatus(job); - // base64 decode FunctionCall args - jobWithStatus.job.multicalls.forEach((multicallArgs) => + (jobsIndexedById, job) => ({ + ...jobsIndexedById, + + [job.id]: JobExtended.withStatus(job).job.multicalls.forEach((multicallArgs) => multicallArgs.calls.forEach((call) => call.forEach((batchCall) => batchCall.actions.forEach( + /** base64 decode FunctionCall args */ (action) => (action.args = JSON.parse(Base64.decode(action.args))) ) ) ) - ); - return { ...jobsIndexedById, [job.id]: jobWithStatus }; - }, + ), + }), + {} ), @@ -50,7 +44,7 @@ const jobsDataFx = async ( .catch((error) => ({ data: null, error: new Error(error), loading: false })) ); -const useJobsData = (contracts: JobEntity.dependencies["contracts"]) => { +const useJobsData = (contracts: JobEntity.Dependencies["contracts"]) => { const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); useEffect(() => void jobsDataFx(contracts, stateUpdate), []); diff --git a/src/entities/job/ui/job-details.scss b/src/entities/job/ui/job-details.scss new file mode 100644 index 00000000..407a37fe --- /dev/null +++ b/src/entities/job/ui/job-details.scss @@ -0,0 +1,26 @@ +@use "sass/color"; +@use "sass/size"; + +.Job { + &-dataInspector { + &-label { + width: fit-content; + margin-left: auto; + } + } + + &-action { + margin-top: 0.5 * size.$gap; + padding: 0 1em; + border-radius: size.$task-radius; + border: 2px solid color.$blue; + font-size: size.$text; + font-weight: 800; + color: darken(color.$blue, 30%) !important; + background-color: rgba(color.$blue, 0.2); + float: right; + &:hover { + background-color: color.$blue; + } + } +} diff --git a/src/entities/job/ui/job-details.tsx b/src/entities/job/ui/job-details.tsx new file mode 100644 index 00000000..589f0cd7 --- /dev/null +++ b/src/entities/job/ui/job-details.tsx @@ -0,0 +1,51 @@ +import { NavLink } from "react-router-dom"; + +import { cronToDate, toTGas } from "../../../shared/lib/converter"; +import { DataInspector } from "../../../shared/ui/components"; + +import { JobConfig, type JobEntity } from "../config"; + +interface JobDetailsTableRowRenderProps extends JobEntity.DataWithStatus {} + +const _Job = "_Job"; + +const JobDisplayStatus = ({ job }: Pick) => { + const statusTextByStatus = { + ...JobConfig.Status, + [JobConfig.Status.Running]: `${JobConfig.Status.Running}: ${job.run_count + 1}/${job.multicalls.length}`, + }; + + return ( + + {JobConfig.StatusIcons[job.status]} + {statusTextByStatus[job.status]} + + ); +}; + +export const jobDetailsTableRowRender = ({ id, job }: JobDetailsTableRowRenderProps) => [ + , + id, + cronToDate(job.cadence).toLocaleString(), + job.croncat_hash.length === 0 ? none : job.croncat_hash, + job.creator, + `${toTGas(job.trigger_gas)} Tgas`, + + <> + + + {job.multicalls.length > 0 && ( + setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0)} + > + View in Editor + + )} + , +]; diff --git a/src/entities/job/ui/jobs-list.scss b/src/entities/job/ui/jobs-list.scss index f595356b..e58cd0bc 100644 --- a/src/entities/job/ui/jobs-list.scss +++ b/src/entities/job/ui/jobs-list.scss @@ -2,38 +2,18 @@ @use "sass/size"; .JobsList { - &-dataInspector { - &-label { - width: fit-content; - margin-left: auto; - } - } + &-body { + .Table-row-content--compact:last-of-type { + align-items: flex-start; - &-viewInEditor { - margin-top: 0.5 * size.$gap; - padding: 0 1em; - border-radius: size.$task-radius; - border: 2px solid color.$blue; - font-size: size.$text; - font-weight: 800; - color: darken(color.$blue, 30%) !important; - background-color: rgba(color.$blue, 0.2); - float: right; - &:hover { - background-color: color.$blue; - } - } - - .Table-row-content--compact:last-of-type { - align-items: flex-start; - - & > span { - &:first-of-type { - position: absolute; - } + & > span { + &:first-of-type { + position: absolute; + } - &:last-of-type { - width: 100%; + &:last-of-type { + width: 100%; + } } } } diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index f675ebc6..a0a8b23b 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,12 +1,12 @@ -import { cronToDate, toTGas } from "../../../shared/lib/converter"; -import { DataInspector, Scrollable, Table, Tile } from "../../../shared/ui/components"; -import { JobDataModel } from "../model/job-data"; -import { JobEntity } from "../config"; -import { NavLink } from "react-router-dom"; +import clsx from "clsx"; +import { Scrollable, Table, Tile } from "../../../shared/ui/components"; +import { type JobEntity } from "../config"; +import { JobDataModel } from "../model/job-data"; +import { jobDetailsTableRowRender } from "./job-details"; import "./jobs-list.scss"; -interface JobsListProps extends JobEntity.dependencies {} +interface JobsListProps extends JobEntity.Dependencies {} const _JobsList = "JobsList"; @@ -14,43 +14,16 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { const { data, loading } = JobDataModel.useAllJobsFrom(contracts); return ( - +

    All jobs

    {data && (
    [ - job.status, - id, - cronToDate(job.cadence).toLocaleString(), - job.croncat_hash.length === 0 ? none : job.croncat_hash, - job.creator, - `${toTGas(job.trigger_gas)} Tgas`, - - <> - - - {job.multicalls.length > 0 && ( - - setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0) - } - > - View in Editor - - )} - , - ])} + rows={Object.values(data).map(jobDetailsTableRowRender)} /> )} From a7a3ddbbc70804c83ff35e6eb019a8534b813941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 11 Oct 2022 20:35:22 +0400 Subject: [PATCH 192/537] wip: Create content placeholders --- src/shared/ui/components/placeholder/index.ts | 1 + .../placeholder/placeholder-content.scss | 9 +++++++ .../placeholder/placeholder-content.tsx | 15 +++++++++++ .../components/placeholder/placeholder.scss | 11 ++++++++ .../ui/components/placeholder/placeholder.tsx | 25 +++++++++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 src/shared/ui/components/placeholder/index.ts create mode 100644 src/shared/ui/components/placeholder/placeholder-content.scss create mode 100644 src/shared/ui/components/placeholder/placeholder-content.tsx create mode 100644 src/shared/ui/components/placeholder/placeholder.scss create mode 100644 src/shared/ui/components/placeholder/placeholder.tsx diff --git a/src/shared/ui/components/placeholder/index.ts b/src/shared/ui/components/placeholder/index.ts new file mode 100644 index 00000000..f7fbedb0 --- /dev/null +++ b/src/shared/ui/components/placeholder/index.ts @@ -0,0 +1 @@ +export { Placeholder } from "./placeholder"; diff --git a/src/shared/ui/components/placeholder/placeholder-content.scss b/src/shared/ui/components/placeholder/placeholder-content.scss new file mode 100644 index 00000000..c9517ce3 --- /dev/null +++ b/src/shared/ui/components/placeholder/placeholder-content.scss @@ -0,0 +1,9 @@ +@use "sass/size"; + +.Placeholder-content { + white-space: nowrap; + + &--noData { + font-size: calc(size.$large-text * 2); + } +} diff --git a/src/shared/ui/components/placeholder/placeholder-content.tsx b/src/shared/ui/components/placeholder/placeholder-content.tsx new file mode 100644 index 00000000..f47a785c --- /dev/null +++ b/src/shared/ui/components/placeholder/placeholder-content.tsx @@ -0,0 +1,15 @@ +import { HTMLProps } from "react"; + +import "./placeholder-content.scss"; + +interface NoDataContentProps extends HTMLProps {} + +export const NoDataContent = ({ className }: NoDataContentProps) => No data.; + +export interface UnknownErrorContentProps extends HTMLProps { + payload?: { error?: Error }; +} + +export const UnknownErrorContent = ({ className, payload }: UnknownErrorContentProps) => ( + {payload?.error?.message ?? "Unknown error."} +); diff --git a/src/shared/ui/components/placeholder/placeholder.scss b/src/shared/ui/components/placeholder/placeholder.scss new file mode 100644 index 00000000..c6da2595 --- /dev/null +++ b/src/shared/ui/components/placeholder/placeholder.scss @@ -0,0 +1,11 @@ +@use "sass/size"; + +.Placeholder { + display: flex; + flex: 1; + align-self: center; + align-items: center; + justify-content: center; + width: 100px; + height: 100px; +} diff --git a/src/shared/ui/components/placeholder/placeholder.tsx b/src/shared/ui/components/placeholder/placeholder.tsx new file mode 100644 index 00000000..c212ca90 --- /dev/null +++ b/src/shared/ui/components/placeholder/placeholder.tsx @@ -0,0 +1,25 @@ +import clsx from "clsx"; +import { HTMLProps, createElement as h } from "react"; + +import { NoDataContent, UnknownErrorContent, type UnknownErrorContentProps } from "./placeholder-content"; +import "./placeholder.scss"; + +const contentByType = { + noData: NoDataContent, + unknownError: UnknownErrorContent, +}; + +interface PlaceholderProps extends HTMLProps { + type: keyof typeof contentByType; + payload?: UnknownErrorContentProps["payload"]; +} +const _Placeholder = "Placeholder"; + +export const Placeholder = ({ className, payload, type }: PlaceholderProps) => ( +
    + {h(contentByType[type], { + className: clsx(`${_Placeholder}-content`, `${_Placeholder}-content--${type}`), + payload, + })} +
    +); From b1a153251b8f34eab9fe13dfd4169dea4e5e9b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 11 Oct 2022 20:35:58 +0400 Subject: [PATCH 193/537] wip: Use content placeholders for jobs list --- src/entities/job/ui/jobs-list.tsx | 20 +++++++++++++++----- src/shared/ui/components/index.ts | 1 + 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index a0a8b23b..b77c5c16 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import { Scrollable, Table, Tile } from "../../../shared/ui/components"; +import { Placeholder, Scrollable, Table, Tile } from "../../../shared/ui/components"; import { type JobEntity } from "../config"; import { JobDataModel } from "../model/job-data"; @@ -11,13 +11,25 @@ interface JobsListProps extends JobEntity.Dependencies {} const _JobsList = "JobsList"; export const JobsList = ({ className, contracts }: JobsListProps) => { - const { data, loading } = JobDataModel.useAllJobsFrom(contracts); + const { data, error, loading } = JobDataModel.useAllJobsFrom(contracts), + dataIsAvailable = data !== null && Object.values(data).length > 0, + noData = data !== null && Object.values(data).length === 0; return (

    All jobs

    - {data && ( + {loading &&
    } + {noData && } + + {error && ( + + )} + + {dataIsAvailable && (
    { /> )} - - {loading &&
    } ); }; diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 97a98d0a..1df1d397 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,6 +1,7 @@ export { DataInspector } from "./data-inspector"; export { Dialog } from "./dialog"; export { NearIcons } from "./icons"; +export { Placeholder } from "./placeholder"; export { PopupMenu } from "./popup-menu"; export { Scrollable } from "./scrollable"; export { Table } from "./table"; From 1693b47a1feb38fda8530561963d8c1dcaf53be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 12:30:11 +0400 Subject: [PATCH 194/537] chore: Format --- src/entities/job/ui/jobs-list.tsx | 1 + src/widgets/export/export.jsx | 48 +++++++++++++++++++++------- src/widgets/export/export.scss | 53 +++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 12 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index b77c5c16..9a381552 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; + import { Placeholder, Scrollable, Table, Tile } from "../../../shared/ui/components"; import { type JobEntity } from "../config"; diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index cbd65ec0..b6979229 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -1,12 +1,16 @@ -import EditOutlinedIcon from "@mui/icons-material/EditOutlined"; -import { InputAdornment } from "@mui/material"; -import Icon from "@mui/material/Icon"; -import TextField from "@mui/material/TextField"; -import Radio from "@mui/material/Radio"; -import RadioGroup from "@mui/material/RadioGroup"; -import FormControlLabel from "@mui/material/FormControlLabel"; -import FormControl from "@mui/material/FormControl"; -import FormLabel from "@mui/material/FormLabel"; +import { EditOutlined as EditOutlinedIcon } from "@mui/icons-material"; + +import { + FormControl, + FormControlLabel, + FormLabel, + Icon, + InputAdornment, + Radio, + RadioGroup, + TextField, +} from "@mui/material"; + import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component } from "react"; @@ -21,6 +25,7 @@ import { signAndSendTxs, view } from "../../shared/lib/wallet"; import { Wallet } from "../../entities"; import { TextInput, TextInputWithUnits } from "../../shared/ui/components"; import { DateTimePicker } from "../../shared/ui/components/date-time-picker"; + import "./export.scss"; export class Export extends Component { @@ -326,6 +331,7 @@ export class Export extends Component { multiline update={this.update} /> + +

    Attach

    + +

    or

    +
    + {attachNEAR ? ( ) : null} + {attachFT ? ( <> + ) : null} + Execution: + } label="Immediate" /> + } @@ -421,24 +437,26 @@ export class Export extends Component { /> + {isJob ? ( { - this.setState({ jobDateTime: value.toJSDate() }); - }} + handleChange={(value) => this.setState({ jobDateTime: value.toJSDate() })} /> ) : null}
    + {/* Display cards' errors */} + {allErrors.length > 0 && (

    {`Card errors (${allErrors.length})`}

    +
    {allErrors.map((e, i) => (

    {`[${e.task.call.name}] Error: ${e.message}`}

    + { @@ -458,6 +477,7 @@ export class Export extends Component {
    )} +
    expand_more +

    this.toggleShowArgs()}>Multicall args

    + {showArgs ? ( )}
    + {showArgs ? (
    {multicallArgsText}
    @@ -490,6 +513,7 @@ export class Export extends Component { <> )}
    +
    {this.renderProposeButton(multicallArgs)}
    diff --git a/src/widgets/export/export.scss b/src/widgets/export/export.scss index 021e80ed..92bb9029 100644 --- a/src/widgets/export/export.scss +++ b/src/widgets/export/export.scss @@ -20,29 +20,36 @@ flex-flow: column nowrap; width: 100%; max-height: 25%; + .sidebar { width: calc(100% - 1.5 * size.$gap); @include mixin.center-items(space-between); + h3 { cursor: pointer; font-size: size.$text; color: color.$light-text; text-align: left; } + .icon { @include mixin.light-icon; cursor: pointer; font-size: size.$text; } + .collapse { position: absolute; left: 0; + &[collapsed="yes"] { transform: rotate(-90deg); } + transition: all 50ms linear; } } + .value { flex: 1; width: 100%; @@ -50,6 +57,7 @@ box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); border-radius: size.$task-radius; overflow-y: scroll; + .code { padding: 0.5 * size.$gap; overflow: auto; @@ -66,49 +74,61 @@ .input-container { padding-top: size.$smaller-text; + .unitInput { @include mixin.center-items(center, flex-start); flex-flow: row nowrap; + .MuiTextField-root { width: unset !important; + &:first-of-type { flex: 2 1 auto; } + &:last-of-type { flex: 1 0 max-content; margin-left: 0.25 * size.$gap; + .MuiInputBase-root { width: 100% !important; font-size: size.$small-text; } } } + &:first-of-type .MuiTextField-root { &:first-of-type fieldset { border-radius: size.$task-radius 0 0 0; } + &:last-of-type fieldset { border-radius: 0 size.$task-radius 0 0; } } + &:last-of-type .MuiTextField-root { &:first-of-type fieldset { border-radius: 0 0 0 size.$task-radius; } + &:last-of-type fieldset { border-radius: 0 0 size.$task-radius 0; } } } + .attachment { @include mixin.center-items(flex-start, center); flex-flow: row nowrap; width: 100%; margin: 0.25 * size.$gap 0; + p { color: color.$light-text; font-size: size.$small-text; } + button { height: 2em; margin: 0 0.5ch; @@ -119,35 +139,43 @@ font-weight: 800; color: color.$light; background-color: rgba(color.$white, 0.1); + &.selected { color: color.$green; border: 1px solid color.$green; } + &:hover { background-color: rgba(color.$white, 0.2); } } } + .MuiTextField-root { p.Mui-error { color: color.$red; font-weight: 800; font-family: font.$text; font-size: size.$small-text; + &::before { content: "Error: "; } } + label { font-family: font.$text; font-weight: 800; + &.Mui-focused { color: color.$light-text; } + &.Mui-error { color: color.$red; } } + .MuiOutlinedInput-root { input, textarea { @@ -155,16 +183,19 @@ font-family: font.$code; font-size: size.$small-text; } + textarea { @include mixin.no-scrollbar; white-space: pre; overflow-x: scroll !important; } + fieldset { border-color: color.$lightish; border-width: 1px; box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); border-radius: 0; + legend { background-color: color.$black; margin-left: -2px; @@ -172,48 +203,60 @@ border-radius: 20px; visibility: visible; } + legend > span { font-size: 0.75em; visibility: hidden; } } + &:hover fieldset { border-color: color.$white; } + &.Mui-focused fieldset { border-color: color.$white; } + &.Mui-error fieldset { border-color: color.$red !important; } } + .MuiInput-underline { &:hover::before, &::before { border-bottom-color: color.$lightish; } + &:hover::after, &::after { border-bottom-color: color.$white; } + input { font-weight: 500; } } + *:not(input) { color: color.$light-text; font-size: 1em; } + width: 100%; font-size: 1.8rem; } + & > .MuiTextField-root { &:first-of-type { margin-top: 0; } + &:first-of-type > .MuiOutlinedInput-root > fieldset { border-radius: size.$task-radius size.$task-radius 0 0; } + &:last-of-type > .MuiOutlinedInput-root > fieldset { border-radius: 0 0 size.$task-radius size.$task-radius; } @@ -226,14 +269,17 @@ .error-container { width: 100%; + .header { padding-left: 0.5 * size.$gap; + h3 { font-size: size.$text; color: color.$red; text-align: left; } } + .error-list { width: 100%; display: flex; @@ -241,6 +287,7 @@ padding-top: 0.5 * size.$gap; box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); border-radius: size.$task-radius; + .error { width: 100%; max-width: calc(100% - size.$gap); @@ -252,9 +299,11 @@ font-size: size.$text; font-weight: 800; color: color.$red; + .msg { @include mixin.no-wrap; } + .icon { @include mixin.light-icon; cursor: pointer; @@ -271,17 +320,21 @@ bottom: 0; border-radius: size.$task-radius; z-index: 1; + &.propose { background-color: color.$green; + &:disabled { background-color: color.$darkish; cursor: not-allowed; } + p { font-size: size.$smaller-text; color: color.$red; } } + &.login { background-color: color.$light; } From 3293490783f4795a014808a74f11be627fc06e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 12:39:34 +0400 Subject: [PATCH 195/537] wip: Create custom radio button component --- src/shared/ui/components/index.ts | 1 + src/shared/ui/components/radio-button/index.ts | 1 + .../components/radio-button/radio-button.scss | 0 .../ui/components/radio-button/radio-button.tsx | 17 +++++++++++++++++ 4 files changed, 19 insertions(+) create mode 100644 src/shared/ui/components/radio-button/index.ts create mode 100644 src/shared/ui/components/radio-button/radio-button.scss create mode 100644 src/shared/ui/components/radio-button/radio-button.tsx diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 1df1d397..072c3f7d 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -3,6 +3,7 @@ export { Dialog } from "./dialog"; export { NearIcons } from "./icons"; export { Placeholder } from "./placeholder"; export { PopupMenu } from "./popup-menu"; +export { RadioButton } from "./radio-button"; export { Scrollable } from "./scrollable"; export { Table } from "./table"; export { Tabs } from "./tabs"; diff --git a/src/shared/ui/components/radio-button/index.ts b/src/shared/ui/components/radio-button/index.ts new file mode 100644 index 00000000..ded12a9a --- /dev/null +++ b/src/shared/ui/components/radio-button/index.ts @@ -0,0 +1 @@ +export { RadioButton } from "./radio-button"; diff --git a/src/shared/ui/components/radio-button/radio-button.scss b/src/shared/ui/components/radio-button/radio-button.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/shared/ui/components/radio-button/radio-button.tsx b/src/shared/ui/components/radio-button/radio-button.tsx new file mode 100644 index 00000000..eb28b582 --- /dev/null +++ b/src/shared/ui/components/radio-button/radio-button.tsx @@ -0,0 +1,17 @@ +import { FormControlLabel, Radio } from "@mui/material"; +import clsx from "clsx"; +import { ComponentProps } from "react"; + +import "./radio-button.scss"; + +interface RadioButtonProps extends ComponentProps {} + +const _RadioButton = "RadioButton"; + +export const RadioButton = ({ className, label, value }: RadioButtonProps) => ( + } + {...{ label, value }} + /> +); From f573c1034d9a2e071da207b0989a561fc6a272da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 13:10:33 +0400 Subject: [PATCH 196/537] wip: Represent basic from building kit as part of UI kit --- src/shared/ui/components/index.ts | 1 + src/shared/ui/components/radio-button/radio-button.tsx | 2 +- src/shared/ui/forms/elements/form-label.scss | 0 src/shared/ui/forms/elements/form-label.tsx | 10 ++++++++++ src/shared/ui/forms/index.ts | 2 ++ 5 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/shared/ui/forms/elements/form-label.scss create mode 100644 src/shared/ui/forms/elements/form-label.tsx create mode 100644 src/shared/ui/forms/index.ts diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 072c3f7d..1d55cda2 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,4 +1,5 @@ export { DataInspector } from "./data-inspector"; +export { DateTimePicker } from "./date-time-picker"; export { Dialog } from "./dialog"; export { NearIcons } from "./icons"; export { Placeholder } from "./placeholder"; diff --git a/src/shared/ui/components/radio-button/radio-button.tsx b/src/shared/ui/components/radio-button/radio-button.tsx index eb28b582..67fe1218 100644 --- a/src/shared/ui/components/radio-button/radio-button.tsx +++ b/src/shared/ui/components/radio-button/radio-button.tsx @@ -4,7 +4,7 @@ import { ComponentProps } from "react"; import "./radio-button.scss"; -interface RadioButtonProps extends ComponentProps {} +interface RadioButtonProps extends Omit, "control"> {} const _RadioButton = "RadioButton"; diff --git a/src/shared/ui/forms/elements/form-label.scss b/src/shared/ui/forms/elements/form-label.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/shared/ui/forms/elements/form-label.tsx b/src/shared/ui/forms/elements/form-label.tsx new file mode 100644 index 00000000..bc262735 --- /dev/null +++ b/src/shared/ui/forms/elements/form-label.tsx @@ -0,0 +1,10 @@ +import { FormLabel as GenericFormLabel, type FormLabelProps as GenericFromLabelProps } from "@mui/material"; +import "./form-label.scss"; + +interface FormLabelProps extends GenericFromLabelProps { + content: string | JSX.Element; +} + +export const FormLabel = ({ content, ...props }: FormLabelProps) => ( + {content} +); diff --git a/src/shared/ui/forms/index.ts b/src/shared/ui/forms/index.ts new file mode 100644 index 00000000..5ed07e1d --- /dev/null +++ b/src/shared/ui/forms/index.ts @@ -0,0 +1,2 @@ +export { FormControl } from "@mui/material"; +export { FormLabel } from "./elements/form-label"; From 27ea20ad4192a50bfc077a34fb212f62bf8fc849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 13:13:45 +0400 Subject: [PATCH 197/537] wip: Use custom form components --- src/widgets/export/export.jsx | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index b6979229..0e777a63 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -1,16 +1,5 @@ import { EditOutlined as EditOutlinedIcon } from "@mui/icons-material"; - -import { - FormControl, - FormControlLabel, - FormLabel, - Icon, - InputAdornment, - Radio, - RadioGroup, - TextField, -} from "@mui/material"; - +import { Icon, InputAdornment, RadioGroup, TextField } from "@mui/material"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component } from "react"; @@ -19,12 +8,12 @@ import { Link } from "react-router-dom"; import { ArgsAccount, ArgsBig, ArgsError, ArgsString } from "../../shared/lib/args"; import { errorMsg } from "../../shared/lib/errors"; import { STORAGE } from "../../shared/lib/persistent"; -import { Big, convert, toGas, toNEAR, toYocto } from "../../shared/lib/converter"; +import { Big, convert, toGas, toNEAR } from "../../shared/lib/converter"; import { Multicall } from "../../shared/lib/contracts/multicall"; import { signAndSendTxs, view } from "../../shared/lib/wallet"; import { Wallet } from "../../entities"; -import { TextInput, TextInputWithUnits } from "../../shared/ui/components"; -import { DateTimePicker } from "../../shared/ui/components/date-time-picker"; +import { DateTimePicker, RadioButton, TextInput, TextInputWithUnits } from "../../shared/ui/components"; +import { FormControl, FormLabel } from "../../shared/ui/forms"; import "./export.scss"; @@ -413,10 +402,13 @@ export class Export extends Component { ) : null} - Execution: + { @@ -424,15 +416,13 @@ export class Export extends Component { else if (value === "scheduled") this.setState({ isJob: true }); }} > - } label="Immediate" /> - } label="Scheduled" /> From de7710dc10521887d64803dd28a7ea76a2236888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 13:40:19 +0400 Subject: [PATCH 198/537] wip: Form kit cleanup --- src/shared/ui/components/index.ts | 1 - src/shared/ui/components/radio-button/index.ts | 1 - .../ui/components/radio-button/radio-button.tsx | 17 ----------------- .../ui/form-kit/elements/form-control.tsx | 1 + .../elements/form-label.scss | 0 .../{forms => form-kit}/elements/form-label.tsx | 0 .../ui/form-kit/elements/form-radio-group.tsx | 1 + .../fields/form-field-radio.scss} | 0 .../ui/form-kit/fields/form-field-radio.tsx | 17 +++++++++++++++++ src/shared/ui/form-kit/index.ts | 7 +++++++ src/shared/ui/forms/index.ts | 2 -- src/widgets/export/export.jsx | 8 ++++---- 12 files changed, 30 insertions(+), 25 deletions(-) delete mode 100644 src/shared/ui/components/radio-button/index.ts delete mode 100644 src/shared/ui/components/radio-button/radio-button.tsx create mode 100644 src/shared/ui/form-kit/elements/form-control.tsx rename src/shared/ui/{forms => form-kit}/elements/form-label.scss (100%) rename src/shared/ui/{forms => form-kit}/elements/form-label.tsx (100%) create mode 100644 src/shared/ui/form-kit/elements/form-radio-group.tsx rename src/shared/ui/{components/radio-button/radio-button.scss => form-kit/fields/form-field-radio.scss} (100%) create mode 100644 src/shared/ui/form-kit/fields/form-field-radio.tsx create mode 100644 src/shared/ui/form-kit/index.ts delete mode 100644 src/shared/ui/forms/index.ts diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 1d55cda2..023b0e7d 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -4,7 +4,6 @@ export { Dialog } from "./dialog"; export { NearIcons } from "./icons"; export { Placeholder } from "./placeholder"; export { PopupMenu } from "./popup-menu"; -export { RadioButton } from "./radio-button"; export { Scrollable } from "./scrollable"; export { Table } from "./table"; export { Tabs } from "./tabs"; diff --git a/src/shared/ui/components/radio-button/index.ts b/src/shared/ui/components/radio-button/index.ts deleted file mode 100644 index ded12a9a..00000000 --- a/src/shared/ui/components/radio-button/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { RadioButton } from "./radio-button"; diff --git a/src/shared/ui/components/radio-button/radio-button.tsx b/src/shared/ui/components/radio-button/radio-button.tsx deleted file mode 100644 index 67fe1218..00000000 --- a/src/shared/ui/components/radio-button/radio-button.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { FormControlLabel, Radio } from "@mui/material"; -import clsx from "clsx"; -import { ComponentProps } from "react"; - -import "./radio-button.scss"; - -interface RadioButtonProps extends Omit, "control"> {} - -const _RadioButton = "RadioButton"; - -export const RadioButton = ({ className, label, value }: RadioButtonProps) => ( - } - {...{ label, value }} - /> -); diff --git a/src/shared/ui/form-kit/elements/form-control.tsx b/src/shared/ui/form-kit/elements/form-control.tsx new file mode 100644 index 00000000..0819ba1d --- /dev/null +++ b/src/shared/ui/form-kit/elements/form-control.tsx @@ -0,0 +1 @@ +export { FormControl } from "@mui/material"; diff --git a/src/shared/ui/forms/elements/form-label.scss b/src/shared/ui/form-kit/elements/form-label.scss similarity index 100% rename from src/shared/ui/forms/elements/form-label.scss rename to src/shared/ui/form-kit/elements/form-label.scss diff --git a/src/shared/ui/forms/elements/form-label.tsx b/src/shared/ui/form-kit/elements/form-label.tsx similarity index 100% rename from src/shared/ui/forms/elements/form-label.tsx rename to src/shared/ui/form-kit/elements/form-label.tsx diff --git a/src/shared/ui/form-kit/elements/form-radio-group.tsx b/src/shared/ui/form-kit/elements/form-radio-group.tsx new file mode 100644 index 00000000..df6dbad3 --- /dev/null +++ b/src/shared/ui/form-kit/elements/form-radio-group.tsx @@ -0,0 +1 @@ +export { RadioGroup as FormRadioGroup } from "@mui/material"; diff --git a/src/shared/ui/components/radio-button/radio-button.scss b/src/shared/ui/form-kit/fields/form-field-radio.scss similarity index 100% rename from src/shared/ui/components/radio-button/radio-button.scss rename to src/shared/ui/form-kit/fields/form-field-radio.scss diff --git a/src/shared/ui/form-kit/fields/form-field-radio.tsx b/src/shared/ui/form-kit/fields/form-field-radio.tsx new file mode 100644 index 00000000..0e31d6de --- /dev/null +++ b/src/shared/ui/form-kit/fields/form-field-radio.tsx @@ -0,0 +1,17 @@ +import { FormControlLabel, Radio } from "@mui/material"; +import clsx from "clsx"; +import { ComponentProps } from "react"; + +import "./form-field-radio.scss"; + +export interface FormFieldRadioProps extends Omit, "control"> {} + +const _FormFieldRadio = "FormFieldRadio"; + +export const FormFieldRadio = ({ className, label, value }: FormFieldRadioProps) => ( + } + {...{ label, value }} + /> +); diff --git a/src/shared/ui/form-kit/index.ts b/src/shared/ui/form-kit/index.ts new file mode 100644 index 00000000..d64f1a88 --- /dev/null +++ b/src/shared/ui/form-kit/index.ts @@ -0,0 +1,7 @@ +/** Elements */ +export { FormControl } from "./elements/form-control"; +export { FormLabel } from "./elements/form-label"; +export { FormRadioGroup } from "./elements/form-radio-group"; + +/** Fields */ +export { FormFieldRadio } from "./fields/form-field-radio"; diff --git a/src/shared/ui/forms/index.ts b/src/shared/ui/forms/index.ts deleted file mode 100644 index 5ed07e1d..00000000 --- a/src/shared/ui/forms/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { FormControl } from "@mui/material"; -export { FormLabel } from "./elements/form-label"; diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index 0e777a63..f97ac94b 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -12,8 +12,8 @@ import { Big, convert, toGas, toNEAR } from "../../shared/lib/converter"; import { Multicall } from "../../shared/lib/contracts/multicall"; import { signAndSendTxs, view } from "../../shared/lib/wallet"; import { Wallet } from "../../entities"; -import { DateTimePicker, RadioButton, TextInput, TextInputWithUnits } from "../../shared/ui/components"; -import { FormControl, FormLabel } from "../../shared/ui/forms"; +import { DateTimePicker, TextInput, TextInputWithUnits } from "../../shared/ui/components"; +import { FormControl, FormLabel, FormFieldRadio } from "../../shared/ui/form-kit"; import "./export.scss"; @@ -416,12 +416,12 @@ export class Export extends Component { else if (value === "scheduled") this.setState({ isJob: true }); }} > - - From 7b79e235a7157fc08a8296399d00ff1d75ff3345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 13:45:14 +0400 Subject: [PATCH 199/537] wip: Reserve subdir for form makers --- src/shared/ui/form-kit/index.ts | 3 +++ src/shared/ui/form-kit/makers/.gitkeep | 0 2 files changed, 3 insertions(+) create mode 100644 src/shared/ui/form-kit/makers/.gitkeep diff --git a/src/shared/ui/form-kit/index.ts b/src/shared/ui/form-kit/index.ts index d64f1a88..3506017d 100644 --- a/src/shared/ui/form-kit/index.ts +++ b/src/shared/ui/form-kit/index.ts @@ -5,3 +5,6 @@ export { FormRadioGroup } from "./elements/form-radio-group"; /** Fields */ export { FormFieldRadio } from "./fields/form-field-radio"; + +/** Makers */ +// e.g. export { FormMakerLoremipsum } from "./makers/form-maker-loremipsum" diff --git a/src/shared/ui/form-kit/makers/.gitkeep b/src/shared/ui/form-kit/makers/.gitkeep new file mode 100644 index 00000000..e69de29b From 46b50c983079007bff3c07fb10faeca6f41c433c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 19:25:06 +0400 Subject: [PATCH 200/537] wip: Fix placeholder styles --- .../components/placeholder/placeholder-content.scss | 11 +++++++++-- src/shared/ui/components/placeholder/placeholder.scss | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/shared/ui/components/placeholder/placeholder-content.scss b/src/shared/ui/components/placeholder/placeholder-content.scss index c9517ce3..0e8aec7d 100644 --- a/src/shared/ui/components/placeholder/placeholder-content.scss +++ b/src/shared/ui/components/placeholder/placeholder-content.scss @@ -1,9 +1,16 @@ +@use "sass/color"; @use "sass/size"; .Placeholder-content { - white-space: nowrap; + padding: size.$gap; + text-align: center; + font-size: calc(size.$large-text * 1.5); + + &--unknownError { + color: darken(color.$red, 20); + } &--noData { - font-size: calc(size.$large-text * 2); + color: color.$darkish; } } diff --git a/src/shared/ui/components/placeholder/placeholder.scss b/src/shared/ui/components/placeholder/placeholder.scss index c6da2595..202c0cf4 100644 --- a/src/shared/ui/components/placeholder/placeholder.scss +++ b/src/shared/ui/components/placeholder/placeholder.scss @@ -6,6 +6,6 @@ align-self: center; align-items: center; justify-content: center; - width: 100px; - height: 100px; + width: 100%; + height: 100%; } From 02100893cd6203fcb32c4c66937fcaf5fb95f608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 19:25:54 +0400 Subject: [PATCH 201/537] wip: Fix job data normalization --- .../{job-extended.ts => job-normalized.ts} | 45 +++++++++++++++---- src/entities/job/model/job-data.ts | 14 +----- 2 files changed, 38 insertions(+), 21 deletions(-) rename src/entities/job/lib/{job-extended.ts => job-normalized.ts} (50%) diff --git a/src/entities/job/lib/job-extended.ts b/src/entities/job/lib/job-normalized.ts similarity index 50% rename from src/entities/job/lib/job-extended.ts rename to src/entities/job/lib/job-normalized.ts index 19793029..ef344725 100644 --- a/src/entities/job/lib/job-extended.ts +++ b/src/entities/job/lib/job-normalized.ts @@ -1,3 +1,5 @@ +import { Base64 } from "js-base64"; + import { JobData } from "../../../shared/lib/contracts/multicall"; import { cronToDate } from "../../../shared/lib/converter"; @@ -20,6 +22,36 @@ const jobToStatus = ({ job }: JobData): string => { } }; +/** + * Decodes base64-encoded arguments of for every multicall's FunctionCall + * and returns a new data structure with encoded version replaced with decoded one. + * + * @returns Updated job data structure. + */ +const jobToJobWithMulticallsDataDecoded = ({ id, job }: JobData) => ({ + id, + + job: { + ...job, + + multicalls: job.multicalls.map((multicall) => ({ + ...multicall, + + calls: multicall.calls.map((batchCalls) => + batchCalls.map((batchCall) => ({ + ...batchCall, + + actions: batchCall.actions.map((action) => ({ + ...action, + + args: JSON.parse(Base64.decode(action.args)), + })), + })) + ), + })), + }, +}); + /** * Calculates the actual job status from the given data * and adds it as an additional property to the new data structure. @@ -28,14 +60,9 @@ const jobToStatus = ({ job }: JobData): string => { * * @returns Extended job data structure. */ -const jobExtendedWithStatus = (job: JobData) => ({ - id: job.id, - job: { - ...job.job, - status: jobToStatus(job), - }, -}); +const jobToJobWithStatus = (job: JobData) => ({ ...job, job: { ...job.job, status: jobToStatus(job) } }); -export const JobExtended = { - withStatus: jobExtendedWithStatus, +export const JobNormalized = { + withMulticallsDataDecoded: jobToJobWithMulticallsDataDecoded, + withStatus: jobToJobWithStatus, }; diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 4c5f92b8..0e10887c 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { Base64 } from "js-base64"; import { type JobEntity } from "../config"; -import { JobExtended } from "../lib/job-extended"; +import { JobNormalized } from "../lib/job-normalized"; type JobsDataFxResponse = { /** Jobs indexed by ID for easy access to each particular job */ @@ -22,17 +22,7 @@ const jobsDataFx = async ( data: data.reduce( (jobsIndexedById, job) => ({ ...jobsIndexedById, - - [job.id]: JobExtended.withStatus(job).job.multicalls.forEach((multicallArgs) => - multicallArgs.calls.forEach((call) => - call.forEach((batchCall) => - batchCall.actions.forEach( - /** base64 decode FunctionCall args */ - (action) => (action.args = JSON.parse(Base64.decode(action.args))) - ) - ) - ) - ), + [job.id]: JobNormalized.withMulticallsDataDecoded(JobNormalized.withStatus(job)), }), {} From 22b4d36935c1a0d32a8bc3ae0569e178493b04a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 19:26:50 +0400 Subject: [PATCH 202/537] wip: Use more precise data availability flags --- src/entities/job/ui/jobs-list.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 9a381552..4d219fe7 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -13,8 +13,8 @@ const _JobsList = "JobsList"; export const JobsList = ({ className, contracts }: JobsListProps) => { const { data, error, loading } = JobDataModel.useAllJobsFrom(contracts), - dataIsAvailable = data !== null && Object.values(data).length > 0, - noData = data !== null && Object.values(data).length === 0; + dataIsAvailable = data !== null && !loading && Object.values(data).length > 0, + noData = data !== null && !loading && Object.values(data).length === 0; return ( From 557557c9659523871509f58bc77b9bdddcf5af4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 19:31:56 +0400 Subject: [PATCH 203/537] wip: Separate initial state --- src/entities/job/model/job-data.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 0e10887c..44b10ea3 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -1,9 +1,14 @@ import { useEffect, useState } from "react"; -import { Base64 } from "js-base64"; import { type JobEntity } from "../config"; import { JobNormalized } from "../lib/job-normalized"; +const jobsDataInitialState = { + data: null, + error: null, + loading: true, +}; + type JobsDataFxResponse = { /** Jobs indexed by ID for easy access to each particular job */ data: Record | null; @@ -19,23 +24,19 @@ const jobsDataFx = async ( await multicall .getJobs() .then((data) => ({ - data: data.reduce( - (jobsIndexedById, job) => ({ - ...jobsIndexedById, - [job.id]: JobNormalized.withMulticallsDataDecoded(JobNormalized.withStatus(job)), - }), - - {} - ), - - error: null, + ...jobsDataInitialState, loading: false, + + data: data.reduce((jobsIndexedById, job) => ({ + ...jobsIndexedById, + [job.id]: JobNormalized.withMulticallsDataDecoded(JobNormalized.withStatus(job)), + })), })) - .catch((error) => ({ data: null, error: new Error(error), loading: false })) + .catch((error) => ({ ...jobsDataInitialState, error: new Error(error), loading: false })) ); const useJobsData = (contracts: JobEntity.Dependencies["contracts"]) => { - const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); + const [state, stateUpdate] = useState(jobsDataInitialState); useEffect(() => void jobsDataFx(contracts, stateUpdate), []); From 2106b856f9b0fdd9745e7b176705c8521dd511bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 19:48:21 +0400 Subject: [PATCH 204/537] fix: Add missing initial object --- src/entities/job/model/job-data.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index 44b10ea3..fcab4bde 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -27,10 +27,13 @@ const jobsDataFx = async ( ...jobsDataInitialState, loading: false, - data: data.reduce((jobsIndexedById, job) => ({ - ...jobsIndexedById, - [job.id]: JobNormalized.withMulticallsDataDecoded(JobNormalized.withStatus(job)), - })), + data: data.reduce( + (jobsIndexedById, job) => ({ + ...jobsIndexedById, + [job.id]: JobNormalized.withMulticallsDataDecoded(JobNormalized.withStatus(job)), + }), + {} + ), })) .catch((error) => ({ ...jobsDataInitialState, error: new Error(error), loading: false })) ); From ab1029a05680d74bc8a10633d368ecd82d3d7696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 19:48:47 +0400 Subject: [PATCH 205/537] wip: Update types --- src/entities/job/lib/job-normalized.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/entities/job/lib/job-normalized.ts b/src/entities/job/lib/job-normalized.ts index ef344725..d61e49b5 100644 --- a/src/entities/job/lib/job-normalized.ts +++ b/src/entities/job/lib/job-normalized.ts @@ -3,7 +3,7 @@ import { Base64 } from "js-base64"; import { JobData } from "../../../shared/lib/contracts/multicall"; import { cronToDate } from "../../../shared/lib/converter"; -import { JobConfig } from "../config"; +import { JobConfig, type JobEntity } from "../config"; /** * Job status is: @@ -12,7 +12,7 @@ import { JobConfig } from "../config"; * - Expired: job not active, and execution moment is in the past. * - Inactive: job not active, but execution moment in the future. */ -const jobToStatus = ({ job }: JobData): string => { +const jobToStatus = ({ job }: JobData): JobEntity.Status => { if (job.is_active) { if (job.run_count > -1) return JobConfig.Status.Running; else return JobConfig.Status.Active; @@ -28,7 +28,7 @@ const jobToStatus = ({ job }: JobData): string => { * * @returns Updated job data structure. */ -const jobToJobWithMulticallsDataDecoded = ({ id, job }: JobData) => ({ +const jobToJobWithMulticallsDataDecoded = ({ id, job }: JobData): JobData => ({ id, job: { @@ -60,7 +60,10 @@ const jobToJobWithMulticallsDataDecoded = ({ id, job }: JobData) => ({ * * @returns Extended job data structure. */ -const jobToJobWithStatus = (job: JobData) => ({ ...job, job: { ...job.job, status: jobToStatus(job) } }); +const jobToJobWithStatus = (job: JobData): JobEntity.DataWithStatus => ({ + ...job, + job: { ...job.job, status: JobConfig.Status[jobToStatus(job)] }, +}); export const JobNormalized = { withMulticallsDataDecoded: jobToJobWithMulticallsDataDecoded, From 1da29c271f30d33a551955477448e4f84c6c93d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 20:13:49 +0400 Subject: [PATCH 206/537] wip: Update icon label typechecking & styles --- .../ui/components/icon-label/icon-label.scss | 14 ++++++++------ src/shared/ui/components/icon-label/icon-label.tsx | 4 +++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/shared/ui/components/icon-label/icon-label.scss b/src/shared/ui/components/icon-label/icon-label.scss index 32bb2912..027a641c 100644 --- a/src/shared/ui/components/icon-label/icon-label.scss +++ b/src/shared/ui/components/icon-label/icon-label.scss @@ -4,18 +4,20 @@ .IconLabel { display: flex; align-items: center; - gap: size.$gap; + gap: calc(size.$gap * 0.6); + line-height: 1; &-icon { - width: 1.5 * size.$gap; - height: 1.5 * size.$gap; + width: fit-content; + height: fit-content; cursor: default !important; border-radius: 50%; box-shadow: 0px 5px 11px -3px rgba(0, 0, 0, 0.1); - & > * { - width: inherit; - height: inherit; + & > img, + & > svg { + width: 1.5 * size.$gap; + height: 1.5 * size.$gap; } } diff --git a/src/shared/ui/components/icon-label/icon-label.tsx b/src/shared/ui/components/icon-label/icon-label.tsx index 94ab58ee..0cfa4cc3 100644 --- a/src/shared/ui/components/icon-label/icon-label.tsx +++ b/src/shared/ui/components/icon-label/icon-label.tsx @@ -1,3 +1,5 @@ +import { Validation } from "../../../lib/validation"; + import "./icon-label.scss"; const _IconLabel = "IconLabel"; @@ -10,7 +12,7 @@ interface IconLabelProps { export const IconLabel = ({ icon, label }: IconLabelProps) => ( - {typeof icon === "string" ? ( + {typeof icon === "string" && Validation.isUrl(icon) ? ( Date: Wed, 12 Oct 2022 18:14:09 +0200 Subject: [PATCH 207/537] fix getJobCount for multicalls without jobs --- src/shared/lib/contracts/multicall.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 2a637126..fd53bc01 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -229,7 +229,9 @@ class Multicall { */ async getJobCount(): Promise { const state = await viewState(this.address, KEY_JOB_COUNT); - return parseInt(state[0].value); + // The counter is added to storage when the 1st job is created. + const jobCount = state.length > 0 ? parseInt(state[0].value) : 0; + return jobCount; } /** From 1e8db601b5338b8e2863a53e5f1300bcb5bb6144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 20:14:37 +0400 Subject: [PATCH 208/537] wip: Render job status as icon label --- src/entities/job/ui/job-details.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/entities/job/ui/job-details.tsx b/src/entities/job/ui/job-details.tsx index 589f0cd7..d32a4cef 100644 --- a/src/entities/job/ui/job-details.tsx +++ b/src/entities/job/ui/job-details.tsx @@ -1,7 +1,7 @@ import { NavLink } from "react-router-dom"; import { cronToDate, toTGas } from "../../../shared/lib/converter"; -import { DataInspector } from "../../../shared/ui/components"; +import { DataInspector, IconLabel } from "../../../shared/ui/components"; import { JobConfig, type JobEntity } from "../config"; @@ -16,10 +16,10 @@ const JobDisplayStatus = ({ job }: Pick) => { }; return ( - - {JobConfig.StatusIcons[job.status]} - {statusTextByStatus[job.status]} - + ); }; From 1eae42376140db75819631a25b0960f613943381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 20:26:59 +0400 Subject: [PATCH 209/537] fix: Remove typo in job root classname --- src/entities/job/ui/job-details.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/entities/job/ui/job-details.tsx b/src/entities/job/ui/job-details.tsx index d32a4cef..c4989614 100644 --- a/src/entities/job/ui/job-details.tsx +++ b/src/entities/job/ui/job-details.tsx @@ -4,10 +4,11 @@ import { cronToDate, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/components"; import { JobConfig, type JobEntity } from "../config"; +import "./job-details.scss"; interface JobDetailsTableRowRenderProps extends JobEntity.DataWithStatus {} -const _Job = "_Job"; +const _Job = "Job"; const JobDisplayStatus = ({ job }: Pick) => { const statusTextByStatus = { From 7c1ba0e64c8d26cf14b156d451c7c7062b765eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 20:47:12 +0400 Subject: [PATCH 210/537] wip: Change editor navlink label --- src/entities/job/ui/job-details.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/job/ui/job-details.tsx b/src/entities/job/ui/job-details.tsx index c4989614..aa9bca03 100644 --- a/src/entities/job/ui/job-details.tsx +++ b/src/entities/job/ui/job-details.tsx @@ -45,7 +45,7 @@ export const jobDetailsTableRowRender = ({ id, job }: JobDetailsTableRowRenderPr className={`${_Job}-action`} onClick={() => setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0)} > - View in Editor + Open in Editor )} , From b5f67e99790375b6df1698dddf06dcd2c8445e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 20:57:25 +0400 Subject: [PATCH 211/537] wip: Pass props directly --- src/shared/ui/form-kit/elements/form-label.tsx | 2 +- src/shared/ui/form-kit/fields/form-field-radio.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/ui/form-kit/elements/form-label.tsx b/src/shared/ui/form-kit/elements/form-label.tsx index bc262735..5bbc7b21 100644 --- a/src/shared/ui/form-kit/elements/form-label.tsx +++ b/src/shared/ui/form-kit/elements/form-label.tsx @@ -6,5 +6,5 @@ interface FormLabelProps extends GenericFromLabelProps { } export const FormLabel = ({ content, ...props }: FormLabelProps) => ( - {content} + {content} ); diff --git a/src/shared/ui/form-kit/fields/form-field-radio.tsx b/src/shared/ui/form-kit/fields/form-field-radio.tsx index 0e31d6de..bca9dce5 100644 --- a/src/shared/ui/form-kit/fields/form-field-radio.tsx +++ b/src/shared/ui/form-kit/fields/form-field-radio.tsx @@ -8,10 +8,10 @@ export interface FormFieldRadioProps extends Omit ( +export const FormFieldRadio = ({ className, ...props }: FormFieldRadioProps) => ( } - {...{ label, value }} + {...props} /> ); From 43cc8a7e6f7a6f2f055aea8bb96431db13ea95b3 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Wed, 12 Oct 2022 19:30:15 +0200 Subject: [PATCH 212/537] temporarily use startAt instead of cronToDate. Only show open in editor for jobs with one multicall --- src/entities/job/lib/job-normalized.ts | 7 +++++-- src/entities/job/ui/job-details.tsx | 7 ++++--- .../ui/components/date-time-picker/date-time-picker.tsx | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/entities/job/lib/job-normalized.ts b/src/entities/job/lib/job-normalized.ts index d61e49b5..5b2e2efd 100644 --- a/src/entities/job/lib/job-normalized.ts +++ b/src/entities/job/lib/job-normalized.ts @@ -1,7 +1,7 @@ import { Base64 } from "js-base64"; import { JobData } from "../../../shared/lib/contracts/multicall"; -import { cronToDate } from "../../../shared/lib/converter"; +import { Big } from "../../../shared/lib/converter"; import { JobConfig, type JobEntity } from "../config"; @@ -17,7 +17,10 @@ const jobToStatus = ({ job }: JobData): JobEntity.Status => { if (job.run_count > -1) return JobConfig.Status.Running; else return JobConfig.Status.Active; } else { - if (cronToDate(job.cadence).getTime() < new Date().getTime()) return JobConfig.Status.Expired; + // Date.now() returns timestamp in milliseconds, we use nanoseconds + const currentTime = Big(Date.now()).times("1000000"); + const jobTime = job.start_at; + if (currentTime.gt(jobTime)) return JobConfig.Status.Expired; else return JobConfig.Status.Inactive; } }; diff --git a/src/entities/job/ui/job-details.tsx b/src/entities/job/ui/job-details.tsx index d32a4cef..87c5842b 100644 --- a/src/entities/job/ui/job-details.tsx +++ b/src/entities/job/ui/job-details.tsx @@ -1,6 +1,6 @@ import { NavLink } from "react-router-dom"; -import { cronToDate, toTGas } from "../../../shared/lib/converter"; +import { Big, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/components"; import { JobConfig, type JobEntity } from "../config"; @@ -26,7 +26,8 @@ const JobDisplayStatus = ({ job }: Pick) => { export const jobDetailsTableRowRender = ({ id, job }: JobDetailsTableRowRenderProps) => [ , id, - cronToDate(job.cadence).toLocaleString(), + // Multicall returns timestamp in nanoseconds, JS Date uses milliseconds + new Date(parseInt(Big(job.start_at).div("1000000").toFixed())).toLocaleString(), job.croncat_hash.length === 0 ? none : job.croncat_hash, job.creator, `${toTGas(job.trigger_gas)} Tgas`, @@ -38,7 +39,7 @@ export const jobDetailsTableRowRender = ({ id, job }: JobDetailsTableRowRenderPr expandLevel={5} /> - {job.multicalls.length > 0 && ( + {job.multicalls.length === 1 && ( Date: Wed, 12 Oct 2022 23:08:07 +0400 Subject: [PATCH 213/537] wip: Override form components' styles --- src/shared/ui/form-kit/elements/form-label.scss | 9 +++++++++ src/shared/ui/form-kit/elements/form-label.tsx | 12 ++++++++++-- .../ui/form-kit/fields/form-field-radio.scss | 17 +++++++++++++++++ .../ui/form-kit/fields/form-field-radio.tsx | 4 ++-- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/shared/ui/form-kit/elements/form-label.scss b/src/shared/ui/form-kit/elements/form-label.scss index e69de29b..3131576d 100644 --- a/src/shared/ui/form-kit/elements/form-label.scss +++ b/src/shared/ui/form-kit/elements/form-label.scss @@ -0,0 +1,9 @@ +@use "sass/color"; +@use "sass/size"; + +.FormLabel { + &.MuiFormLabel-root { + font-size: size.$text; + color: color.$white; + } +} diff --git a/src/shared/ui/form-kit/elements/form-label.tsx b/src/shared/ui/form-kit/elements/form-label.tsx index 5bbc7b21..e6c708fb 100644 --- a/src/shared/ui/form-kit/elements/form-label.tsx +++ b/src/shared/ui/form-kit/elements/form-label.tsx @@ -1,10 +1,18 @@ import { FormLabel as GenericFormLabel, type FormLabelProps as GenericFromLabelProps } from "@mui/material"; + import "./form-label.scss"; -interface FormLabelProps extends GenericFromLabelProps { +interface FormLabelProps extends Omit { content: string | JSX.Element; } +const _FormLabel = "FormLabel"; + export const FormLabel = ({ content, ...props }: FormLabelProps) => ( - {content} + + {content} + ); diff --git a/src/shared/ui/form-kit/fields/form-field-radio.scss b/src/shared/ui/form-kit/fields/form-field-radio.scss index e69de29b..7a6cbf84 100644 --- a/src/shared/ui/form-kit/fields/form-field-radio.scss +++ b/src/shared/ui/form-kit/fields/form-field-radio.scss @@ -0,0 +1,17 @@ +@use "sass/color"; +@use "sass/size"; + +.FormFieldRadio { + &-button.MuiButtonBase-root { + color: color.$white; + + &.Mui-checked { + color: color.$white; + } + } + + &-label.MuiFormControlLabel-label { + color: color.$white; + font-size: size.$text; + } +} diff --git a/src/shared/ui/form-kit/fields/form-field-radio.tsx b/src/shared/ui/form-kit/fields/form-field-radio.tsx index bca9dce5..1bd84491 100644 --- a/src/shared/ui/form-kit/fields/form-field-radio.tsx +++ b/src/shared/ui/form-kit/fields/form-field-radio.tsx @@ -10,8 +10,8 @@ const _FormFieldRadio = "FormFieldRadio"; export const FormFieldRadio = ({ className, ...props }: FormFieldRadioProps) => ( } + classes={{ root: clsx(_FormFieldRadio, className), label: `${_FormFieldRadio}-label` }} + control={} {...props} /> ); From 063e676b8f365d05eec86418b0f69ac13c1ba564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 23:09:02 +0400 Subject: [PATCH 214/537] wip: Customize execution settings section appearance --- src/widgets/export/export.jsx | 3 ++- src/widgets/export/export.scss | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index f97ac94b..712d7a02 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -401,7 +401,7 @@ export class Export extends Component { ) : null} - + Date: Wed, 12 Oct 2022 23:12:42 +0400 Subject: [PATCH 215/537] wip: Update form kit --- .../ui/form-kit/fields/form-field-radio.tsx | 17 ----------------- .../{form-field-radio.scss => form-radio.scss} | 2 +- src/shared/ui/form-kit/fields/form-radio.tsx | 17 +++++++++++++++++ src/shared/ui/form-kit/index.ts | 5 +---- src/shared/ui/form-kit/makers/.gitkeep | 0 src/widgets/export/export.jsx | 6 +++--- 6 files changed, 22 insertions(+), 25 deletions(-) delete mode 100644 src/shared/ui/form-kit/fields/form-field-radio.tsx rename src/shared/ui/form-kit/fields/{form-field-radio.scss => form-radio.scss} (94%) create mode 100644 src/shared/ui/form-kit/fields/form-radio.tsx delete mode 100644 src/shared/ui/form-kit/makers/.gitkeep diff --git a/src/shared/ui/form-kit/fields/form-field-radio.tsx b/src/shared/ui/form-kit/fields/form-field-radio.tsx deleted file mode 100644 index 1bd84491..00000000 --- a/src/shared/ui/form-kit/fields/form-field-radio.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { FormControlLabel, Radio } from "@mui/material"; -import clsx from "clsx"; -import { ComponentProps } from "react"; - -import "./form-field-radio.scss"; - -export interface FormFieldRadioProps extends Omit, "control"> {} - -const _FormFieldRadio = "FormFieldRadio"; - -export const FormFieldRadio = ({ className, ...props }: FormFieldRadioProps) => ( - } - {...props} - /> -); diff --git a/src/shared/ui/form-kit/fields/form-field-radio.scss b/src/shared/ui/form-kit/fields/form-radio.scss similarity index 94% rename from src/shared/ui/form-kit/fields/form-field-radio.scss rename to src/shared/ui/form-kit/fields/form-radio.scss index 7a6cbf84..216f3c4a 100644 --- a/src/shared/ui/form-kit/fields/form-field-radio.scss +++ b/src/shared/ui/form-kit/fields/form-radio.scss @@ -1,7 +1,7 @@ @use "sass/color"; @use "sass/size"; -.FormFieldRadio { +.FormRadio { &-button.MuiButtonBase-root { color: color.$white; diff --git a/src/shared/ui/form-kit/fields/form-radio.tsx b/src/shared/ui/form-kit/fields/form-radio.tsx new file mode 100644 index 00000000..049995af --- /dev/null +++ b/src/shared/ui/form-kit/fields/form-radio.tsx @@ -0,0 +1,17 @@ +import { FormControlLabel, Radio } from "@mui/material"; +import clsx from "clsx"; +import { ComponentProps } from "react"; + +import "./form-radio.scss"; + +export interface FormRadioProps extends Omit, "control"> {} + +const _FormRadio = "FormRadio"; + +export const FormRadio = ({ className, ...props }: FormRadioProps) => ( + } + {...props} + /> +); diff --git a/src/shared/ui/form-kit/index.ts b/src/shared/ui/form-kit/index.ts index 3506017d..48132d24 100644 --- a/src/shared/ui/form-kit/index.ts +++ b/src/shared/ui/form-kit/index.ts @@ -4,7 +4,4 @@ export { FormLabel } from "./elements/form-label"; export { FormRadioGroup } from "./elements/form-radio-group"; /** Fields */ -export { FormFieldRadio } from "./fields/form-field-radio"; - -/** Makers */ -// e.g. export { FormMakerLoremipsum } from "./makers/form-maker-loremipsum" +export { FormRadio } from "./fields/form-radio"; diff --git a/src/shared/ui/form-kit/makers/.gitkeep b/src/shared/ui/form-kit/makers/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index 712d7a02..d0e9a037 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -13,7 +13,7 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { signAndSendTxs, view } from "../../shared/lib/wallet"; import { Wallet } from "../../entities"; import { DateTimePicker, TextInput, TextInputWithUnits } from "../../shared/ui/components"; -import { FormControl, FormLabel, FormFieldRadio } from "../../shared/ui/form-kit"; +import { FormControl, FormLabel, FormRadio } from "../../shared/ui/form-kit"; import "./export.scss"; @@ -416,12 +416,12 @@ export class Export extends Component { else if (value === "scheduled") this.setState({ isJob: true }); }} > - - From 77ac87414f4b92ee62036109fe3381b3344810d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 12 Oct 2022 23:25:24 +0400 Subject: [PATCH 216/537] wip: Don't change form label color on focus --- src/shared/ui/form-kit/elements/form-label.scss | 4 ++++ src/shared/ui/form-kit/elements/form-label.tsx | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shared/ui/form-kit/elements/form-label.scss b/src/shared/ui/form-kit/elements/form-label.scss index 3131576d..9b771943 100644 --- a/src/shared/ui/form-kit/elements/form-label.scss +++ b/src/shared/ui/form-kit/elements/form-label.scss @@ -6,4 +6,8 @@ font-size: size.$text; color: color.$white; } + + &.is-focused.Mui-focused { + color: color.$white; + } } diff --git a/src/shared/ui/form-kit/elements/form-label.tsx b/src/shared/ui/form-kit/elements/form-label.tsx index e6c708fb..d3bb55f9 100644 --- a/src/shared/ui/form-kit/elements/form-label.tsx +++ b/src/shared/ui/form-kit/elements/form-label.tsx @@ -10,7 +10,7 @@ const _FormLabel = "FormLabel"; export const FormLabel = ({ content, ...props }: FormLabelProps) => ( {content} From 895667d8fefdbb32f621b444d5c82776d52d942a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 13 Oct 2022 18:00:08 +0400 Subject: [PATCH 217/537] wip: Improve styling --- src/widgets/export/export.jsx | 1 - src/widgets/export/export.scss | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index d0e9a037..e9f3c2f0 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -505,7 +505,6 @@ export class Export extends Component { )}
    -
    {this.renderProposeButton(multicallArgs)} ); diff --git a/src/widgets/export/export.scss b/src/widgets/export/export.scss index aa952284..574274b0 100644 --- a/src/widgets/export/export.scss +++ b/src/widgets/export/export.scss @@ -16,7 +16,6 @@ .ExecutionSettings { &-modeSelector.MuiFormControl-root { width: 100%; - padding: size.$gap 0; } } @@ -80,6 +79,9 @@ } .input-container { + display: flex; + flex-direction: column; + gap: size.$gap; padding-top: size.$smaller-text; .unitInput { @@ -322,6 +324,7 @@ } .button { + margin-top: auto; padding: 0.25 * size.$gap 0.5 * size.$gap; position: sticky; bottom: 0; From 746029fa192c4df8e4e84cd772e0cbb5b80bf49d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 13 Oct 2022 18:45:19 +0400 Subject: [PATCH 218/537] wip: Update classnames --- src/widgets/export/export.jsx | 22 ++++++++++--- src/widgets/export/export.scss | 58 +++++++++++++++++----------------- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index e9f3c2f0..ba3c1122 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -1,5 +1,6 @@ import { EditOutlined as EditOutlinedIcon } from "@mui/icons-material"; import { Icon, InputAdornment, RadioGroup, TextField } from "@mui/material"; +import clsx from "clsx"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component } from "react"; @@ -17,6 +18,17 @@ import { FormControl, FormLabel, FormRadio } from "../../shared/ui/form-kit"; import "./export.scss"; +class config { + static #rootClass = "Editor-menu-exportTab"; + + static classes = { + root: config.#rootClass, + action: config.#rootClass + "-action", + action__login: config.#rootClass + "-action--login", + action__propose: config.#rootClass + "-action--propose", + }; +} + export class Export extends Component { static contextType = Wallet.useSelector(); @@ -137,7 +149,7 @@ export class Export extends Component { if (!walletSelector.isSignedIn()) { return ( - - - +

    or

    + + + {isJob ? ( 0 && ( -
    +

    {`Card errors (${allErrors.length})`}

    @@ -483,8 +471,8 @@ export class Export extends Component {
    )} -
    -
    +
    +
    this.toggleShowArgs()} diff --git a/src/widgets/export/export.scss b/src/widgets/export/export.scss index 5d12165a..31dbbb01 100644 --- a/src/widgets/export/export.scss +++ b/src/widgets/export/export.scss @@ -4,7 +4,7 @@ @use "sass/mixin"; @use "sass/font"; -.Editor-menu-exportTab { +.Export { @include mixin.full; @include mixin.no-scrollbar; display: flex; @@ -44,308 +44,312 @@ background-color: color.$light; } } -} -.section { - flex: 1; - position: relative; - @include mixin.center-items(flex-start); - flex-flow: column nowrap; - width: 100%; - max-height: 25%; - - .sidebar { - width: calc(100% - 1.5 * size.$gap); - @include mixin.center-items(space-between); - - h3 { - cursor: pointer; - font-size: size.$text; - color: color.$light-text; - text-align: left; - } + &-section { + flex: 1; + position: relative; + @include mixin.center-items(flex-start); + flex-flow: column nowrap; + width: 100%; + max-height: 25%; - .icon { - @include mixin.light-icon; - cursor: pointer; - font-size: size.$text; - } + .header { + width: calc(100% - 1.5 * size.$gap); + @include mixin.center-items(space-between); - .collapse { - position: absolute; - left: 0; + h3 { + cursor: pointer; + font-size: size.$text; + color: color.$light-text; + text-align: left; + } - &[collapsed="yes"] { - transform: rotate(-90deg); + .icon { + @include mixin.light-icon; + cursor: pointer; + font-size: size.$text; } - transition: all 50ms linear; + .collapse { + position: absolute; + left: 0; + + &[collapsed="yes"] { + transform: rotate(-90deg); + } + + transition: all 50ms linear; + } } - } - .value { - flex: 1; - width: 100%; - @include mixin.no-scrollbar; - box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); - border-radius: size.$task-radius; - overflow-y: scroll; - - .code { - padding: 0.5 * size.$gap; - overflow: auto; - white-space: pre-wrap; - white-space: -moz-pre-wrap; - white-space: -o-pre-wrap; - word-wrap: break-word; - font-family: font.$code; - font-size: size.$small-text; - color: color.$light-text; + .value { + flex: 1; + width: 100%; + @include mixin.no-scrollbar; + box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); + border-radius: size.$task-radius; + overflow-y: scroll; + + .code { + padding: 0.5 * size.$gap; + overflow: auto; + white-space: pre-wrap; + white-space: -moz-pre-wrap; + white-space: -o-pre-wrap; + word-wrap: break-word; + font-family: font.$code; + font-size: size.$small-text; + color: color.$light-text; + } } } -} -.input-container { - display: flex; - flex-direction: column; - gap: size.$gap; - padding-top: size.$smaller-text; + &-inputs { + display: flex; + flex-direction: column; + padding-top: size.$smaller-text; - .unitInput { - @include mixin.center-items(center, flex-start); - flex-flow: row nowrap; + .unitInput { + @include mixin.center-items(center, flex-start); + flex-flow: row nowrap; - .MuiTextField-root { - width: unset !important; + .MuiTextField-root { + width: unset !important; - &:first-of-type { - flex: 2 1 auto; - } + &:first-of-type { + flex: 2 1 auto; + } - &:last-of-type { - flex: 1 0 max-content; - margin-left: 0.25 * size.$gap; + &:last-of-type { + flex: 1 0 max-content; + margin-left: 0.25 * size.$gap; - .MuiInputBase-root { - width: 100% !important; - font-size: size.$small-text; + .MuiInputBase-root { + width: 100% !important; + font-size: size.$small-text; + } } } - } - &:first-of-type .MuiTextField-root { - &:first-of-type fieldset { - border-radius: size.$task-radius 0 0 0; - } + &:first-of-type .MuiTextField-root { + &:first-of-type fieldset { + border-radius: size.$task-radius 0 0 0; + } - &:last-of-type fieldset { - border-radius: 0 size.$task-radius 0 0; + &:last-of-type fieldset { + border-radius: 0 size.$task-radius 0 0; + } } - } - &:last-of-type .MuiTextField-root { - &:first-of-type fieldset { - border-radius: 0 0 0 size.$task-radius; - } + &:last-of-type .MuiTextField-root { + &:first-of-type fieldset { + border-radius: 0 0 0 size.$task-radius; + } - &:last-of-type fieldset { - border-radius: 0 0 size.$task-radius 0; + &:last-of-type fieldset { + border-radius: 0 0 size.$task-radius 0; + } } } - } - - .attachment { - @include mixin.center-items(flex-start, center); - flex-flow: row nowrap; - width: 100%; - margin: 0.25 * size.$gap 0; - p { - color: color.$light-text; - font-size: size.$small-text; - } + &-choice { + @include mixin.center-items(flex-start, center); + flex-flow: row nowrap; + width: 100%; + margin: 0.25 * size.$gap 0; - button { - height: 2em; - margin: 0 0.5ch; - padding: 0 1em; - border-radius: size.$task-radius; - border: 1px solid color.$light; - font-size: size.$small-text; - font-weight: 800; - color: color.$light; - background-color: rgba(color.$white, 0.1); - - &.selected { - color: color.$green; - border: 1px solid color.$green; + p { + color: color.$light-text; + font-weight: 800; + font-size: size.$small-text; } - &:hover { - background-color: rgba(color.$white, 0.2); - } - } - } + button { + height: 2em; + margin: 0 0.75ch; + padding: 0 1em; + border-radius: size.$task-radius; + border: 1px solid color.$light; + font-size: size.$small-text; + font-weight: 800; + color: color.$light; + background-color: rgba(color.$white, 0.1); - .MuiTextField-root { - p.Mui-error { - color: color.$red; - font-weight: 800; - font-family: font.$text; - font-size: size.$small-text; + &.selected { + color: color.$green; + border: 1px solid color.$green; + } - &::before { - content: "Error: "; + &:hover { + background-color: rgba(color.$white, 0.2); + } } } - label { - font-family: font.$text; - font-weight: 800; - - &.Mui-focused { - color: color.$light-text; - } - - &.Mui-error { - color: color.$red; - } + &-dateTimePicker { + margin-top: 0.25 * size.$gap !important; } - .MuiOutlinedInput-root { - input, - textarea { - color: color.$white; - font-family: font.$code; + .MuiTextField-root { + p.Mui-error { + color: color.$red; + font-weight: 800; + font-family: font.$text; font-size: size.$small-text; - } - textarea { - @include mixin.no-scrollbar; - white-space: pre; - overflow-x: scroll !important; + &::before { + content: "Error: "; + } } - fieldset { - border-color: color.$lightish; - border-width: 1px; - box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); - border-radius: 0; - - legend { - background-color: color.$black; - margin-left: -2px; - padding: 2px; - border-radius: 20px; - visibility: visible; + label { + font-family: font.$text; + font-weight: 800; + + &.Mui-focused { + color: color.$light-text; } - legend > span { - font-size: 0.75em; - visibility: hidden; + &.Mui-error { + color: color.$red; } } - &:hover fieldset { - border-color: color.$white; - } + .MuiOutlinedInput-root { + input, + textarea { + color: color.$white; + font-family: font.$code; + font-size: size.$small-text; + } - &.Mui-focused fieldset { - border-color: color.$white; - } + textarea { + @include mixin.no-scrollbar; + white-space: pre; + overflow-x: scroll !important; + } - &.Mui-error fieldset { - border-color: color.$red !important; - } - } + fieldset { + border-color: color.$lightish; + border-width: 1px; + box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); + border-radius: 0; + + legend { + background-color: color.$black; + margin-left: -2px; + padding: 2px; + border-radius: 20px; + visibility: visible; + } + + legend > span { + font-size: 0.75em; + visibility: hidden; + } + } - .MuiInput-underline { - &:hover::before, - &::before { - border-bottom-color: color.$lightish; - } + &:hover fieldset { + border-color: color.$white; + } - &:hover::after, - &::after { - border-bottom-color: color.$white; - } + &.Mui-focused fieldset { + border-color: color.$white; + } - input { - font-weight: 500; + &.Mui-error fieldset { + border-color: color.$red !important; + } } - } - *:not(input) { - color: color.$light-text; - font-size: 1em; - } + .MuiInput-underline { + &:hover::before, + &::before { + border-bottom-color: color.$lightish; + } - width: 100%; - font-size: 1.8rem; - } + &:hover::after, + &::after { + border-bottom-color: color.$white; + } - & > .MuiTextField-root { - &:first-of-type { - margin-top: 0; - } + input { + font-weight: 500; + } + } - &:first-of-type > .MuiOutlinedInput-root > fieldset { - border-radius: size.$task-radius size.$task-radius 0 0; - } + *:not(input) { + color: color.$light-text; + font-size: 1em; + } - &:last-of-type > .MuiOutlinedInput-root > fieldset { - border-radius: 0 0 size.$task-radius size.$task-radius; + width: 100%; + font-size: 1.8rem; } - } -} -.MuiMenuItem-root { - font-size: size.$small-text !important; -} - -.error-container { - width: 100%; + & > .MuiTextField-root { + &:first-of-type { + margin-top: 0; + } - .header { - padding-left: 0.5 * size.$gap; + &:first-of-type > .MuiOutlinedInput-root > fieldset { + border-radius: size.$task-radius size.$task-radius 0 0; + } - h3 { - font-size: size.$text; - color: color.$red; - text-align: left; + &:last-of-type > .MuiOutlinedInput-root > fieldset { + border-radius: 0 0 size.$task-radius size.$task-radius; + } } } - .error-list { + &-errors { width: 100%; - display: flex; - flex-flow: column nowrap; - padding-top: 0.5 * size.$gap; - box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); - border-radius: size.$task-radius; - .error { - width: 100%; - max-width: calc(100% - size.$gap); - padding: 0.5 * size.$gap; - padding-top: 0; - @include mixin.center-items(space-between); - gap: 0.5 * size.$gap; - flex-flow: row nowrap; - font-size: size.$text; - font-weight: 800; - color: color.$red; + .header { + padding-left: 0.5 * size.$gap; - .msg { - @include mixin.no-wrap; + h3 { + font-size: size.$text; + color: color.$red; + text-align: left; } + } - .icon { - @include mixin.light-icon; - cursor: pointer; + .error-list { + width: 100%; + display: flex; + flex-flow: column nowrap; + padding-top: 0.5 * size.$gap; + box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); + border-radius: size.$task-radius; + + .error { + width: 100%; + max-width: calc(100% - size.$gap); + padding: 0.5 * size.$gap; + padding-top: 0; + @include mixin.center-items(space-between); + gap: 0.5 * size.$gap; + flex-flow: row nowrap; + font-size: size.$text; + font-weight: 800; color: color.$red; - font-size: size.$large-text; + + .msg { + @include mixin.no-wrap; + } + + .icon { + @include mixin.light-icon; + cursor: pointer; + color: color.$red; + font-size: size.$large-text; + } } } } } + +.MuiMenuItem-root { + font-size: size.$small-text !important; +} From c4fbd84ffe5833c3a77dfd67d9fc8011338c3633 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Fri, 14 Oct 2022 04:07:34 +0200 Subject: [PATCH 225/537] fix: styling touch-up --- src/shared/ui/components/date-time-picker/date-time-picker.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shared/ui/components/date-time-picker/date-time-picker.scss b/src/shared/ui/components/date-time-picker/date-time-picker.scss index 2c009e28..43d537bc 100644 --- a/src/shared/ui/components/date-time-picker/date-time-picker.scss +++ b/src/shared/ui/components/date-time-picker/date-time-picker.scss @@ -4,6 +4,8 @@ .DateTimePicker { &-modal { + border-radius: size.$task-radius !important; + * { font-family: font.$text !important; font-size: size.$text !important; From 0154867213b8775bc263a44164a5245715da80b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 14 Oct 2022 16:04:52 +0400 Subject: [PATCH 226/537] wip: Fix typo --- src/widgets/export/export.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index 1ce9f231..2b57268d 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -413,7 +413,7 @@ export class Export extends Component { }); }} > - immediatly + immediately

    or

    From a2a39a1d3b885a3f8d1f2ff0f23b80b0688d4803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 14 Oct 2022 17:09:36 +0400 Subject: [PATCH 227/537] wip: Update classes --- src/widgets/export/export.jsx | 8 ++++---- src/widgets/export/export.scss | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index 2b57268d..1a34bc4f 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -313,7 +313,7 @@ export class Export extends Component { return (
    -
    +
    -
    +

    Attach

    + + ); + } else { + return ( + <> +
    + + setAddAdmin(true)} + > + + +

    Admins

    + +
      + {addAdmins.map((admin) => ( +
    • + +
    • + ))} + {addAdmin ? ( + setAddAdmins((arr) => [...arr, e.target.value])} /> + ) : null} +
    +
    + + + setAddToken(true)} + > + + + +

    Whitelisted Tokens

    + +
      + {addTokens.map((token) => ( +
    • + +
    • + ))} + {addToken ? ( + setAddTokens((arr) => [...arr, e.target.value])} /> + ) : null} +
    +
    + + +

    + Job Bond + + + {`Ⓝ`} + +

    +
    + + + setEditCroncat(true)} + > + + +

    Croncat Manager

    +
      +
    • + {editCroncat ? ( + { + setCroncatManager(e.target.value); + setEditCroncat(false); + }} + defaultValue={multicall.croncatManager} + size="small" + /> + ) : ( + + )} +
    • +
    +
    + +
    + + ); + } +}; export const DaoConfigTab = { connect: (props: DaoConfigTabComponentProps) => ({ diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 210b1da2..b1d83879 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -24,6 +24,10 @@ const Ctx = Wallet.useSelector(); interface Props {} +enum Mode { + view = "VIEW", + edit = "EDIT", +} interface State { name: ArgsAccount; dao: SputnikDAO; @@ -31,6 +35,7 @@ interface State { loading: boolean; proposed: number; proposedInfo: ProposalOutput | null; + mode?: Mode; } const _DaoPage = "DaoPage"; diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 6a4fd2b5..d5590c5a 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -68,6 +68,7 @@ class Multicall { address: string; admins: string[] = []; + croncatManager: string = ""; // only whitelisted tokens can be attached to multicalls or job activations. tokensWhitelist: string[] = []; // job bond amount must be attached as deposit when adding new jobs. @@ -84,7 +85,7 @@ class Multicall { static async init(multicallAddress: string): Promise { // verify address is a Multicall instance, fetch its info and mark it ready const newMulticall = new Multicall(multicallAddress); - const [isMulticall, admins, tokensWhitelist, jobBond] = await Promise.all([ + const [isMulticall, admins, croncatManager, tokensWhitelist, jobBond] = await Promise.all([ // on failure set isMulticall to false Multicall.isMulticall(multicallAddress).catch((err) => { return false; @@ -93,6 +94,10 @@ class Multicall { newMulticall.getAdmins().catch((err) => { return []; }), + //on failure set manager list to be empty + newMulticall.getCroncatManager().catch((err) => { + return ""; + }), // on failure set tokens whitelist to be empty newMulticall.getWhitelistedTokens().catch((err) => { return []; @@ -103,6 +108,7 @@ class Multicall { }), ]); newMulticall.admins = admins; + newMulticall.croncatManager = croncatManager; newMulticall.tokensWhitelist = tokensWhitelist; newMulticall.jobBond = jobBond; // set ready to true if address is a Multicall instance and it has at least 1 admin. From 4abc8654315e2bb73f355765c1bfba028e6ff091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 17 Oct 2022 21:22:36 +0400 Subject: [PATCH 231/537] chore: Format --- src/pages/dao/config/config.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 547b8e2a..99683d8f 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -32,6 +32,7 @@ const Link = ({ > {addr.value} + {deleteIcon ? : editIcon ? : null} ); @@ -103,6 +104,7 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi
    + - +
      + {multicall.tokensWhitelist.map((token) => ( +
    • + +
    • + ))} +
    + + + +

    + Job Bond + {`${multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "..."} Ⓝ`} +

    +
    + + +

    Croncat Manager

    +
      +
    • + +
    • +
    +
    + +
    + +
    +
    ); } else { return ( - <> -
    - - setAddAdmin(true)} - > - - - -

    Admins

    - -
      - {addAdmins.map((admin) => ( -
    • - -
    • - ))} - - {addAdmin ? ( - setAddAdmins((arr) => [...arr, e.target.value])} /> - ) : null} -
    -
    - - - setAddToken(true)} - > - - - -

    Whitelisted Tokens

    - -
      - {addTokens.map((token) => ( -
    • - -
    • - ))} - - {addToken ? ( - setAddTokens((arr) => [...arr, e.target.value])} /> - ) : null} -
    -
    - - -

    - Job Bond - - + + setAddAdmin(true)} + > + + + +

    Admins

    + +
      + {addAdmins.map((admin) => ( +
    • + - {`Ⓝ`} - -

    -
    - - - setEditCroncat(true)} - > - - - -

    Croncat Manager

    - -
      -
    • - {editCroncat ? ( - { - setCroncatManager(e.target.value); - setEditCroncat(false); - }} - defaultValue={multicall.croncatManager} - size="small" - /> - ) : ( - - )}
    • -
    -
    + ))} + + {addAdmin ? ( + setAddAdmins((arr) => [...arr, e.target.value])} /> + ) : null} + + + + + setAddToken(true)} + > + + + +

    Whitelisted Tokens

    + +
      + {addTokens.map((token) => ( +
    • + +
    • + ))} + + {addToken ? ( + setAddTokens((arr) => [...arr, e.target.value])} /> + ) : null} +
    +
    + + +

    + Job Bond + + + {`Ⓝ`} + +

    +
    + + + setEditCroncat(true)} + > + + + +

    Croncat Manager

    + +
      +
    • + {editCroncat ? ( + { + setCroncatManager(e.target.value); + setEditCroncat(false); + }} + defaultValue={multicall.croncatManager} + size="small" + /> + ) : ( + + )} +
    • +
    +
    +
    - +
    ); } }; From c7e91df0032b9b1cc61c136e7cc7136bc72209fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 00:04:45 +0400 Subject: [PATCH 233/537] feat: Create `Button` shared ui component --- src/shared/ui/components/button/button.scss | 26 +++++++++++++++++ src/shared/ui/components/button/button.tsx | 22 ++++++++++++++ src/shared/ui/components/button/index.ts | 1 + src/shared/ui/components/dialog/dialog.scss | 14 --------- src/shared/ui/components/dialog/dialog.tsx | 32 ++++++++++----------- src/shared/ui/components/index.ts | 18 ++++++++---- 6 files changed, 77 insertions(+), 36 deletions(-) create mode 100644 src/shared/ui/components/button/button.scss create mode 100644 src/shared/ui/components/button/button.tsx create mode 100644 src/shared/ui/components/button/index.ts diff --git a/src/shared/ui/components/button/button.scss b/src/shared/ui/components/button/button.scss new file mode 100644 index 00000000..0af8d536 --- /dev/null +++ b/src/shared/ui/components/button/button.scss @@ -0,0 +1,26 @@ +@use "sass/color"; +@use "sass/size"; + +.Button { + border-radius: size.$task-radius; + padding: 0.25 * size.$gap size.$gap; + font-size: size.$text; + background-color: color.$dark; + + &:disabled { + background-color: color.$darkish; + cursor: not-allowed; + } + + &--success { + background-color: color.$green; + } + + &--error { + background-color: color.$red; + } + + &-label { + text-transform: uppercase; + } +} diff --git a/src/shared/ui/components/button/button.tsx b/src/shared/ui/components/button/button.tsx new file mode 100644 index 00000000..def383a9 --- /dev/null +++ b/src/shared/ui/components/button/button.tsx @@ -0,0 +1,22 @@ +import clsx from "clsx"; +import { ButtonHTMLAttributes } from "react"; + +import "./button.scss"; + +interface ButtonProps extends Omit, "children"> { + color: "default" | "success" | "error"; + label: string; + noRender?: boolean; +} + +const _Button = "Button"; + +export const Button = ({ className, color = "default", label = "Submit", noRender = false, ...props }: ButtonProps) => + noRender ? null : ( + + ); diff --git a/src/shared/ui/components/button/index.ts b/src/shared/ui/components/button/index.ts new file mode 100644 index 00000000..398a3c50 --- /dev/null +++ b/src/shared/ui/components/button/index.ts @@ -0,0 +1 @@ +export { Button } from "./button"; diff --git a/src/shared/ui/components/dialog/dialog.scss b/src/shared/ui/components/dialog/dialog.scss index 956b1811..feb39ba8 100644 --- a/src/shared/ui/components/dialog/dialog.scss +++ b/src/shared/ui/components/dialog/dialog.scss @@ -51,18 +51,4 @@ padding-top: 0; } } - - &-action { - font-size: size.$text; - border-radius: size.$task-radius; - padding: 0.25 * size.$gap size.$gap; - - &--cancel { - background-color: color.$red; - } - - &--done { - background-color: color.$green; - } - } } diff --git a/src/shared/ui/components/dialog/dialog.tsx b/src/shared/ui/components/dialog/dialog.tsx index 28a78a01..558ccd6b 100644 --- a/src/shared/ui/components/dialog/dialog.tsx +++ b/src/shared/ui/components/dialog/dialog.tsx @@ -7,6 +7,8 @@ import { import { clsx } from "clsx"; import { PropsWithChildren } from "react"; +import { Button } from "../button"; + import "./dialog.scss"; interface DialogProps extends PropsWithChildren { @@ -45,28 +47,26 @@ export const Dialog = ({ {children} - {!noCancel ? ( - - ) : null} + + /> ); diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 00bacf97..1e0c68aa 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,13 +1,19 @@ -export { DataInspector } from "./data-inspector"; -export { DateTimePicker, type DateTimePickerProps } from "./date-time-picker"; -export { Dialog } from "./dialog"; +/** Atoms */ +export { Button } from "./button"; export { NearIcons } from "./icons"; export { Placeholder } from "./placeholder"; export { PopupMenu } from "./popup-menu"; export { Scrollable } from "./scrollable"; +export { Tile } from "./tile"; +export { Tooltip } from "./tooltip"; + +/** Molecules */ +export { IconLabel } from "./icon-label"; + +/** Uncategorized ( yet ) */ +export { DataInspector } from "./data-inspector"; +export { DateTimePicker, type DateTimePickerProps } from "./date-time-picker"; +export { Dialog } from "./dialog"; export { Table } from "./table"; export { Tabs } from "./tabs"; export { TextInput, TextInputWithUnits } from "./text-input"; -export { Tile } from "./tile"; -export { IconLabel } from "./icon-label"; -export { Tooltip } from "./tooltip"; From 9100727bc91502d39fcf7cf5305e2c6c84404deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 00:07:19 +0400 Subject: [PATCH 234/537] fix: Make `Button` color optional --- src/shared/ui/components/button/button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/components/button/button.tsx b/src/shared/ui/components/button/button.tsx index def383a9..1cd3c9d6 100644 --- a/src/shared/ui/components/button/button.tsx +++ b/src/shared/ui/components/button/button.tsx @@ -4,7 +4,7 @@ import { ButtonHTMLAttributes } from "react"; import "./button.scss"; interface ButtonProps extends Omit, "children"> { - color: "default" | "success" | "error"; + color?: "default" | "success" | "error"; label: string; noRender?: boolean; } From 9f6152e3e6991ab106f9103ec1155ccfbf72ac7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 00:37:50 +0400 Subject: [PATCH 235/537] wip: Integrate title into `Tile` & Fix typings --- src/entities/job/config.ts | 6 ++++-- src/entities/job/ui/jobs-list.tsx | 7 ++++--- src/shared/ui/components/tile/tile.scss | 2 +- src/shared/ui/components/tile/tile.tsx | 11 +++++++++-- src/widgets/tokens-balances/config.ts | 6 ++++-- src/widgets/tokens-balances/ui/tokens-balances.tsx | 11 ++++++----- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/entities/job/config.ts b/src/entities/job/config.ts index 6e54533f..531c25ad 100644 --- a/src/entities/job/config.ts +++ b/src/entities/job/config.ts @@ -1,6 +1,6 @@ import { type JobData, type Multicall } from "../../shared/lib/contracts/multicall"; -export namespace JobEntity { +namespace JobEntity { export interface Dependencies { className?: string; contracts: { multicall: Multicall }; @@ -21,7 +21,7 @@ export namespace JobEntity { }; } -export class JobConfig { +class JobConfig { static readonly Status = JobEntity.Status; static StatusIcons = { @@ -32,3 +32,5 @@ export class JobConfig { [JobEntity.Status.Unknown]: "❔", }; } + +export { JobConfig, type JobEntity }; diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 4d219fe7..326eaef9 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -17,9 +17,10 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { noData = data !== null && !loading && Object.values(data).length === 0; return ( - -

    All jobs

    - + {loading &&
    } {noData && } diff --git a/src/shared/ui/components/tile/tile.scss b/src/shared/ui/components/tile/tile.scss index bf9b3d50..c80fa0d4 100644 --- a/src/shared/ui/components/tile/tile.scss +++ b/src/shared/ui/components/tile/tile.scss @@ -10,7 +10,7 @@ background-color: color.$lightest; font-size: size.$small-text; - .title { + &-title { padding: 0.5 * size.$gap size.$gap; font-size: size.$large-text; diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index 35ea8a45..f87fc515 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -5,6 +5,13 @@ import "./tile.scss"; const _Tile = "Tile"; -export interface TileProps extends PropsWithChildren, HTMLAttributes {} +export interface TileProps extends PropsWithChildren, HTMLAttributes { + title: string; +} -export const Tile = ({ children, className }: TileProps) =>
    {children}
    ; +export const Tile = ({ children, className, title }: TileProps) => ( +
    +

    {title}

    + {children} +
    +); diff --git a/src/widgets/tokens-balances/config.ts b/src/widgets/tokens-balances/config.ts index 28708793..7c9e34c5 100644 --- a/src/widgets/tokens-balances/config.ts +++ b/src/widgets/tokens-balances/config.ts @@ -1,7 +1,9 @@ import { NearTokenEntity, FungibleTokenEntity } from "../../entities"; -export namespace TokensBalancesWidget { - export interface Dependencies extends NearTokenEntity.dependencies, FungibleTokenEntity.dependencies { +namespace TokensBalancesWidget { + export interface Dependencies extends NearTokenEntity.Dependencies, FungibleTokenEntity.Dependencies { className?: string; } } + +export { type TokensBalancesWidget }; diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index 18f95c59..679ac06a 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -1,16 +1,17 @@ import { Tile, Scrollable, Table } from "../../../shared/ui/components"; import { FungibleToken, NearToken } from "../../../entities"; -import { Dependencies } from "../config"; +import { type TokensBalancesWidget } from "../config"; -export const TokensBalances = ({ className, contracts }: Dependencies) => { +export const TokensBalances = ({ className, contracts }: TokensBalancesWidget.Dependencies) => { const nearTokenBalances = NearToken.balancesRender({ contracts }), fungibleTokensBalances = FungibleToken.allBalancesRender({ contracts }); return ( - -

    Tokens balances

    - + {(nearTokenBalances ?? fungibleTokensBalances) && (
    Date: Wed, 19 Oct 2022 01:08:47 +0400 Subject: [PATCH 236/537] wip: Make tile title optional --- src/shared/ui/components/tile/tile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index f87fc515..e8c379c6 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -6,12 +6,12 @@ import "./tile.scss"; const _Tile = "Tile"; export interface TileProps extends PropsWithChildren, HTMLAttributes { - title: string; + title?: string; } export const Tile = ({ children, className, title }: TileProps) => (
    -

    {title}

    + {title &&

    {title}

    } {children}
    ); From cd4e0b2569cbab81109e12f523a8a1162004bb5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 01:23:44 +0400 Subject: [PATCH 237/537] wip: Fix loader styles --- sass/_base.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sass/_base.scss b/sass/_base.scss index a38157fd..a76dff3d 100644 --- a/sass/_base.scss +++ b/sass/_base.scss @@ -62,8 +62,8 @@ align-self: center; align-items: center; justify-content: center; - width: 100px; - height: 100px; + width: 100%; + height: 100%; &::after { content: " "; From ac9bfc79d887784e288a0587deb0162b1ca8ff9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 01:24:06 +0400 Subject: [PATCH 238/537] wip: Add tile content wrapper --- src/shared/ui/components/tile/tile.scss | 5 +++++ src/shared/ui/components/tile/tile.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/shared/ui/components/tile/tile.scss b/src/shared/ui/components/tile/tile.scss index c80fa0d4..f1b95853 100644 --- a/src/shared/ui/components/tile/tile.scss +++ b/src/shared/ui/components/tile/tile.scss @@ -19,6 +19,11 @@ } } + &-content { + width: 100%; + height: 100%; + } + @for $i from 0 to 3 { .MuiSvgIcon-root:nth-of-type(#{$i + 1}) { position: absolute; diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index e8c379c6..b96425bd 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -12,6 +12,6 @@ export interface TileProps extends PropsWithChildren, HTMLAttributes (
    {title &&

    {title}

    } - {children} +
    {children}
    ); From 54bb2b594571c7684e1d7fd5c4ef72a1e7dcd75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 01:27:55 +0400 Subject: [PATCH 239/537] wip: Apply tile classname to content rather than root --- src/shared/ui/components/tile/tile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index b96425bd..a5441c40 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -10,8 +10,8 @@ export interface TileProps extends PropsWithChildren, HTMLAttributes ( -
    +
    {title &&

    {title}

    } -
    {children}
    +
    {children}
    ); From b16b0df56ba9aa73b2874436373d69d14cbc506f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 01:56:17 +0400 Subject: [PATCH 240/537] wip: Fix styles and props naming --- src/entities/job/ui/jobs-list.tsx | 2 +- src/pages/dao/funds/funds.tsx | 2 +- src/pages/dao/jobs/jobs.tsx | 2 +- src/shared/ui/components/scrollable/scrollable.scss | 5 +---- src/shared/ui/components/tabs/item.tsx | 6 +++--- src/shared/ui/components/tabs/tabs.tsx | 7 ++++--- src/shared/ui/components/tile/tile.scss | 2 +- src/shared/ui/components/tile/tile.tsx | 6 +++--- src/widgets/menu/menu.jsx | 6 +++--- src/widgets/tokens-balances/ui/tokens-balances.tsx | 2 +- 10 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 326eaef9..6add835e 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -19,7 +19,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { return ( {loading &&
    } {noData && } diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index 4b4aeddf..5295ef83 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -22,6 +22,6 @@ export const DaoFundsTab = { connect: (props: DaoFundsTabComponentProps) => ({ content: , lazy: true, - title: "Funds", + name: "Funds", }), }; diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index e7fbe4c8..401feefa 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -22,6 +22,6 @@ export const DaoJobsTab = { connect: (props: DaoJobsTabComponentProps) => ({ content: , lazy: true, - title: "Jobs", + name: "Jobs", }), }; diff --git a/src/shared/ui/components/scrollable/scrollable.scss b/src/shared/ui/components/scrollable/scrollable.scss index 601bef82..b5703378 100644 --- a/src/shared/ui/components/scrollable/scrollable.scss +++ b/src/shared/ui/components/scrollable/scrollable.scss @@ -5,8 +5,5 @@ @include mixin.no-scrollbar; overflow-y: scroll; position: absolute; - top: calc(size.$large-text + 1.5 * size.$gap); - bottom: 0; - left: 0; - right: 0; + inset: 0; } diff --git a/src/shared/ui/components/tabs/item.tsx b/src/shared/ui/components/tabs/item.tsx index 679642fd..9685f94c 100644 --- a/src/shared/ui/components/tabs/item.tsx +++ b/src/shared/ui/components/tabs/item.tsx @@ -9,15 +9,15 @@ const _TabsItem = "Tabs-item", export interface TabsItemButtonProps extends React.HTMLAttributes { invertedColors?: boolean; onClick: VoidFunction; - title: string; + label: string; } -export const TabsItemButton = ({ className, invertedColors = false, onClick, title }: TabsItemButtonProps) => ( +export const TabsItemButton = ({ className, invertedColors = false, label, onClick }: TabsItemButtonProps) => ( ); diff --git a/src/shared/ui/components/tabs/tabs.tsx b/src/shared/ui/components/tabs/tabs.tsx index 9d63351e..c13a6c71 100644 --- a/src/shared/ui/components/tabs/tabs.tsx +++ b/src/shared/ui/components/tabs/tabs.tsx @@ -8,7 +8,7 @@ interface TabsProps extends Pick { activeItemIndexOverride?: number; activeItemSwitchOverride?: Dispatch>; classes?: TabsLayoutProps["classes"] & {}; - items: { content: JSX.Element; lazy?: boolean; title: string }[]; + items: { content: JSX.Element; lazy?: boolean; name: string }[]; } export const Tabs = ({ @@ -31,12 +31,13 @@ export const Tabs = ({ return ( ( + buttons={items.map(({ name }, itemIndex) => ( ))} > diff --git a/src/shared/ui/components/tile/tile.scss b/src/shared/ui/components/tile/tile.scss index f1b95853..762c28e3 100644 --- a/src/shared/ui/components/tile/tile.scss +++ b/src/shared/ui/components/tile/tile.scss @@ -10,7 +10,7 @@ background-color: color.$lightest; font-size: size.$small-text; - &-title { + &-heading { padding: 0.5 * size.$gap size.$gap; font-size: size.$large-text; diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index a5441c40..1ac59395 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -6,12 +6,12 @@ import "./tile.scss"; const _Tile = "Tile"; export interface TileProps extends PropsWithChildren, HTMLAttributes { - title?: string; + heading?: string | null; } -export const Tile = ({ children, className, title }: TileProps) => ( +export const Tile = ({ children, className, heading }: TileProps) => (
    - {title &&

    {title}

    } + {heading &&

    {heading}

    }
    {children}
    ); diff --git a/src/widgets/menu/menu.jsx b/src/widgets/menu/menu.jsx index af959a14..3ad9e5a6 100644 --- a/src/widgets/menu/menu.jsx +++ b/src/widgets/menu/menu.jsx @@ -45,7 +45,7 @@ export class Menu extends Component { }} items={[ { - title: "Build", + name: "Build", content: ( , }, { - title: "Export", + name: "Export", content: , }, ]} diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index 679ac06a..d8e4bc8d 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -10,7 +10,7 @@ export const TokensBalances = ({ className, contracts }: TokensBalancesWidget.De return ( {(nearTokenBalances ?? fungibleTokensBalances) && ( From ab51ab8f99b9e9ab28131c46b975c9c885b1e715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 02:15:06 +0400 Subject: [PATCH 241/537] wip: Fix background colors --- src/shared/ui/components/button/button.scss | 2 +- src/shared/ui/components/tabs/item.scss | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/ui/components/button/button.scss b/src/shared/ui/components/button/button.scss index 0af8d536..d9438d2e 100644 --- a/src/shared/ui/components/button/button.scss +++ b/src/shared/ui/components/button/button.scss @@ -5,7 +5,7 @@ border-radius: size.$task-radius; padding: 0.25 * size.$gap size.$gap; font-size: size.$text; - background-color: color.$dark; + background-color: color.$light; &:disabled { background-color: color.$darkish; diff --git a/src/shared/ui/components/tabs/item.scss b/src/shared/ui/components/tabs/item.scss index d2afe087..7ee7d3d1 100644 --- a/src/shared/ui/components/tabs/item.scss +++ b/src/shared/ui/components/tabs/item.scss @@ -39,11 +39,11 @@ &.is-active, &.is-active:hover { - background-color: color.$white; + background-color: color.$lightest; } &:hover { - background-color: rgba(color.$white, 0.1); + background-color: rgba(color.$lightest, 0.1); } } } From f07bdaf211d8a25c694712866134dccd2ba3aae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 19 Oct 2022 02:53:31 +0400 Subject: [PATCH 242/537] wip: Update DAO config tab --- src/pages/dao/config/config.scss | 32 ++++++---------- src/pages/dao/config/config.tsx | 63 ++++++++++++++++---------------- 2 files changed, 42 insertions(+), 53 deletions(-) diff --git a/src/pages/dao/config/config.scss b/src/pages/dao/config/config.scss index 4548abf3..c5e05461 100644 --- a/src/pages/dao/config/config.scss +++ b/src/pages/dao/config/config.scss @@ -6,37 +6,27 @@ .DaoConfigTab { display: grid; grid-template-columns: 1fr 1fr; - grid-template-rows: 3fr 3fr 1fr; + grid-template-rows: 6fr 4fr; gap: 0px 0px; grid-template-areas: - "AdminsList TokenWhitelist" - "CroncatManager TokenWhitelist" - "JobBond actions"; + "admins tokensWhitelist" + "jobsSettings proposalForm"; - &-actions { + &-proposalForm { @include mixin.center-items(space-evenly, center); - grid-area: actions; + grid-area: proposalForm; } - .AdminsList { - grid-area: AdminsList; + &-admins { + grid-area: admins; } - .CroncatManager { - grid-area: CroncatManager; + &-jobsSettings { + grid-area: jobsSettings; } - .TokenWhitelist { - grid-area: TokenWhitelist; - } - - .JobBond { - grid-area: JobBond; - - &-title { - @include mixin.center-items(space-between, center); - height: 100%; - } + &-tokensWhitelist { + grid-area: tokensWhitelist; } } diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 24ebe82d..54d985d8 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -6,7 +6,7 @@ import { HTMLProps, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { toNEAR } from "../../../shared/lib/converter"; -import { Tile } from "../../../shared/ui/components"; +import { Button, Tile } from "../../../shared/ui/components"; import "./config.scss"; @@ -63,9 +63,10 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi if (!editMode) { return (
    - -

    Admins

    - +
      {multicall.admins.map((admin) => (
    • @@ -75,9 +76,10 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi
    - -

    Whitelisted Tokens

    - +
      {multicall.tokensWhitelist.map((token) => (
    • @@ -87,30 +89,27 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi
    - -

    - Job Bond - {`${multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "..."} Ⓝ`} -

    -
    + +

    Croncat Manager

    + - -

    Croncat Manager

    -
      -
    • - -
    • -
    +

    Job Bond

    + {`${multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "..."} Ⓝ`}
    -
    - -
    + /> +
    ); } else { @@ -124,7 +123,7 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi -

    Admins

    +

    Admins

      {addAdmins.map((admin) => ( @@ -142,7 +141,7 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi
    - + setAddToken(true)} @@ -150,7 +149,7 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi -

    Whitelisted Tokens

    +

    Whitelisted Tokens

    + + )} + + ); +}; diff --git a/src/entities/multicall/ui/whitelisted-token.tsx b/src/entities/multicall/ui/whitelisted-token.tsx new file mode 100644 index 00000000..31f4f12b --- /dev/null +++ b/src/entities/multicall/ui/whitelisted-token.tsx @@ -0,0 +1,26 @@ +import { ArgsAccount } from "../../../shared/lib/args"; +import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; + +interface MulticallWhitelistedTokenProps { + address: FungibleToken["address"]; +} + +const MulticallWhitelistedToken = ({ address }: MulticallWhitelistedTokenProps) => { + const addr = new ArgsAccount(address); + + return ( + + + {addr.value} + + + ); +}; + +export const multicallWhitelistedTokenTableRow = (address: MulticallWhitelistedTokenProps["address"]) => [ + , +]; From 8b21b52220a1507c5e3ce16320b7f23ba53e9c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 00:35:21 +0400 Subject: [PATCH 253/537] wip: Use multicall tokens whitelist on dao config tab --- src/pages/dao/config/config.tsx | 24 ++++++++++-------------- src/pages/dao/dao.tsx | 6 +++++- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 15f20d6b..814e0ecf 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -3,8 +3,10 @@ import { IconButton } from "@mui/material"; import clsx from "clsx"; import { HTMLProps, useState } from "react"; +import { Multicall } from "../../../entities"; import { ArgsAccount, ArgsString } from "../../../shared/lib/args"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; +import { MulticallContract } from "../../../shared/lib/contracts/multicall"; +import { SputnikDAOContract } from "../../../shared/lib/contracts/sputnik-dao"; import { toNEAR } from "../../../shared/lib/converter"; import { Button, TextInput, Tile } from "../../../shared/ui/components"; @@ -40,13 +42,15 @@ const Link = ({ interface DaoConfigTabComponentProps extends HTMLProps { contracts: { - multicall: Multicall; + multicall: MulticallContract; }; + + daoContract: SputnikDAOContract; } const _DaoConfigTab = "DaoConfigTab"; -const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfigTabComponentProps) => { +const DaoConfigTabComponent = ({ className, contracts: { multicall }, daoContract }: DaoConfigTabComponentProps) => { const [editMode, setEditMode] = useState(false); const [addTokens, setAddTokens] = useState(multicall.tokensWhitelist); const [addToken, setAddToken] = useState(false); @@ -69,18 +73,10 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfi {!editMode && ( - -
      - {multicall.tokensWhitelist.map((token) => ( -
    • - -
    • - ))} -
    -
    + daoContractAddress={daoContract.address} + /> )} {editMode && ( diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index b1d83879..08419a90 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -402,7 +402,11 @@ export class DaoPage extends Component { Date: Thu, 20 Oct 2022 01:21:37 +0400 Subject: [PATCH 254/537] wip: Integrate reused placeholders into `Tile` --- src/entities/job/ui/jobs-list.tsx | 34 ++++++------------- .../multicall/ui/tokens-whitelist.tsx | 32 ++++++----------- src/shared/ui/components/table/table.tsx | 2 +- src/shared/ui/components/tile/tile.tsx | 23 +++++++++++-- 4 files changed, 43 insertions(+), 48 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 65b24775..3b893d3a 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,6 +1,6 @@ import clsx from "clsx"; -import { Placeholder, Scrollable, Table, Tile } from "../../../shared/ui/components"; +import { Scrollable, Table, Tile } from "../../../shared/ui/components"; import { type JobEntity } from "../config"; import { JobDataModel } from "../model/job-data"; @@ -12,35 +12,23 @@ interface JobsListProps extends JobEntity.Dependencies {} const _JobsList = "JobsList"; export const JobsList = ({ className, contracts }: JobsListProps) => { - const { data, error, loading } = JobDataModel.useAllJobsFrom(contracts), - dataIsAvailable = data !== null && !loading && Object.values(data).length > 0, - noData = data !== null && !loading && Object.values(data).length === 0; + const { data, error, loading } = JobDataModel.useAllJobsFrom(contracts); return ( - {loading &&
    } - {noData && } - - {error && ( - +
    - )} - - {dataIsAvailable && ( - -
    - - )} + ); }; diff --git a/src/entities/multicall/ui/tokens-whitelist.tsx b/src/entities/multicall/ui/tokens-whitelist.tsx index e1ba1cc2..c8bfe85e 100644 --- a/src/entities/multicall/ui/tokens-whitelist.tsx +++ b/src/entities/multicall/ui/tokens-whitelist.tsx @@ -13,35 +13,23 @@ interface MulticallTokensWhitelistProps extends MulticallEntity.Dependencies { const _MulticallTokensWhitelist = "MulticallTokensWhitelist"; export const MulticallTokensWhitelist = ({ className, daoContractAddress }: MulticallTokensWhitelistProps) => { - const { data, error, loading } = TokensWhitelistModel.useAllTokensFor(daoContractAddress), - dataIsAvailable = data !== null && !loading && data.length > 0, - noData = data !== null && !loading && data.length === 0; + const { data, error, loading } = TokensWhitelistModel.useAllTokensFor(daoContractAddress); return ( - {loading &&
    } - {noData && } - - {error && ( - +
    - )} - - {dataIsAvailable && ( - -
    - - )} + ); }; diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index e4be25b6..6ab4738f 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -27,7 +27,7 @@ interface TableProps extends HTMLAttributes { */ displayMode?: "default" | "compact" | "classic"; header: TableRowProps["headerCells"]; - rows?: TableRowProps["cells"][]; + rows?: TableRowProps["cells"][] | null; } const _Table = "Table"; diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index 1ac59395..f446d369 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -1,17 +1,36 @@ import clsx from "clsx"; import { HTMLAttributes, PropsWithChildren } from "react"; +import { Placeholder } from "../placeholder"; + import "./tile.scss"; const _Tile = "Tile"; export interface TileProps extends PropsWithChildren, HTMLAttributes { + error?: Error | null; heading?: string | null; + loading?: boolean; + noData?: boolean; } -export const Tile = ({ children, className, heading }: TileProps) => ( +export const Tile = ({ children, className, error, heading, loading = false, noData = false }: TileProps) => (
    {heading &&

    {heading}

    } -
    {children}
    + +
    + {loading &&
    } + + {!loading && noData && } + + {!loading && error && ( + + )} + + {!loading && !noData && !error && children} +
    ); From 2eba6983498a9be31100f580b629cf3cf7327485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 01:24:14 +0400 Subject: [PATCH 255/537] chore: Format --- src/entities/job/ui/jobs-list.tsx | 4 ++-- src/entities/multicall/ui/tokens-whitelist.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 3b893d3a..f23b023d 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -1,9 +1,9 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/components"; - -import { type JobEntity } from "../config"; import { JobDataModel } from "../model/job-data"; +import { type JobEntity } from "../config"; + import { jobDetailsTableRow } from "./job-details"; import "./jobs-list.scss"; diff --git a/src/entities/multicall/ui/tokens-whitelist.tsx b/src/entities/multicall/ui/tokens-whitelist.tsx index c8bfe85e..90fabad9 100644 --- a/src/entities/multicall/ui/tokens-whitelist.tsx +++ b/src/entities/multicall/ui/tokens-whitelist.tsx @@ -1,9 +1,9 @@ import clsx from "clsx"; -import { Placeholder, Scrollable, Table, Tile } from "../../../shared/ui/components"; - +import { Scrollable, Table, Tile } from "../../../shared/ui/components"; import { TokensWhitelistModel } from "../model/tokens-whitelist"; import { type MulticallEntity } from "../config"; + import { multicallWhitelistedTokenTableRow } from "./whitelisted-token"; interface MulticallTokensWhitelistProps extends MulticallEntity.Dependencies { From 27ba568a271360bfaac7abb4534003f6e4fe9d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 02:42:49 +0400 Subject: [PATCH 256/537] wip: Fix scrolling for all tiles rather than specific ones --- src/pages/dao/funds/funds.scss | 2 -- src/pages/dao/jobs/jobs.scss | 2 -- src/shared/ui/components/tile/tile.scss | 2 ++ 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/dao/funds/funds.scss b/src/pages/dao/funds/funds.scss index dc5e3306..e42f32a7 100644 --- a/src/pages/dao/funds/funds.scss +++ b/src/pages/dao/funds/funds.scss @@ -9,7 +9,5 @@ &-tokenBalances { grid-area: tokenBalances; - position: relative; - overflow: hidden; } } diff --git a/src/pages/dao/jobs/jobs.scss b/src/pages/dao/jobs/jobs.scss index 3d17cf44..66fd24cf 100644 --- a/src/pages/dao/jobs/jobs.scss +++ b/src/pages/dao/jobs/jobs.scss @@ -8,7 +8,5 @@ &-jobsList { grid-area: jobsList; - position: relative; - overflow: hidden; } } diff --git a/src/shared/ui/components/tile/tile.scss b/src/shared/ui/components/tile/tile.scss index 59119616..17b8182a 100644 --- a/src/shared/ui/components/tile/tile.scss +++ b/src/shared/ui/components/tile/tile.scss @@ -22,8 +22,10 @@ &-content { display: flex; flex-flow: column nowrap; + position: relative; width: auto; height: 100%; + overflow: hidden; } @for $i from 0 to 3 { From 4cd52c0c5cf184a210b84937c0a4b4e06083d33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 02:51:17 +0400 Subject: [PATCH 257/537] wip: Use darker link color --- src/global.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global.scss b/src/global.scss index aad5d9db..8d283620 100644 --- a/src/global.scss +++ b/src/global.scss @@ -23,7 +23,7 @@ body { } a { - color: color.$blue !important; + color: darken(color.$blue, 30%); text-decoration: none; cursor: pointer; } From 6a69b33c79a18222c8728542c0f135a995971c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 03:17:18 +0400 Subject: [PATCH 258/537] fix: Add missing effects' dependencies --- src/entities/fungible-token/model/ft-balances.ts | 2 +- src/entities/job/model/job-data.ts | 2 +- src/entities/multicall/model/tokens-whitelist.ts | 2 +- src/entities/near-token/model/near-balances.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/entities/fungible-token/model/ft-balances.ts b/src/entities/fungible-token/model/ft-balances.ts index d0a37b50..08cb313b 100644 --- a/src/entities/fungible-token/model/ft-balances.ts +++ b/src/entities/fungible-token/model/ft-balances.ts @@ -57,7 +57,7 @@ const fungibleTokensDataFx = async ( const useAllFungibleTokensData = (contracts: FungibleTokenEntity.Dependencies["contracts"]) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void fungibleTokensDataFx(contracts, stateUpdate), []); + useEffect(() => void fungibleTokensDataFx(contracts, stateUpdate), [contracts, stateUpdate]); return state; }; diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts index ae5da6e1..7bb9568e 100644 --- a/src/entities/job/model/job-data.ts +++ b/src/entities/job/model/job-data.ts @@ -39,7 +39,7 @@ const jobsDataFx = async ( const useJobsData = (contracts: JobEntity.Dependencies["contracts"]) => { const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - useEffect(() => void jobsDataFx(contracts, stateUpdate), []); + useEffect(() => void jobsDataFx(contracts, stateUpdate), [contracts, stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/multicall/model/tokens-whitelist.ts b/src/entities/multicall/model/tokens-whitelist.ts index c267179d..454c5f52 100644 --- a/src/entities/multicall/model/tokens-whitelist.ts +++ b/src/entities/multicall/model/tokens-whitelist.ts @@ -26,7 +26,7 @@ const whitelistedTokensDataFx = async ( const useAllWhitelistedTokensData = (daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"]) => { const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - useEffect(() => void whitelistedTokensDataFx(daoContractAddress, stateUpdate), []); + useEffect(() => void whitelistedTokensDataFx(daoContractAddress, stateUpdate), [daoContractAddress, stateUpdate]); return state; }; diff --git a/src/entities/near-token/model/near-balances.ts b/src/entities/near-token/model/near-balances.ts index 7fd7fb1c..61d0875e 100644 --- a/src/entities/near-token/model/near-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -41,7 +41,7 @@ const nearTokenDataFx = async ( const useNearTokenData = (contracts: NearTokenEntity.Dependencies["contracts"]) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void nearTokenDataFx(contracts, stateUpdate), []); + useEffect(() => void nearTokenDataFx(contracts, stateUpdate), [contracts, stateUpdate]); return state; }; From 6c4851cb80843c83c591e908142f82f42b023ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 03:18:15 +0400 Subject: [PATCH 259/537] fix: Remove redundant updates --- src/pages/dao/dao.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 08419a90..e722675b 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -428,7 +428,6 @@ export class DaoPage extends Component { () => { this.errors.address.validOrNull(daoAccount); this.loadInfo(); - this.forceUpdate(); } ); } @@ -456,7 +455,6 @@ export class DaoPage extends Component { if (daoAccount.isValid()) { this.loadInfoDebounced(); } - this.forceUpdate(); }} InputProps={{ endAdornment: ( From 10f8accf27590421f4ad1518c4ed4eaeae7eb103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 03:18:46 +0400 Subject: [PATCH 260/537] wip: Add namespace prefix --- src/entities/multicall/index.ts | 2 +- .../ui/{tokens-whitelist.tsx => mc-tokens-whitelist.tsx} | 2 +- .../ui/{whitelisted-token.tsx => mc-whitelisted-token.tsx} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/entities/multicall/ui/{tokens-whitelist.tsx => mc-tokens-whitelist.tsx} (93%) rename src/entities/multicall/ui/{whitelisted-token.tsx => mc-whitelisted-token.tsx} (100%) diff --git a/src/entities/multicall/index.ts b/src/entities/multicall/index.ts index 90ea472e..ddf0e305 100644 --- a/src/entities/multicall/index.ts +++ b/src/entities/multicall/index.ts @@ -1,5 +1,5 @@ import { MulticallConfig, type MulticallEntity } from "./config"; -import { MulticallTokensWhitelist } from "./ui/tokens-whitelist"; +import { MulticallTokensWhitelist } from "./ui/mc-tokens-whitelist"; class Multicall extends MulticallConfig { static TokensWhitelist = MulticallTokensWhitelist; diff --git a/src/entities/multicall/ui/tokens-whitelist.tsx b/src/entities/multicall/ui/mc-tokens-whitelist.tsx similarity index 93% rename from src/entities/multicall/ui/tokens-whitelist.tsx rename to src/entities/multicall/ui/mc-tokens-whitelist.tsx index 90fabad9..6cfdf8e5 100644 --- a/src/entities/multicall/ui/tokens-whitelist.tsx +++ b/src/entities/multicall/ui/mc-tokens-whitelist.tsx @@ -4,7 +4,7 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/components"; import { TokensWhitelistModel } from "../model/tokens-whitelist"; import { type MulticallEntity } from "../config"; -import { multicallWhitelistedTokenTableRow } from "./whitelisted-token"; +import { multicallWhitelistedTokenTableRow } from "./mc-whitelisted-token"; interface MulticallTokensWhitelistProps extends MulticallEntity.Dependencies { className?: string; diff --git a/src/entities/multicall/ui/whitelisted-token.tsx b/src/entities/multicall/ui/mc-whitelisted-token.tsx similarity index 100% rename from src/entities/multicall/ui/whitelisted-token.tsx rename to src/entities/multicall/ui/mc-whitelisted-token.tsx From a0bcf766dd7cce4933b301448221490fc8f18845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 03:57:07 +0400 Subject: [PATCH 261/537] wip: Add multicall admins table --- src/entities/multicall/index.ts | 6 ++- src/entities/multicall/model/mc-admins.ts | 41 +++++++++++++++++++ src/entities/multicall/model/mc-tokens.ts | 41 +++++++++++++++++++ .../multicall/model/tokens-whitelist.ts | 36 ---------------- src/entities/multicall/ui/mc-admin.tsx | 27 ++++++++++++ src/entities/multicall/ui/mc-admins.tsx | 35 ++++++++++++++++ .../multicall/ui/mc-tokens-whitelist.tsx | 17 ++++---- .../multicall/ui/mc-whitelisted-token.tsx | 4 +- src/pages/dao/config/config.tsx | 2 +- 9 files changed, 161 insertions(+), 48 deletions(-) create mode 100644 src/entities/multicall/model/mc-admins.ts create mode 100644 src/entities/multicall/model/mc-tokens.ts delete mode 100644 src/entities/multicall/model/tokens-whitelist.ts create mode 100644 src/entities/multicall/ui/mc-admin.tsx create mode 100644 src/entities/multicall/ui/mc-admins.tsx diff --git a/src/entities/multicall/index.ts b/src/entities/multicall/index.ts index ddf0e305..20e5a12c 100644 --- a/src/entities/multicall/index.ts +++ b/src/entities/multicall/index.ts @@ -1,8 +1,10 @@ import { MulticallConfig, type MulticallEntity } from "./config"; -import { MulticallTokensWhitelist } from "./ui/mc-tokens-whitelist"; +import { MulticallAdminsTable } from "./ui/mc-admins"; +import { MulticallTokensWhitelistTable } from "./ui/mc-tokens-whitelist"; class Multicall extends MulticallConfig { - static TokensWhitelist = MulticallTokensWhitelist; + static AdminsTable = MulticallAdminsTable; + static TokensWhitelistTable = MulticallTokensWhitelistTable; } export { Multicall, MulticallEntity }; diff --git a/src/entities/multicall/model/mc-admins.ts b/src/entities/multicall/model/mc-admins.ts new file mode 100644 index 00000000..0736c624 --- /dev/null +++ b/src/entities/multicall/model/mc-admins.ts @@ -0,0 +1,41 @@ +import { useEffect, useState } from "react"; + +import { ArgsAccount } from "../../../shared/lib/args"; +import { MulticallContract } from "../../../shared/lib/contracts/multicall"; +import { Props } from "../../../shared/lib/props"; + +import { type MulticallEntity } from "../config"; + +type MulticallAdminsAllEntriesFetchFxResponse = { + data: MulticallContract["admins"] | null; + error: Error | null; + loading: boolean; +}; + +export class MulticallAdminsModel { + static allEntriesFetchFx = async ( + daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"], + callback: (result: MulticallAdminsAllEntriesFetchFxResponse) => void + ) => + await MulticallContract.instanceDataFetchFx( + `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, + + (multicallInstanceData) => + callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) + ); + + static useAllEntries = (daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"]) => { + const [state, stateUpdate] = useState({ + data: null, + error: null, + loading: true, + }); + + useEffect( + () => void MulticallAdminsModel.allEntriesFetchFx(daoContractAddress, stateUpdate), + [daoContractAddress, stateUpdate] + ); + + return state; + }; +} diff --git a/src/entities/multicall/model/mc-tokens.ts b/src/entities/multicall/model/mc-tokens.ts new file mode 100644 index 00000000..d4c19dac --- /dev/null +++ b/src/entities/multicall/model/mc-tokens.ts @@ -0,0 +1,41 @@ +import { useEffect, useState } from "react"; + +import { ArgsAccount } from "../../../shared/lib/args"; +import { MulticallContract } from "../../../shared/lib/contracts/multicall"; +import { Props } from "../../../shared/lib/props"; + +import { type MulticallEntity } from "../config"; + +type MulticallTokensWhitelistFetchFxResponse = { + data: MulticallContract["tokensWhitelist"] | null; + error: Error | null; + loading: boolean; +}; + +export class MulticallTokensModel { + static whitelistFetchFx = async ( + daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"], + callback: (result: MulticallTokensWhitelistFetchFxResponse) => void + ) => + await MulticallContract.instanceDataFetchFx( + `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, + + (multicallInstanceData) => + callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) + ); + + static useWhitelist = (daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"]) => { + const [state, stateUpdate] = useState({ + data: null, + error: null, + loading: true, + }); + + useEffect( + () => void MulticallTokensModel.whitelistFetchFx(daoContractAddress, stateUpdate), + [daoContractAddress, stateUpdate] + ); + + return state; + }; +} diff --git a/src/entities/multicall/model/tokens-whitelist.ts b/src/entities/multicall/model/tokens-whitelist.ts deleted file mode 100644 index 454c5f52..00000000 --- a/src/entities/multicall/model/tokens-whitelist.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { useEffect, useState } from "react"; - -import { ArgsAccount } from "../../../shared/lib/args"; -import { MulticallContract } from "../../../shared/lib/contracts/multicall"; -import { Props } from "../../../shared/lib/props"; - -import { type MulticallEntity } from "../config"; - -type WhitelistedTokensDataFxResponse = { - data: MulticallContract["tokensWhitelist"] | null; - error: Error | null; - loading: boolean; -}; - -const whitelistedTokensDataFx = async ( - daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"], - callback: (result: WhitelistedTokensDataFxResponse) => void -) => - await MulticallContract.instanceDataFetchFx( - `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, - - (multicallInstanceData) => - callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) - ); - -const useAllWhitelistedTokensData = (daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"]) => { - const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - - useEffect(() => void whitelistedTokensDataFx(daoContractAddress, stateUpdate), [daoContractAddress, stateUpdate]); - - return state; -}; - -export class TokensWhitelistModel { - static useAllTokensFor = useAllWhitelistedTokensData; -} diff --git a/src/entities/multicall/ui/mc-admin.tsx b/src/entities/multicall/ui/mc-admin.tsx new file mode 100644 index 00000000..d7c3842f --- /dev/null +++ b/src/entities/multicall/ui/mc-admin.tsx @@ -0,0 +1,27 @@ +import { Account } from "near-api-js"; + +import { ArgsAccount } from "../../../shared/lib/args"; + +interface MulticallAdminEntryProps { + address: Account["accountId"]; +} + +const MulticallAdminEntry = ({ address }: MulticallAdminEntryProps) => { + const addr = new ArgsAccount(address); + + return ( + + + {addr.value} + + + ); +}; + +export const multicallAdminTableRow = (address: MulticallAdminEntryProps["address"]) => [ + , +]; diff --git a/src/entities/multicall/ui/mc-admins.tsx b/src/entities/multicall/ui/mc-admins.tsx new file mode 100644 index 00000000..b7f3dde1 --- /dev/null +++ b/src/entities/multicall/ui/mc-admins.tsx @@ -0,0 +1,35 @@ +import clsx from "clsx"; + +import { Scrollable, Table, Tile } from "../../../shared/ui/components"; +import { MulticallAdminsModel } from "../model/mc-admins"; +import { type MulticallEntity } from "../config"; + +import { multicallAdminTableRow } from "./mc-admin"; + +interface MulticallAdminsTableProps extends MulticallEntity.Dependencies { + className?: string; +} + +const _MulticallAdminsTable = "MulticallAdminsTable"; + +export const MulticallAdminsTable = ({ className, daoContractAddress }: MulticallAdminsTableProps) => { + const { data, error, loading } = MulticallAdminsModel.useAllEntries(daoContractAddress); + + return ( + + +
    + + + ); +}; diff --git a/src/entities/multicall/ui/mc-tokens-whitelist.tsx b/src/entities/multicall/ui/mc-tokens-whitelist.tsx index 6cfdf8e5..7b4e1fec 100644 --- a/src/entities/multicall/ui/mc-tokens-whitelist.tsx +++ b/src/entities/multicall/ui/mc-tokens-whitelist.tsx @@ -1,30 +1,33 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/components"; -import { TokensWhitelistModel } from "../model/tokens-whitelist"; +import { MulticallTokensModel } from "../model/mc-tokens"; import { type MulticallEntity } from "../config"; import { multicallWhitelistedTokenTableRow } from "./mc-whitelisted-token"; -interface MulticallTokensWhitelistProps extends MulticallEntity.Dependencies { +interface MulticallTokensWhitelistTableProps extends MulticallEntity.Dependencies { className?: string; } -const _MulticallTokensWhitelist = "MulticallTokensWhitelist"; +const _MulticallTokensWhitelistTable = "MulticallTokensWhitelistTable"; -export const MulticallTokensWhitelist = ({ className, daoContractAddress }: MulticallTokensWhitelistProps) => { - const { data, error, loading } = TokensWhitelistModel.useAllTokensFor(daoContractAddress); +export const MulticallTokensWhitelistTable = ({ + className, + daoContractAddress, +}: MulticallTokensWhitelistTableProps) => { + const { data, error, loading } = MulticallTokensModel.useWhitelist(daoContractAddress); return (
    { +const MulticallWhitelistedTokenEntry = ({ address }: MulticallWhitelistedTokenProps) => { const addr = new ArgsAccount(address); return ( @@ -22,5 +22,5 @@ const MulticallWhitelistedToken = ({ address }: MulticallWhitelistedTokenProps) }; export const multicallWhitelistedTokenTableRow = (address: MulticallWhitelistedTokenProps["address"]) => [ - , + , ]; diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 814e0ecf..ca8eb850 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -73,7 +73,7 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall }, daoContrac {!editMode && ( - From 38e2301d2a38633cec4eb6d2003a672171ad81d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 04:00:16 +0400 Subject: [PATCH 262/537] fix: Replace wrong property name --- src/entities/multicall/model/mc-admins.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/entities/multicall/model/mc-admins.ts b/src/entities/multicall/model/mc-admins.ts index 0736c624..71f00263 100644 --- a/src/entities/multicall/model/mc-admins.ts +++ b/src/entities/multicall/model/mc-admins.ts @@ -19,9 +19,7 @@ export class MulticallAdminsModel { ) => await MulticallContract.instanceDataFetchFx( `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, - - (multicallInstanceData) => - callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) + (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) ); static useAllEntries = (daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"]) => { From 5ffa0368f34a03598a9ff6c9ae7dc4c1fd3d5b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 04:00:39 +0400 Subject: [PATCH 263/537] wip: Use admins table on dao config tab --- src/pages/dao/config/config.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index ca8eb850..076fcd3a 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -59,18 +59,10 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall }, daoContrac return (
    - -
      - {multicall.admins.map((admin) => ( -
    • - -
    • - ))} -
    -
    + daoContractAddress={daoContract.address} + /> {!editMode && ( Date: Thu, 20 Oct 2022 04:36:36 +0400 Subject: [PATCH 264/537] wip: Cure ocd ( cleanup ) --- src/entities/job/index.ts | 4 +- src/entities/job/model/job-data.ts | 53 ------------------- src/entities/job/model/jobs-data.ts | 51 ++++++++++++++++++ .../ui/{job-details.scss => job-entry.scss} | 0 .../job/ui/{job-details.tsx => job-entry.tsx} | 6 +-- .../ui/{jobs-list.scss => jobs-table.scss} | 2 +- .../job/ui/{jobs-list.tsx => jobs-table.tsx} | 20 +++---- .../ui/{mc-admin.tsx => mc-admin-entry.tsx} | 0 src/entities/multicall/ui/mc-admins.tsx | 2 +- src/pages/dao/jobs/jobs.tsx | 4 +- 10 files changed, 70 insertions(+), 72 deletions(-) delete mode 100644 src/entities/job/model/job-data.ts create mode 100644 src/entities/job/model/jobs-data.ts rename src/entities/job/ui/{job-details.scss => job-entry.scss} (100%) rename src/entities/job/ui/{job-details.tsx => job-entry.tsx} (88%) rename src/entities/job/ui/{jobs-list.scss => jobs-table.scss} (96%) rename src/entities/job/ui/{jobs-list.tsx => jobs-table.tsx} (52%) rename src/entities/multicall/ui/{mc-admin.tsx => mc-admin-entry.tsx} (100%) diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index d4ba9a0b..8e8afb4e 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,8 +1,8 @@ import { JobConfig, type JobEntity } from "./config"; -import { JobsList } from "./ui/jobs-list"; +import { JobsTable } from "./ui/jobs-table"; class Job extends JobConfig { - static ListOfAll = JobsList; + static EntriesTable = JobsTable; } export { Job, type JobEntity }; diff --git a/src/entities/job/model/job-data.ts b/src/entities/job/model/job-data.ts deleted file mode 100644 index 7bb9568e..00000000 --- a/src/entities/job/model/job-data.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { useEffect, useState } from "react"; - -import { type JobEntity } from "../config"; -import { JobNormalized } from "../lib/job-normalized"; - -type JobsDataFxResponse = { - /** Jobs indexed by ID for easy access to each particular job */ - data: Record | null; - error?: Error | null; - loading: boolean; -}; - -const jobsDataFx = async ( - { multicall }: JobEntity.Dependencies["contracts"], - callback: (result: JobsDataFxResponse) => void -) => - callback( - await multicall - .getJobs() - .then((data) => ({ - data: data.reduce( - (jobsIndexedById, job) => ({ - ...jobsIndexedById, - [job.id]: JobNormalized.withMulticallsDataDecoded(JobNormalized.withStatus(job)), - }), - {} - ), - - error: null, - loading: false, - })) - .catch((error) => ({ - data: null, - error: new Error(error), - loading: false, - })) - ); - -const useJobsData = (contracts: JobEntity.Dependencies["contracts"]) => { - const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - - useEffect(() => void jobsDataFx(contracts, stateUpdate), [contracts, stateUpdate]); - - useEffect(() => { - state.error instanceof Error && void console.error(state.error); - }, [state]); - - return state; -}; - -export class JobDataModel { - static useAllJobsFrom = useJobsData; -} diff --git a/src/entities/job/model/jobs-data.ts b/src/entities/job/model/jobs-data.ts new file mode 100644 index 00000000..0137b217 --- /dev/null +++ b/src/entities/job/model/jobs-data.ts @@ -0,0 +1,51 @@ +import { useEffect, useState } from "react"; + +import { type JobEntity } from "../config"; +import { JobNormalized } from "../lib/job-normalized"; + +type JobAllEntriesFetchFxResponse = { + /** Jobs indexed by ID for easy access to each particular job */ + data: Record | null; + error?: Error | null; + loading: boolean; +}; + +export class JobDataModel { + static allEntriesFetchFx = async ( + { multicall }: JobEntity.Dependencies["contracts"], + callback: (result: JobAllEntriesFetchFxResponse) => void + ) => + callback( + await multicall + .getJobs() + .then((data) => ({ + data: data.reduce( + (jobsIndexedById, job) => ({ + ...jobsIndexedById, + [job.id]: JobNormalized.withMulticallsDataDecoded(JobNormalized.withStatus(job)), + }), + {} + ), + + error: null, + loading: false, + })) + .catch((error) => ({ + data: null, + error: new Error(error), + loading: false, + })) + ); + + static useAllEntries = (contracts: JobEntity.Dependencies["contracts"]) => { + const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); + + useEffect(() => void JobDataModel.allEntriesFetchFx(contracts, stateUpdate), [contracts, stateUpdate]); + + useEffect(() => { + state.error instanceof Error && void console.error(state.error); + }, [state]); + + return state; + }; +} diff --git a/src/entities/job/ui/job-details.scss b/src/entities/job/ui/job-entry.scss similarity index 100% rename from src/entities/job/ui/job-details.scss rename to src/entities/job/ui/job-entry.scss diff --git a/src/entities/job/ui/job-details.tsx b/src/entities/job/ui/job-entry.tsx similarity index 88% rename from src/entities/job/ui/job-details.tsx rename to src/entities/job/ui/job-entry.tsx index 71055d3f..336a7f78 100644 --- a/src/entities/job/ui/job-details.tsx +++ b/src/entities/job/ui/job-entry.tsx @@ -4,9 +4,9 @@ import { Big, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/components"; import { JobConfig, type JobEntity } from "../config"; -import "./job-details.scss"; +import "./job-entry.scss"; -interface JobDetailsTableRowRenderProps extends JobEntity.DataWithStatus {} +interface JobEntryProps extends JobEntity.DataWithStatus {} const _Job = "Job"; @@ -24,7 +24,7 @@ const JobDisplayStatus = ({ job }: Pick) => { ); }; -export const jobDetailsTableRow = ({ id, job }: JobDetailsTableRowRenderProps) => [ +export const jobTableRow = ({ id, job }: JobEntryProps) => [ , id, // Multicall returns timestamp in nanoseconds, JS Date uses milliseconds diff --git a/src/entities/job/ui/jobs-list.scss b/src/entities/job/ui/jobs-table.scss similarity index 96% rename from src/entities/job/ui/jobs-list.scss rename to src/entities/job/ui/jobs-table.scss index e58cd0bc..f481a03b 100644 --- a/src/entities/job/ui/jobs-list.scss +++ b/src/entities/job/ui/jobs-table.scss @@ -1,7 +1,7 @@ @use "sass/color"; @use "sass/size"; -.JobsList { +.JobsTable { &-body { .Table-row-content--compact:last-of-type { align-items: flex-start; diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-table.tsx similarity index 52% rename from src/entities/job/ui/jobs-list.tsx rename to src/entities/job/ui/jobs-table.tsx index f23b023d..d9963d14 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -1,32 +1,32 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/components"; -import { JobDataModel } from "../model/job-data"; +import { JobDataModel } from "../model/jobs-data"; import { type JobEntity } from "../config"; -import { jobDetailsTableRow } from "./job-details"; -import "./jobs-list.scss"; +import { jobTableRow } from "./job-entry"; +import "./jobs-table.scss"; -interface JobsListProps extends JobEntity.Dependencies {} +interface JobsTableProps extends JobEntity.Dependencies {} -const _JobsList = "JobsList"; +const _JobsTable = "JobsTable"; -export const JobsList = ({ className, contracts }: JobsListProps) => { - const { data, error, loading } = JobDataModel.useAllJobsFrom(contracts); +export const JobsTable = ({ className, contracts }: JobsTableProps) => { + const { data, error, loading } = JobDataModel.useAllEntries(contracts); return (
    diff --git a/src/entities/multicall/ui/mc-admin.tsx b/src/entities/multicall/ui/mc-admin-entry.tsx similarity index 100% rename from src/entities/multicall/ui/mc-admin.tsx rename to src/entities/multicall/ui/mc-admin-entry.tsx diff --git a/src/entities/multicall/ui/mc-admins.tsx b/src/entities/multicall/ui/mc-admins.tsx index b7f3dde1..0e563628 100644 --- a/src/entities/multicall/ui/mc-admins.tsx +++ b/src/entities/multicall/ui/mc-admins.tsx @@ -4,7 +4,7 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/components"; import { MulticallAdminsModel } from "../model/mc-admins"; import { type MulticallEntity } from "../config"; -import { multicallAdminTableRow } from "./mc-admin"; +import { multicallAdminTableRow } from "./mc-admin-entry"; interface MulticallAdminsTableProps extends MulticallEntity.Dependencies { className?: string; diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 401feefa..3ce186af 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -5,13 +5,13 @@ import { Job } from "../../../entities"; import "./jobs.scss"; -interface DaoJobsTabComponentProps extends HTMLProps, ComponentProps {} +interface DaoJobsTabComponentProps extends HTMLProps, ComponentProps {} const _DaoJobsTab = "DaoJobsTab"; const DaoJobsTabComponent = ({ className, contracts }: DaoJobsTabComponentProps) => (
    - From 3cb5d6e16bcfb21d543125695e8d565847bb04cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 04:47:36 +0400 Subject: [PATCH 265/537] feat: Update UI kti --- .../ui/components/button-group/button-group.scss | 7 +++++++ .../ui/components/button-group/button-group.tsx | 12 ++++++++++++ src/shared/ui/components/button-group/index.ts | 1 + src/shared/ui/components/index.ts | 7 ++++--- 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/shared/ui/components/button-group/button-group.scss create mode 100644 src/shared/ui/components/button-group/button-group.tsx create mode 100644 src/shared/ui/components/button-group/index.ts diff --git a/src/shared/ui/components/button-group/button-group.scss b/src/shared/ui/components/button-group/button-group.scss new file mode 100644 index 00000000..a55efb5a --- /dev/null +++ b/src/shared/ui/components/button-group/button-group.scss @@ -0,0 +1,7 @@ +@use "sass/mixin"; + +.ButtonGroup { + @include mixin.center-items(space-between, center); + flex-flow: row nowrap; + padding: size.$gap; +} diff --git a/src/shared/ui/components/button-group/button-group.tsx b/src/shared/ui/components/button-group/button-group.tsx new file mode 100644 index 00000000..953ef468 --- /dev/null +++ b/src/shared/ui/components/button-group/button-group.tsx @@ -0,0 +1,12 @@ +import clsx from "clsx"; +import { HTMLProps } from "react"; + +import "./button-group"; + +export interface ButtonGroupProps extends HTMLProps {} + +const _ButtonGroup = "ButtonGroup"; + +export const ButtonGroup = ({ children, className }: ButtonGroupProps) => ( +
    {children}
    +); diff --git a/src/shared/ui/components/button-group/index.ts b/src/shared/ui/components/button-group/index.ts new file mode 100644 index 00000000..4f0b2848 --- /dev/null +++ b/src/shared/ui/components/button-group/index.ts @@ -0,0 +1 @@ +export { ButtonGroup } from "./button-group"; diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 1e0c68aa..ba23806a 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -1,19 +1,20 @@ /** Atoms */ export { Button } from "./button"; +export { ButtonGroup } from "./button-group"; export { NearIcons } from "./icons"; export { Placeholder } from "./placeholder"; export { PopupMenu } from "./popup-menu"; export { Scrollable } from "./scrollable"; -export { Tile } from "./tile"; export { Tooltip } from "./tooltip"; /** Molecules */ export { IconLabel } from "./icon-label"; +export { TextInput, TextInputWithUnits } from "./text-input"; +export { Tile } from "./tile"; -/** Uncategorized ( yet ) */ +/** Organisms */ export { DataInspector } from "./data-inspector"; export { DateTimePicker, type DateTimePickerProps } from "./date-time-picker"; export { Dialog } from "./dialog"; export { Table } from "./table"; export { Tabs } from "./tabs"; -export { TextInput, TextInputWithUnits } from "./text-input"; From 1839ce6a5e66d3d333a85f5566bd4b245b462bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 05:12:57 +0400 Subject: [PATCH 266/537] wip: Update & fix button group styles --- .../ui/components/button-group/button-group.scss | 9 +++++++++ src/shared/ui/components/button-group/button-group.tsx | 10 ++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/shared/ui/components/button-group/button-group.scss b/src/shared/ui/components/button-group/button-group.scss index a55efb5a..bbdc2954 100644 --- a/src/shared/ui/components/button-group/button-group.scss +++ b/src/shared/ui/components/button-group/button-group.scss @@ -1,7 +1,16 @@ @use "sass/mixin"; +@use "sass/size"; .ButtonGroup { @include mixin.center-items(space-between, center); flex-flow: row nowrap; padding: size.$gap; + + &--end { + margin-top: auto; + } + + &--start { + margin-bottom: auto; + } } diff --git a/src/shared/ui/components/button-group/button-group.tsx b/src/shared/ui/components/button-group/button-group.tsx index 953ef468..a5bd2e18 100644 --- a/src/shared/ui/components/button-group/button-group.tsx +++ b/src/shared/ui/components/button-group/button-group.tsx @@ -1,12 +1,14 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import "./button-group"; +import "./button-group.scss"; -export interface ButtonGroupProps extends HTMLProps {} +export interface ButtonGroupProps extends HTMLProps { + placement?: "end" | "start"; +} const _ButtonGroup = "ButtonGroup"; -export const ButtonGroup = ({ children, className }: ButtonGroupProps) => ( -
    {children}
    +export const ButtonGroup = ({ children, className, placement = "end" }: ButtonGroupProps) => ( +
    {children}
    ); From 8c7a39aacfbe99b63e1f7d54e090427a29e1fad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 05:13:22 +0400 Subject: [PATCH 267/537] wip: Update DAO config tab styles --- src/pages/dao/config/config.scss | 5 +++- src/pages/dao/config/config.tsx | 42 +++++++++++++++++--------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/pages/dao/config/config.scss b/src/pages/dao/config/config.scss index c5e05461..be0f2379 100644 --- a/src/pages/dao/config/config.scss +++ b/src/pages/dao/config/config.scss @@ -14,8 +14,11 @@ "jobsSettings proposalForm"; &-proposalForm { - @include mixin.center-items(space-evenly, center); grid-area: proposalForm; + + &:not(.is-inEditMode) { + @include mixin.center-items(space-evenly, center); + } } &-admins { diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 076fcd3a..4b16129e 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -8,7 +8,7 @@ import { ArgsAccount, ArgsString } from "../../../shared/lib/args"; import { MulticallContract } from "../../../shared/lib/contracts/multicall"; import { SputnikDAOContract } from "../../../shared/lib/contracts/sputnik-dao"; import { toNEAR } from "../../../shared/lib/converter"; -import { Button, TextInput, Tile } from "../../../shared/ui/components"; +import { Button, ButtonGroup, TextInput, Tile } from "../../../shared/ui/components"; import "./config.scss"; @@ -149,30 +149,32 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall }, daoContrac - {!editMode ? ( -
    ); From af8d7c85f28f70f511eaa9c368a68d54340658c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 05:33:30 +0400 Subject: [PATCH 268/537] wip: Add optional `onChange` to text input --- src/shared/ui/components/text-input/text-input.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/ui/components/text-input/text-input.tsx b/src/shared/ui/components/text-input/text-input.tsx index 2761b63e..88bd3f69 100644 --- a/src/shared/ui/components/text-input/text-input.tsx +++ b/src/shared/ui/components/text-input/text-input.tsx @@ -11,7 +11,7 @@ interface TextInputProps extends Omit { render() { - const { label, value, error, update, ...props } = this.props; + const { label, value, error, onChange, update, ...props } = this.props; const errors = Array.isArray(error) ? error : [error]; @@ -22,6 +22,7 @@ export class TextInput extends Component { size="small" onChange={(event) => { if (value) { + onChange?.(event); value.value = event.target.value; errors.forEach((error) => error?.validOrNull(value)); update?.(event, this); From baadbe334c4d13be10e27c02c15a6f3155b6b5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 06:57:05 +0400 Subject: [PATCH 269/537] wip: Export multicall config changes type --- src/shared/lib/contracts/multicall.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 2cd925b0..4635728e 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -305,4 +305,4 @@ class Multicall { } export { Multicall, Multicall as MulticallContract }; -export type { JobData, MulticallArgs }; +export type { JobData, MulticallArgs, MulticallConfigChanges }; From b7b2473257832c6f8ccee39fae3564bda977edb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 06:58:00 +0400 Subject: [PATCH 270/537] wip: Expose whitelisted token table row renderer --- src/entities/multicall/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/entities/multicall/index.ts b/src/entities/multicall/index.ts index 20e5a12c..9cda6114 100644 --- a/src/entities/multicall/index.ts +++ b/src/entities/multicall/index.ts @@ -1,10 +1,12 @@ import { MulticallConfig, type MulticallEntity } from "./config"; import { MulticallAdminsTable } from "./ui/mc-admins"; import { MulticallTokensWhitelistTable } from "./ui/mc-tokens-whitelist"; +import { multicallWhitelistedTokenTableRow } from "./ui/mc-whitelisted-token"; class Multicall extends MulticallConfig { static AdminsTable = MulticallAdminsTable; static TokensWhitelistTable = MulticallTokensWhitelistTable; + static whitelistedTokenTableRow = multicallWhitelistedTokenTableRow; } export { Multicall, MulticallEntity }; From 2e9033839496faca0359f1f6984fa85d84902d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 07:41:44 +0400 Subject: [PATCH 271/537] wip: Remove optional `onChange` from TextInput // Oh gosh, this component is cursed --- src/shared/ui/components/text-input/text-input.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/shared/ui/components/text-input/text-input.tsx b/src/shared/ui/components/text-input/text-input.tsx index 88bd3f69..2761b63e 100644 --- a/src/shared/ui/components/text-input/text-input.tsx +++ b/src/shared/ui/components/text-input/text-input.tsx @@ -11,7 +11,7 @@ interface TextInputProps extends Omit { render() { - const { label, value, error, onChange, update, ...props } = this.props; + const { label, value, error, update, ...props } = this.props; const errors = Array.isArray(error) ? error : [error]; @@ -22,7 +22,6 @@ export class TextInput extends Component { size="small" onChange={(event) => { if (value) { - onChange?.(event); value.value = event.target.value; errors.forEach((error) => error?.validOrNull(value)); update?.(event, this); From f8d4dd49c1f66a74256c800026ad84e6f4caa06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 07:45:56 +0400 Subject: [PATCH 272/537] wip: Update button related styles --- src/pages/dao/config/config.scss | 5 +++++ src/shared/ui/components/button-group/button-group.scss | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/dao/config/config.scss b/src/pages/dao/config/config.scss index be0f2379..05469b1d 100644 --- a/src/pages/dao/config/config.scss +++ b/src/pages/dao/config/config.scss @@ -18,6 +18,11 @@ &:not(.is-inEditMode) { @include mixin.center-items(space-evenly, center); + + .ButtonGroup { + justify-content: center; + margin-top: 0; + } } } diff --git a/src/shared/ui/components/button-group/button-group.scss b/src/shared/ui/components/button-group/button-group.scss index bbdc2954..38e26ae9 100644 --- a/src/shared/ui/components/button-group/button-group.scss +++ b/src/shared/ui/components/button-group/button-group.scss @@ -4,7 +4,7 @@ .ButtonGroup { @include mixin.center-items(space-between, center); flex-flow: row nowrap; - padding: size.$gap; + width: 100%; &--end { margin-top: auto; From c0658306bb9aa4c24ed42e6b192e23b24b5c7d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 07:47:01 +0400 Subject: [PATCH 273/537] feat: Create NEAR link shared UI component --- src/shared/ui/components/index.ts | 3 ++- src/shared/ui/components/near-link/index.ts | 1 + .../ui/components/near-link/near-link.tsx | 20 +++++++++++++++++++ src/shared/ui/components/tile/index.ts | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/shared/ui/components/near-link/index.ts create mode 100644 src/shared/ui/components/near-link/near-link.tsx diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index ba23806a..7280fc56 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -2,6 +2,7 @@ export { Button } from "./button"; export { ButtonGroup } from "./button-group"; export { NearIcons } from "./icons"; +export { NearLink, type NearLinkProps } from "./near-link"; export { Placeholder } from "./placeholder"; export { PopupMenu } from "./popup-menu"; export { Scrollable } from "./scrollable"; @@ -10,7 +11,7 @@ export { Tooltip } from "./tooltip"; /** Molecules */ export { IconLabel } from "./icon-label"; export { TextInput, TextInputWithUnits } from "./text-input"; -export { Tile } from "./tile"; +export { Tile, type TileProps } from "./tile"; /** Organisms */ export { DataInspector } from "./data-inspector"; diff --git a/src/shared/ui/components/near-link/index.ts b/src/shared/ui/components/near-link/index.ts new file mode 100644 index 00000000..b4627c77 --- /dev/null +++ b/src/shared/ui/components/near-link/index.ts @@ -0,0 +1 @@ +export { NearLink, type NearLinkProps } from "./near-link"; diff --git a/src/shared/ui/components/near-link/near-link.tsx b/src/shared/ui/components/near-link/near-link.tsx new file mode 100644 index 00000000..7ab91b47 --- /dev/null +++ b/src/shared/ui/components/near-link/near-link.tsx @@ -0,0 +1,20 @@ +import { Account } from "near-api-js"; +import { ArgsAccount } from "../../../lib/args"; + +export interface NearLinkProps { + address: Account["accountId"]; +} + +export const NearLink = ({ address }: NearLinkProps) => { + const addr = new ArgsAccount(address); + + return ( + + {addr.value} + + ); +}; diff --git a/src/shared/ui/components/tile/index.ts b/src/shared/ui/components/tile/index.ts index 62039cf7..d40b3c43 100644 --- a/src/shared/ui/components/tile/index.ts +++ b/src/shared/ui/components/tile/index.ts @@ -1 +1 @@ -export { Tile } from "./tile"; +export { Tile, type TileProps } from "./tile"; From 12c52726c840cffdf25aaa0f96898c745c13699f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 07:48:34 +0400 Subject: [PATCH 274/537] wip: Add slots to multicall tokens whitelist --- src/entities/multicall/ui/mc-tokens-whitelist.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/entities/multicall/ui/mc-tokens-whitelist.tsx b/src/entities/multicall/ui/mc-tokens-whitelist.tsx index 7b4e1fec..38f8d62e 100644 --- a/src/entities/multicall/ui/mc-tokens-whitelist.tsx +++ b/src/entities/multicall/ui/mc-tokens-whitelist.tsx @@ -7,14 +7,18 @@ import { type MulticallEntity } from "../config"; import { multicallWhitelistedTokenTableRow } from "./mc-whitelisted-token"; interface MulticallTokensWhitelistTableProps extends MulticallEntity.Dependencies { + additionalItems?: JSX.Element[][]; className?: string; + toolbarContent?: JSX.Element; } const _MulticallTokensWhitelistTable = "MulticallTokensWhitelistTable"; export const MulticallTokensWhitelistTable = ({ + additionalItems, className, daoContractAddress, + toolbarContent, }: MulticallTokensWhitelistTableProps) => { const { data, error, loading } = MulticallTokensModel.useWhitelist(daoContractAddress); @@ -30,7 +34,7 @@ export const MulticallTokensWhitelistTable = ({ className={`${_MulticallTokensWhitelistTable}-body`} displayMode="compact" header={["Contract address"]} - rows={data?.map(multicallWhitelistedTokenTableRow)} + rows={(data?.map(multicallWhitelistedTokenTableRow) ?? []).concat(additionalItems ?? [])} /> From b24dd0e48f70bf41a1c5ab7b5e0bd1442e98dcb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 07:49:39 +0400 Subject: [PATCH 275/537] wip: Update DAO config tab --- src/pages/dao/config/config.tsx | 197 ++++++++++++++++---------------- src/pages/dao/dao.tsx | 4 +- 2 files changed, 103 insertions(+), 98 deletions(-) diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 4b16129e..cbf0b7dd 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -1,108 +1,108 @@ -import { AddOutlined, DeleteOutlined, EditOutlined } from "@mui/icons-material"; +import { AddOutlined, DeleteOutlined, EditOutlined, PreviewOutlined, VisibilityOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; import clsx from "clsx"; -import { HTMLProps, useState } from "react"; +import { HTMLProps, useReducer, useState } from "react"; import { Multicall } from "../../../entities"; import { ArgsAccount, ArgsString } from "../../../shared/lib/args"; -import { MulticallContract } from "../../../shared/lib/contracts/multicall"; +import { type MulticallConfigChanges, type MulticallContract } from "../../../shared/lib/contracts/multicall"; import { SputnikDAOContract } from "../../../shared/lib/contracts/sputnik-dao"; import { toNEAR } from "../../../shared/lib/converter"; -import { Button, ButtonGroup, TextInput, Tile } from "../../../shared/ui/components"; +import { Button, ButtonGroup, NearLink, TextInput, Tile } from "../../../shared/ui/components"; import "./config.scss"; -const Link = ({ - address, - deleteIcon = false, - editIcon = false, - onClick, -}: { - address: string; - deleteIcon?: boolean; - editIcon?: boolean; - onClick?: () => {}; -}) => { - const addr = new ArgsAccount(address); +interface DaoConfigTabComponentProps extends HTMLProps { + daoContractAddress: SputnikDAOContract["address"]; + multicallContract: MulticallContract; +} - return ( - - - {addr.value} - +const _DaoConfigTab = "DaoConfigTab"; - {deleteIcon ? : editIcon ? : null} - - ); -}; +const DaoConfigTabComponent = ({ className, daoContractAddress, multicallContract }: DaoConfigTabComponentProps) => { + const [editMode, editModeSwitch] = useState(false), + [tokensWhitelistEditMode, tokensWhitelistEditModeSwitch] = useState(false), + [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); -interface DaoConfigTabComponentProps extends HTMLProps { - contracts: { - multicall: MulticallContract; + const changesDiffInitialState = { + removeTokens: [], + addTokens: [], + jobBond: "", + croncatManager: "", }; - daoContract: SputnikDAOContract; -} - -const _DaoConfigTab = "DaoConfigTab"; + const [changesDiff, changesDiffUpdate] = useReducer( + ( + previousState: MulticallConfigChanges, + + update: { + reset?: boolean; + field?: keyof MulticallConfigChanges; + value?: MulticallConfigChanges[keyof MulticallConfigChanges]; + } + ): MulticallConfigChanges => + update.reset + ? changesDiffInitialState + : { + ...previousState, + + ...(update.field && update.value + ? { + [update.field as keyof MulticallConfigChanges]: Array.isArray(update.value) + ? (previousState[update.field as keyof MulticallConfigChanges] as string[]).concat( + update.value + ) + : update.value, + } + : {}), + }, + + changesDiffInitialState + ); -const DaoConfigTabComponent = ({ className, contracts: { multicall }, daoContract }: DaoConfigTabComponentProps) => { - const [editMode, setEditMode] = useState(false); - const [addTokens, setAddTokens] = useState(multicall.tokensWhitelist); - const [addToken, setAddToken] = useState(false); - const [croncatManager, setCroncatManager] = useState(""); - const [editCroncat, setEditCroncat] = useState(false); + console.log(changesDiff); return (
    - {!editMode && ( - - )} - - {editMode && ( - - setAddToken(true)} - > - - - -
      - {addTokens.map((token) => ( -
    • - -
    • - ))} - - {addToken ? ( - - setAddTokens((previousState) => [...previousState, event.target.value]) - } - /> - ) : null} -
    -
    - )} + + changesDiffUpdate({ field: "addTokens", value: event.target.value }) + } + />, + ] + : [] + )} + className={`${_DaoConfigTab}-tokensWhitelist`} + daoContractAddress={daoContractAddress} + toolbarContent={ + tokensWhitelistEditMode ? ( + tokensWhitelistEditModeSwitch(false)} + > + + + ) : ( + tokensWhitelistEditModeSwitch(true)} + > + + + ) + } + /> { - setEditMode(true); - setEditCroncat(true); + editModeSwitch(true); + jobsSettingsEditModeSwitch(true); }} > - {editMode && editCroncat ? ( + {editMode && jobsSettingsEditMode ? ( { - setCroncatManager(event.target.value); - setEditCroncat(false); - }} - value={new ArgsString(multicall.croncatManager)} + onBlur={(event) => changesDiffUpdate({ field: "croncatManager", value: event.target.value })} + value={new ArgsString(multicallContract.croncatManager)} fullWidth /> ) : ( - + )}

    Job bond

    - {!editMode && (multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "...") + " Ⓝ"} + {!editMode && (multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "...") + " Ⓝ"} {editMode && ( changesDiffUpdate({ field: "jobBond", value: event.target.value })} type="number" - value={new ArgsString(multicall.jobBond !== "" ? toNEAR(multicall.jobBond) : "")} + value={ + new ArgsString( + multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "" + ) + } /> )} @@ -157,20 +159,23 @@ const DaoConfigTabComponent = ({ className, contracts: { multicall }, daoContrac
    tokensWhitelistEditModeSwitch(false)} - > + tokensWhitelistEditModeSwitch(false)}> ) : ( - tokensWhitelistEditModeSwitch(true)} - > + tokensWhitelistEditModeSwitch(true)}> ) diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 97ad15ce..7666128e 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -40,9 +40,13 @@ align-items: center; font-size: calc(1.1 * size.$text); - &:first-of-type { - padding: calc(size.$gap / 2); + &:not(&--denseHeader) { + &:first-of-type { + padding: calc(size.$gap / 2); + } + } + &:first-of-type { & > span { &:first-of-type { display: none; diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index e06d41e7..9f6bb79c 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -1,4 +1,5 @@ import { TableCell, TableRow as MuiTableRow, Typography } from "@mui/material"; +import clsx from "clsx"; import "./row.scss"; @@ -6,6 +7,7 @@ const _TableRow = "Table-row"; export interface TableRowProps { cells?: (string | number | JSX.Element)[] | null; + denseHeader?: boolean; headerCells: string[]; } @@ -19,11 +21,13 @@ export const TableRow = ({ cells, headerCells }: TableRowProps) => ( ); -export const TableRowCard = ({ cells, headerCells }: TableRowProps) => ( +export const TableRowCard = ({ cells, denseHeader, headerCells }: TableRowProps) => (
    {headerCells.map((headerCell, headerCellIndex) => (
    {headerCell} diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 6ab4738f..43e6f9cc 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -13,7 +13,7 @@ import { HTMLAttributes } from "react"; import { TableRowCard, TableRow, type TableRowProps } from "./row"; import "./table.scss"; -interface TableProps extends HTMLAttributes { +interface TableProps extends HTMLAttributes, Pick { /** * `"classic"` mode is a classic table view. * @@ -32,7 +32,7 @@ interface TableProps extends HTMLAttributes { const _Table = "Table"; -export const Table = ({ className, displayMode = "default", header, rows }: TableProps) => { +export const Table = ({ className, denseHeader = false, displayMode = "default", header, rows }: TableProps) => { const mediumOrSmallScreen = useMediaQuery(useTheme().breakpoints.down("md")), classicModeRequired = (!mediumOrSmallScreen && displayMode === "default") || displayMode === "classic", compactModeRequired = (mediumOrSmallScreen && displayMode === "default") || displayMode === "compact"; @@ -70,7 +70,7 @@ export const Table = ({ className, displayMode = "default", header, rows }: Tabl ))}
    diff --git a/src/shared/ui/components/tile/tile.scss b/src/shared/ui/components/tile/tile.scss index 17b8182a..335ac350 100644 --- a/src/shared/ui/components/tile/tile.scss +++ b/src/shared/ui/components/tile/tile.scss @@ -11,11 +11,28 @@ font-size: size.$small-text; &-heading { + display: flex; + flex-flow: row nowrap; + align-items: center; + gap: size.$gap; padding-bottom: calc(size.$gap * 1); - font-size: size.$large-text; - span { - float: right; + &-text, + svg { + font-size: size.$large-text; + } + + &-slot { + &--left, + &--right { + .MuiButtonBase-root { + padding: 4px; + } + } + + &--right { + margin-left: auto; + } } } @@ -27,14 +44,4 @@ height: 100%; overflow: hidden; } - - @for $i from 0 to 3 { - .MuiSvgIcon-root:nth-of-type(#{$i + 1}) { - position: absolute; - font-size: size.$large-text; - top: calc(0.5 * size.$gap + size.$gap / 6); - right: calc(0.5 * size.$gap + $i * (size.$large-text + 0.25 * size.$gap) + size.$gap / 6); - cursor: pointer; - } - } } diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index f446d369..7fd6d45f 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -10,13 +10,34 @@ const _Tile = "Tile"; export interface TileProps extends PropsWithChildren, HTMLAttributes { error?: Error | null; heading?: string | null; + headingSlotsContent?: { left?: JSX.Element; right?: JSX.Element }; loading?: boolean; noData?: boolean; } -export const Tile = ({ children, className, error, heading, loading = false, noData = false }: TileProps) => ( +export const Tile = ({ + children, + className, + error, + heading, + headingSlotsContent, + loading = false, + noData = false, +}: TileProps) => (
    - {heading &&

    {heading}

    } + {heading && ( + + {headingSlotsContent?.left && ( + {headingSlotsContent?.left} + )} + +

    {heading}

    + + {headingSlotsContent?.right && ( + {headingSlotsContent?.right} + )} +
    + )}
    {loading &&
    } From 1139686ddafc6be5aeaeb95379ddfcf4ffcc804c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 20 Oct 2022 09:23:36 +0400 Subject: [PATCH 277/537] wip: Trigger edit mode on token add action --- src/pages/dao/config/config.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index dfeefe0c..9f259388 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -87,11 +87,21 @@ const DaoConfigTabComponent = ({ className, daoContractAddress, multicallContrac daoContractAddress={daoContractAddress} toolbarContent={ tokensWhitelistEditMode ? ( - tokensWhitelistEditModeSwitch(false)}> + { + editModeSwitch(true); + tokensWhitelistEditModeSwitch(false); + }} + > ) : ( - tokensWhitelistEditModeSwitch(true)}> + { + editModeSwitch(true); + tokensWhitelistEditModeSwitch(true); + }} + > ) From bf5314a8f35ba490ed78f245f2571c5dea8b6592 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Thu, 20 Oct 2022 20:56:50 +0200 Subject: [PATCH 278/537] fix: remove unnecessary code --- src/entities/wallet/ui/wallet.scss | 2 +- .../ui/components/icon-label/icon-label.scss | 2 +- .../placeholder/placeholder-content.scss | 2 +- src/shared/ui/components/table/row.scss | 22 +++++++++---------- src/shared/ui/components/table/table.scss | 8 +++---- src/shared/ui/components/tile/tile.scss | 2 +- src/widgets/export/export.jsx | 7 ------ 7 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/entities/wallet/ui/wallet.scss b/src/entities/wallet/ui/wallet.scss index 9a0da83f..16ff3fd6 100644 --- a/src/entities/wallet/ui/wallet.scss +++ b/src/entities/wallet/ui/wallet.scss @@ -38,7 +38,7 @@ position: absolute; left: calc(0.7 * size.$sidebar-width + 2px); top: calc(-0.125 * size.$gap - 1px); - padding: calc(0.25 * size.$gap) 0 calc(0.25 * size.$gap) size.$gap; + padding: 0.25 * size.$gap size.$gap; color: rgba(color.$text, 0.25); font-size: size.$text; white-space: nowrap; diff --git a/src/shared/ui/components/icon-label/icon-label.scss b/src/shared/ui/components/icon-label/icon-label.scss index 027a641c..0c26c783 100644 --- a/src/shared/ui/components/icon-label/icon-label.scss +++ b/src/shared/ui/components/icon-label/icon-label.scss @@ -4,7 +4,7 @@ .IconLabel { display: flex; align-items: center; - gap: calc(size.$gap * 0.6); + gap: 0.6 * size.$gap; line-height: 1; &-icon { diff --git a/src/shared/ui/components/placeholder/placeholder-content.scss b/src/shared/ui/components/placeholder/placeholder-content.scss index 0e8aec7d..5bb5d645 100644 --- a/src/shared/ui/components/placeholder/placeholder-content.scss +++ b/src/shared/ui/components/placeholder/placeholder-content.scss @@ -4,7 +4,7 @@ .Placeholder-content { padding: size.$gap; text-align: center; - font-size: calc(size.$large-text * 1.5); + font-size: 1.5 * size.$large-text; &--unknownError { color: darken(color.$red, 20); diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 60664ed9..d92f395c 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -17,11 +17,11 @@ &:first-of-type { text-align: left; font-family: font.$text; - padding-left: calc(1.25 * size.$gap); + padding-left: 1.25 * size.$gap; } &:last-of-type { - padding-right: calc(1.25 * size.$gap); + padding-right: 1.25 * size.$gap; } } @@ -32,9 +32,9 @@ &--compact { display: flex; flex-direction: column; - gap: calc(size.$gap / 2); + gap: 0.5 * size.$gap; border-radius: size.$task-radius; - padding: calc(size.$gap / 2); + padding: 0.5 * size.$gap; background-color: color.$white; } @@ -43,10 +43,10 @@ display: flex; justify-content: space-between; align-items: center; - font-size: calc(1.1 * size.$text); + font-size: 1.1 * size.$text; &:first-of-type { - padding: calc(size.$gap / 2); + padding: 0.5 * size.$gap; & > span { &:first-of-type { @@ -60,18 +60,18 @@ } &:not(:first-of-type) { - padding: calc(size.$gap / 1.5) size.$gap; + padding: 0.5 * size.$gap size.$gap; background-color: rgba(color.$lightest, 0.7); } &:nth-of-type(2) { - border-top-left-radius: calc(size.$task-radius / 1.2); - border-top-right-radius: calc(size.$task-radius / 1.2); + border-top-left-radius: 0.8 * size.$task-radius; + border-top-right-radius: 0.8 * size.$task-radius; } &:last-of-type { - border-bottom-left-radius: calc(size.$task-radius / 1.2); - border-bottom-right-radius: calc(size.$task-radius / 1.2); + border-bottom-left-radius: 0.8 * size.$task-radius; + border-bottom-right-radius: 0.8 * size.$task-radius; } span:first-of-type { diff --git a/src/shared/ui/components/table/table.scss b/src/shared/ui/components/table/table.scss index 9d553f77..d4aa37cd 100644 --- a/src/shared/ui/components/table/table.scss +++ b/src/shared/ui/components/table/table.scss @@ -9,7 +9,7 @@ .MuiTableCell-root { border-bottom: none; - padding: calc(0.5 * size.$gap); + padding: 0.5 * size.$gap; } table { @@ -31,11 +31,11 @@ &:first-of-type { text-align: left; - padding-left: calc(1.25 * size.$gap); + padding-left: 1.25 * size.$gap; } &:last-of-type { - padding-right: calc(1.25 * size.$gap); + padding-right: 1.25 * size.$gap; } } } @@ -43,7 +43,7 @@ &--compact { display: flex; flex-flow: column nowrap; - padding: calc(1.25 * size.$gap); + padding: 1.25 * size.$gap; gap: size.$gap; } } diff --git a/src/shared/ui/components/tile/tile.scss b/src/shared/ui/components/tile/tile.scss index bf9b3d50..61e71d12 100644 --- a/src/shared/ui/components/tile/tile.scss +++ b/src/shared/ui/components/tile/tile.scss @@ -5,7 +5,7 @@ display: flex; flex-flow: column nowrap; position: relative; - padding: calc(0.25 * size.$gap); + padding: 0.25 * size.$gap; border-radius: size.$task-radius; background-color: color.$lightest; font-size: size.$small-text; diff --git a/src/widgets/export/export.jsx b/src/widgets/export/export.jsx index 1ce9f231..02df6507 100644 --- a/src/widgets/export/export.jsx +++ b/src/widgets/export/export.jsx @@ -245,13 +245,6 @@ export class Export extends Component { ]); signAndSendTxs([addJobTx, proposeJobTx]); } - // WALLET_COMPONENT.state.currentDAO.proposeMulticall( - // desc.value, - // multicallArgs, - // // if attach NEAR disabled, ignore depo amount and attach 1 yocto. - // attachNEAR ? convert(depo.value, depo.unit) : "1", - // convert(gas.value, gas.unit) - // ); } }} > From 695a05282913cf991ddbc5a58437c7f7d3c4282b Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Thu, 20 Oct 2022 21:05:16 +0200 Subject: [PATCH 279/537] change grid layout on config page --- src/pages/dao/config/config.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/dao/config/config.scss b/src/pages/dao/config/config.scss index faa3d5c2..d27d51ea 100644 --- a/src/pages/dao/config/config.scss +++ b/src/pages/dao/config/config.scss @@ -7,8 +7,8 @@ display: grid; grid-template: - "AdminsList ." 6fr - "TokenWhitelist ." 5fr + "TokenWhitelist AdminsList" 6fr + "TokenWhitelist AdminsList" 5fr "TokenWhitelist JobBond" 1fr / 1fr 1fr; .AdminsList { From 5cece32120b8bd0b8160dbc327c87ff87cd9cd53 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Thu, 20 Oct 2022 21:06:34 +0200 Subject: [PATCH 280/537] remove plus sign on admin tile --- src/pages/dao/config/config.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 832e5516..124d0c3e 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -37,7 +37,6 @@ const _DaoConfigTab = "DaoConfigTab"; const DaoConfigTabComponent = ({ className, contracts: { multicall } }: DaoConfigTabComponentProps) => (
    -

    Admins

      From ceef642287004b738b5909770a01f8f6f7dfe0e1 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Thu, 20 Oct 2022 21:32:38 +0200 Subject: [PATCH 281/537] changed font to code font --- src/pages/dao/funds/funds.scss | 7 +++++++ src/pages/dao/jobs/jobs.scss | 7 +++++++ .../ui/components/data-inspector/data-inspector.scss | 12 ++++++++++-- src/shared/ui/components/table/row.scss | 6 ++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/pages/dao/funds/funds.scss b/src/pages/dao/funds/funds.scss index 41036ca4..e91c97a6 100644 --- a/src/pages/dao/funds/funds.scss +++ b/src/pages/dao/funds/funds.scss @@ -12,5 +12,12 @@ padding-bottom: size.$gap; position: relative; overflow: hidden; + .Table-row-content--compact { + &:not(&:first-of-type) { + span:last-of-type { + font-family: font.$code; + } + } + } } } diff --git a/src/pages/dao/jobs/jobs.scss b/src/pages/dao/jobs/jobs.scss index f9d1d4a1..995b6843 100644 --- a/src/pages/dao/jobs/jobs.scss +++ b/src/pages/dao/jobs/jobs.scss @@ -11,5 +11,12 @@ padding-bottom: size.$gap; position: relative; overflow: hidden; + .Table-row-content--compact { + &:not(&:first-of-type) { + span:last-of-type { + font-family: font.$code; + } + } + } } } diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss index c9451690..989f8352 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.scss +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -1,18 +1,26 @@ @use "sass/color"; @use "sass/size"; +@use "sass/mixin"; +@use "sass/font"; .DataInspector { &-label { color: darken(color.$blue, 30%); cursor: pointer; + & > span { + font-family: font.$text !important; + } } &-body { + @include mixin.no-scrollbar; margin-top: 0.5 * size.$gap; - padding: 0.5 * size.$gap; + overflow-x: scroll; + overflow-y: hidden; & * { - font-size: size.$large-text; + font-size: size.$text; + font-family: font.$code !important; } div > span { diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index d92f395c..9bdec8b1 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -62,6 +62,12 @@ &:not(:first-of-type) { padding: 0.5 * size.$gap size.$gap; background-color: rgba(color.$lightest, 0.7); + & > span:last-of-type { + text-overflow: ellipsis; + white-space: nowrap; + padding-left: 1.5rem; + overflow: hidden; + } } &:nth-of-type(2) { From 6df25bae50e816ae8fe87a6bcd2a58f8ca862342 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Thu, 20 Oct 2022 21:33:50 +0200 Subject: [PATCH 282/537] shave tokens beard --- src/shared/ui/components/icon-label/icon-label.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/components/icon-label/icon-label.scss b/src/shared/ui/components/icon-label/icon-label.scss index 0c26c783..d02451cf 100644 --- a/src/shared/ui/components/icon-label/icon-label.scss +++ b/src/shared/ui/components/icon-label/icon-label.scss @@ -5,7 +5,7 @@ display: flex; align-items: center; gap: 0.6 * size.$gap; - line-height: 1; + line-height: 0; &-icon { width: fit-content; From 677fb8d7124e3fb6d6b96b47bf78a9c080a76c16 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Thu, 20 Oct 2022 22:00:29 +0200 Subject: [PATCH 283/537] reverse job order --- src/entities/job/ui/jobs-list.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/job/ui/jobs-list.tsx b/src/entities/job/ui/jobs-list.tsx index 4d219fe7..f6835650 100644 --- a/src/entities/job/ui/jobs-list.tsx +++ b/src/entities/job/ui/jobs-list.tsx @@ -36,7 +36,7 @@ export const JobsList = ({ className, contracts }: JobsListProps) => { className={`${_JobsList}-body`} displayMode="compact" header={["Status", "ID", "Start at", "Croncat hash", "Creator", "Trigger gas", "Multicalls"]} - rows={Object.values(data).map(jobDetailsTableRowRender)} + rows={Object.values(data).map(jobDetailsTableRowRender).reverse()} /> )} From bd4010a70d8bbd24d083b8f87746ad1497401f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 03:52:00 +0400 Subject: [PATCH 284/537] wip: reverse jobs order --- src/entities/job/ui/jobs-table.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index d9963d14..fa9ce01f 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -26,7 +26,9 @@ export const JobsTable = ({ className, contracts }: JobsTableProps) => { className={`${_JobsTable}-body`} displayMode="compact" header={["Status", "ID", "Start at", "Croncat hash", "Creator", "Trigger gas", "Multicalls"]} - rows={Object.values(data ?? {}).map(jobTableRow)} + rows={Object.values(data ?? {}) + .map(jobTableRow) + .reverse()} /> From bbe9d540b98bda7969a87891951f8f44eff38926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 08:32:05 +0400 Subject: [PATCH 285/537] wip: Extract DAO config editor into widget --- src/pages/dao/config/config.scss | 32 +-- src/pages/dao/config/config.tsx | 190 +----------------- src/widgets/dao-config-editor/config.ts | 15 ++ src/widgets/dao-config-editor/index.ts | 8 + .../ui/dao-config-editor.scss | 40 ++++ .../ui/dao-config-editor.tsx | 189 +++++++++++++++++ src/widgets/index.ts | 1 + 7 files changed, 266 insertions(+), 209 deletions(-) create mode 100644 src/widgets/dao-config-editor/config.ts create mode 100644 src/widgets/dao-config-editor/index.ts create mode 100644 src/widgets/dao-config-editor/ui/dao-config-editor.scss create mode 100644 src/widgets/dao-config-editor/ui/dao-config-editor.tsx diff --git a/src/pages/dao/config/config.scss b/src/pages/dao/config/config.scss index 05469b1d..e9689694 100644 --- a/src/pages/dao/config/config.scss +++ b/src/pages/dao/config/config.scss @@ -6,35 +6,13 @@ .DaoConfigTab { display: grid; grid-template-columns: 1fr 1fr; - grid-template-rows: 6fr 4fr; - gap: 0px 0px; + grid-template-rows: 1fr 1fr; grid-template-areas: - "admins tokensWhitelist" - "jobsSettings proposalForm"; + "DaoConfigEditor DaoConfigEditor" + "DaoConfigEditor DaoConfigEditor"; - &-proposalForm { - grid-area: proposalForm; - - &:not(.is-inEditMode) { - @include mixin.center-items(space-evenly, center); - - .ButtonGroup { - justify-content: center; - margin-top: 0; - } - } - } - - &-admins { - grid-area: admins; - } - - &-jobsSettings { - grid-area: jobsSettings; - } - - &-tokensWhitelist { - grid-area: tokensWhitelist; + .DaoConfigEditor { + grid-area: DaoConfigEditor; } } diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index bc4a4914..91361011 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -1,193 +1,19 @@ -import { AddOutlined, DeleteOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; -import { IconButton } from "@mui/material"; import clsx from "clsx"; -import { HTMLProps, useReducer, useState } from "react"; +import { HTMLProps } from "react"; -import { Multicall } from "../../../entities"; -import { ArgsAccount, ArgsString } from "../../../shared/lib/args"; -import { type MulticallConfigChanges, type MulticallContract } from "../../../shared/lib/contracts/multicall"; -import { SputnikDAOContract } from "../../../shared/lib/contracts/sputnik-dao"; -import { toNEAR } from "../../../shared/lib/converter"; -import { Button, ButtonGroup, NearLink, TextInput, Tile } from "../../../shared/ui/components"; +import { DaoConfigEditor, type DaoConfigEditorWidget } from "../../../widgets"; import "./config.scss"; -interface DaoConfigTabComponentProps extends HTMLProps { - daoContractAddress: SputnikDAOContract["address"]; - multicallContract: MulticallContract; -} +interface DaoConfigTabComponentProps extends HTMLProps, DaoConfigEditorWidget.Dependencies {} const _DaoConfigTab = "DaoConfigTab"; -const DaoConfigTabComponent = ({ className, daoContractAddress, multicallContract }: DaoConfigTabComponentProps) => { - const [editMode, editModeSwitch] = useState(false), - [tokensWhitelistEditMode, tokensWhitelistEditModeSwitch] = useState(false), - [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); - - const changesDiffInitialState = { - removeTokens: [], - addTokens: [], - jobBond: "", - croncatManager: "", - }; - - const [changesDiff, changesDiffUpdate] = useReducer( - ( - previousState: MulticallConfigChanges, - - update: { - reset?: boolean; - field?: keyof MulticallConfigChanges; - value?: MulticallConfigChanges[keyof MulticallConfigChanges]; - } - ): MulticallConfigChanges => - update.reset - ? changesDiffInitialState - : { - ...previousState, - - ...(update.field && update.value - ? { - [update.field as keyof MulticallConfigChanges]: Array.isArray(update.value) - ? (previousState[update.field as keyof MulticallConfigChanges] as string[]).concat( - update.value - ) - : update.value, - } - : {}), - }, - - changesDiffInitialState - ); - - console.log(changesDiff); - - return ( -
      - - - - changesDiffUpdate({ field: "addTokens", value: event.target.value }) - } - />, - ] - : [] - )} - className={`${_DaoConfigTab}-tokensWhitelist`} - daoContractAddress={daoContractAddress} - toolbarContent={ - tokensWhitelistEditMode ? ( - { - editModeSwitch(true); - tokensWhitelistEditModeSwitch(false); - }} - > - - - ) : ( - { - editModeSwitch(true); - tokensWhitelistEditModeSwitch(true); - }} - > - - - ) - } - /> - - -

      Croncat manager

      - - { - editModeSwitch(true); - jobsSettingsEditModeSwitch(true); - }} - > - - - - {editMode && jobsSettingsEditMode ? ( - changesDiffUpdate({ field: "croncatManager", value: event.target.value })} - value={new ArgsString(multicallContract.croncatManager)} - fullWidth - /> - ) : ( - - )} - -

      Job bond

      - - - {!editMode && (multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "...") + " Ⓝ"} - - {editMode && ( - changesDiffUpdate({ field: "jobBond", value: event.target.value })} - type="number" - value={ - new ArgsString( - multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "" - ) - } - /> - )} - -
      - - - - {!editMode ? ( -
      - ); -}; +const DaoConfigTabComponent = ({ className, ...props }: DaoConfigTabComponentProps) => ( +
      + +
      +); export const DaoConfigTab = { connect: (props: DaoConfigTabComponentProps) => ({ diff --git a/src/widgets/dao-config-editor/config.ts b/src/widgets/dao-config-editor/config.ts new file mode 100644 index 00000000..174ed6ce --- /dev/null +++ b/src/widgets/dao-config-editor/config.ts @@ -0,0 +1,15 @@ +import { HTMLProps } from "react"; + +import { MulticallContract } from "../../shared/lib/contracts/multicall"; +import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; + +namespace DaoConfigEditorWidget { + export interface Dependencies extends HTMLProps { + daoContractAddress: SputnikDAOContract["address"]; + multicallContract: MulticallContract; + } +} + +class DaoConfigEditorConfig {} + +export { DaoConfigEditorConfig, type DaoConfigEditorWidget }; diff --git a/src/widgets/dao-config-editor/index.ts b/src/widgets/dao-config-editor/index.ts new file mode 100644 index 00000000..a8cc27fa --- /dev/null +++ b/src/widgets/dao-config-editor/index.ts @@ -0,0 +1,8 @@ +import { DaoConfigEditorConfig, type DaoConfigEditorWidget } from "./config"; +import { DaoConfigEditorUI } from "./ui/dao-config-editor"; + +class DaoConfigEditor extends DaoConfigEditorConfig { + static UI = DaoConfigEditorUI; +} + +export { DaoConfigEditor, type DaoConfigEditorWidget }; diff --git a/src/widgets/dao-config-editor/ui/dao-config-editor.scss b/src/widgets/dao-config-editor/ui/dao-config-editor.scss new file mode 100644 index 00000000..d2b51503 --- /dev/null +++ b/src/widgets/dao-config-editor/ui/dao-config-editor.scss @@ -0,0 +1,40 @@ +@use "sass/color"; +@use "sass/font"; +@use "sass/mixin"; +@use "sass/size"; + +.DaoConfigEditor { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: 6fr 4fr; + gap: size.$gap; + + grid-template-areas: + "admins tokensWhitelist" + "jobsSettings proposalForm"; + + &-proposalForm { + grid-area: proposalForm; + + &:not(.is-inEditMode) { + @include mixin.center-items(space-evenly, center); + + .ButtonGroup { + justify-content: center; + margin-top: 0; + } + } + } + + &-admins { + grid-area: admins; + } + + &-jobsSettings { + grid-area: jobsSettings; + } + + &-tokensWhitelist { + grid-area: tokensWhitelist; + } +} diff --git a/src/widgets/dao-config-editor/ui/dao-config-editor.tsx b/src/widgets/dao-config-editor/ui/dao-config-editor.tsx new file mode 100644 index 00000000..800e1cec --- /dev/null +++ b/src/widgets/dao-config-editor/ui/dao-config-editor.tsx @@ -0,0 +1,189 @@ +import { AddOutlined, DeleteOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; +import { IconButton } from "@mui/material"; +import clsx from "clsx"; +import { useReducer, useState } from "react"; + +import { Multicall } from "../../../entities"; +import { ArgsString } from "../../../shared/lib/args"; +import { type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; +import { toNEAR } from "../../../shared/lib/converter"; +import { Button, ButtonGroup, NearLink, TextInput, Tile } from "../../../shared/ui/components"; +import { type DaoConfigEditorWidget } from "../config"; + +import "./dao-config-editor.scss"; + +const _DaoConfigEditor = "DaoConfigEditor"; + +export const DaoConfigEditorUI = ({ + className, + daoContractAddress, + multicallContract, +}: DaoConfigEditorWidget.Dependencies) => { + const [editMode, editModeSwitch] = useState(false), + [tokensWhitelistEditMode, tokensWhitelistEditModeSwitch] = useState(false), + [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); + + const changesDiffInitialState = { + removeTokens: [], + addTokens: [], + jobBond: "", + croncatManager: "", + }; + + const [changesDiff, changesDiffUpdate] = useReducer( + ( + previousState: MulticallConfigChanges, + + update: { + reset?: boolean; + field?: keyof MulticallConfigChanges; + value?: MulticallConfigChanges[keyof MulticallConfigChanges]; + } + ): MulticallConfigChanges => + update.reset + ? changesDiffInitialState + : { + ...previousState, + + ...(update.field && update.value + ? { + [update.field as keyof MulticallConfigChanges]: Array.isArray(update.value) + ? (previousState[update.field as keyof MulticallConfigChanges] as string[]).concat( + update.value + ) + : update.value, + } + : {}), + }, + + changesDiffInitialState + ); + + console.log(changesDiff); + + return ( +
      + + + + changesDiffUpdate({ field: "addTokens", value: event.target.value }) + } + />, + ] + : [] + )} + className={`${_DaoConfigEditor}-tokensWhitelist`} + daoContractAddress={daoContractAddress} + toolbarContent={ + tokensWhitelistEditMode ? ( + { + editModeSwitch(true); + tokensWhitelistEditModeSwitch(false); + }} + > + + + ) : ( + { + editModeSwitch(true); + tokensWhitelistEditModeSwitch(true); + }} + > + + + ) + } + /> + + +

      Croncat manager

      + + { + editModeSwitch(true); + jobsSettingsEditModeSwitch(true); + }} + > + + + + {editMode && jobsSettingsEditMode ? ( + changesDiffUpdate({ field: "croncatManager", value: event.target.value })} + value={new ArgsString(multicallContract.croncatManager)} + fullWidth + /> + ) : ( + + )} + +

      Job bond

      + + + {!editMode && (multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "...") + " Ⓝ"} + + {editMode && ( + changesDiffUpdate({ field: "jobBond", value: event.target.value })} + type="number" + value={ + new ArgsString( + multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "" + ) + } + /> + )} + +
      + + + + {!editMode ? ( +
      + ); +}; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index f115ff00..28a1c50f 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -1,4 +1,5 @@ export { Column } from "./column/column.jsx"; +export { DaoConfigEditor, type DaoConfigEditorWidget } from "./dao-config-editor"; export { DialogsLayer } from "./dialogs-layer"; export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; From 36f9c183e5128724a531ba1190da131a52852111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 08:59:11 +0400 Subject: [PATCH 286/537] wip: Extract NEAR native token character --- src/shared/ui/components/icons/near/near.tsx | 3 +++ src/widgets/dao-config-editor/ui/dao-config-editor.tsx | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/shared/ui/components/icons/near/near.tsx b/src/shared/ui/components/icons/near/near.tsx index f8194959..73175d77 100644 --- a/src/shared/ui/components/icons/near/near.tsx +++ b/src/shared/ui/components/icons/near/near.tsx @@ -16,6 +16,8 @@ const NativeTokenIconFilled = ({ className }: NativeTokenIconProps) => ( ); +const NEAR_NATIVE_TOKEN_CHARACTER = "Ⓝ"; + const _GenericTokenIcon = "GenericTokenIcon"; interface GenericTokenIconProps extends SVGProps {} @@ -43,4 +45,5 @@ const GenericTokenIconFilled = ({ className }: GenericTokenIconProps) => ( export const NearIcons = { GenericTokenFilled: GenericTokenIconFilled, NativeTokenFilled: NativeTokenIconFilled, + NATIVE_TOKEN_CHARACTER: NEAR_NATIVE_TOKEN_CHARACTER, }; diff --git a/src/widgets/dao-config-editor/ui/dao-config-editor.tsx b/src/widgets/dao-config-editor/ui/dao-config-editor.tsx index 800e1cec..7fe60f98 100644 --- a/src/widgets/dao-config-editor/ui/dao-config-editor.tsx +++ b/src/widgets/dao-config-editor/ui/dao-config-editor.tsx @@ -7,7 +7,7 @@ import { Multicall } from "../../../entities"; import { ArgsString } from "../../../shared/lib/args"; import { type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; import { toNEAR } from "../../../shared/lib/converter"; -import { Button, ButtonGroup, NearLink, TextInput, Tile } from "../../../shared/ui/components"; +import { Button, ButtonGroup, NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; import { type DaoConfigEditorWidget } from "../config"; import "./dao-config-editor.scss"; @@ -136,11 +136,14 @@ export const DaoConfigEditorUI = ({

      Job bond

      - {!editMode && (multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "...") + " Ⓝ"} + {!editMode && + `${multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "..."} ${ + NearIcons.NATIVE_TOKEN_CHARACTER + }`} {editMode && ( changesDiffUpdate({ field: "jobBond", value: event.target.value })} type="number" value={ From d026c5aa78cdadd8c878cd77e53e9140b6309f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 10:45:55 +0400 Subject: [PATCH 287/537] =?UTF-8?q?wip:=20Remove=20overhead=20&=20Improve?= =?UTF-8?q?=20consistency=20...=20or=20vice=20versa=3F=20=F0=9F=A4=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/job/ui/jobs-table.scss | 27 +++++++++++++------ src/entities/job/ui/jobs-table.tsx | 2 +- src/entities/multicall/ui/mc-admins.tsx | 2 +- .../multicall/ui/mc-tokens-whitelist.tsx | 2 +- src/pages/dao/config/config.scss | 9 ------- src/pages/dao/config/config.tsx | 15 ++++++----- src/pages/dao/dao.tsx | 6 ++--- src/pages/dao/funds/funds.scss | 22 ++++----------- src/pages/dao/funds/funds.tsx | 22 +++++++-------- src/pages/dao/jobs/jobs.scss | 21 ++++----------- src/pages/dao/jobs/jobs.tsx | 18 ++++++------- src/shared/ui/components/tile/tile.tsx | 12 ++++----- .../ui/dao-config-editor.scss | 1 + .../ui/dao-config-editor.tsx | 12 ++++----- src/widgets/tokens-balances/index.ts | 6 ++++- .../tokens-balances/ui/tokens-balances.scss | 13 +++++++++ .../tokens-balances/ui/tokens-balances.tsx | 12 +++++++-- 17 files changed, 104 insertions(+), 98 deletions(-) create mode 100644 src/widgets/tokens-balances/ui/tokens-balances.scss diff --git a/src/entities/job/ui/jobs-table.scss b/src/entities/job/ui/jobs-table.scss index f481a03b..be6da1e7 100644 --- a/src/entities/job/ui/jobs-table.scss +++ b/src/entities/job/ui/jobs-table.scss @@ -1,18 +1,29 @@ @use "sass/color"; +@use "sass/font"; @use "sass/size"; .JobsTable { - &-body { - .Table-row-content--compact:last-of-type { - align-items: flex-start; + grid-area: JobsTable; - & > span { - &:first-of-type { - position: absolute; + &-body { + .Table-row-content--compact { + &:not(&:first-of-type) { + span:last-of-type { + font-family: font.$code; } + } + + &:last-of-type { + align-items: flex-start; + + & > span { + &:first-of-type { + position: absolute; + } - &:last-of-type { - width: 100%; + &:last-of-type { + width: 100%; + } } } } diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index fa9ce01f..4ec9edce 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -16,7 +16,7 @@ export const JobsTable = ({ className, contracts }: JobsTableProps) => { return ( , DaoConfigEditorWidget.Dependencies {} +interface DaoConfigTabUIProps extends HTMLProps, DaoConfigEditorWidget.Dependencies {} const _DaoConfigTab = "DaoConfigTab"; -const DaoConfigTabComponent = ({ className, ...props }: DaoConfigTabComponentProps) => ( -
      - +const DaoConfigTabUI = ({ className, daoContractAddress, multicallContract, ...props }: DaoConfigTabUIProps) => ( +
      +
      ); export const DaoConfigTab = { - connect: (props: DaoConfigTabComponentProps) => ({ - content: , + uiConnect: (props: DaoConfigTabUIProps) => ({ + content: , name: "Config", }), }; diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 1c6cfb87..75d1bf77 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -402,13 +402,13 @@ export class DaoPage extends Component { ); diff --git a/src/pages/dao/funds/funds.scss b/src/pages/dao/funds/funds.scss index 46ea984b..d84793ef 100644 --- a/src/pages/dao/funds/funds.scss +++ b/src/pages/dao/funds/funds.scss @@ -1,21 +1,9 @@ -@use "sass/color"; -@use "sass/font"; -@use "sass/mixin"; -@use "sass/size"; - .DaoFundsTab { display: grid; - grid-template: "tokenBalances" 1fr / 1fr; - - &-tokenBalances { - grid-area: tokenBalances; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr 1fr; - .Table-row-content--compact { - &:not(&:first-of-type) { - span:last-of-type { - font-family: font.$code; - } - } - } - } + grid-template-areas: + "TokensBalances TokensBalances" + "TokensBalances TokensBalances"; } diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index 5295ef83..5ede9fbb 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -1,26 +1,26 @@ import clsx from "clsx"; -import { ComponentProps, HTMLProps } from "react"; +import { HTMLProps } from "react"; -import { TokensBalances } from "../../../widgets"; +import { TokensBalances, type TokensBalancesWidget } from "../../../widgets"; import "./funds.scss"; -interface DaoFundsTabComponentProps extends HTMLProps, ComponentProps {} +interface DaoFundsTabUIProps extends HTMLProps, TokensBalancesWidget.Dependencies {} const _DaoFundsTab = "DaoFundsTab"; -const DaoFundsTabComponent = ({ className, contracts }: DaoFundsTabComponentProps) => ( -
      - +const DaoFundsTabUI = ({ className, contracts, ...props }: DaoFundsTabUIProps) => ( +
      +
      ); export const DaoFundsTab = { - connect: (props: DaoFundsTabComponentProps) => ({ - content: , + uiConnect: (props: DaoFundsTabUIProps) => ({ + content: , lazy: true, name: "Funds", }), diff --git a/src/pages/dao/jobs/jobs.scss b/src/pages/dao/jobs/jobs.scss index a17cc27f..5292825e 100644 --- a/src/pages/dao/jobs/jobs.scss +++ b/src/pages/dao/jobs/jobs.scss @@ -1,20 +1,9 @@ -@use "sass/color"; -@use "sass/font"; -@use "sass/size"; - .DaoJobsTab { display: grid; - grid-template: "jobsList " auto / 100%; - - &-jobsList { - grid-area: jobsList; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr 1fr; - .Table-row-content--compact { - &:not(&:first-of-type) { - span:last-of-type { - font-family: font.$code; - } - } - } - } + grid-template-areas: + "JobsTable JobsTable" + "JobsTable JobsTable"; } diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 3ce186af..7e3fef00 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -5,22 +5,22 @@ import { Job } from "../../../entities"; import "./jobs.scss"; -interface DaoJobsTabComponentProps extends HTMLProps, ComponentProps {} +interface DaoJobsTabUIProps extends HTMLProps, ComponentProps {} const _DaoJobsTab = "DaoJobsTab"; -const DaoJobsTabComponent = ({ className, contracts }: DaoJobsTabComponentProps) => ( -
      - +const DaoJobsTabUI = ({ className, contracts, ...props }: DaoJobsTabUIProps) => ( +
      +
      ); export const DaoJobsTab = { - connect: (props: DaoJobsTabComponentProps) => ({ - content: , + uiConnect: (props: DaoJobsTabUIProps) => ({ + content: , lazy: true, name: "Jobs", }), diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index 7fd6d45f..4dbb44c6 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -7,7 +7,8 @@ import "./tile.scss"; const _Tile = "Tile"; -export interface TileProps extends PropsWithChildren, HTMLAttributes { +export interface TileProps extends PropsWithChildren, Omit, "className"> { + classes?: Partial["className"]>>; error?: Error | null; heading?: string | null; headingSlotsContent?: { left?: JSX.Element; right?: JSX.Element }; @@ -17,16 +18,16 @@ export interface TileProps extends PropsWithChildren, HTMLAttributes ( -
      +
      {heading && ( - + {headingSlotsContent?.left && ( {headingSlotsContent?.left} )} @@ -39,9 +40,8 @@ export const Tile = ({ )} -
      +
      {loading &&
      } - {!loading && noData && } {!loading && error && ( diff --git a/src/widgets/dao-config-editor/ui/dao-config-editor.scss b/src/widgets/dao-config-editor/ui/dao-config-editor.scss index d2b51503..6630faa3 100644 --- a/src/widgets/dao-config-editor/ui/dao-config-editor.scss +++ b/src/widgets/dao-config-editor/ui/dao-config-editor.scss @@ -4,6 +4,7 @@ @use "sass/size"; .DaoConfigEditor { + grid-area: DaoConfigEditor; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 6fr 4fr; diff --git a/src/widgets/dao-config-editor/ui/dao-config-editor.tsx b/src/widgets/dao-config-editor/ui/dao-config-editor.tsx index 7fe60f98..23e2c064 100644 --- a/src/widgets/dao-config-editor/ui/dao-config-editor.tsx +++ b/src/widgets/dao-config-editor/ui/dao-config-editor.tsx @@ -12,13 +12,11 @@ import { type DaoConfigEditorWidget } from "../config"; import "./dao-config-editor.scss"; +interface DaoConfigEditorUIProps extends DaoConfigEditorWidget.Dependencies {} + const _DaoConfigEditor = "DaoConfigEditor"; -export const DaoConfigEditorUI = ({ - className, - daoContractAddress, - multicallContract, -}: DaoConfigEditorWidget.Dependencies) => { +export const DaoConfigEditorUI = ({ className, daoContractAddress, multicallContract }: DaoConfigEditorUIProps) => { const [editMode, editModeSwitch] = useState(false), [tokensWhitelistEditMode, tokensWhitelistEditModeSwitch] = useState(false), [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); @@ -108,7 +106,7 @@ export const DaoConfigEditorUI = ({ />

      Croncat manager

      @@ -157,7 +155,7 @@ export const DaoConfigEditorUI = ({
      diff --git a/src/widgets/tokens-balances/index.ts b/src/widgets/tokens-balances/index.ts index 6a67baf8..7302c7c4 100644 --- a/src/widgets/tokens-balances/index.ts +++ b/src/widgets/tokens-balances/index.ts @@ -1,4 +1,8 @@ -import { TokensBalances } from "./ui/tokens-balances"; +import { TokensBalancesUI } from "./ui/tokens-balances"; import { type TokensBalancesWidget } from "./config"; +class TokensBalances { + static UI = TokensBalancesUI; +} + export { TokensBalances, type TokensBalancesWidget }; diff --git a/src/widgets/tokens-balances/ui/tokens-balances.scss b/src/widgets/tokens-balances/ui/tokens-balances.scss new file mode 100644 index 00000000..c71c356f --- /dev/null +++ b/src/widgets/tokens-balances/ui/tokens-balances.scss @@ -0,0 +1,13 @@ +@use "sass/font"; + +.TokensBalances { + grid-area: TokensBalances; + + .Table-row-content--compact { + &:not(&:first-of-type) { + span:last-of-type { + font-family: font.$code; + } + } + } +} diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index d8e4bc8d..74425f87 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -1,15 +1,23 @@ +import clsx from "clsx"; + import { Tile, Scrollable, Table } from "../../../shared/ui/components"; import { FungibleToken, NearToken } from "../../../entities"; import { type TokensBalancesWidget } from "../config"; -export const TokensBalances = ({ className, contracts }: TokensBalancesWidget.Dependencies) => { +import "./tokens-balances.scss"; + +interface TokensBalancesUIProps extends TokensBalancesWidget.Dependencies {} + +const _TokensBalances = "TokensBalances"; + +export const TokensBalancesUI = ({ className, contracts }: TokensBalancesUIProps) => { const nearTokenBalances = NearToken.balancesRender({ contracts }), fungibleTokensBalances = FungibleToken.allBalancesRender({ contracts }); return ( {(nearTokenBalances ?? fungibleTokensBalances) && ( From 7a50aa1abb5374a03fc2c367286ccd2167d68412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 12:01:17 +0400 Subject: [PATCH 288/537] wip: Implement placeholder function --- src/shared/lib/fn.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/shared/lib/fn.ts diff --git a/src/shared/lib/fn.ts b/src/shared/lib/fn.ts new file mode 100644 index 00000000..da630951 --- /dev/null +++ b/src/shared/lib/fn.ts @@ -0,0 +1,5 @@ +const returnVoid = () => {}; + +export const Fn = { + returnVoid, +}; From 20cd52ea2ea5f3bfb00b6e1ef62f7bbf2288da16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 12:09:41 +0400 Subject: [PATCH 289/537] wip: Expose table props --- src/shared/ui/components/index.ts | 2 +- src/shared/ui/components/table/index.ts | 2 +- src/shared/ui/components/table/table.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index 7280fc56..eceff58b 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -17,5 +17,5 @@ export { Tile, type TileProps } from "./tile"; export { DataInspector } from "./data-inspector"; export { DateTimePicker, type DateTimePickerProps } from "./date-time-picker"; export { Dialog } from "./dialog"; -export { Table } from "./table"; +export { Table, type TableProps } from "./table"; export { Tabs } from "./tabs"; diff --git a/src/shared/ui/components/table/index.ts b/src/shared/ui/components/table/index.ts index 8efc4312..e78abecf 100644 --- a/src/shared/ui/components/table/index.ts +++ b/src/shared/ui/components/table/index.ts @@ -1 +1 @@ -export { Table } from "./table"; +export { Table, type TableProps } from "./table"; diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 43e6f9cc..5722dd4b 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -13,7 +13,7 @@ import { HTMLAttributes } from "react"; import { TableRowCard, TableRow, type TableRowProps } from "./row"; import "./table.scss"; -interface TableProps extends HTMLAttributes, Pick { +export interface TableProps extends HTMLAttributes, Pick { /** * `"classic"` mode is a classic table view. * From 9b71de561fdcdac587ac2cff5d4a2353cb062277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 13:13:02 +0400 Subject: [PATCH 290/537] wip: Eliminate naming overhead --- src/entities/job/model/{jobs-data.ts => job.ts} | 10 +++++----- src/entities/job/ui/{job-entry.scss => job.scss} | 0 src/entities/job/ui/{job-entry.tsx => job.tsx} | 2 +- src/entities/job/ui/jobs-table.tsx | 6 +++--- src/entities/multicall/model/mc-admins.ts | 12 ++++++------ src/entities/multicall/model/mc-tokens.ts | 6 +++--- src/entities/multicall/ui/mc-admins.tsx | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) rename src/entities/job/model/{jobs-data.ts => job.ts} (79%) rename src/entities/job/ui/{job-entry.scss => job.scss} (100%) rename src/entities/job/ui/{job-entry.tsx => job.tsx} (98%) diff --git a/src/entities/job/model/jobs-data.ts b/src/entities/job/model/job.ts similarity index 79% rename from src/entities/job/model/jobs-data.ts rename to src/entities/job/model/job.ts index 0137b217..f2a88ae1 100644 --- a/src/entities/job/model/jobs-data.ts +++ b/src/entities/job/model/job.ts @@ -3,17 +3,17 @@ import { useEffect, useState } from "react"; import { type JobEntity } from "../config"; import { JobNormalized } from "../lib/job-normalized"; -type JobAllEntriesFetchFxResponse = { +type JobAllEntries = { /** Jobs indexed by ID for easy access to each particular job */ data: Record | null; error?: Error | null; loading: boolean; }; -export class JobDataModel { +export class JobModel { static allEntriesFetchFx = async ( { multicall }: JobEntity.Dependencies["contracts"], - callback: (result: JobAllEntriesFetchFxResponse) => void + callback: (result: JobAllEntries) => void ) => callback( await multicall @@ -38,9 +38,9 @@ export class JobDataModel { ); static useAllEntries = (contracts: JobEntity.Dependencies["contracts"]) => { - const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); + const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - useEffect(() => void JobDataModel.allEntriesFetchFx(contracts, stateUpdate), [contracts, stateUpdate]); + useEffect(() => void JobModel.allEntriesFetchFx(contracts, stateUpdate), [contracts, stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/job/ui/job-entry.scss b/src/entities/job/ui/job.scss similarity index 100% rename from src/entities/job/ui/job-entry.scss rename to src/entities/job/ui/job.scss diff --git a/src/entities/job/ui/job-entry.tsx b/src/entities/job/ui/job.tsx similarity index 98% rename from src/entities/job/ui/job-entry.tsx rename to src/entities/job/ui/job.tsx index 336a7f78..d8fc03d3 100644 --- a/src/entities/job/ui/job-entry.tsx +++ b/src/entities/job/ui/job.tsx @@ -4,7 +4,7 @@ import { Big, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/components"; import { JobConfig, type JobEntity } from "../config"; -import "./job-entry.scss"; +import "./job.scss"; interface JobEntryProps extends JobEntity.DataWithStatus {} diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 4ec9edce..b47c8588 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -1,10 +1,10 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/components"; -import { JobDataModel } from "../model/jobs-data"; +import { JobModel } from "../model/job"; import { type JobEntity } from "../config"; -import { jobTableRow } from "./job-entry"; +import { jobTableRow } from "./job"; import "./jobs-table.scss"; interface JobsTableProps extends JobEntity.Dependencies {} @@ -12,7 +12,7 @@ interface JobsTableProps extends JobEntity.Dependencies {} const _JobsTable = "JobsTable"; export const JobsTable = ({ className, contracts }: JobsTableProps) => { - const { data, error, loading } = JobDataModel.useAllEntries(contracts); + const { data, error, loading } = JobModel.useAllEntries(contracts); return ( void + callback: (result: MulticallAdminsAddressList) => void ) => await MulticallContract.instanceDataFetchFx( `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) ); - static useAllEntries = (daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"]) => { - const [state, stateUpdate] = useState({ + static useAddressList = (daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"]) => { + const [state, stateUpdate] = useState({ data: null, error: null, loading: true, }); useEffect( - () => void MulticallAdminsModel.allEntriesFetchFx(daoContractAddress, stateUpdate), + () => void MulticallAdminsModel.addressListFetchFx(daoContractAddress, stateUpdate), [daoContractAddress, stateUpdate] ); diff --git a/src/entities/multicall/model/mc-tokens.ts b/src/entities/multicall/model/mc-tokens.ts index d4c19dac..e5c862c0 100644 --- a/src/entities/multicall/model/mc-tokens.ts +++ b/src/entities/multicall/model/mc-tokens.ts @@ -6,7 +6,7 @@ import { Props } from "../../../shared/lib/props"; import { type MulticallEntity } from "../config"; -type MulticallTokensWhitelistFetchFxResponse = { +export type MulticallTokensWhitelist = { data: MulticallContract["tokensWhitelist"] | null; error: Error | null; loading: boolean; @@ -15,7 +15,7 @@ type MulticallTokensWhitelistFetchFxResponse = { export class MulticallTokensModel { static whitelistFetchFx = async ( daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"], - callback: (result: MulticallTokensWhitelistFetchFxResponse) => void + callback: (result: MulticallTokensWhitelist) => void ) => await MulticallContract.instanceDataFetchFx( `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, @@ -25,7 +25,7 @@ export class MulticallTokensModel { ); static useWhitelist = (daoContractAddress: MulticallEntity.Dependencies["daoContractAddress"]) => { - const [state, stateUpdate] = useState({ + const [state, stateUpdate] = useState({ data: null, error: null, loading: true, diff --git a/src/entities/multicall/ui/mc-admins.tsx b/src/entities/multicall/ui/mc-admins.tsx index 1d863e91..cc96c981 100644 --- a/src/entities/multicall/ui/mc-admins.tsx +++ b/src/entities/multicall/ui/mc-admins.tsx @@ -13,7 +13,7 @@ interface MulticallAdminsTableProps extends MulticallEntity.Dependencies { const _MulticallAdminsTable = "MulticallAdminsTable"; export const MulticallAdminsTable = ({ className, daoContractAddress }: MulticallAdminsTableProps) => { - const { data, error, loading } = MulticallAdminsModel.useAllEntries(daoContractAddress); + const { data, error, loading } = MulticallAdminsModel.useAddressList(daoContractAddress); return ( Date: Fri, 21 Oct 2022 15:36:17 +0400 Subject: [PATCH 291/537] wip: Add footer slot to tile --- src/shared/ui/components/tile/tile.scss | 8 +++++++- src/shared/ui/components/tile/tile.tsx | 18 +++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/shared/ui/components/tile/tile.scss b/src/shared/ui/components/tile/tile.scss index 335ac350..6fede9b7 100644 --- a/src/shared/ui/components/tile/tile.scss +++ b/src/shared/ui/components/tile/tile.scss @@ -22,7 +22,7 @@ font-size: size.$large-text; } - &-slot { + &-corner { &--left, &--right { .MuiButtonBase-root { @@ -44,4 +44,10 @@ height: 100%; overflow: hidden; } + + &-footer { + display: flex; + justify-content: center; + margin-top: auto; + } } diff --git a/src/shared/ui/components/tile/tile.tsx b/src/shared/ui/components/tile/tile.tsx index 4dbb44c6..e581525e 100644 --- a/src/shared/ui/components/tile/tile.tsx +++ b/src/shared/ui/components/tile/tile.tsx @@ -8,10 +8,11 @@ import "./tile.scss"; const _Tile = "Tile"; export interface TileProps extends PropsWithChildren, Omit, "className"> { - classes?: Partial["className"]>>; + classes?: Partial["className"]>>; error?: Error | null; + footer?: JSX.Element | null; heading?: string | null; - headingSlotsContent?: { left?: JSX.Element; right?: JSX.Element }; + headingCorners?: { left?: JSX.Element; right?: JSX.Element }; loading?: boolean; noData?: boolean; } @@ -20,22 +21,23 @@ export const Tile = ({ children, classes, error, + footer, heading, - headingSlotsContent, + headingCorners, loading = false, noData = false, }: TileProps) => (
      {heading && ( - {headingSlotsContent?.left && ( - {headingSlotsContent?.left} + {headingCorners?.left && ( + {headingCorners?.left} )}

      {heading}

      - {headingSlotsContent?.right && ( - {headingSlotsContent?.right} + {headingCorners?.right && ( + {headingCorners?.right} )}
      )} @@ -53,5 +55,7 @@ export const Tile = ({ {!loading && !noData && !error && children}
      + + {footer &&
      {footer}
      }
      ); From 42a8529250a2fc16716a647c3feb1fc1e6686372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 15:36:42 +0400 Subject: [PATCH 292/537] wip: Update multicall contract types --- src/shared/lib/contracts/multicall.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 4635728e..23b1852f 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -1,6 +1,9 @@ +import { Account } from "near-api-js"; + import { type Tx, viewAccount, viewState, view } from "../wallet"; import { Big, toGas, dateToCron, toYocto } from "../converter"; import { ArgsAccount } from "../args"; +import { FungibleToken } from "../standards/fungibleToken"; import type { FunctionCallAction as daoFunctionCallAction, SputnikDAOContract } from "./sputnik-dao"; @@ -42,6 +45,10 @@ type JobData = { }; }; +type MulticallAdminData = Account["accountId"]; + +type WhitelistedTokenData = FungibleToken["address"]; + type FunctionCall = { func: string; args: string; // base64 encoded JSON args @@ -72,10 +79,10 @@ class Multicall { static CRONCAT_FEE: string = toYocto("0.0275"); address: string; - admins: string[] = []; + admins: MulticallAdminData[] = []; croncatManager: string = ""; // only whitelisted tokens can be attached to multicalls or job activations. - tokensWhitelist: string[] = []; + tokensWhitelist: WhitelistedTokenData[] = []; // job bond amount must be attached as deposit when adding new jobs. // needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). jobBond: string = ""; From 27f61bb64868687396a6f05443d6fd7c86e38246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 16:52:19 +0400 Subject: [PATCH 293/537] wip: Update multicall tokens whitelist --- .../multicall/ui/mc-tokens-whitelist.tsx | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/entities/multicall/ui/mc-tokens-whitelist.tsx b/src/entities/multicall/ui/mc-tokens-whitelist.tsx index 9bccb020..2807a924 100644 --- a/src/entities/multicall/ui/mc-tokens-whitelist.tsx +++ b/src/entities/multicall/ui/mc-tokens-whitelist.tsx @@ -1,15 +1,18 @@ import clsx from "clsx"; -import { Scrollable, Table, Tile } from "../../../shared/ui/components"; +import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; +import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/components"; import { MulticallTokensModel } from "../model/mc-tokens"; import { type MulticallEntity } from "../config"; import { multicallWhitelistedTokenTableRow } from "./mc-whitelisted-token"; -interface MulticallTokensWhitelistTableProps extends MulticallEntity.Dependencies { - additionalItems?: JSX.Element[][]; +interface MulticallTokensWhitelistTableProps + extends MulticallEntity.Dependencies, + Pick { + additionalItems?: FungibleToken["address"][]; className?: string; - toolbarContent?: JSX.Element; + customItemRenderer?: (item: FungibleToken["address"]) => JSX.Element[]; } const _MulticallTokensWhitelistTable = "MulticallTokensWhitelistTable"; @@ -17,8 +20,10 @@ const _MulticallTokensWhitelistTable = "MulticallTokensWhitelistTable"; export const MulticallTokensWhitelistTable = ({ additionalItems, className, + customItemRenderer, daoContractAddress, - toolbarContent, + footer, + headingCorners, }: MulticallTokensWhitelistTableProps) => { const { data, error, loading } = MulticallTokensModel.useWhitelist(daoContractAddress); @@ -26,9 +31,8 @@ export const MulticallTokensWhitelistTable = ({
    From 22242bf933bd0034d7611cef0abf73c52e5d65ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 21 Oct 2022 17:03:09 +0400 Subject: [PATCH 294/537] wip: Update config editor --- src/pages/dao/config/config.scss | 4 +- src/pages/dao/config/config.tsx | 6 +- src/widgets/dao-config-editor/index.ts | 8 -- src/widgets/index.ts | 2 +- .../config.ts | 6 +- src/widgets/multicall-config-editor/index.ts | 8 ++ .../ui/multicall-config-editor.scss} | 4 +- .../ui/multicall-config-editor.tsx} | 110 +++++++++--------- 8 files changed, 75 insertions(+), 73 deletions(-) delete mode 100644 src/widgets/dao-config-editor/index.ts rename src/widgets/{dao-config-editor => multicall-config-editor}/config.ts (71%) create mode 100644 src/widgets/multicall-config-editor/index.ts rename src/widgets/{dao-config-editor/ui/dao-config-editor.scss => multicall-config-editor/ui/multicall-config-editor.scss} (92%) rename src/widgets/{dao-config-editor/ui/dao-config-editor.tsx => multicall-config-editor/ui/multicall-config-editor.tsx} (63%) diff --git a/src/pages/dao/config/config.scss b/src/pages/dao/config/config.scss index 8d8f16d6..e91e89ea 100644 --- a/src/pages/dao/config/config.scss +++ b/src/pages/dao/config/config.scss @@ -4,6 +4,6 @@ grid-template-rows: 1fr 1fr; grid-template-areas: - "DaoConfigEditor DaoConfigEditor" - "DaoConfigEditor DaoConfigEditor"; + "MulticallConfigEditor MulticallConfigEditor" + "MulticallConfigEditor MulticallConfigEditor"; } diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index bf94a7c6..f247faf7 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -1,11 +1,11 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { DaoConfigEditor, type DaoConfigEditorWidget } from "../../../widgets"; +import { MulticallConfigEditor, type MulticallConfigEditorWidget } from "../../../widgets"; import "./config.scss"; -interface DaoConfigTabUIProps extends HTMLProps, DaoConfigEditorWidget.Dependencies {} +interface DaoConfigTabUIProps extends HTMLProps, MulticallConfigEditorWidget.Dependencies {} const _DaoConfigTab = "DaoConfigTab"; @@ -14,7 +14,7 @@ const DaoConfigTabUI = ({ className, daoContractAddress, multicallContract, ...p className={clsx(_DaoConfigTab, className)} {...props} > - + ); diff --git a/src/widgets/dao-config-editor/index.ts b/src/widgets/dao-config-editor/index.ts deleted file mode 100644 index a8cc27fa..00000000 --- a/src/widgets/dao-config-editor/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { DaoConfigEditorConfig, type DaoConfigEditorWidget } from "./config"; -import { DaoConfigEditorUI } from "./ui/dao-config-editor"; - -class DaoConfigEditor extends DaoConfigEditorConfig { - static UI = DaoConfigEditorUI; -} - -export { DaoConfigEditor, type DaoConfigEditorWidget }; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 28a1c50f..97489170 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -1,9 +1,9 @@ export { Column } from "./column/column.jsx"; -export { DaoConfigEditor, type DaoConfigEditorWidget } from "./dao-config-editor"; export { DialogsLayer } from "./dialogs-layer"; export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export/export.jsx"; +export { MulticallConfigEditor, type MulticallConfigEditorWidget } from "./multicall-config-editor"; export { Sidebar } from "./sidebar/sidebar.jsx"; export { TokensBalances, type TokensBalancesWidget } from "./tokens-balances"; diff --git a/src/widgets/dao-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts similarity index 71% rename from src/widgets/dao-config-editor/config.ts rename to src/widgets/multicall-config-editor/config.ts index 174ed6ce..2686b1e6 100644 --- a/src/widgets/dao-config-editor/config.ts +++ b/src/widgets/multicall-config-editor/config.ts @@ -3,13 +3,13 @@ import { HTMLProps } from "react"; import { MulticallContract } from "../../shared/lib/contracts/multicall"; import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; -namespace DaoConfigEditorWidget { +namespace MulticallConfigEditorWidget { export interface Dependencies extends HTMLProps { daoContractAddress: SputnikDAOContract["address"]; multicallContract: MulticallContract; } } -class DaoConfigEditorConfig {} +class MulticallConfigEditorConfig {} -export { DaoConfigEditorConfig, type DaoConfigEditorWidget }; +export { MulticallConfigEditorConfig, type MulticallConfigEditorWidget }; diff --git a/src/widgets/multicall-config-editor/index.ts b/src/widgets/multicall-config-editor/index.ts new file mode 100644 index 00000000..a6579d03 --- /dev/null +++ b/src/widgets/multicall-config-editor/index.ts @@ -0,0 +1,8 @@ +import { MulticallConfigEditorConfig, type MulticallConfigEditorWidget } from "./config"; +import { MulticallConfigEditorUI } from "./ui/multicall-config-editor"; + +class MulticallConfigEditor extends MulticallConfigEditorConfig { + static UI = MulticallConfigEditorUI; +} + +export { MulticallConfigEditor, type MulticallConfigEditorWidget }; diff --git a/src/widgets/dao-config-editor/ui/dao-config-editor.scss b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss similarity index 92% rename from src/widgets/dao-config-editor/ui/dao-config-editor.scss rename to src/widgets/multicall-config-editor/ui/multicall-config-editor.scss index 6630faa3..70639ce9 100644 --- a/src/widgets/dao-config-editor/ui/dao-config-editor.scss +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss @@ -3,8 +3,8 @@ @use "sass/mixin"; @use "sass/size"; -.DaoConfigEditor { - grid-area: DaoConfigEditor; +.MulticallConfigEditor { + grid-area: MulticallConfigEditor; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 6fr 4fr; diff --git a/src/widgets/dao-config-editor/ui/dao-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx similarity index 63% rename from src/widgets/dao-config-editor/ui/dao-config-editor.tsx rename to src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index 23e2c064..c26a0965 100644 --- a/src/widgets/dao-config-editor/ui/dao-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -8,17 +8,21 @@ import { ArgsString } from "../../../shared/lib/args"; import { type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; import { toNEAR } from "../../../shared/lib/converter"; import { Button, ButtonGroup, NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; -import { type DaoConfigEditorWidget } from "../config"; +import { type MulticallConfigEditorWidget } from "../config"; -import "./dao-config-editor.scss"; +import "./multicall-config-editor.scss"; -interface DaoConfigEditorUIProps extends DaoConfigEditorWidget.Dependencies {} +interface MulticallConfigEditorUIProps extends MulticallConfigEditorWidget.Dependencies {} -const _DaoConfigEditor = "DaoConfigEditor"; +const _MulticallConfigEditor = "MulticallConfigEditor"; -export const DaoConfigEditorUI = ({ className, daoContractAddress, multicallContract }: DaoConfigEditorUIProps) => { +export const MulticallConfigEditorUI = ({ + className, + daoContractAddress, + multicallContract, +}: MulticallConfigEditorUIProps) => { const [editMode, editModeSwitch] = useState(false), - [tokensWhitelistEditMode, tokensWhitelistEditModeSwitch] = useState(false), + [tokensWhitelistAddMode, tokensWhitelistAddModeSwitch] = useState(false), [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); const changesDiffInitialState = { @@ -35,24 +39,26 @@ export const DaoConfigEditorUI = ({ className, daoContractAddress, multicallCont update: { reset?: boolean; field?: keyof MulticallConfigChanges; - value?: MulticallConfigChanges[keyof MulticallConfigChanges]; + value?: string; } - ): MulticallConfigChanges => - update.reset - ? changesDiffInitialState - : { - ...previousState, - - ...(update.field && update.value - ? { - [update.field as keyof MulticallConfigChanges]: Array.isArray(update.value) - ? (previousState[update.field as keyof MulticallConfigChanges] as string[]).concat( - update.value - ) - : update.value, - } - : {}), - }, + ): MulticallConfigChanges => { + if (update.reset) { + return changesDiffInitialState; + } else { + return Object.assign( + previousState, + + update.field && + update.value && { + [update.field]: Array.isArray(previousState[update.field]) + ? previousState[update.field].includes(update.value) + ? previousState[update.field] + : previousState[update.field].concat(update.value) + : update.value, + } + ); + } + }, changesDiffInitialState ); @@ -60,53 +66,42 @@ export const DaoConfigEditorUI = ({ className, daoContractAddress, multicallCont console.log(changesDiff); return ( -
    +
    - changesDiffUpdate({ field: "addTokens", value: event.target.value }) - } - />, - ] - : [] - )} - className={`${_DaoConfigEditor}-tokensWhitelist`} + additionalItems={changesDiff.addTokens} + className={`${_MulticallConfigEditor}-tokensWhitelist`} daoContractAddress={daoContractAddress} - toolbarContent={ - tokensWhitelistEditMode ? ( - { - editModeSwitch(true); - tokensWhitelistEditModeSwitch(false); + footer={ + tokensWhitelistAddMode ? ( + { + changesDiffUpdate({ field: "addTokens", value: event.target.value }); + tokensWhitelistAddModeSwitch(false); }} - > - - - ) : ( + /> + ) : null + } + headingCorners={{ + right: ( { editModeSwitch(true); - tokensWhitelistEditModeSwitch(true); + tokensWhitelistAddModeSwitch(true); }} > - ) - } + ), + }} />

    Croncat manager

    @@ -155,9 +150,16 @@ export const DaoConfigEditorUI = ({ className, daoContractAddress, multicallCont
    + {editMode && ( +
    +

    Description

    + +
    + )} + {!editMode ? (
    + + + ); +}; diff --git a/src/entities/multicall/ui/mc-tokens-whitelist.tsx b/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx similarity index 58% rename from src/entities/multicall/ui/mc-tokens-whitelist.tsx rename to src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx index 2f15f162..4d16382a 100644 --- a/src/entities/multicall/ui/mc-tokens-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx @@ -2,36 +2,34 @@ import clsx from "clsx"; import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/components"; -import { MulticallTokensModel } from "../model/mc-tokens"; -import { type MulticallEntity } from "../config"; +import { MITokensModel } from "../model/mi-tokens"; +import { type MIEntity } from "../config"; -import { multicallWhitelistedTokenTableRow } from "./mc-whitelisted-token"; +import { miWhitelistedTokenTableRowRender } from "./mi-whitelisted-token"; -interface MulticallTokensWhitelistTableProps - extends MulticallEntity.Dependencies, - Pick { +interface MITokensWhitelistTableProps extends MIEntity.Dependencies, Pick { ItemComponent?: TableProps["RowComponent"]; ItemCompactComponent?: TableProps["RowCompactComponent"]; additionalItems?: FungibleToken["address"][]; className?: string; } -const _MulticallTokensWhitelistTable = "MulticallTokensWhitelistTable"; +const _MITokensWhitelistTable = "MITokensWhitelistTable"; -export const MulticallTokensWhitelistTable = ({ +export const MITokensWhitelistTable = ({ ItemComponent, ItemCompactComponent, additionalItems, className, - ownerContractAddress, + controllerContractAddress, footer, headingCorners, -}: MulticallTokensWhitelistTableProps) => { - const { data, error, loading } = MulticallTokensModel.useWhitelist(ownerContractAddress); +}: MITokensWhitelistTableProps) => { + const { data, error, loading } = MITokensModel.useWhitelist(controllerContractAddress); return ( diff --git a/src/entities/multicall/ui/mc-whitelisted-token.tsx b/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx similarity index 60% rename from src/entities/multicall/ui/mc-whitelisted-token.tsx rename to src/entities/multicall-instance/ui/mi-whitelisted-token.tsx index aaee0e04..f283ca2f 100644 --- a/src/entities/multicall/ui/mc-whitelisted-token.tsx +++ b/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx @@ -1,11 +1,11 @@ import { ArgsAccount } from "../../../shared/lib/args"; import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; -interface MulticallWhitelistedTokenProps { +interface MIWhitelistedTokenProps { address: FungibleToken["address"]; } -const MulticallWhitelistedTokenEntry = ({ address }: MulticallWhitelistedTokenProps) => { +const MIWhitelistedTokenEntry = ({ address }: MIWhitelistedTokenProps) => { const addr = new ArgsAccount(address); return ( @@ -21,6 +21,6 @@ const MulticallWhitelistedTokenEntry = ({ address }: MulticallWhitelistedTokenPr ); }; -export const multicallWhitelistedTokenTableRow = (address: MulticallWhitelistedTokenProps["address"]) => [ - , +export const miWhitelistedTokenTableRowRender = (item: MIWhitelistedTokenProps["address"]) => [ + , ]; diff --git a/src/entities/multicall/config.ts b/src/entities/multicall/config.ts deleted file mode 100644 index f25f113b..00000000 --- a/src/entities/multicall/config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; - -namespace MulticallEntity { - export interface Dependencies { - ownerContractAddress: SputnikDAOContract["address"]; - } -} - -class MulticallConfig { - // all the constants must be grouped in objects whenever it's possible and stored here as static properties -} - -export { MulticallConfig, type MulticallEntity }; diff --git a/src/entities/multicall/index.ts b/src/entities/multicall/index.ts deleted file mode 100644 index 9cda6114..00000000 --- a/src/entities/multicall/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { MulticallConfig, type MulticallEntity } from "./config"; -import { MulticallAdminsTable } from "./ui/mc-admins"; -import { MulticallTokensWhitelistTable } from "./ui/mc-tokens-whitelist"; -import { multicallWhitelistedTokenTableRow } from "./ui/mc-whitelisted-token"; - -class Multicall extends MulticallConfig { - static AdminsTable = MulticallAdminsTable; - static TokensWhitelistTable = MulticallTokensWhitelistTable; - static whitelistedTokenTableRow = multicallWhitelistedTokenTableRow; -} - -export { Multicall, MulticallEntity }; diff --git a/src/entities/multicall/model/mc-admins.ts b/src/entities/multicall/model/mc-admins.ts deleted file mode 100644 index ab4f276f..00000000 --- a/src/entities/multicall/model/mc-admins.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { useEffect, useState } from "react"; - -import { ArgsAccount } from "../../../shared/lib/args"; -import { MulticallContract } from "../../../shared/lib/contracts/multicall"; -import { Props } from "../../../shared/lib/props"; - -import { type MulticallEntity } from "../config"; - -export type MulticallAdminsAddressList = { - data: MulticallContract["admins"] | null; - error: Error | null; - loading: boolean; -}; - -export class MulticallAdminsModel { - static addressListFetchFx = async ( - ownerContractAddress: MulticallEntity.Dependencies["ownerContractAddress"], - callback: (result: MulticallAdminsAddressList) => void - ) => - await MulticallContract.instanceDataFetchFx( - `${ArgsAccount.deconstructAddress(ownerContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, - (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) - ); - - static useAddressList = (ownerContractAddress: MulticallEntity.Dependencies["ownerContractAddress"]) => { - const [state, stateUpdate] = useState({ - data: null, - error: null, - loading: true, - }); - - useEffect( - () => void MulticallAdminsModel.addressListFetchFx(ownerContractAddress, stateUpdate), - [ownerContractAddress, stateUpdate] - ); - - return state; - }; -} diff --git a/src/entities/multicall/ui/mc-admins.tsx b/src/entities/multicall/ui/mc-admins.tsx deleted file mode 100644 index 3da5f694..00000000 --- a/src/entities/multicall/ui/mc-admins.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import clsx from "clsx"; - -import { Scrollable, Table, Tile } from "../../../shared/ui/components"; -import { MulticallAdminsModel } from "../model/mc-admins"; -import { type MulticallEntity } from "../config"; - -import { multicallAdminTableRow } from "./mc-admin-entry"; - -interface MulticallAdminsTableProps extends MulticallEntity.Dependencies { - className?: string; -} - -const _MulticallAdminsTable = "MulticallAdminsTable"; - -export const MulticallAdminsTable = ({ className, ownerContractAddress }: MulticallAdminsTableProps) => { - const { data, error, loading } = MulticallAdminsModel.useAddressList(ownerContractAddress); - - return ( - - -
    - - - ); -}; diff --git a/src/features/index.ts b/src/features/index.ts index e31ff1f7..f2ff6a89 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1 +1,2 @@ export { DappLogin } from "./dapp-login"; +export { MITokensWhitelistEdit } from "./multicall-instance/tokens-whitelist-edit"; diff --git a/src/features/multicall-instance/tokens-whitelist-edit/config.ts b/src/features/multicall-instance/tokens-whitelist-edit/config.ts new file mode 100644 index 00000000..9c52baca --- /dev/null +++ b/src/features/multicall-instance/tokens-whitelist-edit/config.ts @@ -0,0 +1,14 @@ +import { HTMLProps } from "react"; + +import { MIEntity } from "../../../entities"; + +namespace MITokensWhitelistEditFeature { + export interface Dependencies extends Omit, "onChange">, MIEntity.Dependencies { + onChange: (payload: { + toAdd: MIEntity.Token["address"][] | []; + toRemove: MIEntity.Token["address"][] | []; + }) => void; + } +} + +export { type MITokensWhitelistEditFeature }; diff --git a/src/features/multicall-instance/tokens-whitelist-edit/index.ts b/src/features/multicall-instance/tokens-whitelist-edit/index.ts new file mode 100644 index 00000000..71b489de --- /dev/null +++ b/src/features/multicall-instance/tokens-whitelist-edit/index.ts @@ -0,0 +1,8 @@ +import { type MITokensWhitelistEditFeature } from "./config"; +import { MITokensWhitelistEditForm } from "./ui/mi-tokens-whitelist-edit-form"; + +class MITokensWhitelistEdit { + static Form = MITokensWhitelistEditForm; +} + +export { MITokensWhitelistEdit, type MITokensWhitelistEditFeature }; diff --git a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx b/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx new file mode 100644 index 00000000..bda9187b --- /dev/null +++ b/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx @@ -0,0 +1,52 @@ +import { CancelOutlined, EditOutlined } from "@mui/icons-material"; +import { IconButton } from "@mui/material"; +import { useEffect, useReducer, useState } from "react"; + +import { TextInput } from "../../../../shared/ui/components"; +import { MI, MIEntity } from "../../../../entities"; +import { type MITokensWhitelistEditFeature } from "../config"; + +interface MITokensWhitelistEditFormProps extends MITokensWhitelistEditFeature.Dependencies {} + +export const MITokensWhitelistEditForm = ({ + className, + controllerContractAddress, + onChange, +}: MITokensWhitelistEditFormProps) => { + const [editModeEnabled, editModeSwitch] = useState(false); + + const [toAdd, markForAddition] = useReducer( + (previousState: MIEntity.Token["address"][], tokenAddress: MIEntity.Token["address"]) => + previousState.includes(tokenAddress) ? previousState : [...previousState, tokenAddress], + + [] + ); + + const [toRemove, markForRemoval] = useReducer( + (previousState: MIEntity.Token["address"][], tokenAddress: MIEntity.Token["address"]) => + previousState.includes(tokenAddress) ? previousState : [...previousState, tokenAddress], + + [] + ); + + useEffect(() => onChange({ toAdd, toRemove }), [toAdd, toRemove, onChange]); + + return ( + markForAddition(event.target.value)} /> : null} + headingCorners={{ + right: editModeEnabled ? ( + editModeSwitch(false)}> + + + ) : ( + editModeSwitch(true)}> + + + ), + }} + {...{ className, controllerContractAddress }} + /> + ); +}; diff --git a/src/pages/dao/config/config.scss b/src/pages/dao/config/config.scss index e91e89ea..0a12a77d 100644 --- a/src/pages/dao/config/config.scss +++ b/src/pages/dao/config/config.scss @@ -4,6 +4,6 @@ grid-template-rows: 1fr 1fr; grid-template-areas: - "MulticallConfigEditor MulticallConfigEditor" - "MulticallConfigEditor MulticallConfigEditor"; + "MIEntityConfigEditor MIEntityConfigEditor" + "MIEntityConfigEditor MIEntityConfigEditor"; } diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 5e4b5b02..707fc0ea 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -1,20 +1,20 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { MulticallConfigEditor, type MulticallConfigEditorWidget } from "../../../widgets"; +import { MIEntityConfigEditor, type MIEntityConfigEditorWidget } from "../../../widgets"; import "./config.scss"; -interface DaoConfigTabUIProps extends HTMLProps, MulticallConfigEditorWidget.Dependencies {} +interface DaoConfigTabUIProps extends HTMLProps, MIEntityConfigEditorWidget.Dependencies {} const _DaoConfigTab = "DaoConfigTab"; -const DaoConfigTabUI = ({ className, ownerContractAddress, multicallContract, ...props }: DaoConfigTabUIProps) => ( +const DaoConfigTabUI = ({ className, controllerContractAddress, multicallContract, ...props }: DaoConfigTabUIProps) => (
    - +
    ); diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 4d157da6..69dcba5a 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -404,7 +404,7 @@ export class DaoPage extends Component { items={[ DaoConfigTab.uiConnect({ className: `${_DaoPage}-content`, - ownerContractAddress: dao.address, + controllerContractAddress: dao.address, multicallContract: multicall, }), DaoFundsTab.uiConnect({ className: `${_DaoPage}-content`, contracts: { dao, multicall } }), diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index db0d48b9..f3b6dff1 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -65,7 +65,7 @@ type MulticallArgs = { calls: BatchCall[][]; }; -class MulticallConfigChanges { +class MIEntityConfigChanges { removeTokens: string[] = []; addTokens: string[] = []; jobBond: string = ""; @@ -134,16 +134,16 @@ class Multicall { * Calls the given callback with a result of multicall contract instantiation, * represented as stateful response. * - * @param ownerContractAddress DAO contract address + * @param controllerContractAddress DAO contract address * @param callback Stateful data fetch callback */ static instanceDataFetchFx = async ( - ownerContractAddress: SputnikDAOContract["address"], + controllerContractAddress: SputnikDAOContract["address"], callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void ) => callback( await Multicall.init( - `${ArgsAccount.deconstructAddress(ownerContractAddress).name}.${Multicall.FACTORY_ADDRESS}` + `${ArgsAccount.deconstructAddress(controllerContractAddress).name}.${Multicall.FACTORY_ADDRESS}` ) .then((multicallInstance) => ({ data: multicallInstance, @@ -184,7 +184,7 @@ class Multicall { * @param configDiff changes to current config of some multicall instance. * @returns actions that can be passed to JSON for DAO "add_proposal". */ - static configDiffToProposalActions(configDiff: MulticallConfigChanges): daoFunctionCallAction[] { + static configDiffToProposalActions(configDiff: MIEntityConfigChanges): daoFunctionCallAction[] { const { removeTokens, addTokens, jobBond, croncatManager } = configDiff; const actions: daoFunctionCallAction[] = []; @@ -312,4 +312,4 @@ class Multicall { } export { Multicall, Multicall as MulticallContract }; -export type { JobData, MulticallArgs, MulticallConfigChanges }; +export type { JobData, MulticallArgs, MIEntityConfigChanges }; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 97489170..c2f6b5bb 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -4,6 +4,6 @@ export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export/export.jsx"; -export { MulticallConfigEditor, type MulticallConfigEditorWidget } from "./multicall-config-editor"; +export { MIEntityConfigEditor, type MIEntityConfigEditorWidget } from "./multicall-config-editor"; export { Sidebar } from "./sidebar/sidebar.jsx"; export { TokensBalances, type TokensBalancesWidget } from "./tokens-balances"; diff --git a/src/widgets/multicall-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts index bf1b8c91..fa279a51 100644 --- a/src/widgets/multicall-config-editor/config.ts +++ b/src/widgets/multicall-config-editor/config.ts @@ -3,13 +3,13 @@ import { HTMLProps } from "react"; import { MulticallContract } from "../../shared/lib/contracts/multicall"; import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; -namespace MulticallConfigEditorWidget { +namespace MIEntityConfigEditorWidget { export interface Dependencies extends HTMLProps { - ownerContractAddress: SputnikDAOContract["address"]; + controllerContractAddress: SputnikDAOContract["address"]; multicallContract: MulticallContract; } } -class MulticallConfigEditorConfig {} +class MIEntityConfigEditorConfig {} -export { MulticallConfigEditorConfig, type MulticallConfigEditorWidget }; +export { MIEntityConfigEditorConfig, type MIEntityConfigEditorWidget }; diff --git a/src/widgets/multicall-config-editor/index.ts b/src/widgets/multicall-config-editor/index.ts index a6579d03..7c83e242 100644 --- a/src/widgets/multicall-config-editor/index.ts +++ b/src/widgets/multicall-config-editor/index.ts @@ -1,8 +1,8 @@ -import { MulticallConfigEditorConfig, type MulticallConfigEditorWidget } from "./config"; -import { MulticallConfigEditorUI } from "./ui/multicall-config-editor"; +import { MIEntityConfigEditorConfig, type MIEntityConfigEditorWidget } from "./config"; +import { MIEntityConfigEditorUI } from "./ui/multicall-config-editor"; -class MulticallConfigEditor extends MulticallConfigEditorConfig { - static UI = MulticallConfigEditorUI; +class MIEntityConfigEditor extends MIEntityConfigEditorConfig { + static UI = MIEntityConfigEditorUI; } -export { MulticallConfigEditor, type MulticallConfigEditorWidget }; +export { MIEntityConfigEditor, type MIEntityConfigEditorWidget }; diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss index 70639ce9..1f7ff99c 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss @@ -3,8 +3,8 @@ @use "sass/mixin"; @use "sass/size"; -.MulticallConfigEditor { - grid-area: MulticallConfigEditor; +.MIEntityConfigEditor { + grid-area: MIEntityConfigEditor; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 6fr 4fr; diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index c26a0965..c83c04d9 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -1,28 +1,36 @@ -import { AddOutlined, DeleteOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; +import { AddOutlined, CancelOutlined, DeleteOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; import clsx from "clsx"; import { useReducer, useState } from "react"; -import { Multicall } from "../../../entities"; +import { MI } from "../../../entities"; +import { MITokensWhitelistEdit } from "../../../features"; import { ArgsString } from "../../../shared/lib/args"; -import { type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; +import { type MIEntityConfigChanges } from "../../../shared/lib/contracts/multicall"; import { toNEAR } from "../../../shared/lib/converter"; -import { Button, ButtonGroup, NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; -import { type MulticallConfigEditorWidget } from "../config"; +import { + Button, + ButtonGroup, + NearIcons, + NearLink, + TableRowCompact, + TextInput, + Tile, +} from "../../../shared/ui/components"; +import { type MIEntityConfigEditorWidget } from "../config"; import "./multicall-config-editor.scss"; -interface MulticallConfigEditorUIProps extends MulticallConfigEditorWidget.Dependencies {} +interface MIEntityConfigEditorUIProps extends MIEntityConfigEditorWidget.Dependencies {} -const _MulticallConfigEditor = "MulticallConfigEditor"; +const _MIEntityConfigEditor = "MIEntityConfigEditor"; -export const MulticallConfigEditorUI = ({ +export const MIEntityConfigEditorUI = ({ className, - daoContractAddress, + controllerContractAddress, multicallContract, -}: MulticallConfigEditorUIProps) => { +}: MIEntityConfigEditorUIProps) => { const [editMode, editModeSwitch] = useState(false), - [tokensWhitelistAddMode, tokensWhitelistAddModeSwitch] = useState(false), [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); const changesDiffInitialState = { @@ -34,14 +42,14 @@ export const MulticallConfigEditorUI = ({ const [changesDiff, changesDiffUpdate] = useReducer( ( - previousState: MulticallConfigChanges, + previousState: MIEntityConfigChanges, update: { reset?: boolean; - field?: keyof MulticallConfigChanges; + field?: keyof MIEntityConfigChanges; value?: string; } - ): MulticallConfigChanges => { + ): MIEntityConfigChanges => { if (update.reset) { return changesDiffInitialState; } else { @@ -66,42 +74,20 @@ export const MulticallConfigEditorUI = ({ console.log(changesDiff); return ( -
    - + - { - changesDiffUpdate({ field: "addTokens", value: event.target.value }); - tokensWhitelistAddModeSwitch(false); - }} - /> - ) : null - } - headingCorners={{ - right: ( - { - editModeSwitch(true); - tokensWhitelistAddModeSwitch(true); - }} - > - - - ), - }} + {}} + {...{ controllerContractAddress }} />

    Croncat manager

    @@ -150,7 +136,7 @@ export const MulticallConfigEditorUI = ({
    {editMode && ( From 03462d9ec67e67778a28d47871c5f7feacf60b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 03:16:26 +0400 Subject: [PATCH 299/537] wip: Update config editing logic & styles --- src/entities/multicall-instance/config.ts | 4 +- .../tokens-whitelist-edit/config.ts | 5 +- .../ui/mi-tokens-whitelist-edit-form.tsx | 46 ++++--- .../ui/multicall-config-editor.scss | 7 +- .../ui/multicall-config-editor.tsx | 113 ++++++++---------- 5 files changed, 88 insertions(+), 87 deletions(-) diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/config.ts index 66a4d5a8..47a3f801 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/config.ts @@ -1,5 +1,5 @@ +import { type MulticallConfigChanges } from "../../shared/lib/contracts/multicall"; import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; -import { FungibleToken } from "../../shared/lib/standards/fungibleToken"; /** * Type declaration for Multicall Instance entity @@ -9,7 +9,7 @@ namespace MIEntity { controllerContractAddress: SputnikDAOContract["address"]; } - export type Token = FungibleToken; + export type ConfigChanges = MulticallConfigChanges; } /** diff --git a/src/features/multicall-instance/tokens-whitelist-edit/config.ts b/src/features/multicall-instance/tokens-whitelist-edit/config.ts index 9c52baca..9e0229e0 100644 --- a/src/features/multicall-instance/tokens-whitelist-edit/config.ts +++ b/src/features/multicall-instance/tokens-whitelist-edit/config.ts @@ -4,10 +4,7 @@ import { MIEntity } from "../../../entities"; namespace MITokensWhitelistEditFeature { export interface Dependencies extends Omit, "onChange">, MIEntity.Dependencies { - onChange: (payload: { - toAdd: MIEntity.Token["address"][] | []; - toRemove: MIEntity.Token["address"][] | []; - }) => void; + onEdit: (payload: Pick) => void; } } diff --git a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx b/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx index bda9187b..ac823b0a 100644 --- a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx +++ b/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx @@ -1,45 +1,61 @@ -import { CancelOutlined, EditOutlined } from "@mui/icons-material"; +import { CancelOutlined, DeleteOutlined, EditOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; -import { useEffect, useReducer, useState } from "react"; +import { useCallback, useEffect, useReducer, useState } from "react"; import { TextInput } from "../../../../shared/ui/components"; import { MI, MIEntity } from "../../../../entities"; import { type MITokensWhitelistEditFeature } from "../config"; +import { Fn } from "../../../../shared/lib/fn"; interface MITokensWhitelistEditFormProps extends MITokensWhitelistEditFeature.Dependencies {} export const MITokensWhitelistEditForm = ({ className, controllerContractAddress, - onChange, + disabled, + onEdit, }: MITokensWhitelistEditFormProps) => { - const [editModeEnabled, editModeSwitch] = useState(false); + const [editModeEnabled, editModeSwitch] = useState(!disabled); - const [toAdd, markForAddition] = useReducer( - (previousState: MIEntity.Token["address"][], tokenAddress: MIEntity.Token["address"]) => - previousState.includes(tokenAddress) ? previousState : [...previousState, tokenAddress], + const [addTokens, markForAddition] = useReducer( + (previousState: MIEntity.ConfigChanges["addTokens"], address: string | null) => + address === null ? [] : previousState.includes(address) ? previousState : [...previousState, address], [] ); - const [toRemove, markForRemoval] = useReducer( - (previousState: MIEntity.Token["address"][], tokenAddress: MIEntity.Token["address"]) => - previousState.includes(tokenAddress) ? previousState : [...previousState, tokenAddress], + const [removeTokens, markForRemoval] = useReducer( + (previousState: MIEntity.ConfigChanges["removeTokens"], address: string | null) => + address === null ? [] : previousState.includes(address) ? previousState : [...previousState, address], [] ); - useEffect(() => onChange({ toAdd, toRemove }), [toAdd, toRemove, onChange]); + const formReset = useCallback(() => { + editModeSwitch(false); + markForAddition(null); + markForRemoval(null); + }, []); + + useEffect(disabled ? formReset : Fn.returnVoid, [disabled, formReset]); + + useEffect(() => onEdit({ addTokens, removeTokens }), [addTokens, removeTokens, onEdit]); return ( markForAddition(event.target.value)} /> : null} headingCorners={{ right: editModeEnabled ? ( - editModeSwitch(false)}> - - + <> + editModeSwitch(false)}> + + + + + + + ) : ( editModeSwitch(true)}> diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss index 1f7ff99c..1f95765a 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss @@ -21,10 +21,13 @@ @include mixin.center-items(space-evenly, center); .ButtonGroup { - justify-content: center; - margin-top: 0; + display: none; } } + + p { + font-size: size.$text; + } } &-admins { diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index c83c04d9..6e740a67 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -1,22 +1,14 @@ -import { AddOutlined, CancelOutlined, DeleteOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; +import { EditOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; import clsx from "clsx"; -import { useReducer, useState } from "react"; +import { useCallback, useEffect, useReducer, useState } from "react"; import { MI } from "../../../entities"; import { MITokensWhitelistEdit } from "../../../features"; import { ArgsString } from "../../../shared/lib/args"; -import { type MIEntityConfigChanges } from "../../../shared/lib/contracts/multicall"; +import { type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; import { toNEAR } from "../../../shared/lib/converter"; -import { - Button, - ButtonGroup, - NearIcons, - NearLink, - TableRowCompact, - TextInput, - Tile, -} from "../../../shared/ui/components"; +import { Button, ButtonGroup, NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; import { type MIEntityConfigEditorWidget } from "../config"; import "./multicall-config-editor.scss"; @@ -33,7 +25,7 @@ export const MIEntityConfigEditorUI = ({ const [editMode, editModeSwitch] = useState(false), [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); - const changesDiffInitialState = { + const changesDiffInitialState: MulticallConfigChanges = { removeTokens: [], addTokens: [], jobBond: "", @@ -42,35 +34,37 @@ export const MIEntityConfigEditorUI = ({ const [changesDiff, changesDiffUpdate] = useReducer( ( - previousState: MIEntityConfigChanges, - - update: { - reset?: boolean; - field?: keyof MIEntityConfigChanges; - value?: string; - } - ): MIEntityConfigChanges => { - if (update.reset) { - return changesDiffInitialState; - } else { - return Object.assign( - previousState, - - update.field && - update.value && { - [update.field]: Array.isArray(previousState[update.field]) - ? previousState[update.field].includes(update.value) - ? previousState[update.field] - : previousState[update.field].concat(update.value) - : update.value, - } - ); - } - }, + previousState: typeof changesDiffInitialState, + update: Partial + ): MulticallConfigChanges => Object.assign(previousState, update), changesDiffInitialState ); + const formReset = useCallback( + () => changesDiffUpdate(changesDiffInitialState), + [changesDiffUpdate, changesDiffInitialState] + ); + + const onCancel = useCallback(() => { + formReset(); + editModeSwitch(false); + }, [editModeSwitch, formReset]); + + const onEdit = useCallback( + (update: Partial) => { + changesDiffUpdate(update); + + editModeSwitch( + JSON.stringify(Object.assign(changesDiff, update)) !== JSON.stringify(changesDiffInitialState) + ); + }, + + [changesDiffUpdate] + ); + + const onSubmit = useCallback(() => editModeSwitch(false), [editModeSwitch]); + console.log(changesDiff); return ( @@ -82,8 +76,8 @@ export const MIEntityConfigEditorUI = ({ {}} - {...{ controllerContractAddress }} + disabled={!editMode} + {...{ controllerContractAddress, onEdit }} /> changesDiffUpdate({ field: "croncatManager", value: event.target.value })} + onBlur={(event) => changesDiffUpdate({ croncatManager: event.target.value })} value={new ArgsString(multicallContract.croncatManager)} fullWidth /> @@ -123,7 +117,7 @@ export const MIEntityConfigEditorUI = ({ {editMode && ( changesDiffUpdate({ field: "jobBond", value: event.target.value })} + update={(event) => changesDiffUpdate({ jobBond: event.target.value })} type="number" value={ new ArgsString( @@ -139,39 +133,30 @@ export const MIEntityConfigEditorUI = ({ classes={{ content: clsx(`${_MIEntityConfigEditor}-proposalForm`, { "is-inEditMode": editMode }) }} heading={editMode ? "Changes proposal" : null} > + {!editMode &&

    To create config changes proposal template, start editing

    } + {editMode && ( -
    -

    Description

    - -
    - )} + <> +
    +

    Description

    + +
    - - {!editMode ? ( -
    ); From 6702ff8055f776795f25b0b2651be28f1a58dc6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 03:16:44 +0400 Subject: [PATCH 300/537] wip: Fix naming --- src/shared/lib/contracts/multicall.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index f3b6dff1..d2822452 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -65,7 +65,7 @@ type MulticallArgs = { calls: BatchCall[][]; }; -class MIEntityConfigChanges { +class MulticallConfigChanges { removeTokens: string[] = []; addTokens: string[] = []; jobBond: string = ""; @@ -312,4 +312,4 @@ class Multicall { } export { Multicall, Multicall as MulticallContract }; -export type { JobData, MulticallArgs, MIEntityConfigChanges }; +export type { JobData, MulticallArgs, MulticallConfigChanges }; From 4d40eb8151854a9d23d2e6db97994bd4f7d1c818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 03:21:54 +0400 Subject: [PATCH 301/537] wip: Add token address minimal length guard --- .../ui/mi-tokens-whitelist-edit-form.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx b/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx index ac823b0a..1b7e93aa 100644 --- a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx +++ b/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx @@ -19,7 +19,11 @@ export const MITokensWhitelistEditForm = ({ const [addTokens, markForAddition] = useReducer( (previousState: MIEntity.ConfigChanges["addTokens"], address: string | null) => - address === null ? [] : previousState.includes(address) ? previousState : [...previousState, address], + address === null + ? [] + : previousState.includes(address) || address.length < 1 + ? previousState + : [...previousState, address], [] ); From e27d217aa83dd1dc9f9cfa3b43927a35dbfde167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 05:16:12 +0400 Subject: [PATCH 302/537] wip: Handle mutual exclusion cases --- .../ui/mi-tokens-whitelist-edit-form.tsx | 69 ++++++++++++++----- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx b/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx index 1b7e93aa..b5b5289b 100644 --- a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx +++ b/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx @@ -3,9 +3,10 @@ import { IconButton } from "@mui/material"; import { useCallback, useEffect, useReducer, useState } from "react"; import { TextInput } from "../../../../shared/ui/components"; +import { Fn } from "../../../../shared/lib/fn"; +import { ArgsString } from "../../../../shared/lib/args"; import { MI, MIEntity } from "../../../../entities"; import { type MITokensWhitelistEditFeature } from "../config"; -import { Fn } from "../../../../shared/lib/fn"; interface MITokensWhitelistEditFormProps extends MITokensWhitelistEditFeature.Dependencies {} @@ -17,29 +18,51 @@ export const MITokensWhitelistEditForm = ({ }: MITokensWhitelistEditFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); - const [addTokens, markForAddition] = useReducer( - (previousState: MIEntity.ConfigChanges["addTokens"], address: string | null) => - address === null - ? [] - : previousState.includes(address) || address.length < 1 - ? previousState - : [...previousState, address], + const [addTokens, markForAddition] = useState([]); - [] - ); + const [removeTokens, markForRemoval] = useState([]); + + const tokenToAddAddress = new ArgsString(""); + + const onAdditionRequest = useCallback( + (input: string) => { + if (removeTokens.includes(input)) { + markForRemoval((markedForRemoval) => markedForRemoval.filter((address) => address !== input)); + } else { + markForAddition((markedForAddition) => + markedForAddition.concat( + [input].filter((address) => !markedForAddition.includes(address) || address.length > 0) + ) + ); + } - const [removeTokens, markForRemoval] = useReducer( - (previousState: MIEntity.ConfigChanges["removeTokens"], address: string | null) => - address === null ? [] : previousState.includes(address) ? previousState : [...previousState, address], + tokenToAddAddress.value = ""; + }, - [] + [markForAddition] ); + const [selected, onSelect] = useState([]); + + const onRemovalRequest = useCallback(() => { + if (selected.some(addTokens.includes)) { + markForAddition((markedForAddition) => markedForAddition.filter((address) => !selected.includes(address))); + } + + markForRemoval((markedForRemoval) => + markedForRemoval.concat( + selected.filter((address) => !markedForRemoval.includes(address) || !addTokens.includes(address)) + ) + ); + + editModeSwitch(false); + }, [editModeSwitch, markForRemoval, selected]); + const formReset = useCallback(() => { + markForAddition([]); + markForRemoval([]); editModeSwitch(false); - markForAddition(null); - markForRemoval(null); - }, []); + }, [editModeSwitch, markForAddition, markForRemoval]); useEffect(disabled ? formReset : Fn.returnVoid, [disabled, formReset]); @@ -48,11 +71,18 @@ export const MITokensWhitelistEditForm = ({ return ( markForAddition(event.target.value)} /> : null} + footer={ + editModeEnabled ? ( + onAdditionRequest(event.target.value)} + value={tokenToAddAddress} + /> + ) : null + } headingCorners={{ right: editModeEnabled ? ( <> - editModeSwitch(false)}> + @@ -66,6 +96,7 @@ export const MITokensWhitelistEditForm = ({ ), }} + onItemsSelected={onSelect} {...{ className, controllerContractAddress }} /> ); From 63f67245d0500b4b445b6af9287870f836f59b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 06:31:54 +0400 Subject: [PATCH 303/537] wip: Create jobs settings edit feature --- src/entities/index.ts | 2 +- src/entities/multicall-instance/config.ts | 4 +- src/entities/multicall-instance/index.ts | 6 +- .../multicall-instance/model/mi-admins.ts | 8 +- .../multicall-instance/model/mi-tokens.ts | 8 +- .../multicall-instance/ui/mi-admins.tsx | 4 +- .../ui/mi-tokens-whitelist.tsx | 6 +- src/features/index.ts | 3 +- src/features/jobs-settings-edit/config.ts | 15 +++ src/features/jobs-settings-edit/index.ts | 8 ++ .../ui/jobs-settings-form.tsx | 63 +++++++++++++ .../tokens-whitelist-edit/config.ts | 11 --- .../tokens-whitelist-edit/index.ts | 8 -- src/features/tokens-whitelist-edit/config.ts | 13 +++ src/features/tokens-whitelist-edit/index.ts | 8 ++ .../ui/tokens-whitelist-form.tsx} | 31 ++++--- src/pages/dao/config/config.scss | 4 +- src/pages/dao/config/config.tsx | 6 +- src/shared/lib/contracts/multicall.ts | 2 +- src/widgets/index.ts | 2 +- src/widgets/multicall-config-editor/config.ts | 18 ++-- src/widgets/multicall-config-editor/index.ts | 10 +- .../ui/multicall-config-editor.scss | 4 +- .../ui/multicall-config-editor.tsx | 91 +++++-------------- 24 files changed, 191 insertions(+), 144 deletions(-) create mode 100644 src/features/jobs-settings-edit/config.ts create mode 100644 src/features/jobs-settings-edit/index.ts create mode 100644 src/features/jobs-settings-edit/ui/jobs-settings-form.tsx delete mode 100644 src/features/multicall-instance/tokens-whitelist-edit/config.ts delete mode 100644 src/features/multicall-instance/tokens-whitelist-edit/index.ts create mode 100644 src/features/tokens-whitelist-edit/config.ts create mode 100644 src/features/tokens-whitelist-edit/index.ts rename src/features/{multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx => tokens-whitelist-edit/ui/tokens-whitelist-form.tsx} (74%) diff --git a/src/entities/index.ts b/src/entities/index.ts index 4f6b29af..bce08ae0 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ export { Task } from "./task"; export { Job, type JobEntity } from "./job"; export { FungibleToken, type FungibleTokenEntity } from "./fungible-token"; -export { MI, type MIEntity } from "./multicall-instance"; +export { MulticallInstance, type MulticallInstanceEntity } from "./multicall-instance"; export { NearToken, type NearTokenEntity } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/config.ts index 47a3f801..f0a01fb3 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/config.ts @@ -4,7 +4,7 @@ import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; /** * Type declaration for Multicall Instance entity */ -namespace MIEntity { +namespace MulticallInstanceEntity { export interface Dependencies { controllerContractAddress: SputnikDAOContract["address"]; } @@ -19,4 +19,4 @@ class MIEntityConfig { // all the constants must be grouped in objects whenever it's possible and stored here as static properties } -export { MIEntityConfig, type MIEntity }; +export { MIEntityConfig, type MulticallInstanceEntity }; diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index bda58cef..347d6cf2 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,13 +1,13 @@ -import { MIEntityConfig, type MIEntity } from "./config"; +import { type MulticallInstanceEntity, MIEntityConfig } from "./config"; import { MIAdminsTable } from "./ui/mi-admins"; import { MITokensWhitelistTable } from "./ui/mi-tokens-whitelist"; /** * Multicall Instance entity */ -class MI extends MIEntityConfig { +class MulticallInstance extends MIEntityConfig { static AdminsTable = MIAdminsTable; static TokensWhitelistTable = MITokensWhitelistTable; } -export { MI, MIEntity }; +export { MulticallInstance, MulticallInstanceEntity }; diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index e36bb722..2a864f88 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -4,7 +4,7 @@ import { ArgsAccount } from "../../../shared/lib/args"; import { MulticallContract } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { type MIEntity } from "../config"; +import { type MulticallInstanceEntity } from "../config"; export type MIAdminsAddressList = { data: MulticallContract["admins"] | null; @@ -14,7 +14,7 @@ export type MIAdminsAddressList = { export class MIAdminsModel { static addressListFetchFx = async ( - controllerContractAddress: MIEntity.Dependencies["controllerContractAddress"], + controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"], callback: (result: MIAdminsAddressList) => void ) => await MulticallContract.instanceDataFetchFx( @@ -22,7 +22,9 @@ export class MIAdminsModel { (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) ); - static useAddressList = (controllerContractAddress: MIEntity.Dependencies["controllerContractAddress"]) => { + static useAddressList = ( + controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"] + ) => { const [state, stateUpdate] = useState({ data: null, error: null, diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index 0a1cf1f4..fbd48219 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -4,7 +4,7 @@ import { ArgsAccount } from "../../../shared/lib/args"; import { MulticallContract } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { type MIEntity } from "../config"; +import { type MulticallInstanceEntity } from "../config"; export type MITokensWhitelist = { data: MulticallContract["tokensWhitelist"] | null; @@ -14,7 +14,7 @@ export type MITokensWhitelist = { export class MITokensModel { static whitelistFetchFx = async ( - controllerContractAddress: MIEntity.Dependencies["controllerContractAddress"], + controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"], callback: (result: MITokensWhitelist) => void ) => await MulticallContract.instanceDataFetchFx( @@ -24,7 +24,9 @@ export class MITokensModel { callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) ); - static useWhitelist = (controllerContractAddress: MIEntity.Dependencies["controllerContractAddress"]) => { + static useWhitelist = ( + controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"] + ) => { const [state, stateUpdate] = useState({ data: null, error: null, diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 322c5f6d..f6276707 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -2,11 +2,11 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/components"; import { MIAdminsModel } from "../model/mi-admins"; -import { type MIEntity } from "../config"; +import { type MulticallInstanceEntity } from "../config"; import { multicallAdminTableRow } from "./mi-admin-entry"; -interface MIAdminsTableProps extends MIEntity.Dependencies { +interface MIAdminsTableProps extends MulticallInstanceEntity.Dependencies { className?: string; } diff --git a/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx b/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx index 4d16382a..e4672d05 100644 --- a/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx @@ -3,11 +3,13 @@ import clsx from "clsx"; import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/components"; import { MITokensModel } from "../model/mi-tokens"; -import { type MIEntity } from "../config"; +import { type MulticallInstanceEntity } from "../config"; import { miWhitelistedTokenTableRowRender } from "./mi-whitelisted-token"; -interface MITokensWhitelistTableProps extends MIEntity.Dependencies, Pick { +interface MITokensWhitelistTableProps + extends MulticallInstanceEntity.Dependencies, + Pick { ItemComponent?: TableProps["RowComponent"]; ItemCompactComponent?: TableProps["RowCompactComponent"]; additionalItems?: FungibleToken["address"][]; diff --git a/src/features/index.ts b/src/features/index.ts index f2ff6a89..092b891f 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,2 +1,3 @@ export { DappLogin } from "./dapp-login"; -export { MITokensWhitelistEdit } from "./multicall-instance/tokens-whitelist-edit"; +export { JobsSettingsEdit, type JobsSettingsEditFeature } from "./jobs-settings-edit"; +export { TokensWhitelistEdit, type TokensWhitelistEditFeature } from "./tokens-whitelist-edit"; diff --git a/src/features/jobs-settings-edit/config.ts b/src/features/jobs-settings-edit/config.ts new file mode 100644 index 00000000..3d11a08e --- /dev/null +++ b/src/features/jobs-settings-edit/config.ts @@ -0,0 +1,15 @@ +import { HTMLProps } from "react"; + +import { MulticallInstanceEntity } from "../../entities"; +import { MulticallContract } from "../../shared/lib/contracts/multicall"; + +namespace JobsSettingsEditFeature { + export interface Dependencies + extends Omit, "onChange">, + Pick { + multicallContract: MulticallContract; + onEdit: (payload: Pick) => void; + } +} + +export { type JobsSettingsEditFeature }; diff --git a/src/features/jobs-settings-edit/index.ts b/src/features/jobs-settings-edit/index.ts new file mode 100644 index 00000000..550b8b8a --- /dev/null +++ b/src/features/jobs-settings-edit/index.ts @@ -0,0 +1,8 @@ +import { type JobsSettingsEditFeature } from "./config"; +import { JobsSettingsForm } from "./ui/jobs-settings-form"; + +class JobsSettingsEdit { + static Form = JobsSettingsForm; +} + +export { JobsSettingsEdit, type JobsSettingsEditFeature }; diff --git a/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx b/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx new file mode 100644 index 00000000..490cbc94 --- /dev/null +++ b/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx @@ -0,0 +1,63 @@ +import { EditOutlined } from "@mui/icons-material"; +import { IconButton } from "@mui/material"; +import { useState } from "react"; + +import { ArgsString } from "../../../shared/lib/args"; +import { toNEAR } from "../../../shared/lib/converter"; +import { NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; +import { type JobsSettingsEditFeature } from "../config"; + +interface JobsSettingsFormProps extends JobsSettingsEditFeature.Dependencies {} + +export const JobsSettingsForm = ({ className, multicallContract }: JobsSettingsFormProps) => { + const [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); + + return ( + +

    Croncat manager

    + + { + editModeSwitch(true); + jobsSettingsEditModeSwitch(true); + }} + > + + + + {editMode && jobsSettingsEditMode ? ( + changesDiffUpdate({ croncatManager: event.target.value })} + value={new ArgsString(multicallContract.croncatManager)} + fullWidth + /> + ) : ( + + )} + +

    Job bond

    + + + {!editMode && + `${multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "..."} ${ + NearIcons.NATIVE_TOKEN_CHARACTER + }`} + + {editMode && ( + changesDiffUpdate({ jobBond: event.target.value })} + type="number" + value={ + new ArgsString(multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "") + } + /> + )} + +
    + ); +}; diff --git a/src/features/multicall-instance/tokens-whitelist-edit/config.ts b/src/features/multicall-instance/tokens-whitelist-edit/config.ts deleted file mode 100644 index 9e0229e0..00000000 --- a/src/features/multicall-instance/tokens-whitelist-edit/config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { HTMLProps } from "react"; - -import { MIEntity } from "../../../entities"; - -namespace MITokensWhitelistEditFeature { - export interface Dependencies extends Omit, "onChange">, MIEntity.Dependencies { - onEdit: (payload: Pick) => void; - } -} - -export { type MITokensWhitelistEditFeature }; diff --git a/src/features/multicall-instance/tokens-whitelist-edit/index.ts b/src/features/multicall-instance/tokens-whitelist-edit/index.ts deleted file mode 100644 index 71b489de..00000000 --- a/src/features/multicall-instance/tokens-whitelist-edit/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { type MITokensWhitelistEditFeature } from "./config"; -import { MITokensWhitelistEditForm } from "./ui/mi-tokens-whitelist-edit-form"; - -class MITokensWhitelistEdit { - static Form = MITokensWhitelistEditForm; -} - -export { MITokensWhitelistEdit, type MITokensWhitelistEditFeature }; diff --git a/src/features/tokens-whitelist-edit/config.ts b/src/features/tokens-whitelist-edit/config.ts new file mode 100644 index 00000000..49f51b80 --- /dev/null +++ b/src/features/tokens-whitelist-edit/config.ts @@ -0,0 +1,13 @@ +import { HTMLProps } from "react"; + +import { MulticallInstanceEntity } from "../../entities"; + +namespace TokensWhitelistEditFeature { + export interface Dependencies + extends Omit, "onChange">, + MulticallInstanceEntity.Dependencies { + onEdit: (payload: Pick) => void; + } +} + +export { type TokensWhitelistEditFeature }; diff --git a/src/features/tokens-whitelist-edit/index.ts b/src/features/tokens-whitelist-edit/index.ts new file mode 100644 index 00000000..66aec675 --- /dev/null +++ b/src/features/tokens-whitelist-edit/index.ts @@ -0,0 +1,8 @@ +import { type TokensWhitelistEditFeature } from "./config"; +import { TokensWhitelistForm } from "./ui/tokens-whitelist-form"; + +class TokensWhitelistEdit { + static Form = TokensWhitelistForm; +} + +export { TokensWhitelistEdit, type TokensWhitelistEditFeature }; diff --git a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx similarity index 74% rename from src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx rename to src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index b5b5289b..2e9bc383 100644 --- a/src/features/multicall-instance/tokens-whitelist-edit/ui/mi-tokens-whitelist-edit-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -2,25 +2,24 @@ import { CancelOutlined, DeleteOutlined, EditOutlined } from "@mui/icons-materia import { IconButton } from "@mui/material"; import { useCallback, useEffect, useReducer, useState } from "react"; -import { TextInput } from "../../../../shared/ui/components"; -import { Fn } from "../../../../shared/lib/fn"; -import { ArgsString } from "../../../../shared/lib/args"; -import { MI, MIEntity } from "../../../../entities"; -import { type MITokensWhitelistEditFeature } from "../config"; +import { TextInput } from "../../../shared/ui/components"; +import { Fn } from "../../../shared/lib/fn"; +import { ArgsString } from "../../../shared/lib/args"; +import { MulticallInstance, MulticallInstanceEntity } from "../../../entities"; +import { type TokensWhitelistEditFeature } from "../config"; -interface MITokensWhitelistEditFormProps extends MITokensWhitelistEditFeature.Dependencies {} +interface TokensWhitelistFormProps extends TokensWhitelistEditFeature.Dependencies {} -export const MITokensWhitelistEditForm = ({ +export const TokensWhitelistForm = ({ className, controllerContractAddress, disabled, onEdit, -}: MITokensWhitelistEditFormProps) => { +}: TokensWhitelistFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); - const [addTokens, markForAddition] = useState([]); - - const [removeTokens, markForRemoval] = useState([]); + const [addTokens, markForAddition] = useState([]), + [removeTokens, markForRemoval] = useState([]); const tokenToAddAddress = new ArgsString(""); @@ -69,7 +68,7 @@ export const MITokensWhitelistEditForm = ({ useEffect(() => onEdit({ addTokens, removeTokens }), [addTokens, removeTokens, onEdit]); return ( - - - - + {selected.length > 0 && ( + + + + )} diff --git a/src/pages/dao/config/config.scss b/src/pages/dao/config/config.scss index 0a12a77d..e91e89ea 100644 --- a/src/pages/dao/config/config.scss +++ b/src/pages/dao/config/config.scss @@ -4,6 +4,6 @@ grid-template-rows: 1fr 1fr; grid-template-areas: - "MIEntityConfigEditor MIEntityConfigEditor" - "MIEntityConfigEditor MIEntityConfigEditor"; + "MulticallConfigEditor MulticallConfigEditor" + "MulticallConfigEditor MulticallConfigEditor"; } diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 707fc0ea..7226270d 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -1,11 +1,11 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { MIEntityConfigEditor, type MIEntityConfigEditorWidget } from "../../../widgets"; +import { MulticallConfigEditor, type MulticallConfigEditorWidget } from "../../../widgets"; import "./config.scss"; -interface DaoConfigTabUIProps extends HTMLProps, MIEntityConfigEditorWidget.Dependencies {} +interface DaoConfigTabUIProps extends HTMLProps, MulticallConfigEditorWidget.Dependencies {} const _DaoConfigTab = "DaoConfigTab"; @@ -14,7 +14,7 @@ const DaoConfigTabUI = ({ className, controllerContractAddress, multicallContrac className={clsx(_DaoConfigTab, className)} {...props} > - + ); diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index d2822452..0abecdf8 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -184,7 +184,7 @@ class Multicall { * @param configDiff changes to current config of some multicall instance. * @returns actions that can be passed to JSON for DAO "add_proposal". */ - static configDiffToProposalActions(configDiff: MIEntityConfigChanges): daoFunctionCallAction[] { + static configDiffToProposalActions(configDiff: MulticallConfigChanges): daoFunctionCallAction[] { const { removeTokens, addTokens, jobBond, croncatManager } = configDiff; const actions: daoFunctionCallAction[] = []; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index c2f6b5bb..97489170 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -4,6 +4,6 @@ export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export/export.jsx"; -export { MIEntityConfigEditor, type MIEntityConfigEditorWidget } from "./multicall-config-editor"; +export { MulticallConfigEditor, type MulticallConfigEditorWidget } from "./multicall-config-editor"; export { Sidebar } from "./sidebar/sidebar.jsx"; export { TokensBalances, type TokensBalancesWidget } from "./tokens-balances"; diff --git a/src/widgets/multicall-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts index fa279a51..4535b709 100644 --- a/src/widgets/multicall-config-editor/config.ts +++ b/src/widgets/multicall-config-editor/config.ts @@ -1,15 +1,13 @@ import { HTMLProps } from "react"; +import { JobsSettingsEditFeature, TokensWhitelistEditFeature } from "../../features"; -import { MulticallContract } from "../../shared/lib/contracts/multicall"; -import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; - -namespace MIEntityConfigEditorWidget { - export interface Dependencies extends HTMLProps { - controllerContractAddress: SputnikDAOContract["address"]; - multicallContract: MulticallContract; - } +namespace MulticallConfigEditorWidget { + export interface Dependencies + extends HTMLProps, + Omit, + Omit {} } -class MIEntityConfigEditorConfig {} +class MulticallConfigEditorConfig {} -export { MIEntityConfigEditorConfig, type MIEntityConfigEditorWidget }; +export { MulticallConfigEditorConfig, type MulticallConfigEditorWidget }; diff --git a/src/widgets/multicall-config-editor/index.ts b/src/widgets/multicall-config-editor/index.ts index 7c83e242..a6579d03 100644 --- a/src/widgets/multicall-config-editor/index.ts +++ b/src/widgets/multicall-config-editor/index.ts @@ -1,8 +1,8 @@ -import { MIEntityConfigEditorConfig, type MIEntityConfigEditorWidget } from "./config"; -import { MIEntityConfigEditorUI } from "./ui/multicall-config-editor"; +import { MulticallConfigEditorConfig, type MulticallConfigEditorWidget } from "./config"; +import { MulticallConfigEditorUI } from "./ui/multicall-config-editor"; -class MIEntityConfigEditor extends MIEntityConfigEditorConfig { - static UI = MIEntityConfigEditorUI; +class MulticallConfigEditor extends MulticallConfigEditorConfig { + static UI = MulticallConfigEditorUI; } -export { MIEntityConfigEditor, type MIEntityConfigEditorWidget }; +export { MulticallConfigEditor, type MulticallConfigEditorWidget }; diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss index 1f95765a..4509b506 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss @@ -3,8 +3,8 @@ @use "sass/mixin"; @use "sass/size"; -.MIEntityConfigEditor { - grid-area: MIEntityConfigEditor; +.MulticallConfigEditor { + grid-area: MulticallConfigEditor; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 6fr 4fr; diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index 6e740a67..d27a34a0 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -1,29 +1,24 @@ -import { EditOutlined } from "@mui/icons-material"; -import { IconButton } from "@mui/material"; import clsx from "clsx"; -import { useCallback, useEffect, useReducer, useState } from "react"; +import { useCallback, useReducer, useState } from "react"; -import { MI } from "../../../entities"; -import { MITokensWhitelistEdit } from "../../../features"; -import { ArgsString } from "../../../shared/lib/args"; +import { MulticallInstance } from "../../../entities"; +import { JobsSettingsEdit, TokensWhitelistEdit } from "../../../features"; import { type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; -import { toNEAR } from "../../../shared/lib/converter"; -import { Button, ButtonGroup, NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; -import { type MIEntityConfigEditorWidget } from "../config"; +import { Button, ButtonGroup, TextInput, Tile } from "../../../shared/ui/components"; +import { type MulticallConfigEditorWidget } from "../config"; import "./multicall-config-editor.scss"; -interface MIEntityConfigEditorUIProps extends MIEntityConfigEditorWidget.Dependencies {} +interface MulticallConfigEditorUIProps extends MulticallConfigEditorWidget.Dependencies {} -const _MIEntityConfigEditor = "MIEntityConfigEditor"; +const _MulticallConfigEditor = "MulticallConfigEditor"; -export const MIEntityConfigEditorUI = ({ +export const MulticallConfigEditorUI = ({ className, controllerContractAddress, multicallContract, -}: MIEntityConfigEditorUIProps) => { - const [editMode, editModeSwitch] = useState(false), - [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); +}: MulticallConfigEditorUIProps) => { + const [editMode, editModeSwitch] = useState(false); const changesDiffInitialState: MulticallConfigChanges = { removeTokens: [], @@ -68,69 +63,27 @@ export const MIEntityConfigEditorUI = ({ console.log(changesDiff); return ( -
    - + - - -

    Croncat manager

    - - { - editModeSwitch(true); - jobsSettingsEditModeSwitch(true); - }} - > - - - - {editMode && jobsSettingsEditMode ? ( - changesDiffUpdate({ croncatManager: event.target.value })} - value={new ArgsString(multicallContract.croncatManager)} - fullWidth - /> - ) : ( - - )} - -

    Job bond

    - - - {!editMode && - `${multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "..."} ${ - NearIcons.NATIVE_TOKEN_CHARACTER - }`} - - {editMode && ( - changesDiffUpdate({ jobBond: event.target.value })} - type="number" - value={ - new ArgsString( - multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "" - ) - } - /> - )} - -
    + {!editMode &&

    To create config changes proposal template, start editing

    } From 02d93bf64a036962a8b781b56d24d71ba439d15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 11:18:02 +0400 Subject: [PATCH 304/537] fix: Reduce styles fine-tuning redundancy --- src/widgets/export/export.scss | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/widgets/export/export.scss b/src/widgets/export/export.scss index 9aaa3ea7..7e89f740 100644 --- a/src/widgets/export/export.scss +++ b/src/widgets/export/export.scss @@ -237,16 +237,10 @@ legend { background-color: color.$black; - margin-left: -2px; - padding: 2px; border-radius: 20px; + padding: 0.15rem; visibility: visible; } - - legend > span { - font-size: 0.75em; - visibility: hidden; - } } &:hover fieldset { @@ -280,7 +274,6 @@ *:not(input) { color: color.$light-text; - font-size: 1em; } width: 100%; From d1e98fc0409ba90ee604b643b59ec5dcf067a98f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 11:19:36 +0400 Subject: [PATCH 305/537] wip: Set MUI textfield font size to default globally --- src/global.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global.scss b/src/global.scss index 8d283620..badf5830 100644 --- a/src/global.scss +++ b/src/global.scss @@ -41,7 +41,7 @@ button { .MuiTextField-root { .MuiInputLabel-root, .MuiInputBase-root { - font-size: 1em; + font-size: size.$text; } } From f4ce85e47c05292ae2dfa30a348b5569843b17b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 12:39:42 +0400 Subject: [PATCH 306/537] wip: Update styles --- src/global.scss | 9 +++++++++ src/shared/ui/components/table/row.scss | 10 +++++++--- src/shared/ui/components/table/row.tsx | 12 ++++++++---- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/global.scss b/src/global.scss index badf5830..40a35aeb 100644 --- a/src/global.scss +++ b/src/global.scss @@ -42,6 +42,15 @@ button { .MuiInputLabel-root, .MuiInputBase-root { font-size: size.$text; + + input { + padding: calc(size.$gap * 0.4) calc(size.$gap * 0.6); + font-size: size.$text; + } + + fieldset { + border-radius: size.$task-radius; + } } } diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 6c383cbd..17766b09 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -29,8 +29,12 @@ flex-direction: column; gap: 0.5 * size.$gap; border-radius: size.$task-radius; - padding: 0.5 * size.$gap; + padding: size.$gap * 0.5; background-color: color.$white; + + &--dense { + padding: calc(size.$gap * 0.4) calc(size.$gap * 0.6); + } } &-content { @@ -40,9 +44,9 @@ align-items: center; font-size: 1.1 * size.$text; - &:not(&--denseHeader) { + &:not(&--dense) { &:first-of-type { - padding: calc(size.$gap / 2); + padding: size.$gap * 0.5; } } diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 912bce85..c05c7aee 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -9,7 +9,7 @@ export type TableHeader = string[]; export interface TableRowProps { cells?: (string | number | JSX.Element)[] | null; - denseHeader?: boolean; + dense?: boolean; header: TableHeader; } @@ -23,12 +23,16 @@ export const TableRow = ({ cells, header }: TableRowProps) => ( ); -export const TableRowCompact = ({ cells, denseHeader, header }: TableRowProps) => ( -
    +export const TableRowCompact = ({ cells, dense, header }: TableRowProps) => ( +
    {header.map((headerCell, headerCellIndex) => (
    From 3a7893ef3e8d513bc5a41c0e6e51ce50fbf79ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 12:40:33 +0400 Subject: [PATCH 307/537] wip: Rename prop --- src/entities/multicall-instance/ui/mi-admins.tsx | 2 +- src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx | 2 +- src/shared/ui/components/table/table.tsx | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index f6276707..fd7e606f 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -25,7 +25,7 @@ export const MIAdminsTable = ({ className, controllerContractAddress }: MIAdmins
    , Pick { +export interface TableProps extends HTMLAttributes, Pick { RowComponent?: typeof TableRow; RowCompactComponent?: typeof TableRowCompact; /** @@ -38,7 +38,7 @@ export const Table = ({ RowComponent = TableRow, RowCompactComponent = TableRowCompact, className, - denseHeader = false, + dense = false, displayMode = "default", header, rows, @@ -79,7 +79,7 @@ export const Table = ({ rows.map((cells, index) => ( ))} From f0cd04b05f543509556f52c357d2ef2a83df37cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 12:41:30 +0400 Subject: [PATCH 308/537] wip: Update config edit related logic & UI --- src/features/jobs-settings-edit/config.ts | 4 +- .../ui/jobs-settings-form.tsx | 89 ++++++++++++++----- src/features/tokens-whitelist-edit/config.ts | 4 +- .../ui/tokens-whitelist-form.tsx | 10 ++- .../ui/multicall-config-editor.scss | 25 ++++-- .../ui/multicall-config-editor.tsx | 75 ++++++++-------- 6 files changed, 135 insertions(+), 72 deletions(-) diff --git a/src/features/jobs-settings-edit/config.ts b/src/features/jobs-settings-edit/config.ts index 3d11a08e..4253a646 100644 --- a/src/features/jobs-settings-edit/config.ts +++ b/src/features/jobs-settings-edit/config.ts @@ -8,8 +8,10 @@ namespace JobsSettingsEditFeature { extends Omit, "onChange">, Pick { multicallContract: MulticallContract; - onEdit: (payload: Pick) => void; + onEdit: (payload: FormState) => void; } + + export type FormState = Pick; } export { type JobsSettingsEditFeature }; diff --git a/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx b/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx index 490cbc94..69bed869 100644 --- a/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx +++ b/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx @@ -1,38 +1,83 @@ -import { EditOutlined } from "@mui/icons-material"; +import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; -import { useState } from "react"; +import { useCallback, useEffect, useMemo, useReducer, useState } from "react"; import { ArgsString } from "../../../shared/lib/args"; import { toNEAR } from "../../../shared/lib/converter"; +import { Fn } from "../../../shared/lib/fn"; import { NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; import { type JobsSettingsEditFeature } from "../config"; interface JobsSettingsFormProps extends JobsSettingsEditFeature.Dependencies {} -export const JobsSettingsForm = ({ className, multicallContract }: JobsSettingsFormProps) => { - const [jobsSettingsEditMode, jobsSettingsEditModeSwitch] = useState(false); +export const JobsSettingsForm = ({ className, disabled, multicallContract, onEdit }: JobsSettingsFormProps) => { + const [editModeEnabled, editModeSwitch] = useState(!disabled); + + const formInitialState: JobsSettingsEditFeature.FormState = { + croncatManager: "", + jobBond: "", + }; + + const [formValues, formValuesUpdate] = useReducer( + (latestState: JobsSettingsEditFeature.FormState, update: Partial) => + Object.assign(latestState, update), + + formInitialState + ); + + const formFields = { + croncatManager: useMemo(() => new ArgsString(multicallContract.croncatManager), []), + + jobBond: useMemo( + () => new ArgsString(multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : ""), + [] + ), + }; + + const formReset = useCallback(() => { + formValuesUpdate(formInitialState); + editModeSwitch(false); + }, [editModeSwitch, formInitialState, formValuesUpdate]); + + useEffect( + disabled && Object.values(formValues).filter(({ length }) => length > 0).length > 0 ? formReset : Fn.returnVoid, + [disabled, formValues, formReset] + ); + + useEffect(() => onEdit(formValues), [formValues.croncatManager, formValues.jobBond, onEdit]); + + console.log(formValues); return ( + {Object.values(formValues).filter(({ length }) => length > 0).length > 0 && ( + editModeSwitch(false)}> + + + )} + + + + + + ) : ( + editModeSwitch(true)}> + + + ), + }} >

    Croncat manager

    - { - editModeSwitch(true); - jobsSettingsEditModeSwitch(true); - }} - > - - - - {editMode && jobsSettingsEditMode ? ( + {editModeEnabled ? ( changesDiffUpdate({ croncatManager: event.target.value })} - value={new ArgsString(multicallContract.croncatManager)} + update={(event) => formValuesUpdate({ croncatManager: event.target.value })} + value={formFields.croncatManager} fullWidth /> ) : ( @@ -42,19 +87,17 @@ export const JobsSettingsForm = ({ className, multicallContract }: JobsSettingsF

    Job bond

    - {!editMode && + {!editModeEnabled && `${multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "..."} ${ NearIcons.NATIVE_TOKEN_CHARACTER }`} - {editMode && ( + {editModeEnabled && ( changesDiffUpdate({ jobBond: event.target.value })} + update={(event) => formValuesUpdate({ jobBond: event.target.value })} type="number" - value={ - new ArgsString(multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "") - } + value={formFields.jobBond} /> )} diff --git a/src/features/tokens-whitelist-edit/config.ts b/src/features/tokens-whitelist-edit/config.ts index 49f51b80..ef7a247e 100644 --- a/src/features/tokens-whitelist-edit/config.ts +++ b/src/features/tokens-whitelist-edit/config.ts @@ -6,8 +6,10 @@ namespace TokensWhitelistEditFeature { export interface Dependencies extends Omit, "onChange">, MulticallInstanceEntity.Dependencies { - onEdit: (payload: Pick) => void; + onEdit: (payload: FormState) => void; } + + export type FormState = Pick; } export { type TokensWhitelistEditFeature }; diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index 2e9bc383..c64e7df8 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -1,11 +1,11 @@ import { CancelOutlined, DeleteOutlined, EditOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; -import { useCallback, useEffect, useReducer, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import { TextInput } from "../../../shared/ui/components"; import { Fn } from "../../../shared/lib/fn"; import { ArgsString } from "../../../shared/lib/args"; -import { MulticallInstance, MulticallInstanceEntity } from "../../../entities"; +import { MulticallInstance } from "../../../entities"; import { type TokensWhitelistEditFeature } from "../config"; interface TokensWhitelistFormProps extends TokensWhitelistEditFeature.Dependencies {} @@ -18,8 +18,8 @@ export const TokensWhitelistForm = ({ }: TokensWhitelistFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); - const [addTokens, markForAddition] = useState([]), - [removeTokens, markForRemoval] = useState([]); + const [addTokens, markForAddition] = useState([]), + [removeTokens, markForRemoval] = useState([]); const tokenToAddAddress = new ArgsString(""); @@ -73,6 +73,8 @@ export const TokensWhitelistForm = ({ footer={ editModeEnabled ? ( onAdditionRequest(event.target.value)} value={tokenToAddAddress} /> diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss index 4509b506..b549fa7c 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss @@ -17,16 +17,29 @@ &-proposalForm { grid-area: proposalForm; - &:not(.is-inEditMode) { - @include mixin.center-items(space-evenly, center); + p { + @include mixin.center-items(); + font-size: size.$text; + } - .ButtonGroup { + form { + display: none; + } + + p, + form { + flex-flow: inherit; + height: inherit; + } + + &.is-inEditMode { + p { display: none; } - } - p { - font-size: size.$text; + form { + display: inherit; + } } } diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index d27a34a0..be71bba0 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -27,18 +27,18 @@ export const MulticallConfigEditorUI = ({ croncatManager: "", }; - const [changesDiff, changesDiffUpdate] = useReducer( + const [formState, formStateUpdate] = useReducer( ( - previousState: typeof changesDiffInitialState, + latestState: typeof changesDiffInitialState, update: Partial - ): MulticallConfigChanges => Object.assign(previousState, update), + ): MulticallConfigChanges => Object.assign(latestState, update), changesDiffInitialState ); const formReset = useCallback( - () => changesDiffUpdate(changesDiffInitialState), - [changesDiffUpdate, changesDiffInitialState] + () => formStateUpdate(changesDiffInitialState), + [formStateUpdate, changesDiffInitialState] ); const onCancel = useCallback(() => { @@ -48,25 +48,23 @@ export const MulticallConfigEditorUI = ({ const onEdit = useCallback( (update: Partial) => { - changesDiffUpdate(update); + const newFormState = Object.assign(formState, update); - editModeSwitch( - JSON.stringify(Object.assign(changesDiff, update)) !== JSON.stringify(changesDiffInitialState) - ); + formStateUpdate(newFormState); + editModeSwitch(Object.values(newFormState).filter(({ length }) => length > 0).length > 0); + console.log(formState); }, - [changesDiffUpdate] + [formState, formStateUpdate] ); const onSubmit = useCallback(() => editModeSwitch(false), [editModeSwitch]); - console.log(changesDiff); - return (
    @@ -86,30 +85,32 @@ export const MulticallConfigEditorUI = ({ }} heading={editMode ? "Changes proposal" : null} > - {!editMode &&

    To create config changes proposal template, start editing

    } - - {editMode && ( - <> -
    -

    Description

    - -
    - - -
    ); From f0458122dfcc0c65bb8123260444d5c244e72659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 13:07:08 +0400 Subject: [PATCH 309/537] fix: Override global font-size --- src/pages/dao/dao.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/dao/dao.scss b/src/pages/dao/dao.scss index 5de14d1b..feac2db7 100644 --- a/src/pages/dao/dao.scss +++ b/src/pages/dao/dao.scss @@ -36,6 +36,7 @@ input { padding: 0; padding-left: 0.5 * size.$gap; + font-size: 1em; } &.Mui-error { From 7a4d675f5152a7a239fc9cbfacb15c4db33c5830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 13:07:41 +0400 Subject: [PATCH 310/537] fix: Prevent empty addresses from adding --- src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index c64e7df8..b14d0684 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -30,7 +30,7 @@ export const TokensWhitelistForm = ({ } else { markForAddition((markedForAddition) => markedForAddition.concat( - [input].filter((address) => !markedForAddition.includes(address) || address.length > 0) + [input].filter((address) => !markedForAddition.includes(address) && address.length > 0) ) ); } From a332425cab7fb9d2e7c870665b89784a03ba1889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 13:13:02 +0400 Subject: [PATCH 311/537] fix: Use singular form --- src/features/index.ts | 2 +- .../config.ts | 4 +- src/features/job-settings-edit/index.ts | 8 +++ .../ui/job-settings-form.scss | 0 .../ui/job-settings-form.tsx} | 56 ++++++++++--------- src/features/jobs-settings-edit/index.ts | 8 --- src/widgets/multicall-config-editor/config.ts | 4 +- .../ui/multicall-config-editor.tsx | 4 +- 8 files changed, 46 insertions(+), 40 deletions(-) rename src/features/{jobs-settings-edit => job-settings-edit}/config.ts (87%) create mode 100644 src/features/job-settings-edit/index.ts create mode 100644 src/features/job-settings-edit/ui/job-settings-form.scss rename src/features/{jobs-settings-edit/ui/jobs-settings-form.tsx => job-settings-edit/ui/job-settings-form.tsx} (65%) delete mode 100644 src/features/jobs-settings-edit/index.ts diff --git a/src/features/index.ts b/src/features/index.ts index 092b891f..8045862f 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,3 +1,3 @@ export { DappLogin } from "./dapp-login"; -export { JobsSettingsEdit, type JobsSettingsEditFeature } from "./jobs-settings-edit"; +export { JobSettingsEdit, type JobSettingsEditFeature } from "./job-settings-edit"; export { TokensWhitelistEdit, type TokensWhitelistEditFeature } from "./tokens-whitelist-edit"; diff --git a/src/features/jobs-settings-edit/config.ts b/src/features/job-settings-edit/config.ts similarity index 87% rename from src/features/jobs-settings-edit/config.ts rename to src/features/job-settings-edit/config.ts index 4253a646..ffcdf011 100644 --- a/src/features/jobs-settings-edit/config.ts +++ b/src/features/job-settings-edit/config.ts @@ -3,7 +3,7 @@ import { HTMLProps } from "react"; import { MulticallInstanceEntity } from "../../entities"; import { MulticallContract } from "../../shared/lib/contracts/multicall"; -namespace JobsSettingsEditFeature { +namespace JobSettingsEditFeature { export interface Dependencies extends Omit, "onChange">, Pick { @@ -14,4 +14,4 @@ namespace JobsSettingsEditFeature { export type FormState = Pick; } -export { type JobsSettingsEditFeature }; +export { type JobSettingsEditFeature }; diff --git a/src/features/job-settings-edit/index.ts b/src/features/job-settings-edit/index.ts new file mode 100644 index 00000000..49442991 --- /dev/null +++ b/src/features/job-settings-edit/index.ts @@ -0,0 +1,8 @@ +import { type JobSettingsEditFeature } from "./config"; +import { JobSettingsForm } from "./ui/job-settings-form"; + +class JobSettingsEdit { + static Form = JobSettingsForm; +} + +export { JobSettingsEdit, type JobSettingsEditFeature }; diff --git a/src/features/job-settings-edit/ui/job-settings-form.scss b/src/features/job-settings-edit/ui/job-settings-form.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx similarity index 65% rename from src/features/jobs-settings-edit/ui/jobs-settings-form.tsx rename to src/features/job-settings-edit/ui/job-settings-form.tsx index 69bed869..93b5431a 100644 --- a/src/features/jobs-settings-edit/ui/jobs-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -6,20 +6,22 @@ import { ArgsString } from "../../../shared/lib/args"; import { toNEAR } from "../../../shared/lib/converter"; import { Fn } from "../../../shared/lib/fn"; import { NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; -import { type JobsSettingsEditFeature } from "../config"; +import { type JobSettingsEditFeature } from "../config"; -interface JobsSettingsFormProps extends JobsSettingsEditFeature.Dependencies {} +interface JobSettingsFormProps extends JobSettingsEditFeature.Dependencies {} -export const JobsSettingsForm = ({ className, disabled, multicallContract, onEdit }: JobsSettingsFormProps) => { +const _JobSettings = "JobSettings"; + +export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit }: JobSettingsFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); - const formInitialState: JobsSettingsEditFeature.FormState = { + const formInitialState: JobSettingsEditFeature.FormState = { croncatManager: "", jobBond: "", }; const [formValues, formValuesUpdate] = useReducer( - (latestState: JobsSettingsEditFeature.FormState, update: Partial) => + (latestState: JobSettingsEditFeature.FormState, update: Partial) => Object.assign(latestState, update), formInitialState @@ -72,35 +74,39 @@ export const JobsSettingsForm = ({ className, disabled, multicallContract, onEdi ), }} > -

    Croncat manager

    - {editModeEnabled ? ( formValuesUpdate({ croncatManager: event.target.value })} value={formFields.croncatManager} fullWidth /> ) : ( - + +

    Croncat manager

    + +
    )} -

    Job bond

    - - - {!editModeEnabled && - `${multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "..."} ${ - NearIcons.NATIVE_TOKEN_CHARACTER - }`} - - {editModeEnabled && ( - formValuesUpdate({ jobBond: event.target.value })} - type="number" - value={formFields.jobBond} - /> - )} - + {editModeEnabled ? ( + formValuesUpdate({ jobBond: event.target.value })} + type="number" + value={formFields.jobBond} + /> + ) : ( + +

    Job bond

    + + + {`${multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "..."} ${ + NearIcons.NATIVE_TOKEN_CHARACTER + }`} + +
    + )}
    ); }; diff --git a/src/features/jobs-settings-edit/index.ts b/src/features/jobs-settings-edit/index.ts deleted file mode 100644 index 550b8b8a..00000000 --- a/src/features/jobs-settings-edit/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { type JobsSettingsEditFeature } from "./config"; -import { JobsSettingsForm } from "./ui/jobs-settings-form"; - -class JobsSettingsEdit { - static Form = JobsSettingsForm; -} - -export { JobsSettingsEdit, type JobsSettingsEditFeature }; diff --git a/src/widgets/multicall-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts index 4535b709..989fe15b 100644 --- a/src/widgets/multicall-config-editor/config.ts +++ b/src/widgets/multicall-config-editor/config.ts @@ -1,11 +1,11 @@ import { HTMLProps } from "react"; -import { JobsSettingsEditFeature, TokensWhitelistEditFeature } from "../../features"; +import { JobSettingsEditFeature, TokensWhitelistEditFeature } from "../../features"; namespace MulticallConfigEditorWidget { export interface Dependencies extends HTMLProps, Omit, - Omit {} + Omit {} } class MulticallConfigEditorConfig {} diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index be71bba0..c7cbd066 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { useCallback, useReducer, useState } from "react"; import { MulticallInstance } from "../../../entities"; -import { JobsSettingsEdit, TokensWhitelistEdit } from "../../../features"; +import { JobSettingsEdit, TokensWhitelistEdit } from "../../../features"; import { type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; import { Button, ButtonGroup, TextInput, Tile } from "../../../shared/ui/components"; import { type MulticallConfigEditorWidget } from "../config"; @@ -73,7 +73,7 @@ export const MulticallConfigEditorUI = ({ {...{ controllerContractAddress, onEdit }} /> - Date: Mon, 24 Oct 2022 14:20:44 +0400 Subject: [PATCH 312/537] wip: Fix job settings form behavior & apply minor changes --- .../ui/job-settings-form.scss | 2 + .../ui/job-settings-form.tsx | 56 +++++++++---------- src/shared/lib/contracts/multicall.ts | 2 +- .../ui/multicall-config-editor.scss | 3 +- .../ui/multicall-config-editor.tsx | 2 +- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/features/job-settings-edit/ui/job-settings-form.scss b/src/features/job-settings-edit/ui/job-settings-form.scss index e69de29b..da87db5f 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.scss +++ b/src/features/job-settings-edit/ui/job-settings-form.scss @@ -0,0 +1,2 @@ +.JobSettings { +} diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index 93b5431a..0e2ad888 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -1,5 +1,6 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; +import clsx from "clsx"; import { useCallback, useEffect, useMemo, useReducer, useState } from "react"; import { ArgsString } from "../../../shared/lib/args"; @@ -8,6 +9,8 @@ import { Fn } from "../../../shared/lib/fn"; import { NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; import { type JobSettingsEditFeature } from "../config"; +import "./job-settings-form.scss"; + interface JobSettingsFormProps extends JobSettingsEditFeature.Dependencies {} const _JobSettings = "JobSettings"; @@ -15,49 +18,45 @@ const _JobSettings = "JobSettings"; export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit }: JobSettingsFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); - const formInitialState: JobSettingsEditFeature.FormState = { - croncatManager: "", - jobBond: "", - }; - - const [formValues, formValuesUpdate] = useReducer( - (latestState: JobSettingsEditFeature.FormState, update: Partial) => - Object.assign(latestState, update), + const formInitialState = { croncatManager: "", jobBond: "" }; - formInitialState - ); + const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ + useState(formInitialState.croncatManager), + useState(formInitialState.jobBond), + ]; const formFields = { - croncatManager: useMemo(() => new ArgsString(multicallContract.croncatManager), []), + croncatManager: useMemo(() => new ArgsString(multicallContract.croncatManager), [disabled]), jobBond: useMemo( () => new ArgsString(multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : ""), - [] + [disabled] ), }; const formReset = useCallback(() => { - formValuesUpdate(formInitialState); + croncatManagerUpdate(formInitialState.croncatManager); + jobBondUpdate(formInitialState.jobBond); editModeSwitch(false); - }, [editModeSwitch, formInitialState, formValuesUpdate]); - - useEffect( - disabled && Object.values(formValues).filter(({ length }) => length > 0).length > 0 ? formReset : Fn.returnVoid, - [disabled, formValues, formReset] - ); + }, [croncatManagerUpdate, editModeSwitch, formInitialState, jobBondUpdate]); - useEffect(() => onEdit(formValues), [formValues.croncatManager, formValues.jobBond, onEdit]); + useEffect(disabled && croncatManager.length > 0 && jobBond.length > 0 ? formReset : Fn.returnVoid, [ + croncatManager, + disabled, + formReset, + jobBond, + ]); - console.log(formValues); + useEffect(() => onEdit({ croncatManager, jobBond }), [croncatManager, jobBond, onEdit]); return ( - {Object.values(formValues).filter(({ length }) => length > 0).length > 0 && ( + {(croncatManager.length > 0 || jobBond.length > 0) && ( editModeSwitch(false)}> @@ -77,14 +76,14 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit {editModeEnabled ? ( formValuesUpdate({ croncatManager: event.target.value })} + update={(event) => croncatManagerUpdate(event.target.value)} value={formFields.croncatManager} fullWidth /> ) : (

    Croncat manager

    - +
    )} @@ -92,7 +91,7 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit formValuesUpdate({ jobBond: event.target.value })} + update={(event) => jobBondUpdate(event.target.value)} type="number" value={formFields.jobBond} /> @@ -101,9 +100,8 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit

    Job bond

    - {`${multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "..."} ${ - NearIcons.NATIVE_TOKEN_CHARACTER - }`} + {jobBond || (multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "...")} + {NearIcons.NATIVE_TOKEN_CHARACTER} )} diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 0abecdf8..519fa5db 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -132,7 +132,7 @@ class Multicall { /** * Calls the given callback with a result of multicall contract instantiation, - * represented as stateful response. + * represented as stateful response. * * @param controllerContractAddress DAO contract address * @param callback Stateful data fetch callback diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss index b549fa7c..90c63284 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss @@ -19,7 +19,8 @@ p { @include mixin.center-items(); - font-size: size.$text; + text-align: center; + font-size: size.$large-text; } form { diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index c7cbd066..11b38655 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -85,7 +85,7 @@ export const MulticallConfigEditorUI = ({ }} heading={editMode ? "Changes proposal" : null} > -

    To create config changes proposal template, start editing

    +

    Start editing to create config changes proposal template

    From b44da851437e6c6dcb98d92958f4d8f51ac7fcd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 24 Oct 2022 14:25:19 +0400 Subject: [PATCH 313/537] wip: Apply standard gap for job settings --- src/features/job-settings-edit/ui/job-settings-form.scss | 5 +++++ src/features/job-settings-edit/ui/job-settings-form.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/features/job-settings-edit/ui/job-settings-form.scss b/src/features/job-settings-edit/ui/job-settings-form.scss index da87db5f..c5a795fa 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.scss +++ b/src/features/job-settings-edit/ui/job-settings-form.scss @@ -1,2 +1,7 @@ +@use "sass/size"; + .JobSettings { + &-content { + gap: size.$gap; + } } diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index 0e2ad888..55df1e57 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -51,7 +51,7 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit return ( Date: Wed, 26 Oct 2022 04:46:25 +0400 Subject: [PATCH 314/537] wip: Update styles --- src/entities/job/ui/jobs-table.tsx | 1 + .../multicall-instance/ui/mi-admins.tsx | 1 + .../ui/mi-tokens-whitelist.tsx | 1 + .../ui/job-settings-form.scss | 7 --- .../ui/components/icon-label/icon-label.scss | 6 ++ .../ui/components/icon-label/icon-label.tsx | 8 ++- src/shared/ui/components/table/row.scss | 61 +++++++++++-------- src/shared/ui/components/table/row.tsx | 7 ++- src/shared/ui/components/table/table.tsx | 5 +- .../tokens-balances/ui/tokens-balances.tsx | 1 + 10 files changed, 63 insertions(+), 35 deletions(-) delete mode 100644 src/features/job-settings-edit/ui/job-settings-form.scss diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index b47c8588..301e1d8f 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -25,6 +25,7 @@ export const JobsTable = ({ className, contracts }: JobsTableProps) => {
    img, & > svg { @@ -23,5 +28,6 @@ &-label { font-weight: bold; + line-height: 0; } } diff --git a/src/shared/ui/components/icon-label/icon-label.tsx b/src/shared/ui/components/icon-label/icon-label.tsx index 0cfa4cc3..8eea7d8d 100644 --- a/src/shared/ui/components/icon-label/icon-label.tsx +++ b/src/shared/ui/components/icon-label/icon-label.tsx @@ -1,3 +1,5 @@ +import clsx from "clsx"; + import { Validation } from "../../../lib/validation"; import "./icon-label.scss"; @@ -10,7 +12,11 @@ interface IconLabelProps { } export const IconLabel = ({ icon, label }: IconLabelProps) => ( - + {typeof icon === "string" && Validation.isUrl(icon) ? ( span { - &:first-of-type { - display: none; - } + &:not(&--entitled) { + padding: 0.5 * size.$gap size.$gap; + background-color: rgba(color.$lightest, 0.7); - &:last-child { - font-size: size.$large-text; - } + &:first-of-type { + border-top-left-radius: 0.8 * size.$task-radius; + border-top-right-radius: 0.8 * size.$task-radius; } } - &:not(:first-of-type) { - padding: 0.5 * size.$gap size.$gap; - background-color: rgba(color.$lightest, 0.7); - & > span:last-of-type { - text-overflow: ellipsis; - white-space: nowrap; - padding-left: 1.5rem; - overflow: hidden; + &--entitled { + &:first-of-type { + & > span { + &:first-of-type { + display: none; + } + + &:last-child { + font-size: size.$large-text; + } + } } - } - &:nth-of-type(2) { - border-top-left-radius: 0.8 * size.$task-radius; - border-top-right-radius: 0.8 * size.$task-radius; - } + &:not(:first-of-type) { + padding: 0.5 * size.$gap size.$gap; + background-color: rgba(color.$lightest, 0.7); - &:last-of-type { - border-bottom-left-radius: 0.8 * size.$task-radius; - border-bottom-right-radius: 0.8 * size.$task-radius; + & > span:last-of-type { + text-overflow: ellipsis; + white-space: nowrap; + padding-left: 1.5rem; + overflow: hidden; + } + } + + &:nth-of-type(2) { + border-top-left-radius: 0.8 * size.$task-radius; + border-top-right-radius: 0.8 * size.$task-radius; + } } span:first-of-type { diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index c05c7aee..25d36c32 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -10,6 +10,10 @@ export type TableHeader = string[]; export interface TableRowProps { cells?: (string | number | JSX.Element)[] | null; dense?: boolean; + /** + * Display first cell of each row as its title in `"compact"` table `displayMode` + */ + entitled?: boolean; header: TableHeader; } @@ -23,7 +27,7 @@ export const TableRow = ({ cells, header }: TableRowProps) => ( ); -export const TableRowCompact = ({ cells, dense, header }: TableRowProps) => ( +export const TableRowCompact = ({ cells, dense, entitled, header }: TableRowProps) => (
    (
    diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 3f03cb69..c49f040a 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -13,7 +13,7 @@ import { HTMLAttributes } from "react"; import { TableRowCompact, TableRow, type TableRowProps, TableHeader } from "./row"; import "./table.scss"; -export interface TableProps extends HTMLAttributes, Pick { +export interface TableProps extends HTMLAttributes, Pick { RowComponent?: typeof TableRow; RowCompactComponent?: typeof TableRowCompact; /** @@ -39,6 +39,7 @@ export const Table = ({ RowCompactComponent = TableRowCompact, className, dense = false, + entitled = false, displayMode = "default", header, rows, @@ -79,7 +80,7 @@ export const Table = ({ rows.map((cells, index) => ( ))}
    diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index 74425f87..8b9c68f9 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -23,6 +23,7 @@ export const TokensBalancesUI = ({ className, contracts }: TokensBalancesUIProps {(nearTokenBalances ?? fungibleTokensBalances) && (
    From 0e61e66bc2731132984ecf05b0e056ec9ddbc6fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 04:48:17 +0400 Subject: [PATCH 315/537] wip: Update job settings styles & Set min job bond --- .../ui/job-settings-form.tsx | 85 +++++++++++-------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index 55df1e57..33293263 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -4,13 +4,11 @@ import clsx from "clsx"; import { useCallback, useEffect, useMemo, useReducer, useState } from "react"; import { ArgsString } from "../../../shared/lib/args"; -import { toNEAR } from "../../../shared/lib/converter"; +import { toNEAR, toYocto } from "../../../shared/lib/converter"; import { Fn } from "../../../shared/lib/fn"; -import { NearIcons, NearLink, TextInput, Tile } from "../../../shared/ui/components"; +import { IconLabel, NearIcons, NearLink, Table, TextInput, Tile } from "../../../shared/ui/components"; import { type JobSettingsEditFeature } from "../config"; -import "./job-settings-form.scss"; - interface JobSettingsFormProps extends JobSettingsEditFeature.Dependencies {} const _JobSettings = "JobSettings"; @@ -51,7 +49,7 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit return ( - {editModeEnabled ? ( - croncatManagerUpdate(event.target.value)} - value={formFields.croncatManager} - fullWidth - /> - ) : ( - -

    Croncat manager

    - -
    - )} - - {editModeEnabled ? ( - jobBondUpdate(event.target.value)} - type="number" - value={formFields.jobBond} - /> - ) : ( - -

    Job bond

    - - - {jobBond || (multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : "...")} - {NearIcons.NATIVE_TOKEN_CHARACTER} - -
    - )} +
    croncatManagerUpdate(event.target.value)} + value={formFields.croncatManager} + fullWidth + /> + ) : ( + + ), + ], + [ + "Job bond", + + editModeEnabled ? ( + jobBondUpdate(toYocto(event.target.value))} + type="number" + value={formFields.jobBond} + /> + ) : ( + + ), + ], + ]} + /> ); }; From 605a1b0fe42eee9368a56c93ec40af505ec117af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 05:45:53 +0400 Subject: [PATCH 316/537] wip: Add reversed mode for icon label --- src/features/job-settings-edit/ui/job-settings-form.tsx | 1 + src/shared/ui/components/icon-label/icon-label.scss | 5 +++++ src/shared/ui/components/icon-label/icon-label.tsx | 8 +++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index 33293263..232699f3 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -111,6 +111,7 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit ? toNEAR(jobBond || multicallContract.jobBond) : "..." } + reversed /> ), ], diff --git a/src/shared/ui/components/icon-label/icon-label.scss b/src/shared/ui/components/icon-label/icon-label.scss index b7d24b90..8496aa2a 100644 --- a/src/shared/ui/components/icon-label/icon-label.scss +++ b/src/shared/ui/components/icon-label/icon-label.scss @@ -3,10 +3,15 @@ .IconLabel { display: flex; + flex-direction: row; align-items: center; gap: 0.6 * size.$gap; line-height: 0; + &--reversed { + flex-direction: row-reverse; + } + &--symbolic { line-height: 1; } diff --git a/src/shared/ui/components/icon-label/icon-label.tsx b/src/shared/ui/components/icon-label/icon-label.tsx index 8eea7d8d..ba428e50 100644 --- a/src/shared/ui/components/icon-label/icon-label.tsx +++ b/src/shared/ui/components/icon-label/icon-label.tsx @@ -9,15 +9,17 @@ const _IconLabel = "IconLabel"; interface IconLabelProps { icon: string | JSX.Element; label: string; + reversed?: boolean; } -export const IconLabel = ({ icon, label }: IconLabelProps) => ( +export const IconLabel = ({ icon, label, reversed = false }: IconLabelProps) => ( - + {typeof icon === "string" && Validation.isUrl(icon) ? ( ( )} - {label} + {label} ); From 4d3803c69876054d1fac09c40fd2239b1e30a4a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 07:58:28 +0400 Subject: [PATCH 317/537] wip: Update styles --- src/entities/job/ui/jobs-table.tsx | 2 +- .../multicall-instance/ui/mi-admins.tsx | 2 +- .../ui/mi-tokens-whitelist.tsx | 2 +- .../ui/job-settings-form.tsx | 6 +- .../ui/components/icon-label/icon-label.scss | 1 + src/shared/ui/components/table/row.scss | 75 +++++++++++++++++-- src/shared/ui/components/table/row.tsx | 12 ++- src/shared/ui/components/table/table.tsx | 7 +- .../tokens-balances/ui/tokens-balances.tsx | 2 +- 9 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 301e1d8f..84c35696 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -23,9 +23,9 @@ export const JobsTable = ({ className, contracts }: JobsTableProps) => { >
    croncatManagerUpdate(event.target.value)} value={formFields.croncatManager} - fullWidth /> ) : ( diff --git a/src/shared/ui/components/icon-label/icon-label.scss b/src/shared/ui/components/icon-label/icon-label.scss index 8496aa2a..dd31d9f9 100644 --- a/src/shared/ui/components/icon-label/icon-label.scss +++ b/src/shared/ui/components/icon-label/icon-label.scss @@ -6,6 +6,7 @@ flex-direction: row; align-items: center; gap: 0.6 * size.$gap; + width: fit-content; line-height: 0; &--reversed { diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 2f3be067..1c30b129 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -42,6 +42,7 @@ display: flex; justify-content: space-between; align-items: center; + gap: size.$gap; font-size: 1.1 * size.$text; &:last-of-type { @@ -59,10 +60,45 @@ padding: 0.5 * size.$gap size.$gap; background-color: rgba(color.$lightest, 0.7); - &:first-of-type { + :first-of-type { border-top-left-radius: 0.8 * size.$task-radius; border-top-right-radius: 0.8 * size.$task-radius; } + + & > span { + &:first-of-type { + text-align: start; + } + } + } + + .MuiFormControl-root { + margin-top: 0; + margin-bottom: 0; + } + + & > span { + &:first-of-type { + flex: 1; + font-weight: 800; + } + + &:not(:first-of-type) { + flex: auto; + text-align: center; + + .MuiInputBase-root input { + text-align: center; + } + } + + &:last-of-type { + text-align: end; + + .MuiInputBase-root input { + text-align: end; + } + } } &--entitled { @@ -82,11 +118,12 @@ padding: 0.5 * size.$gap size.$gap; background-color: rgba(color.$lightest, 0.7); - & > span:last-of-type { - text-overflow: ellipsis; - white-space: nowrap; - padding-left: 1.5rem; - overflow: hidden; + & > span { + &:last-of-type { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } } } @@ -94,10 +131,32 @@ border-top-left-radius: 0.8 * size.$task-radius; border-top-right-radius: 0.8 * size.$task-radius; } + + &--centeredTitle { + &:first-of-type { + & > span:not(:first-of-type) { + text-align: center; + } + } + } } - span:first-of-type { - font-weight: 800; + &--noKeys { + & > span { + &:first-of-type { + display: none; + } + + &:not(:first-of-type) { + display: flex; + justify-content: center; + text-align: center; + + .MuiInputBase-root input { + text-align: center; + } + } + } } } } diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 25d36c32..f869894b 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -9,12 +9,14 @@ export type TableHeader = string[]; export interface TableRowProps { cells?: (string | number | JSX.Element)[] | null; + centeredTitle?: boolean; dense?: boolean; /** * Display first cell of each row as its title in `"compact"` table `displayMode` */ entitled?: boolean; header: TableHeader; + noKeys?: boolean; } export const TableRow = ({ cells, header }: TableRowProps) => ( @@ -27,7 +29,7 @@ export const TableRow = ({ cells, header }: TableRowProps) => ( ); -export const TableRowCompact = ({ cells, dense, entitled, header }: TableRowProps) => ( +export const TableRowCompact = ({ cells, centeredTitle, dense, entitled, header, noKeys }: TableRowProps) => (
    {header.map((headerCell, headerCellIndex) => (
    diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index c49f040a..da00adf5 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -13,9 +13,10 @@ import { HTMLAttributes } from "react"; import { TableRowCompact, TableRow, type TableRowProps, TableHeader } from "./row"; import "./table.scss"; -export interface TableProps extends HTMLAttributes, Pick { +export interface TableProps extends HTMLAttributes, Pick { RowComponent?: typeof TableRow; RowCompactComponent?: typeof TableRowCompact; + RowProps?: Omit; /** * `"classic"` mode is a classic table view. * @@ -37,9 +38,9 @@ const _Table = "Table"; export const Table = ({ RowComponent = TableRow, RowCompactComponent = TableRowCompact, + RowProps, className, dense = false, - entitled = false, displayMode = "default", header, rows, @@ -80,7 +81,7 @@ export const Table = ({ rows.map((cells, index) => ( ))}
    diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/tokens-balances/ui/tokens-balances.tsx index 8b9c68f9..18f5b8eb 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/tokens-balances/ui/tokens-balances.tsx @@ -23,7 +23,7 @@ export const TokensBalancesUI = ({ className, contracts }: TokensBalancesUIProps {(nearTokenBalances ?? fungibleTokensBalances) && (
    From 0de080aba5b13b60123932a99b235ab013c09326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 08:06:25 +0400 Subject: [PATCH 318/537] wip: Remove unused code --- src/entities/multicall-instance/config.ts | 4 ++-- src/entities/multicall-instance/index.ts | 12 ++++++------ .../multicall-instance/model/mi-admins.ts | 10 +++++----- .../multicall-instance/model/mi-tokens.ts | 10 +++++----- .../multicall-instance/ui/mi-admin-entry.tsx | 8 +++++--- .../multicall-instance/ui/mi-admins.tsx | 18 ++++++++---------- .../ui/mi-tokens-whitelist.tsx | 17 ++++++----------- .../ui/mi-whitelisted-token.tsx | 8 ++++---- 8 files changed, 41 insertions(+), 46 deletions(-) diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/config.ts index f0a01fb3..441cde59 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/config.ts @@ -15,8 +15,8 @@ namespace MulticallInstanceEntity { /** * Multicall Instance entity config */ -class MIEntityConfig { +class MulticallInstanceEntityConfig { // all the constants must be grouped in objects whenever it's possible and stored here as static properties } -export { MIEntityConfig, type MulticallInstanceEntity }; +export { MulticallInstanceEntityConfig, type MulticallInstanceEntity }; diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 347d6cf2..3161e2a2 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,13 +1,13 @@ -import { type MulticallInstanceEntity, MIEntityConfig } from "./config"; -import { MIAdminsTable } from "./ui/mi-admins"; -import { MITokensWhitelistTable } from "./ui/mi-tokens-whitelist"; +import { type MulticallInstanceEntity, MulticallInstanceEntityConfig } from "./config"; +import { MulticallInstanceAdminsTable } from "./ui/mi-admins"; +import { MulticallInstanceTokensWhitelistTable } from "./ui/mi-tokens-whitelist"; /** * Multicall Instance entity */ -class MulticallInstance extends MIEntityConfig { - static AdminsTable = MIAdminsTable; - static TokensWhitelistTable = MITokensWhitelistTable; +class MulticallInstance extends MulticallInstanceEntityConfig { + static AdminsTable = MulticallInstanceAdminsTable; + static TokensWhitelistTable = MulticallInstanceTokensWhitelistTable; } export { MulticallInstance, MulticallInstanceEntity }; diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index 2a864f88..bcd9e98d 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -6,16 +6,16 @@ import { Props } from "../../../shared/lib/props"; import { type MulticallInstanceEntity } from "../config"; -export type MIAdminsAddressList = { +export type MulticallInstanceAdminsAddressList = { data: MulticallContract["admins"] | null; error: Error | null; loading: boolean; }; -export class MIAdminsModel { +export class MulticallInstanceAdminsModel { static addressListFetchFx = async ( controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"], - callback: (result: MIAdminsAddressList) => void + callback: (result: MulticallInstanceAdminsAddressList) => void ) => await MulticallContract.instanceDataFetchFx( `${ArgsAccount.deconstructAddress(controllerContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, @@ -25,14 +25,14 @@ export class MIAdminsModel { static useAddressList = ( controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"] ) => { - const [state, stateUpdate] = useState({ + const [state, stateUpdate] = useState({ data: null, error: null, loading: true, }); useEffect( - () => void MIAdminsModel.addressListFetchFx(controllerContractAddress, stateUpdate), + () => void MulticallInstanceAdminsModel.addressListFetchFx(controllerContractAddress, stateUpdate), [controllerContractAddress, stateUpdate] ); diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index fbd48219..08b1fc1d 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -6,16 +6,16 @@ import { Props } from "../../../shared/lib/props"; import { type MulticallInstanceEntity } from "../config"; -export type MITokensWhitelist = { +export type MulticallInstanceTokensWhitelist = { data: MulticallContract["tokensWhitelist"] | null; error: Error | null; loading: boolean; }; -export class MITokensModel { +export class MulticallInstanceTokensModel { static whitelistFetchFx = async ( controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"], - callback: (result: MITokensWhitelist) => void + callback: (result: MulticallInstanceTokensWhitelist) => void ) => await MulticallContract.instanceDataFetchFx( `${ArgsAccount.deconstructAddress(controllerContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, @@ -27,14 +27,14 @@ export class MITokensModel { static useWhitelist = ( controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"] ) => { - const [state, stateUpdate] = useState({ + const [state, stateUpdate] = useState({ data: null, error: null, loading: true, }); useEffect( - () => void MITokensModel.whitelistFetchFx(controllerContractAddress, stateUpdate), + () => void MulticallInstanceTokensModel.whitelistFetchFx(controllerContractAddress, stateUpdate), [controllerContractAddress, stateUpdate] ); diff --git a/src/entities/multicall-instance/ui/mi-admin-entry.tsx b/src/entities/multicall-instance/ui/mi-admin-entry.tsx index b3fe8d92..fee89cbd 100644 --- a/src/entities/multicall-instance/ui/mi-admin-entry.tsx +++ b/src/entities/multicall-instance/ui/mi-admin-entry.tsx @@ -2,11 +2,11 @@ import { Account } from "near-api-js"; import { ArgsAccount } from "../../../shared/lib/args"; -interface MIAdminEntryProps { +interface MulticallInstanceAdminEntryProps { address: Account["accountId"]; } -const MIAdminEntry = ({ address }: MIAdminEntryProps) => { +const MulticallInstanceAdminEntry = ({ address }: MulticallInstanceAdminEntryProps) => { const addr = new ArgsAccount(address); return ( @@ -22,4 +22,6 @@ const MIAdminEntry = ({ address }: MIAdminEntryProps) => { ); }; -export const multicallAdminTableRow = (address: MIAdminEntryProps["address"]) => []; +export const multicallAdminTableRow = (address: MulticallInstanceAdminEntryProps["address"]) => [ + , +]; diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index d21eae58..4c3898dc 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,23 +1,22 @@ -import clsx from "clsx"; - import { Scrollable, Table, Tile } from "../../../shared/ui/components"; -import { MIAdminsModel } from "../model/mi-admins"; +import { MulticallInstanceAdminsModel } from "../model/mi-admins"; import { type MulticallInstanceEntity } from "../config"; import { multicallAdminTableRow } from "./mi-admin-entry"; -interface MIAdminsTableProps extends MulticallInstanceEntity.Dependencies { +interface MulticallInstanceAdminsTableProps extends MulticallInstanceEntity.Dependencies { className?: string; } -const _MIAdminsTable = "MIAdminsTable"; - -export const MIAdminsTable = ({ className, controllerContractAddress }: MIAdminsTableProps) => { - const { data, error, loading } = MIAdminsModel.useAddressList(controllerContractAddress); +export const MulticallInstanceAdminsTable = ({ + className, + controllerContractAddress, +}: MulticallInstanceAdminsTableProps) => { + const { data, error, loading } = MulticallInstanceAdminsModel.useAddressList(controllerContractAddress); return (
    { ItemComponent?: TableProps["RowComponent"]; @@ -16,9 +14,7 @@ interface MITokensWhitelistTableProps className?: string; } -const _MITokensWhitelistTable = "MITokensWhitelistTable"; - -export const MITokensWhitelistTable = ({ +export const MulticallInstanceTokensWhitelistTable = ({ ItemComponent, ItemCompactComponent, additionalItems, @@ -26,12 +22,12 @@ export const MITokensWhitelistTable = ({ controllerContractAddress, footer, headingCorners, -}: MITokensWhitelistTableProps) => { - const { data, error, loading } = MITokensModel.useWhitelist(controllerContractAddress); +}: MulticallInstanceTokensWhitelistTableProps) => { + const { data, error, loading } = MulticallInstanceTokensModel.useWhitelist(controllerContractAddress); return ( { +const MulticallInstanceWhitelistedTokenEntry = ({ address }: MulticallInstanceWhitelistedTokenProps) => { const addr = new ArgsAccount(address); return ( @@ -21,6 +21,6 @@ const MIWhitelistedTokenEntry = ({ address }: MIWhitelistedTokenProps) => { ); }; -export const miWhitelistedTokenTableRowRender = (item: MIWhitelistedTokenProps["address"]) => [ - , +export const miWhitelistedTokenTableRowRender = (item: MulticallInstanceWhitelistedTokenProps["address"]) => [ + , ]; From 71d22d64e94ac5c4a4b1295926ed30ba4b7f999b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 09:48:03 +0400 Subject: [PATCH 319/537] feat: Allow tables to have selectable rows --- .../fungible-token/ui/ft-balances.tsx | 22 +++-- src/entities/job/ui/job.tsx | 58 +++++++------ src/entities/job/ui/jobs-table.tsx | 4 +- .../multicall-instance/ui/mi-admin-entry.tsx | 7 +- .../ui/mi-whitelisted-token.tsx | 7 +- src/entities/near-token/ui/near-balances.tsx | 22 +++-- .../ui/job-settings-form.tsx | 84 ++++++++++--------- .../data-inspector/data-inspector.scss | 2 + src/shared/ui/components/table/row.tsx | 68 ++++++++++----- src/shared/ui/components/table/table.tsx | 36 ++++++-- 10 files changed, 189 insertions(+), 121 deletions(-) diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index eab01a33..7ab9010a 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -11,14 +11,18 @@ export const fungibleTokensBalancesRender = ({ contracts }: FungibleTokensBalanc return !data ? null - : data.map(({ dao, metadata, multicall, total }) => [ - } - label={metadata.symbol} - />, + : data.map(({ dao, metadata, multicall, total }) => ({ + content: [ + } + label={metadata.symbol} + />, - FungibleTokenFormat.amountToDisplayAmount(multicall, metadata.decimals), - FungibleTokenFormat.amountToDisplayAmount(dao, metadata.decimals), - FungibleTokenFormat.amountToDisplayAmount(total, metadata.decimals), - ]); + FungibleTokenFormat.amountToDisplayAmount(multicall, metadata.decimals), + FungibleTokenFormat.amountToDisplayAmount(dao, metadata.decimals), + FungibleTokenFormat.amountToDisplayAmount(total, metadata.decimals), + ], + + id: metadata.symbol, + })); }; diff --git a/src/entities/job/ui/job.tsx b/src/entities/job/ui/job.tsx index d8fc03d3..ca60c681 100644 --- a/src/entities/job/ui/job.tsx +++ b/src/entities/job/ui/job.tsx @@ -24,30 +24,34 @@ const JobDisplayStatus = ({ job }: Pick) => { ); }; -export const jobTableRow = ({ id, job }: JobEntryProps) => [ - , - id, - // Multicall returns timestamp in nanoseconds, JS Date uses milliseconds - new Date(parseInt(Big(job.start_at).div("1000000").toFixed())).toLocaleString(), - job.croncat_hash.length === 0 ? none : job.croncat_hash, - job.creator, - `${toTGas(job.trigger_gas)} Tgas`, - - <> - - - {job.multicalls.length === 1 && ( - setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0)} - > - Open in Editor - - )} - , -]; +export const jobTableRowRender = ({ id, job }: JobEntryProps) => ({ + content: [ + , + id, + /** Multicall returns timestamp in nanoseconds, JS Date uses milliseconds */ + new Date(parseInt(Big(job.start_at).div("1000000").toFixed())).toLocaleString(), + job.croncat_hash.length === 0 ? none : job.croncat_hash, + job.creator, + `${toTGas(job.trigger_gas)} Tgas`, + + <> + + + {job.multicalls.length === 1 && ( + setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0)} + > + Open in Editor + + )} + , + ], + + id: id.toString(), +}); diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 84c35696..c4aeb1d3 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -4,7 +4,7 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/components"; import { JobModel } from "../model/job"; import { type JobEntity } from "../config"; -import { jobTableRow } from "./job"; +import { jobTableRowRender } from "./job"; import "./jobs-table.scss"; interface JobsTableProps extends JobEntity.Dependencies {} @@ -28,7 +28,7 @@ export const JobsTable = ({ className, contracts }: JobsTableProps) => { displayMode="compact" header={["Status", "ID", "Start at", "Croncat hash", "Creator", "Trigger gas", "Multicalls"]} rows={Object.values(data ?? {}) - .map(jobTableRow) + .map(jobTableRowRender) .reverse()} /> diff --git a/src/entities/multicall-instance/ui/mi-admin-entry.tsx b/src/entities/multicall-instance/ui/mi-admin-entry.tsx index fee89cbd..ac456462 100644 --- a/src/entities/multicall-instance/ui/mi-admin-entry.tsx +++ b/src/entities/multicall-instance/ui/mi-admin-entry.tsx @@ -22,6 +22,7 @@ const MulticallInstanceAdminEntry = ({ address }: MulticallInstanceAdminEntryPro ); }; -export const multicallAdminTableRow = (address: MulticallInstanceAdminEntryProps["address"]) => [ - , -]; +export const multicallAdminTableRow = (item: MulticallInstanceAdminEntryProps["address"]) => ({ + content: [], + id: item, +}); diff --git a/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx b/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx index 8fe0ec16..0bfc3d66 100644 --- a/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx +++ b/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx @@ -21,6 +21,7 @@ const MulticallInstanceWhitelistedTokenEntry = ({ address }: MulticallInstanceWh ); }; -export const miWhitelistedTokenTableRowRender = (item: MulticallInstanceWhitelistedTokenProps["address"]) => [ - , -]; +export const miWhitelistedTokenTableRowRender = (item: MulticallInstanceWhitelistedTokenProps["address"]) => ({ + content: [], + id: item, +}); diff --git a/src/entities/near-token/ui/near-balances.tsx b/src/entities/near-token/ui/near-balances.tsx index 954d8e20..96232553 100644 --- a/src/entities/near-token/ui/near-balances.tsx +++ b/src/entities/near-token/ui/near-balances.tsx @@ -10,14 +10,18 @@ export const nearTokenBalancesRender = ({ contracts }: NearTokenBalancesRenderPr return !data ? null - : [ - } - label="NEAR" - />, + : { + content: [ + } + label="NEAR" + />, - data.multicall, - data.dao, - data.total, - ]; + data.multicall, + data.dao, + data.total, + ], + + id: "NEAR", + }; }; diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index 8857a9a3..b3d6dc19 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -77,44 +77,52 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit dense header={["Option", "Value"]} rows={[ - [ - "Croncat manager", - - editModeEnabled ? ( - croncatManagerUpdate(event.target.value)} - value={formFields.croncatManager} - /> - ) : ( - - ), - ], - [ - "Job bond", - - editModeEnabled ? ( - jobBondUpdate(toYocto(event.target.value))} - type="number" - value={formFields.jobBond} - /> - ) : ( - - ), - ], + { + id: "croncatManager", + + content: [ + "Croncat manager", + + editModeEnabled ? ( + croncatManagerUpdate(event.target.value)} + value={formFields.croncatManager} + /> + ) : ( + + ), + ], + }, + { + id: "jobBond", + + content: [ + "Job bond", + + editModeEnabled ? ( + jobBondUpdate(toYocto(event.target.value))} + type="number" + value={formFields.jobBond} + /> + ) : ( + + ), + ], + }, ]} /> diff --git a/src/shared/ui/components/data-inspector/data-inspector.scss b/src/shared/ui/components/data-inspector/data-inspector.scss index 989f8352..b9de5c4a 100644 --- a/src/shared/ui/components/data-inspector/data-inspector.scss +++ b/src/shared/ui/components/data-inspector/data-inspector.scss @@ -4,6 +4,8 @@ @use "sass/font"; .DataInspector { + text-align: start; + &-label { color: darken(color.$blue, 30%); cursor: pointer; diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index f869894b..1a084b54 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -1,5 +1,6 @@ -import { TableCell, TableRow as MuiTableRow, Typography } from "@mui/material"; +import { Checkbox, TableCell, TableRow as MuiTableRow } from "@mui/material"; import clsx from "clsx"; +import { ChangeEvent, useCallback } from "react"; import "./row.scss"; @@ -16,7 +17,10 @@ export interface TableRowProps { */ entitled?: boolean; header: TableHeader; + id: string; noKeys?: boolean; + onSelect?: (selectedRow: { id: TableRowProps["id"]; checked: boolean }) => void; + selectable: boolean; } export const TableRow = ({ cells, header }: TableRowProps) => ( @@ -29,25 +33,43 @@ export const TableRow = ({ cells, header }: TableRowProps) => ( ); -export const TableRowCompact = ({ cells, centeredTitle, dense, entitled, header, noKeys }: TableRowProps) => ( -
    - {header.map((headerCell, headerCellIndex) => ( -
    - {headerCell} - {cells ? cells[headerCellIndex] : "No data"} -
    - ))} -
    -); +export const TableRowCompact = ({ + cells, + centeredTitle, + dense, + entitled, + header, + id, + noKeys, + onSelect, + selectable, +}: TableRowProps) => { + const onSelectMemoized = useCallback( + (_event: ChangeEvent, checked: boolean) => onSelect?.({ checked, id }), + [onSelect] + ); + + return ( +
    + {header.map((headerCell, headerCellIndex) => ( +
    + {selectable && } + {headerCell} + {cells ? cells[headerCellIndex] : "No data"} +
    + ))} +
    + ); +}; diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index da00adf5..0b1ba9d3 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -8,7 +8,7 @@ import { useTheme, } from "@mui/material"; import clsx from "clsx"; -import { HTMLAttributes } from "react"; +import { HTMLAttributes, useCallback, useEffect, useState } from "react"; import { TableRowCompact, TableRow, type TableRowProps, TableHeader } from "./row"; import "./table.scss"; @@ -16,7 +16,7 @@ import "./table.scss"; export interface TableProps extends HTMLAttributes, Pick { RowComponent?: typeof TableRow; RowCompactComponent?: typeof TableRowCompact; - RowProps?: Omit; + RowProps?: Omit; /** * `"classic"` mode is a classic table view. * @@ -30,7 +30,8 @@ export interface TableProps extends HTMLAttributes, Pick void; + rows?: { id: TableRowProps["id"]; content: TableRowProps["cells"] }[] | null; } const _Table = "Table"; @@ -43,12 +44,26 @@ export const Table = ({ dense = false, displayMode = "default", header, + onRowsSelected, rows, }: TableProps) => { const mediumOrSmallScreen = useMediaQuery(useTheme().breakpoints.down("md")), classicModeRequired = (!mediumOrSmallScreen && displayMode === "default") || displayMode === "classic", compactModeRequired = (mediumOrSmallScreen && displayMode === "default") || displayMode === "compact"; + const [selectedRowsIds, selectedRowsIdsUpdate] = useState([]), + rowSelectionEnabled = onRowsSelected !== undefined; + + const onRowSelect = useCallback( + ({ id, checked }: { id: TableRowProps["id"]; checked: boolean }) => + selectedRowsIdsUpdate((latestState) => + checked ? latestState.concat([id]) : latestState.filter((rowId) => rowId !== id) + ), + [selectedRowsIdsUpdate] + ); + + useEffect(() => void onRowsSelected?.(selectedRowsIds), [selectedRowsIds]); + return ( <> {classicModeRequired && ( @@ -63,10 +78,13 @@ export const Table = ({ - {(rows ?? header).map((cells, index) => ( + {(rows ?? header).map((row, index) => ( ))} @@ -78,10 +96,14 @@ export const Table = ({ {compactModeRequired && (
    {rows && - rows.map((cells, index) => ( + rows.map((row, index) => ( ))}
    From cdd16285a46e4190d1daee661d36ab3b520f23fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 10:39:02 +0400 Subject: [PATCH 320/537] wip: Add global styles override for MUi checkbox --- src/global.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/global.scss b/src/global.scss index 40a35aeb..3339fac4 100644 --- a/src/global.scss +++ b/src/global.scss @@ -38,6 +38,13 @@ button { cursor: pointer; } +.MuiCheckbox-root { + .MuiSvgIcon-root { + width: 2rem; + height: 2rem; + } +} + .MuiTextField-root { .MuiInputLabel-root, .MuiInputBase-root { From 1cbd02f7eeb2cbb868a7ef1322ca8c217658dd52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 11:42:56 +0400 Subject: [PATCH 321/537] wip: Update MUI checkbox global styles --- src/global.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/global.scss b/src/global.scss index 3339fac4..c79bff57 100644 --- a/src/global.scss +++ b/src/global.scss @@ -40,8 +40,8 @@ button { .MuiCheckbox-root { .MuiSvgIcon-root { - width: 2rem; - height: 2rem; + width: size.$large-text; + height: size.$large-text; } } From 36ccb8e34d4370fce1a521772795afb60f51d4aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 11:44:04 +0400 Subject: [PATCH 322/537] wip: Update table row selection logic & styles --- .../multicall-instance/ui/mi-tokens-whitelist.tsx | 3 +++ src/shared/ui/components/table/row.scss | 10 ++++++++++ src/shared/ui/components/table/row.tsx | 7 ++++++- src/shared/ui/components/table/table.tsx | 8 +++++--- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx b/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx index 86bea9bb..5156d3a7 100644 --- a/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx @@ -12,6 +12,7 @@ interface MulticallInstanceTokensWhitelistTableProps ItemCompactComponent?: TableProps["RowCompactComponent"]; additionalItems?: FungibleToken["address"][]; className?: string; + onItemsSelected?: TableProps["onRowsSelected"]; } export const MulticallInstanceTokensWhitelistTable = ({ @@ -22,6 +23,7 @@ export const MulticallInstanceTokensWhitelistTable = ({ controllerContractAddress, footer, headingCorners, + onItemsSelected, }: MulticallInstanceTokensWhitelistTableProps) => { const { data, error, loading } = MulticallInstanceTokensModel.useWhitelist(controllerContractAddress); @@ -40,6 +42,7 @@ export const MulticallInstanceTokensWhitelistTable = ({ dense displayMode="compact" header={["Contract address"]} + onRowsSelected={onItemsSelected} rows={data?.concat(additionalItems ?? []).map(miWhitelistedTokenTableRowRender)} /> diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 1c30b129..3ea6d9a0 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -159,5 +159,15 @@ } } } + + &--compact &-slot { + &--start { + display: flex; + + .MuiCheckbox-root { + padding: calc(size.$text / 4); + } + } + } } } diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 1a084b54..c0668b78 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -65,7 +65,12 @@ export const TableRowCompact = ({ })} key={headerCellIndex} > - {selectable && } + {selectable && ( +
    + +
    + )} + {headerCell} {cells ? cells[headerCellIndex] : "No data"} diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 0b1ba9d3..2a96c374 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -30,7 +30,7 @@ export interface TableProps extends HTMLAttributes, Pick void; + onRowsSelected?: ((selectedRowsIds: TableRowProps["id"][]) => void) | null; rows?: { id: TableRowProps["id"]; content: TableRowProps["cells"] }[] | null; } @@ -52,12 +52,14 @@ export const Table = ({ compactModeRequired = (mediumOrSmallScreen && displayMode === "default") || displayMode === "compact"; const [selectedRowsIds, selectedRowsIdsUpdate] = useState([]), - rowSelectionEnabled = onRowsSelected !== undefined; + rowSelectionEnabled = typeof onRowsSelected === "function"; const onRowSelect = useCallback( ({ id, checked }: { id: TableRowProps["id"]; checked: boolean }) => selectedRowsIdsUpdate((latestState) => - checked ? latestState.concat([id]) : latestState.filter((rowId) => rowId !== id) + checked + ? latestState.concat([id].filter((rowId) => !latestState.includes(rowId))) + : latestState.filter((rowId) => rowId !== id) ), [selectedRowsIdsUpdate] ); From 680e09010638335e4a845014e6ee3f363fe8b642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 11:46:40 +0400 Subject: [PATCH 323/537] fix: Prevent removal request failing --- .../ui/tokens-whitelist-form.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index b14d0684..51aca1fd 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -38,24 +38,24 @@ export const TokensWhitelistForm = ({ tokenToAddAddress.value = ""; }, - [markForAddition] + [markForAddition, markForRemoval, removeTokens] ); - const [selected, onSelect] = useState([]); + const [selected, onSelected] = useState([]); const onRemovalRequest = useCallback(() => { - if (selected.some(addTokens.includes)) { + if (selected.some((address) => addTokens.includes(address))) { markForAddition((markedForAddition) => markedForAddition.filter((address) => !selected.includes(address))); } markForRemoval((markedForRemoval) => markedForRemoval.concat( - selected.filter((address) => !markedForRemoval.includes(address) || !addTokens.includes(address)) + selected.filter((address) => !markedForRemoval.includes(address) && !addTokens.includes(address)) ) ); editModeSwitch(false); - }, [editModeSwitch, markForRemoval, selected]); + }, [addTokens, editModeSwitch, markForAddition, markForRemoval, selected]); const formReset = useCallback(() => { markForAddition([]); @@ -99,7 +99,7 @@ export const TokensWhitelistForm = ({ ), }} - onItemsSelected={onSelect} + onItemsSelected={editModeEnabled ? onSelected : null} {...{ className, controllerContractAddress }} /> ); From edf5674eabf1a970b99617a3f8fed367dcd41ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 26 Oct 2022 12:54:56 +0400 Subject: [PATCH 324/537] wip: Fix state management issues & Add proposal creation --- .../ui/tokens-whitelist-form.tsx | 4 +- .../ui/multicall-config-editor.tsx | 49 +++++++++++++------ 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index 51aca1fd..86ccdc53 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -1,6 +1,6 @@ import { CancelOutlined, DeleteOutlined, EditOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { TextInput } from "../../../shared/ui/components"; import { Fn } from "../../../shared/lib/fn"; @@ -21,7 +21,7 @@ export const TokensWhitelistForm = ({ const [addTokens, markForAddition] = useState([]), [removeTokens, markForRemoval] = useState([]); - const tokenToAddAddress = new ArgsString(""); + const tokenToAddAddress = useMemo(() => new ArgsString(""), []); const onAdditionRequest = useCallback( (input: string) => { diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index 11b38655..174fc8db 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -1,9 +1,11 @@ import clsx from "clsx"; -import { useCallback, useReducer, useState } from "react"; +import { useCallback, useMemo, useState } from "react"; import { MulticallInstance } from "../../../entities"; import { JobSettingsEdit, TokensWhitelistEdit } from "../../../features"; -import { type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; +import { ArgsString } from "../../../shared/lib/args"; +import { MulticallContract, type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; +import { SputnikDAOContract } from "../../../shared/lib/contracts/sputnik-dao"; import { Button, ButtonGroup, TextInput, Tile } from "../../../shared/ui/components"; import { type MulticallConfigEditorWidget } from "../config"; @@ -27,14 +29,8 @@ export const MulticallConfigEditorUI = ({ croncatManager: "", }; - const [formState, formStateUpdate] = useReducer( - ( - latestState: typeof changesDiffInitialState, - update: Partial - ): MulticallConfigChanges => Object.assign(latestState, update), - - changesDiffInitialState - ); + const [formState, formStateUpdate] = useState(changesDiffInitialState), + [proposalDescription, proposalDescriptionUpdate] = useState(""); const formReset = useCallback( () => formStateUpdate(changesDiffInitialState), @@ -48,17 +44,31 @@ export const MulticallConfigEditorUI = ({ const onEdit = useCallback( (update: Partial) => { - const newFormState = Object.assign(formState, update); + formStateUpdate((latestState) => Object.assign(latestState, update)); + + editModeSwitch( + Object.values(Object.assign(formState, update)).filter(({ length }) => length > 0).length > 0 + ); - formStateUpdate(newFormState); - editModeSwitch(Object.values(newFormState).filter(({ length }) => length > 0).length > 0); - console.log(formState); + console.log(formState, proposalDescription); }, - [formState, formStateUpdate] + [editModeSwitch, formState, formStateUpdate, proposalDescription] ); - const onSubmit = useCallback(() => editModeSwitch(false), [editModeSwitch]); + const onSubmit = useCallback(() => { + SputnikDAOContract.init(controllerContractAddress) + .then((instanceController) => + instanceController.proposeFunctionCall( + proposalDescription, + multicallContract.address, + MulticallContract.configDiffToProposalActions(formState) + ) + ) + .catch(console.error); + + editModeSwitch(false); + }, [controllerContractAddress, editModeSwitch]); return (
    @@ -94,6 +104,9 @@ export const MulticallConfigEditorUI = ({ label="Description" minRows={3} multiline + required + update={(event) => void proposalDescriptionUpdate(event.target.value)} + value={useMemo(() => new ArgsString(""), [])} />
    @@ -106,6 +119,10 @@ export const MulticallConfigEditorUI = ({
    <>, + }, + }} additionalItems={addTokens} footer={ editModeEnabled ? ( @@ -87,7 +92,7 @@ export const TokensWhitelistForm = ({ ) } headingCorners={{ - right: editModeEnabled ? ( + end: editModeEnabled ? ( <> {selected.length > 0 && ( diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 3ea6d9a0..f85d3e0c 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -2,7 +2,7 @@ @use "sass/size"; @use "sass/font"; -.Table-row { +.TableRow { overflow: hidden; position: relative; white-space: pre; @@ -160,13 +160,19 @@ } } + &--compact &-checkbox { + display: flex; + + .MuiCheckbox-root { + padding: calc(size.$text / 4); + } + } + &--compact &-slot { &--start { - display: flex; + } - .MuiCheckbox-root { - padding: calc(size.$text / 4); - } + &--end { } } } diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index c0668b78..aefa5b32 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -4,7 +4,7 @@ import { ChangeEvent, useCallback } from "react"; import "./row.scss"; -const _TableRow = "Table-row"; +const _TableRow = "TableRow"; export type TableHeader = string[]; @@ -21,6 +21,10 @@ export interface TableRowProps { noKeys?: boolean; onSelect?: (selectedRow: { id: TableRowProps["id"]; checked: boolean }) => void; selectable: boolean; + /** + * Components that will be rendered inside the target slots of each row with row's id passed as prop + */ + slots?: Partial JSX.Element>>; } export const TableRow = ({ cells, header }: TableRowProps) => ( @@ -43,6 +47,7 @@ export const TableRowCompact = ({ noKeys, onSelect, selectable, + slots, }: TableRowProps) => { const onSelectMemoized = useCallback( (_event: ChangeEvent, checked: boolean) => onSelect?.({ checked, id }), @@ -66,13 +71,25 @@ export const TableRowCompact = ({ key={headerCellIndex} > {selectable && ( -
    +
    )} + {slots?.Start && ( +
    + +
    + )} + {headerCell} {cells ? cells[headerCellIndex] : "No data"} + + {slots?.End && ( +
    + +
    + )}
    ))} diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 70dbc935..39921198 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -14,8 +14,9 @@ import { TableRowCompact, TableRow, type TableRowProps, TableHeader } from "./ro import "./table.scss"; export interface TableProps extends HTMLAttributes, Pick { - RowComponent?: typeof TableRow; - RowCompactComponent?: typeof TableRowCompact; + /** + * Props to bypass into **each** row + */ RowProps?: Omit; /** * `"classic"` mode is a classic table view. @@ -37,8 +38,6 @@ export interface TableProps extends HTMLAttributes, Pick {(rows ?? header).map((row, index) => ( - {rows && rows.map((row, index) => ( - {heading && ( - {headingCorners?.left && ( - {headingCorners?.left} + {headingCorners?.start && ( + {headingCorners?.start} )}

    {heading}

    - - {headingCorners?.right && ( - {headingCorners?.right} - )} + {headingCorners?.end && {headingCorners?.end}}
    )} diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index a485cbf7..75a0fb2d 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -51,7 +51,8 @@ export const MulticallConfigEditorUI = ({ Object.values(Object.assign(formState, update)).filter(({ length }) => length > 0).length > 0 ); - console.log(proposalDescription); + // TODO: Remove before release. This is for debug purposes only + console.table({ proposalDescription }); console.table(formState); }, @@ -77,25 +78,25 @@ export const MulticallConfigEditorUI = ({ return (
    diff --git a/src/widgets/tokens-balances/ui/tokens-balances.scss b/src/widgets/tokens-balances/ui/tokens-balances.scss index c71c356f..d2e86bf1 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.scss +++ b/src/widgets/tokens-balances/ui/tokens-balances.scss @@ -3,7 +3,7 @@ .TokensBalances { grid-area: TokensBalances; - .Table-row-content--compact { + .TableRow-content--compact { &:not(&:first-of-type) { span:last-of-type { font-family: font.$code; From 662628520b0fee2ed4b1c6713ab74a8b026957ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 28 Oct 2022 08:24:23 +0400 Subject: [PATCH 330/537] wip: Update compact table row slot styles --- src/shared/ui/components/table/row.scss | 5 +++++ src/shared/ui/components/table/row.tsx | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index f85d3e0c..1128c402 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -169,10 +169,15 @@ } &--compact &-slot { + display: flex; + align-items: center; + &--start { + justify-content: start; } &--end { + justify-content: end; } } } diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index aefa5b32..c1c58744 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -77,7 +77,12 @@ export const TableRowCompact = ({ )} {slots?.Start && ( -
    +
    )} @@ -86,7 +91,12 @@ export const TableRowCompact = ({ {cells ? cells[headerCellIndex] : "No data"} {slots?.End && ( -
    +
    )} From 2da412f269d9bfae926c533bbfafdd88d5d94d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 28 Oct 2022 11:47:27 +0400 Subject: [PATCH 331/537] wip: Fix token lists cross-checking & update styles --- src/features/tokens-whitelist-edit/config.ts | 13 +++- .../ui/tokens-whitelist-form.tsx | 75 +++++++++---------- src/shared/ui/components/table/row.scss | 6 +- 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/features/tokens-whitelist-edit/config.ts b/src/features/tokens-whitelist-edit/config.ts index ef7a247e..42d67cda 100644 --- a/src/features/tokens-whitelist-edit/config.ts +++ b/src/features/tokens-whitelist-edit/config.ts @@ -6,10 +6,19 @@ namespace TokensWhitelistEditFeature { export interface Dependencies extends Omit, "onChange">, MulticallInstanceEntity.Dependencies { - onEdit: (payload: FormState) => void; + onEdit: (payload: Pick) => void; } - export type FormState = Pick; + export interface FormStates + extends Record< + keyof Pick, + Set< + MulticallInstanceEntity.ConfigChanges[keyof Pick< + MulticallInstanceEntity.ConfigChanges, + "addTokens" | "removeTokens" + >][number] + > + > {} } export { type TokensWhitelistEditFeature }; diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index 5f56d026..8c2f4567 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -18,20 +18,20 @@ export const TokensWhitelistForm = ({ }: TokensWhitelistFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); - const [addTokens, markForAddition] = useState([]), - [removeTokens, markForRemoval] = useState([]); + const [addTokens, markForAddition] = useState(new Set()), + [removeTokens, markForRemoval] = useState(new Set()); const tokenToAddAddress = useMemo(() => new ArgsString(""), []); const onAdditionRequest = useCallback( (input: string) => { - if (removeTokens.includes(input)) { - markForRemoval((markedForRemoval) => markedForRemoval.filter((address) => address !== input)); + if (removeTokens.has(input)) { + markForRemoval( + (markedForRemoval) => new Set(Array.from(markedForRemoval).filter((address) => address !== input)) + ); } else { markForAddition((markedForAddition) => - markedForAddition.concat( - [input].filter((address) => !markedForAddition.includes(address) && address.length > 0) - ) + input.length > 0 ? new Set(markedForAddition.add(input)) : markedForAddition ); } @@ -41,40 +41,46 @@ export const TokensWhitelistForm = ({ [markForAddition, markForRemoval, removeTokens] ); - const [selected, onSelected] = useState([]); - - const onRemovalRequest = useCallback(() => { - if (selected.some((address) => addTokens.includes(address))) { - markForAddition((markedForAddition) => markedForAddition.filter((address) => !selected.includes(address))); - } - - markForRemoval((markedForRemoval) => - markedForRemoval.concat( - selected.filter((address) => !markedForRemoval.includes(address) && !addTokens.includes(address)) - ) - ); - - editModeSwitch(false); - }, [addTokens, editModeSwitch, markForAddition, markForRemoval, selected]); + const onRemovalRequest = useCallback( + (input: string) => { + if (addTokens.has(input)) { + markForAddition( + (markedForAddition) => new Set(Array.from(markedForAddition).filter((address) => address !== input)) + ); + } else { + markForRemoval((markedForRemoval) => new Set(markedForRemoval.add(input))); + } + }, + [addTokens, editModeSwitch, markForAddition, markForRemoval] + ); const formReset = useCallback(() => { - markForAddition([]); - markForRemoval([]); + markForAddition(new Set()); + markForRemoval(new Set()); editModeSwitch(false); }, [editModeSwitch, markForAddition, markForRemoval]); useEffect(disabled ? formReset : Fn.returnVoid, [disabled, formReset]); - useEffect(() => onEdit({ addTokens, removeTokens }), [addTokens, removeTokens, onEdit]); + useEffect( + () => onEdit({ addTokens: Array.from(addTokens), removeTokens: Array.from(removeTokens) }), + [addTokens, removeTokens, onEdit] + ); return ( <>, + End: editModeEnabled + ? ({ rowId }) => ( + onRemovalRequest(rowId)}> + + + ) + : void null, }, }} - additionalItems={addTokens} + additionalItems={Array.from(addTokens)} footer={ editModeEnabled ? ( - {selected.length > 0 && ( - - - - )} - - - - - + + + ) : ( editModeSwitch(true)}> ), }} - onItemsSelected={editModeEnabled ? onSelected : null} {...{ className, controllerContractAddress }} /> ); diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 1128c402..fb5df8bf 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -108,7 +108,7 @@ display: none; } - &:last-child { + &:last-of-type { font-size: size.$large-text; } } @@ -179,6 +179,10 @@ &--end { justify-content: end; } + + > * { + position: absolute; + } } } } From 62325bbbb649b7aaf7c1b08410490d84036dc8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 28 Oct 2022 11:51:49 +0400 Subject: [PATCH 332/537] fix: Use updated prop name & Remove unused code --- src/features/job-settings-edit/ui/job-settings-form.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index b3d6dc19..803e94ad 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -1,7 +1,6 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; -import clsx from "clsx"; -import { useCallback, useEffect, useMemo, useReducer, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { ArgsString } from "../../../shared/lib/args"; import { toNEAR, toYocto } from "../../../shared/lib/converter"; @@ -11,8 +10,6 @@ import { type JobSettingsEditFeature } from "../config"; interface JobSettingsFormProps extends JobSettingsEditFeature.Dependencies {} -const _JobSettings = "JobSettings"; - export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit }: JobSettingsFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); @@ -52,7 +49,7 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit classes={{ root: className }} heading="Jobs settings" headingCorners={{ - right: editModeEnabled ? ( + end: editModeEnabled ? ( <> {(croncatManager.length > 0 || jobBond.length > 0) && ( editModeSwitch(false)}> From 1b4e33213c6330db96cbeb018562a2ef1cdf3ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 28 Oct 2022 12:24:37 +0400 Subject: [PATCH 333/537] wip: Update styles for dense tables --- src/shared/ui/components/table/row.scss | 10 +++------- src/shared/ui/components/table/table.scss | 4 ++++ src/shared/ui/components/table/table.tsx | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index fb5df8bf..f1bbe008 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -27,14 +27,10 @@ &--compact { display: flex; flex-direction: column; - gap: 0.5 * size.$gap; + gap: calc(size.$gap / 2); border-radius: size.$task-radius; - padding: size.$gap * 0.5; + padding: calc(size.$gap / 2); background-color: color.$white; - - &--dense { - padding: calc(size.$gap * 0.4) calc(size.$gap * 0.6); - } } &-content { @@ -52,7 +48,7 @@ &:not(&--dense) { &:first-of-type { - padding: size.$gap * 0.5; + padding: calc(size.$gap / 2); } } diff --git a/src/shared/ui/components/table/table.scss b/src/shared/ui/components/table/table.scss index 7e5e6850..b45317b5 100644 --- a/src/shared/ui/components/table/table.scss +++ b/src/shared/ui/components/table/table.scss @@ -39,4 +39,8 @@ flex-flow: column nowrap; gap: size.$gap; } + + &--compact.Table--dense { + gap: calc(size.$gap / 2); + } } diff --git a/src/shared/ui/components/table/table.tsx b/src/shared/ui/components/table/table.tsx index 39921198..4c992bc8 100644 --- a/src/shared/ui/components/table/table.tsx +++ b/src/shared/ui/components/table/table.tsx @@ -71,7 +71,7 @@ export const Table = ({ {classicModeRequired && (
    - + {header.map((headerCell, index) => ( {headerCell} @@ -96,7 +96,7 @@ export const Table = ({ )} {compactModeRequired && ( -
    +
    {rows && rows.map((row, index) => ( Date: Fri, 28 Oct 2022 11:57:59 +0200 Subject: [PATCH 334/537] fix: proposal info not getting into tx --- .../ui/multicall-config-editor.tsx | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index 75a0fb2d..a99b6349 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -30,8 +30,8 @@ export const MulticallConfigEditorUI = ({ croncatManager: "", }; - const [formState, formStateUpdate] = useState(changesDiffInitialState), - [proposalDescription, proposalDescriptionUpdate] = useState(""); + const [formState, formStateUpdate] = useState(changesDiffInitialState); + const [proposalDescription, proposalDescriptionUpdate] = useState(""); const formReset = useCallback( () => formStateUpdate(changesDiffInitialState), @@ -59,21 +59,23 @@ export const MulticallConfigEditorUI = ({ [editModeSwitch, formState, formStateUpdate, proposalDescription] ); - const onSubmit = useCallback(() => { - SputnikDAOContract.init(controllerContractAddress) - .then((instanceController) => - instanceController - .proposeFunctionCall( - proposalDescription, - multicallContract.address, - MulticallContract.configDiffToProposalActions(formState) - ) - .then((someTx) => signAndSendTxs([someTx])) - ) - .catch(console.error); - - editModeSwitch(false); - }, [controllerContractAddress, editModeSwitch]); + const onSubmit = useCallback( + (event: React.MouseEvent) => { + event.preventDefault(); + SputnikDAOContract.init(controllerContractAddress) + .then((instanceController) => + instanceController + .proposeFunctionCall( + proposalDescription, + multicallContract.address, + MulticallContract.configDiffToProposalActions(formState) + ) + .then((someTx) => signAndSendTxs([someTx])) + ) + .catch(console.error); + }, + [controllerContractAddress, proposalDescription] + ); return (
    @@ -129,6 +131,8 @@ export const MulticallConfigEditorUI = ({ proposalDescription.length === 0 } label="Submit" + // clicking buttons inside a from element can lead to page refresh. + // IMPORTANT: call event.preventDefault() inside the click handler. onClick={onSubmit} /> From 032fab75e3643183783de2e9118f5503096f2098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 31 Oct 2022 16:06:44 +0400 Subject: [PATCH 335/537] wip: Apply minor amendments --- src/entities/multicall-instance/config.ts | 8 +++- .../multicall-instance/model/mi-admins.ts | 12 +++--- .../multicall-instance/model/mi-tokens.ts | 12 +++--- .../multicall-instance/ui/mi-admins.tsx | 7 +--- .../ui/mi-tokens-whitelist.tsx | 4 +- src/features/job-settings-edit/config.ts | 2 +- .../ui/tokens-whitelist-form.tsx | 9 +---- src/pages/dao/config/config.tsx | 4 +- src/pages/dao/dao.tsx | 33 ++++++++--------- src/shared/lib/contracts/multicall.ts | 8 ++-- src/widgets/multicall-config-editor/config.ts | 9 +++-- .../ui/multicall-config-editor.tsx | 37 ++++++++----------- 12 files changed, 65 insertions(+), 80 deletions(-) diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/config.ts index 441cde59..f98edd66 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/config.ts @@ -1,12 +1,13 @@ import { type MulticallConfigChanges } from "../../shared/lib/contracts/multicall"; import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; +import { toYocto } from "../../shared/lib/converter"; /** * Type declaration for Multicall Instance entity */ namespace MulticallInstanceEntity { export interface Dependencies { - controllerContractAddress: SputnikDAOContract["address"]; + daoContractAddress: SputnikDAOContract["address"]; } export type ConfigChanges = MulticallConfigChanges; @@ -16,7 +17,10 @@ namespace MulticallInstanceEntity { * Multicall Instance entity config */ class MulticallInstanceEntityConfig { - // all the constants must be grouped in objects whenever it's possible and stored here as static properties + /** + * Minimum balance needed for storage + state. + */ + static MIN_BALANCE = toYocto(1 /* NEAR */); } export { MulticallInstanceEntityConfig, type MulticallInstanceEntity }; diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index bcd9e98d..3c330e51 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -14,17 +14,15 @@ export type MulticallInstanceAdminsAddressList = { export class MulticallInstanceAdminsModel { static addressListFetchFx = async ( - controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"], + daoContractAddress: MulticallInstanceEntity.Dependencies["daoContractAddress"], callback: (result: MulticallInstanceAdminsAddressList) => void ) => await MulticallContract.instanceDataFetchFx( - `${ArgsAccount.deconstructAddress(controllerContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, + `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) ); - static useAddressList = ( - controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"] - ) => { + static useAddressList = (daoContractAddress: MulticallInstanceEntity.Dependencies["daoContractAddress"]) => { const [state, stateUpdate] = useState({ data: null, error: null, @@ -32,8 +30,8 @@ export class MulticallInstanceAdminsModel { }); useEffect( - () => void MulticallInstanceAdminsModel.addressListFetchFx(controllerContractAddress, stateUpdate), - [controllerContractAddress, stateUpdate] + () => void MulticallInstanceAdminsModel.addressListFetchFx(daoContractAddress, stateUpdate), + [daoContractAddress, stateUpdate] ); return state; diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index 08b1fc1d..3d5db96e 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -14,19 +14,17 @@ export type MulticallInstanceTokensWhitelist = { export class MulticallInstanceTokensModel { static whitelistFetchFx = async ( - controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"], + daoContractAddress: MulticallInstanceEntity.Dependencies["daoContractAddress"], callback: (result: MulticallInstanceTokensWhitelist) => void ) => await MulticallContract.instanceDataFetchFx( - `${ArgsAccount.deconstructAddress(controllerContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, + `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, (multicallInstanceData) => callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) ); - static useWhitelist = ( - controllerContractAddress: MulticallInstanceEntity.Dependencies["controllerContractAddress"] - ) => { + static useWhitelist = (daoContractAddress: MulticallInstanceEntity.Dependencies["daoContractAddress"]) => { const [state, stateUpdate] = useState({ data: null, error: null, @@ -34,8 +32,8 @@ export class MulticallInstanceTokensModel { }); useEffect( - () => void MulticallInstanceTokensModel.whitelistFetchFx(controllerContractAddress, stateUpdate), - [controllerContractAddress, stateUpdate] + () => void MulticallInstanceTokensModel.whitelistFetchFx(daoContractAddress, stateUpdate), + [daoContractAddress, stateUpdate] ); return state; diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index ab66bf82..dd0ea3f0 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -8,11 +8,8 @@ interface MulticallInstanceAdminsTableProps extends MulticallInstanceEntity.Depe className?: string; } -export const MulticallInstanceAdminsTable = ({ - className, - controllerContractAddress, -}: MulticallInstanceAdminsTableProps) => { - const { data, error, loading } = MulticallInstanceAdminsModel.useAddressList(controllerContractAddress); +export const MulticallInstanceAdminsTable = ({ className, daoContractAddress }: MulticallInstanceAdminsTableProps) => { + const { data, error, loading } = MulticallInstanceAdminsModel.useAddressList(daoContractAddress); return ( { - const { data, error, loading } = MulticallInstanceTokensModel.useWhitelist(controllerContractAddress); + const { data, error, loading } = MulticallInstanceTokensModel.useWhitelist(daoContractAddress); return ( , "onChange">, - Pick { + Pick { multicallContract: MulticallContract; onEdit: (payload: FormState) => void; } diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index 8c2f4567..8f3ba558 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -10,12 +10,7 @@ import { type TokensWhitelistEditFeature } from "../config"; interface TokensWhitelistFormProps extends TokensWhitelistEditFeature.Dependencies {} -export const TokensWhitelistForm = ({ - className, - controllerContractAddress, - disabled, - onEdit, -}: TokensWhitelistFormProps) => { +export const TokensWhitelistForm = ({ className, daoContractAddress, disabled, onEdit }: TokensWhitelistFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); const [addTokens, markForAddition] = useState(new Set()), @@ -108,7 +103,7 @@ export const TokensWhitelistForm = ({ ), }} - {...{ className, controllerContractAddress }} + {...{ className, daoContractAddress }} /> ); }; diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 7226270d..f9089270 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -9,12 +9,12 @@ interface DaoConfigTabUIProps extends HTMLProps, MulticallConfig const _DaoConfigTab = "DaoConfigTab"; -const DaoConfigTabUI = ({ className, controllerContractAddress, multicallContract, ...props }: DaoConfigTabUIProps) => ( +const DaoConfigTabUI = ({ className, contracts, ...props }: DaoConfigTabUIProps) => (
    - +
    ); diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 69dcba5a..a4360e48 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -3,7 +3,7 @@ import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component, ContextType } from "react"; -import { Wallet } from "../../entities"; +import { MulticallInstance, Wallet } from "../../entities"; import { signAndSendTxs } from "../../shared/lib/wallet"; import { ArgsAccount, ArgsError } from "../../shared/lib/args"; import { SputnikDAO, SputnikUI, ProposalStatus } from "../../shared/lib/contracts/sputnik-dao"; @@ -18,16 +18,10 @@ import { DaoJobsTab } from "./jobs/jobs"; import { DaoConfigTab } from "./config/config"; import "./dao.scss"; -// minimum balance a multicall instance needs for storage + state. -const MIN_INSTANCE_BALANCE = toYocto(1); // 1 NEAR const Ctx = Wallet.useSelector(); interface Props {} -enum Mode { - view = "VIEW", - edit = "EDIT", -} interface State { name: ArgsAccount; dao: SputnikDAO; @@ -35,7 +29,6 @@ interface State { loading: boolean; proposed: number; proposedInfo: ProposalOutput | null; - mode?: Mode; } const _DaoPage = "DaoPage"; @@ -141,7 +134,7 @@ export class DaoPage extends Component { return null; } - const depo = Big(this.fee).plus(MIN_INSTANCE_BALANCE); + const depo = Big(this.fee).plus(MulticallInstance.MIN_BALANCE); const daoSearchInput: HTMLInputElement = document.querySelector(".DaoSearch input")!; // can user propose a FunctionCall to DAO? @@ -314,8 +307,10 @@ export class DaoPage extends Component { noContract.isBad = false; noDao.isBad = false; - // chosen address violates NEAR AccountId rules. if (address.isBad) { + /* + * Chosen address violates NEAR AccountId rules. + */ noContract.isBad = true; noDao.isBad = true; @@ -326,7 +321,9 @@ export class DaoPage extends Component { this.setState({ loading: true }); - // initialize DAO and multicall objects + /* + * Initialize DAO and multicall objects + */ Promise.all([ SputnikDAO.init(daoAddress).catch((e) => new SputnikDAO(daoAddress)), Multicall.init(multicallAddress).catch((e) => new Multicall(multicallAddress)), @@ -343,7 +340,9 @@ export class DaoPage extends Component { return; } else { - // DAO correctly initialized, try to fetch multicall info + /* + * DAO correctly initialized, try to fetch multicall info + */ Promise.all([this.proposalAlreadyExists(dao).catch(console.error)]).then(([proposalData]) => this.setState(({ proposed }) => ({ dao, @@ -392,7 +391,9 @@ export class DaoPage extends Component { if (loading) return
    ; - // everything should be loaded + /* + * Everything should be loaded + */ if (!multicall.admins || !multicall.tokensWhitelist || !multicall.jobBond) { console.error("multicall infos incomplete", multicall); return
    Unexpected error! Multicall might be outdated.
    ; @@ -402,11 +403,7 @@ export class DaoPage extends Component { void ) => callback( await Multicall.init( - `${ArgsAccount.deconstructAddress(controllerContractAddress).name}.${Multicall.FACTORY_ADDRESS}` + `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${Multicall.FACTORY_ADDRESS}` ) .then((multicallInstance) => ({ data: multicallInstance, @@ -152,7 +152,7 @@ class Multicall { })) .catch((error) => ({ data: null, - error: new Error(error), + error, loading: false, })) ); diff --git a/src/widgets/multicall-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts index 989fe15b..31815b7d 100644 --- a/src/widgets/multicall-config-editor/config.ts +++ b/src/widgets/multicall-config-editor/config.ts @@ -1,11 +1,12 @@ import { HTMLProps } from "react"; import { JobSettingsEditFeature, TokensWhitelistEditFeature } from "../../features"; +import { MulticallContract } from "../../shared/lib/contracts/multicall"; +import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; namespace MulticallConfigEditorWidget { - export interface Dependencies - extends HTMLProps, - Omit, - Omit {} + export interface Dependencies extends HTMLProps { + contracts: { dao: SputnikDAOContract; multicall: MulticallContract }; + } } class MulticallConfigEditorConfig {} diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index a99b6349..00c950bd 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -5,7 +5,6 @@ import { MulticallInstance } from "../../../entities"; import { JobSettingsEdit, TokensWhitelistEdit } from "../../../features"; import { ArgsString } from "../../../shared/lib/args"; import { MulticallContract, type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; -import { SputnikDAOContract } from "../../../shared/lib/contracts/sputnik-dao"; import { signAndSendTxs } from "../../../shared/lib/wallet"; import { Button, ButtonGroup, TextInput, Tile } from "../../../shared/ui/components"; import { type MulticallConfigEditorWidget } from "../config"; @@ -16,11 +15,7 @@ interface MulticallConfigEditorUIProps extends MulticallConfigEditorWidget.Depen const _MulticallConfigEditor = "MulticallConfigEditor"; -export const MulticallConfigEditorUI = ({ - className, - controllerContractAddress, - multicallContract, -}: MulticallConfigEditorUIProps) => { +export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfigEditorUIProps) => { const [editMode, editModeSwitch] = useState(false); const changesDiffInitialState: MulticallConfigChanges = { @@ -62,38 +57,40 @@ export const MulticallConfigEditorUI = ({ const onSubmit = useCallback( (event: React.MouseEvent) => { event.preventDefault(); - SputnikDAOContract.init(controllerContractAddress) - .then((instanceController) => - instanceController - .proposeFunctionCall( - proposalDescription, - multicallContract.address, - MulticallContract.configDiffToProposalActions(formState) - ) - .then((someTx) => signAndSendTxs([someTx])) + + void contracts.dao + .proposeFunctionCall( + proposalDescription, + contracts.multicall.address, + MulticallContract.configDiffToProposalActions(formState) ) + .then((someTx) => signAndSendTxs([someTx])) .catch(console.error); }, - [controllerContractAddress, proposalDescription] + + [contracts, proposalDescription] ); return (
    From 7a2026efc6e107e2bb50e222b80f6cda55382fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 31 Oct 2022 18:43:52 +0400 Subject: [PATCH 336/537] fix: Reset child forms properly --- src/features/job-settings-edit/config.ts | 1 + .../ui/job-settings-form.tsx | 29 ++++++----- src/features/tokens-whitelist-edit/config.ts | 1 + .../ui/tokens-whitelist-form.tsx | 11 +++-- .../ui/multicall-config-editor.tsx | 48 +++++++++++++------ 5 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/features/job-settings-edit/config.ts b/src/features/job-settings-edit/config.ts index d0943803..ea3b7677 100644 --- a/src/features/job-settings-edit/config.ts +++ b/src/features/job-settings-edit/config.ts @@ -9,6 +9,7 @@ namespace JobSettingsEditFeature { Pick { multicallContract: MulticallContract; onEdit: (payload: FormState) => void; + resetTrigger: (callback: EventListener) => void; } export type FormState = Pick; diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index 803e94ad..39ce745d 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -4,13 +4,18 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { ArgsString } from "../../../shared/lib/args"; import { toNEAR, toYocto } from "../../../shared/lib/converter"; -import { Fn } from "../../../shared/lib/fn"; import { IconLabel, NearIcons, NearLink, Table, TextInput, Tile } from "../../../shared/ui/components"; import { type JobSettingsEditFeature } from "../config"; interface JobSettingsFormProps extends JobSettingsEditFeature.Dependencies {} -export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit }: JobSettingsFormProps) => { +export const JobSettingsForm = ({ + className, + disabled, + multicallContract, + onEdit, + resetTrigger, +}: JobSettingsFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); const formInitialState = { croncatManager: "", jobBond: "" }; @@ -30,17 +35,15 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit }; const formReset = useCallback(() => { - croncatManagerUpdate(formInitialState.croncatManager); - jobBondUpdate(formInitialState.jobBond); - editModeSwitch(false); + formFields.croncatManager.value = multicallContract.croncatManager; + formFields.jobBond.value = toNEAR(multicallContract.jobBond); + + void croncatManagerUpdate(formInitialState.croncatManager); + void jobBondUpdate(formInitialState.jobBond); + void editModeSwitch(false); }, [croncatManagerUpdate, editModeSwitch, formInitialState, jobBondUpdate]); - useEffect(disabled && croncatManager.length > 0 && jobBond.length > 0 ? formReset : Fn.returnVoid, [ - croncatManager, - disabled, - formReset, - jobBond, - ]); + useEffect(() => resetTrigger(formReset), [formReset, resetTrigger]); useEffect(() => onEdit({ croncatManager, jobBond }), [croncatManager, jobBond, onEdit]); @@ -83,7 +86,7 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit editModeEnabled ? ( croncatManagerUpdate(event.target.value)} + update={(event) => void croncatManagerUpdate(event.target.value)} value={formFields.croncatManager} /> ) : ( @@ -103,7 +106,7 @@ export const JobSettingsForm = ({ className, disabled, multicallContract, onEdit endAdornment: NearIcons.NATIVE_TOKEN_CHARACTER, inputProps: { min: 0, step: 0.001 }, }} - update={(event) => jobBondUpdate(toYocto(event.target.value))} + update={(event) => void jobBondUpdate(toYocto(event.target.value))} type="number" value={formFields.jobBond} /> diff --git a/src/features/tokens-whitelist-edit/config.ts b/src/features/tokens-whitelist-edit/config.ts index 42d67cda..ef18a850 100644 --- a/src/features/tokens-whitelist-edit/config.ts +++ b/src/features/tokens-whitelist-edit/config.ts @@ -7,6 +7,7 @@ namespace TokensWhitelistEditFeature { extends Omit, "onChange">, MulticallInstanceEntity.Dependencies { onEdit: (payload: Pick) => void; + resetTrigger: (callback: EventListener) => void; } export interface FormStates diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index 8f3ba558..54ebd486 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -3,14 +3,19 @@ import { IconButton } from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; import { TextInput } from "../../../shared/ui/components"; -import { Fn } from "../../../shared/lib/fn"; import { ArgsString } from "../../../shared/lib/args"; import { MulticallInstance } from "../../../entities"; import { type TokensWhitelistEditFeature } from "../config"; interface TokensWhitelistFormProps extends TokensWhitelistEditFeature.Dependencies {} -export const TokensWhitelistForm = ({ className, daoContractAddress, disabled, onEdit }: TokensWhitelistFormProps) => { +export const TokensWhitelistForm = ({ + className, + daoContractAddress, + disabled, + onEdit, + resetTrigger, +}: TokensWhitelistFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); const [addTokens, markForAddition] = useState(new Set()), @@ -55,7 +60,7 @@ export const TokensWhitelistForm = ({ className, daoContractAddress, disabled, o editModeSwitch(false); }, [editModeSwitch, markForAddition, markForRemoval]); - useEffect(disabled ? formReset : Fn.returnVoid, [disabled, formReset]); + useEffect(() => resetTrigger(formReset), [formReset, resetTrigger]); useEffect( () => onEdit({ addTokens: Array.from(addTokens), removeTokens: Array.from(removeTokens) }), diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index 00c950bd..24299c72 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -25,30 +25,44 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi croncatManager: "", }; - const [formState, formStateUpdate] = useState(changesDiffInitialState); - const [proposalDescription, proposalDescriptionUpdate] = useState(""); + const [formState, formStateUpdate] = useState(changesDiffInitialState), + formValues = { proposalDescription: useMemo(() => new ArgsString(""), []) }, + [proposalDescription, proposalDescriptionUpdate] = useState(formValues.proposalDescription.value), + _childFormsResetRequested = "childFormsResetRequested"; - const formReset = useCallback( - () => formStateUpdate(changesDiffInitialState), - [formStateUpdate, changesDiffInitialState] - ); + const childFormsResetRequested = { + dispatch: () => document.dispatchEvent(new CustomEvent(_childFormsResetRequested)), + + subscribe: (callback: EventListener) => { + void document.addEventListener(_childFormsResetRequested, callback); + + return () => void document.removeEventListener(_childFormsResetRequested, callback); + }, + }; + + const formReset = useCallback(() => { + void childFormsResetRequested.dispatch(); + void proposalDescriptionUpdate(""); + void formStateUpdate(changesDiffInitialState); + + formValues.proposalDescription.value = ""; + }, [formStateUpdate, changesDiffInitialState]); const onCancel = useCallback(() => { - formReset(); - editModeSwitch(false); - }, [editModeSwitch, formReset]); + void formReset(); + void editModeSwitch(false); + }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( (update: Partial) => { - formStateUpdate((latestState) => Object.assign(latestState, update)); + void formStateUpdate((latestState) => Object.assign(latestState, update)); - editModeSwitch( + void editModeSwitch( Object.values(Object.assign(formState, update)).filter(({ length }) => length > 0).length > 0 ); // TODO: Remove before release. This is for debug purposes only - console.table({ proposalDescription }); - console.table(formState); + console.table({ proposalDescription, ...formState }); }, [editModeSwitch, formState, formStateUpdate, proposalDescription] @@ -56,7 +70,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi const onSubmit = useCallback( (event: React.MouseEvent) => { - event.preventDefault(); + void event.preventDefault(); void contracts.dao .proposeFunctionCall( @@ -82,6 +96,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi className={_MulticallConfigEditor + "-tokensWhitelist"} daoContractAddress={contracts.dao.address} disabled={!editMode} + resetTrigger={childFormsResetRequested.subscribe} {...{ onEdit }} /> @@ -90,6 +105,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi daoContractAddress={contracts.dao.address} disabled={!editMode} multicallContract={contracts.multicall} + resetTrigger={childFormsResetRequested.subscribe} {...{ onEdit }} /> @@ -110,7 +126,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi multiline required update={(event) => void proposalDescriptionUpdate(event.target.value)} - value={useMemo(() => new ArgsString(""), [])} + value={formValues.proposalDescription} />
    @@ -119,6 +135,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi color="error" label="Cancel" onClick={onCancel} + type="reset" />
    - + {header.map((headerCell, index) => ( {headerCell} @@ -103,7 +103,7 @@ export const Table = ({ )} {compactModeRequired && ( -
    +
    {rows && rows.map((row, index) => ( Date: Wed, 2 Nov 2022 21:30:45 +0400 Subject: [PATCH 341/537] wip: Export TextInput-like proptypes --- src/shared/ui/components/index.ts | 2 +- src/shared/ui/components/text-input/index.ts | 2 +- src/shared/ui/components/text-input/text-input.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/ui/components/index.ts b/src/shared/ui/components/index.ts index ac9388e4..187850d7 100644 --- a/src/shared/ui/components/index.ts +++ b/src/shared/ui/components/index.ts @@ -10,7 +10,7 @@ export { Tooltip } from "./tooltip"; /** Molecules */ export { IconLabel } from "./icon-label"; -export { TextInput, TextInputWithUnits } from "./text-input"; +export { TextInput, type TextInputProps, TextInputWithUnits, type TextInputWithUnitsProps } from "./text-input"; export { Tile, type TileProps } from "./tile"; /** Organisms */ diff --git a/src/shared/ui/components/text-input/index.ts b/src/shared/ui/components/text-input/index.ts index 95be585a..8eafe224 100644 --- a/src/shared/ui/components/text-input/index.ts +++ b/src/shared/ui/components/text-input/index.ts @@ -1 +1 @@ -export { TextInput, TextInputWithUnits } from "./text-input"; +export { TextInput, type TextInputProps, TextInputWithUnits, type TextInputWithUnitsProps } from "./text-input"; diff --git a/src/shared/ui/components/text-input/text-input.tsx b/src/shared/ui/components/text-input/text-input.tsx index 2761b63e..a74ca6c9 100644 --- a/src/shared/ui/components/text-input/text-input.tsx +++ b/src/shared/ui/components/text-input/text-input.tsx @@ -3,7 +3,7 @@ import { MenuItem, TextField, TextFieldProps } from "@mui/material"; import { ArgsError, ArgsString } from "../../../lib/args"; -interface TextInputProps extends Omit { +export interface TextInputProps extends Omit { error?: ArgsError; update?: (event: ChangeEvent, component: Component) => void; value?: ArgsString; @@ -37,7 +37,7 @@ export class TextInput extends Component { } } -interface TextInputWithUnitsProps extends TextInputProps { +export interface TextInputWithUnitsProps extends TextInputProps { value: ArgsString; // TODO!: Extend the interface } From e0a9381354e47a9f22b5a1bf278f5a89c489f5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 2 Nov 2022 21:32:35 +0400 Subject: [PATCH 342/537] wip: Use safer and more flexible typings --- src/shared/lib/contracts/multicall.ts | 47 ++++++++++++++++++--------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index e806b53c..368ae3ca 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -57,7 +57,7 @@ type FunctionCall = { }; type BatchCall = { - address: string; + address: Account["accountId"]; actions: FunctionCall[]; }; @@ -65,27 +65,37 @@ type MulticallArgs = { calls: BatchCall[][]; }; -class MulticallConfigChanges { - removeTokens: string[] = []; - addTokens: string[] = []; - jobBond: string = ""; - croncatManager: string = ""; +enum MulticallConfigParamKey { + croncatManager = "croncatManager", + jobBond = "jobBond", } +enum MulticallTokensWhitelistDiffKey { + addTokens = "addTokens", + removeTokens = "removeTokens", +} + +type MulticallConfigDiff = { + [MulticallTokensWhitelistDiffKey.removeTokens]: string[]; + [MulticallTokensWhitelistDiffKey.addTokens]: string[]; + [MulticallConfigParamKey.jobBond]: string; + [MulticallConfigParamKey.croncatManager]: string; +}; + class Multicall { static FACTORY_ADDRESS: string = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; static CONTRACT_CODE_HASHES: string[] = CONTRACT_CODE_HASHES_SELECTOR[window.NEAR_ENV]; // 0.025 NEAR is the min required by croncat for a non-recurring task. Assume trigger of 270 Tgas and 0 NEAR. static CRONCAT_FEE: string = toYocto("0.0275"); - address: string; + address: Account["accountId"]; admins: MulticallAdminData[] = []; - croncatManager: string = ""; + [MulticallConfigParamKey.croncatManager]: string = ""; // only whitelisted tokens can be attached to multicalls or job activations. tokensWhitelist: WhitelistedTokenData[] = []; // job bond amount must be attached as deposit when adding new jobs. // needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). - jobBond: string = ""; + [MulticallConfigParamKey.jobBond]: string = ""; // Multicall instance is ready when info (admins...) are fetched & assigned correctly. ready: boolean = false; @@ -119,6 +129,7 @@ class Multicall { return ""; }), ]); + newMulticall.admins = admins; newMulticall.croncatManager = croncatManager; newMulticall.tokensWhitelist = tokensWhitelist; @@ -163,7 +174,7 @@ class Multicall { * * @param accountId */ - static async isMulticall(accountId: string): Promise { + static async isMulticall(accountId: Account["accountId"]): Promise { const accountInfo = await viewAccount(accountId); const codeHash: string = accountInfo.code_hash; return Multicall.CONTRACT_CODE_HASHES.includes(codeHash); @@ -184,8 +195,12 @@ class Multicall { * @param configDiff changes to current config of some multicall instance. * @returns actions that can be passed to JSON for DAO "add_proposal". */ - static configDiffToProposalActions(configDiff: MulticallConfigChanges): daoFunctionCallAction[] { - const { removeTokens, addTokens, jobBond, croncatManager } = configDiff; + static configDiffToProposalActions({ + removeTokens = [], + addTokens = [], + jobBond = "", + croncatManager = "", + }: MulticallConfigDiff): daoFunctionCallAction[] { const actions: daoFunctionCallAction[] = []; // action: change croncat manager address @@ -243,7 +258,7 @@ class Multicall { } /** - * get croncat manager address that was regitered on the multicall instance. + * get croncat manager address that was registered on the multicall instance. */ async getCroncatManager(): Promise { return view(this.address, "get_croncat_manager", {}); @@ -282,7 +297,7 @@ class Multicall { * @param triggerGas Gas amount. Will be allocated for every tx in this job. * @returns */ - // TODO: currenty budget is hard-coded for jobs with 1 multicall + // TODO: currently budget is hard-coded for jobs with 1 multicall async addJob(multicalls: MulticallArgs[], triggerDate: Date, triggerGas: string): Promise { // crontab in CronCat format. See: https://github.com/CronCats/Schedule const cadence: string = dateToCron(triggerDate); @@ -311,5 +326,5 @@ class Multicall { } } -export { Multicall, Multicall as MulticallContract }; -export type { JobData, MulticallArgs, MulticallConfigChanges }; +export { Multicall, Multicall as MulticallContract, MulticallConfigParamKey, MulticallTokensWhitelistDiffKey }; +export type { JobData, MulticallArgs, MulticallConfigDiff }; From 5c6aefe4b40c20f21589d5ff99ebe24a73524d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 2 Nov 2022 21:36:00 +0400 Subject: [PATCH 343/537] fix: Diff is not `Entity`'s scope of responsibility --- src/entities/multicall-instance/config.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/config.ts index f98edd66..ccea3f22 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/config.ts @@ -1,4 +1,3 @@ -import { type MulticallConfigChanges } from "../../shared/lib/contracts/multicall"; import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; import { toYocto } from "../../shared/lib/converter"; @@ -9,8 +8,6 @@ namespace MulticallInstanceEntity { export interface Dependencies { daoContractAddress: SputnikDAOContract["address"]; } - - export type ConfigChanges = MulticallConfigChanges; } /** From 749c17bf68430c3d815807aa4b0153a8e217b554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 2 Nov 2022 21:40:10 +0400 Subject: [PATCH 344/537] wip: Update core typedefs --- src/features/job-settings-edit/config.ts | 17 ++++++++++++++--- src/features/tokens-whitelist-edit/config.ts | 14 ++++++-------- .../ui/multicall-config-editor.tsx | 12 ++++++------ 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/features/job-settings-edit/config.ts b/src/features/job-settings-edit/config.ts index 463f426b..ff8e4ebb 100644 --- a/src/features/job-settings-edit/config.ts +++ b/src/features/job-settings-edit/config.ts @@ -1,9 +1,18 @@ import { HTMLProps } from "react"; import { MulticallInstanceEntity } from "../../entities"; -import { MulticallContract } from "../../shared/lib/contracts/multicall"; + +import { + type MulticallConfigDiff, + MulticallConfigParamKey, + MulticallContract, +} from "../../shared/lib/contracts/multicall"; namespace JobSettingsEditFeature { + export type DiffKey = MulticallConfigParamKey; + + export type FormState = Pick; + export interface Dependencies extends Omit, "onChange">, Pick { @@ -11,8 +20,10 @@ namespace JobSettingsEditFeature { onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } +} - export type FormState = Pick; +class JobSettingsEditConfig { + static DiffKey = MulticallConfigParamKey; } -export { type JobSettingsEditFeature }; +export { JobSettingsEditConfig, type JobSettingsEditFeature }; diff --git a/src/features/tokens-whitelist-edit/config.ts b/src/features/tokens-whitelist-edit/config.ts index 6896ea23..7c1d1518 100644 --- a/src/features/tokens-whitelist-edit/config.ts +++ b/src/features/tokens-whitelist-edit/config.ts @@ -1,24 +1,22 @@ import { HTMLProps } from "react"; +import { type MulticallTokensWhitelistDiffKey, type MulticallConfigDiff } from "../../shared/lib/contracts/multicall"; import { MulticallInstanceEntity } from "../../entities"; namespace TokensWhitelistEditFeature { + export type DiffKey = MulticallTokensWhitelistDiffKey; + export interface Dependencies extends Omit, "onChange">, MulticallInstanceEntity.Dependencies { - onEdit: (payload: Pick) => void; + onEdit: (payload: Pick) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } export interface FormStates extends Record< - keyof Pick, - Set< - MulticallInstanceEntity.ConfigChanges[keyof Pick< - MulticallInstanceEntity.ConfigChanges, - "addTokens" | "removeTokens" - >][number] - > + keyof Pick, + Set][number]> > {} } diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index 4d365fdc..f6166f49 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -1,10 +1,10 @@ import clsx from "clsx"; -import { useCallback, useMemo, useState } from "react"; +import { type MouseEvent, useCallback, useMemo, useState } from "react"; import { MulticallInstance } from "../../../entities"; import { JobSettingsEdit, TokensWhitelistEdit } from "../../../features"; import { ArgsString } from "../../../shared/lib/args"; -import { MulticallContract, type MulticallConfigChanges } from "../../../shared/lib/contracts/multicall"; +import { MulticallContract, type MulticallConfigDiff } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; import { Button, ButtonGroup, TextInput, Tile } from "../../../shared/ui/components"; import { type MulticallConfigEditorWidget } from "../config"; @@ -18,14 +18,14 @@ const _MulticallConfigEditor = "MulticallConfigEditor"; export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfigEditorUIProps) => { const [editMode, editModeSwitch] = useState(false); - const changesDiffInitialState: MulticallConfigChanges = { + const changesDiffInitialState: MulticallConfigDiff = { removeTokens: [], addTokens: [], jobBond: "", croncatManager: "", }; - const [formState, formStateUpdate] = useState(changesDiffInitialState), + const [formState, formStateUpdate] = useState(changesDiffInitialState), formValues = { proposalDescription: useMemo(() => new ArgsString(""), []) }, [proposalDescription, proposalDescriptionUpdate] = useState(formValues.proposalDescription.value), _childFormsResetRequested = "childFormsResetRequested"; @@ -54,7 +54,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( - (update: Partial) => { + (update: Partial) => { void formStateUpdate((latestState) => Object.assign(latestState, update)); void editModeSwitch( @@ -69,7 +69,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi ); const onSubmit = useCallback( - (event: React.MouseEvent) => { + (event: MouseEvent) => { void event.preventDefault(); void contracts.dao From ce0adad76295e890a11d1c0bbc04912cfd6dfd1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 2 Nov 2022 21:42:49 +0400 Subject: [PATCH 345/537] wip: Change highlight color variants --- .../ui/tokens-whitelist-form.tsx | 3 +-- src/shared/ui/components/table/row.scss | 12 ++++++++++-- src/shared/ui/components/table/row.tsx | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index f201adad..a0b7ba5f 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -70,8 +70,7 @@ export const TokensWhitelistForm = ({ return ( - (addTokens.has(id) && "success") || (removeTokens.has(id) && "error") || null, + idToHighlightColor: (id) => (addTokens.has(id) && "green") || (removeTokens.has(id) && "red") || null, slots: { End: editModeEnabled diff --git a/src/shared/ui/components/table/row.scss b/src/shared/ui/components/table/row.scss index 320fd7fd..6dceb5fe 100644 --- a/src/shared/ui/components/table/row.scss +++ b/src/shared/ui/components/table/row.scss @@ -34,13 +34,21 @@ } &--highlighted { - &--success { + &--blue { + background-color: color.$blue; + } + + &--green { background-color: color.$green; } - &--error { + &--red { background-color: color.$red; } + + &--yellow { + background-color: color.$yellow; + } } &-content { diff --git a/src/shared/ui/components/table/row.tsx b/src/shared/ui/components/table/row.tsx index 1df4e83d..0b42e566 100644 --- a/src/shared/ui/components/table/row.tsx +++ b/src/shared/ui/components/table/row.tsx @@ -18,7 +18,7 @@ export interface TableRowProps { entitled?: boolean; header: TableHeader; id: string; - idToHighlightColor?: (id: TableRowProps["id"]) => "success" | "error" | null; + idToHighlightColor?: (id: TableRowProps["id"]) => "blue" | "green" | "red" | "yellow" | null; noKeys?: boolean; onSelect?: (selectedRow: { id: TableRowProps["id"]; checked: boolean }) => void; selectable: boolean; From 4b9f15a6b227f507488fc10b78cb54a05ce2e70e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 2 Nov 2022 21:44:11 +0400 Subject: [PATCH 346/537] wip: Implement changes color highlighting for job settings --- .../ui/job-settings-form.tsx | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index f7bae16f..407fc1da 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -4,8 +4,8 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { ArgsString } from "../../../shared/lib/args"; import { toNEAR, toYocto } from "../../../shared/lib/converter"; -import { IconLabel, NearIcons, NearLink, Table, TextInput, Tile } from "../../../shared/ui/components"; -import { type JobSettingsEditFeature } from "../config"; +import { IconLabel, NearIcons, NearLink, Table, TextInput, TextInputProps, Tile } from "../../../shared/ui/components"; +import { JobSettingsEditConfig, type JobSettingsEditFeature } from "../config"; interface JobSettingsFormProps extends JobSettingsEditFeature.Dependencies {} @@ -18,7 +18,10 @@ export const JobSettingsForm = ({ }: JobSettingsFormProps) => { const [editModeEnabled, editModeSwitch] = useState(!disabled); - const formInitialState = { croncatManager: "", jobBond: "" }; + const formInitialState: JobSettingsEditFeature.FormState = { + [JobSettingsEditConfig.DiffKey.croncatManager]: "", + [JobSettingsEditConfig.DiffKey.jobBond]: "", + }; const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ useState(formInitialState.croncatManager), @@ -34,6 +37,11 @@ export const JobSettingsForm = ({ ), }; + const onCroncatManagerChange = useCallback["update"]>( + (event) => void croncatManagerUpdate(event.target.value), + [croncatManagerUpdate] + ); + const formReset = useCallback(() => { formFields.croncatManager.value = multicallContract.croncatManager; formFields.jobBond.value = toNEAR(multicallContract.jobBond); @@ -72,13 +80,24 @@ export const JobSettingsForm = ({ }} >
    + ({ croncatManager, jobBond }[id] === formInitialState[id as JobSettingsEditFeature.DiffKey] || + { croncatManager, jobBond }[id] === multicallContract[id as JobSettingsEditFeature.DiffKey] + ? null + : "blue"), + + entitled: true, + noKeys: true, + }} displayMode="compact" dense header={["Option", "Value"]} rows={[ { - id: "croncatManager", + id: JobSettingsEditConfig.DiffKey.croncatManager, content: [ "Croncat manager", @@ -86,7 +105,7 @@ export const JobSettingsForm = ({ editModeEnabled ? ( void croncatManagerUpdate(event.target.value)} + update={onCroncatManagerChange} value={formFields.croncatManager} /> ) : ( @@ -95,7 +114,7 @@ export const JobSettingsForm = ({ ], }, { - id: "jobBond", + id: JobSettingsEditConfig.DiffKey.jobBond, content: [ "Job bond", From a0429c2524bdb1e3608f5415c2def81e62bab69c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 2 Nov 2022 22:01:32 +0400 Subject: [PATCH 347/537] feat: Implement removal mark rollback --- .../ui/tokens-whitelist-form.tsx | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index a0b7ba5f..2a5a4169 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -1,4 +1,4 @@ -import { CancelOutlined, DeleteOutlined, EditOutlined } from "@mui/icons-material"; +import { CancelOutlined, DeleteOutlined, EditOutlined, SettingsBackupRestoreOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; @@ -73,13 +73,19 @@ export const TokensWhitelistForm = ({ idToHighlightColor: (id) => (addTokens.has(id) && "green") || (removeTokens.has(id) && "red") || null, slots: { - End: editModeEnabled - ? ({ rowId }) => ( - void onRemovalRequest(rowId)}> - - - ) - : void null, + End: + (editModeEnabled && + (({ rowId }) => + removeTokens.has(rowId) ? ( + void onAdditionRequest(rowId)}> + + + ) : ( + void onRemovalRequest(rowId)}> + + + ))) || + void null, }, }} footer={ From cca04b0cd3aa01050b45a02f9bb0b7648e203a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 2 Nov 2022 22:06:37 +0400 Subject: [PATCH 348/537] wip: Fix type incompatibility --- .../multicall-config-editor/ui/multicall-config-editor.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index f6166f49..4a1fd0e6 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import { type MouseEvent, useCallback, useMemo, useState } from "react"; +import { type MouseEventHandler, useCallback, useMemo, useState } from "react"; import { MulticallInstance } from "../../../entities"; import { JobSettingsEdit, TokensWhitelistEdit } from "../../../features"; @@ -68,8 +68,8 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi [editModeSwitch, formState, formStateUpdate, proposalDescription] ); - const onSubmit = useCallback( - (event: MouseEvent) => { + const onSubmit = useCallback( + (event) => { void event.preventDefault(); void contracts.dao From ca686e90eee7cbff02bcd2df44136f3cd4890e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 2 Nov 2022 22:29:28 +0400 Subject: [PATCH 349/537] wip: Expose configs & Update typedefs --- src/features/job-settings-edit/index.ts | 4 ++-- src/features/tokens-whitelist-edit/config.ts | 8 ++++++-- src/features/tokens-whitelist-edit/index.ts | 4 ++-- .../ui/multicall-config-editor.tsx | 8 ++++---- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/features/job-settings-edit/index.ts b/src/features/job-settings-edit/index.ts index 49442991..d8b39e7b 100644 --- a/src/features/job-settings-edit/index.ts +++ b/src/features/job-settings-edit/index.ts @@ -1,7 +1,7 @@ -import { type JobSettingsEditFeature } from "./config"; +import { JobSettingsEditConfig, type JobSettingsEditFeature } from "./config"; import { JobSettingsForm } from "./ui/job-settings-form"; -class JobSettingsEdit { +class JobSettingsEdit extends JobSettingsEditConfig { static Form = JobSettingsForm; } diff --git a/src/features/tokens-whitelist-edit/config.ts b/src/features/tokens-whitelist-edit/config.ts index 7c1d1518..b58728ac 100644 --- a/src/features/tokens-whitelist-edit/config.ts +++ b/src/features/tokens-whitelist-edit/config.ts @@ -1,6 +1,6 @@ import { HTMLProps } from "react"; -import { type MulticallTokensWhitelistDiffKey, type MulticallConfigDiff } from "../../shared/lib/contracts/multicall"; +import { MulticallTokensWhitelistDiffKey, type MulticallConfigDiff } from "../../shared/lib/contracts/multicall"; import { MulticallInstanceEntity } from "../../entities"; namespace TokensWhitelistEditFeature { @@ -20,4 +20,8 @@ namespace TokensWhitelistEditFeature { > {} } -export { type TokensWhitelistEditFeature }; +class TokensWhitelistEditConfig { + static DiffKey = MulticallTokensWhitelistDiffKey; +} + +export { TokensWhitelistEditConfig, type TokensWhitelistEditFeature }; diff --git a/src/features/tokens-whitelist-edit/index.ts b/src/features/tokens-whitelist-edit/index.ts index 66aec675..8970904e 100644 --- a/src/features/tokens-whitelist-edit/index.ts +++ b/src/features/tokens-whitelist-edit/index.ts @@ -1,7 +1,7 @@ -import { type TokensWhitelistEditFeature } from "./config"; +import { TokensWhitelistEditConfig, type TokensWhitelistEditFeature } from "./config"; import { TokensWhitelistForm } from "./ui/tokens-whitelist-form"; -class TokensWhitelistEdit { +class TokensWhitelistEdit extends TokensWhitelistEditConfig { static Form = TokensWhitelistForm; } diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index 4a1fd0e6..cd146a18 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -19,10 +19,10 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi const [editMode, editModeSwitch] = useState(false); const changesDiffInitialState: MulticallConfigDiff = { - removeTokens: [], - addTokens: [], - jobBond: "", - croncatManager: "", + [TokensWhitelistEdit.DiffKey.removeTokens]: [], + [TokensWhitelistEdit.DiffKey.addTokens]: [], + [JobSettingsEdit.DiffKey.jobBond]: "", + [JobSettingsEdit.DiffKey.croncatManager]: "", }; const [formState, formStateUpdate] = useState(changesDiffInitialState), From da3c4f7a9d75d9eeb585a25b90c9d4f1e948e3dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 3 Nov 2022 13:52:08 +0400 Subject: [PATCH 350/537] fix: Reset form value if it's identical to contract's one --- .../ui/job-settings-form.tsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index 407fc1da..9e57f8d2 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -29,19 +29,30 @@ export const JobSettingsForm = ({ ]; const formFields = { - croncatManager: useMemo(() => new ArgsString(multicallContract.croncatManager), [disabled]), + croncatManager: useMemo(() => new ArgsString(multicallContract.croncatManager), [disabled, multicallContract]), jobBond: useMemo( () => new ArgsString(multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : ""), - [disabled] + [disabled, multicallContract] ), }; const onCroncatManagerChange = useCallback["update"]>( - (event) => void croncatManagerUpdate(event.target.value), + ({ target: { value } }) => + void croncatManagerUpdate( + value !== multicallContract.croncatManager ? value : formInitialState.croncatManager + ), + [croncatManagerUpdate] ); + const onJobBondChange = useCallback["update"]>( + ({ target: { value } }) => + void jobBondUpdate(value !== toNEAR(multicallContract.jobBond) ? toYocto(value) : formInitialState.jobBond), + + [jobBondUpdate] + ); + const formReset = useCallback(() => { formFields.croncatManager.value = multicallContract.croncatManager; formFields.jobBond.value = toNEAR(multicallContract.jobBond); @@ -125,7 +136,7 @@ export const JobSettingsForm = ({ endAdornment: NearIcons.NATIVE_TOKEN_CHARACTER, inputProps: { min: 0, step: 0.001 }, }} - update={(event) => void jobBondUpdate(toYocto(event.target.value))} + update={onJobBondChange} type="number" value={formFields.jobBond} /> From a4195683f443235695697df7242deb8f67d92b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 4 Nov 2022 15:51:34 +0400 Subject: [PATCH 351/537] chore: Update spell checker dictionary --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9d8e0e8f..ab361244 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -20,5 +20,6 @@ "[scss]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true - } + }, + "cSpell.words": ["mcce"] } From da856333b684d49616b919d612fbfd1f3c9fe785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 4 Nov 2022 16:52:42 +0400 Subject: [PATCH 352/537] wip: Update `TextInput` props --- src/shared/ui/components/text-input/text-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/components/text-input/text-input.tsx b/src/shared/ui/components/text-input/text-input.tsx index a74ca6c9..0905d887 100644 --- a/src/shared/ui/components/text-input/text-input.tsx +++ b/src/shared/ui/components/text-input/text-input.tsx @@ -5,7 +5,7 @@ import { ArgsError, ArgsString } from "../../../lib/args"; export interface TextInputProps extends Omit { error?: ArgsError; - update?: (event: ChangeEvent, component: Component) => void; + update?: (event: ChangeEvent, component?: Component) => void; value?: ArgsString; } From 01a679da2fc8c05eb5d6f38a85e92adbcf71b441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 4 Nov 2022 16:54:31 +0400 Subject: [PATCH 353/537] wip: Separate proposal submit form --- src/widgets/multicall-config-editor/config.ts | 7 +- src/widgets/multicall-config-editor/index.ts | 2 +- ...nfig-editor.scss => mc-config-editor.scss} | 0 ...config-editor.tsx => mc-config-editor.tsx} | 80 +++++-------------- .../ui/mcce-proposal-submit.tsx | 72 +++++++++++++++++ 5 files changed, 100 insertions(+), 61 deletions(-) rename src/widgets/multicall-config-editor/ui/{multicall-config-editor.scss => mc-config-editor.scss} (100%) rename src/widgets/multicall-config-editor/ui/{multicall-config-editor.tsx => mc-config-editor.tsx} (55%) create mode 100644 src/widgets/multicall-config-editor/ui/mcce-proposal-submit.tsx diff --git a/src/widgets/multicall-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts index 31815b7d..24d4a0f4 100644 --- a/src/widgets/multicall-config-editor/config.ts +++ b/src/widgets/multicall-config-editor/config.ts @@ -1,12 +1,15 @@ import { HTMLProps } from "react"; -import { JobSettingsEditFeature, TokensWhitelistEditFeature } from "../../features"; -import { MulticallContract } from "../../shared/lib/contracts/multicall"; +import { MulticallConfigDiff, MulticallContract } from "../../shared/lib/contracts/multicall"; import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; namespace MulticallConfigEditorWidget { export interface Dependencies extends HTMLProps { contracts: { dao: SputnikDAOContract; multicall: MulticallContract }; } + + export type ChangesDiff = MulticallConfigDiff; + + export type ProposalDescription = Parameters[0]; } class MulticallConfigEditorConfig {} diff --git a/src/widgets/multicall-config-editor/index.ts b/src/widgets/multicall-config-editor/index.ts index a6579d03..4c309601 100644 --- a/src/widgets/multicall-config-editor/index.ts +++ b/src/widgets/multicall-config-editor/index.ts @@ -1,5 +1,5 @@ import { MulticallConfigEditorConfig, type MulticallConfigEditorWidget } from "./config"; -import { MulticallConfigEditorUI } from "./ui/multicall-config-editor"; +import { MulticallConfigEditorUI } from "./ui/mc-config-editor"; class MulticallConfigEditor extends MulticallConfigEditorConfig { static UI = MulticallConfigEditorUI; diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.scss b/src/widgets/multicall-config-editor/ui/mc-config-editor.scss similarity index 100% rename from src/widgets/multicall-config-editor/ui/multicall-config-editor.scss rename to src/widgets/multicall-config-editor/ui/mc-config-editor.scss diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/mc-config-editor.tsx similarity index 55% rename from src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx rename to src/widgets/multicall-config-editor/ui/mc-config-editor.tsx index cd146a18..24177d7d 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/mc-config-editor.tsx @@ -1,15 +1,15 @@ import clsx from "clsx"; -import { type MouseEventHandler, useCallback, useMemo, useState } from "react"; +import { useCallback, useMemo, useState, FormEventHandler } from "react"; import { MulticallInstance } from "../../../entities"; import { JobSettingsEdit, TokensWhitelistEdit } from "../../../features"; import { ArgsString } from "../../../shared/lib/args"; -import { MulticallContract, type MulticallConfigDiff } from "../../../shared/lib/contracts/multicall"; +import { MulticallContract } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { Button, ButtonGroup, TextInput, Tile } from "../../../shared/ui/components"; -import { type MulticallConfigEditorWidget } from "../config"; +import { MulticallConfigEditorWidget } from "../config"; -import "./multicall-config-editor.scss"; +import { MulticallConfigEditorProposalSubmit } from "./mcce-proposal-submit"; +import "./mc-config-editor.scss"; interface MulticallConfigEditorUIProps extends MulticallConfigEditorWidget.Dependencies {} @@ -18,14 +18,14 @@ const _MulticallConfigEditor = "MulticallConfigEditor"; export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfigEditorUIProps) => { const [editMode, editModeSwitch] = useState(false); - const changesDiffInitialState: MulticallConfigDiff = { + const changesDiffInitialState: MulticallConfigEditorWidget.ChangesDiff = { [TokensWhitelistEdit.DiffKey.removeTokens]: [], [TokensWhitelistEdit.DiffKey.addTokens]: [], [JobSettingsEdit.DiffKey.jobBond]: "", [JobSettingsEdit.DiffKey.croncatManager]: "", }; - const [formState, formStateUpdate] = useState(changesDiffInitialState), + const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), formValues = { proposalDescription: useMemo(() => new ArgsString(""), []) }, [proposalDescription, proposalDescriptionUpdate] = useState(formValues.proposalDescription.value), _childFormsResetRequested = "childFormsResetRequested"; @@ -43,10 +43,10 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi const formReset = useCallback(() => { void childFormsResetRequested.dispatch(); void proposalDescriptionUpdate(""); - void formStateUpdate(changesDiffInitialState); + void changesDiffUpdate(changesDiffInitialState); formValues.proposalDescription.value = ""; - }, [formStateUpdate, changesDiffInitialState]); + }, [changesDiffUpdate, changesDiffInitialState]); const onCancel = useCallback(() => { void formReset(); @@ -54,21 +54,21 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( - (update: Partial) => { - void formStateUpdate((latestState) => Object.assign(latestState, update)); + (update: Partial) => { + void changesDiffUpdate((latestState) => Object.assign(latestState, update)); void editModeSwitch( - Object.values(Object.assign(formState, update)).filter(({ length }) => length > 0).length > 0 + Object.values(Object.assign(changesDiff, update)).filter(({ length }) => length > 0).length > 0 ); // TODO: Remove before release. This is for debug purposes only - console.table({ proposalDescription, ...formState }); + console.table({ proposalDescription, ...changesDiff }); }, - [editModeSwitch, formState, formStateUpdate, proposalDescription] + [editModeSwitch, changesDiff, changesDiffUpdate, proposalDescription] ); - const onSubmit = useCallback( + const onSubmit = useCallback( (event) => { void event.preventDefault(); @@ -76,7 +76,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi .proposeFunctionCall( proposalDescription, contracts.multicall.address, - MulticallContract.configDiffToProposalActions(formState) + MulticallContract.configDiffToProposalActions(changesDiff) ) .then((someTx) => signAndSendTxs([someTx])) .catch(console.error); @@ -109,48 +109,12 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi {...{ onEdit }} /> - -

    Start editing to create config changes proposal template

    - -
    -
    - void proposalDescriptionUpdate(event.target.value)} - value={formValues.proposalDescription} - /> -
    - - - } - followCursor - leaveDelay={3000} + leaveDelay={2000} > - {element} + ); }; From 22a610bf49b1c83955bd88f0f2647ab4a9815bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 17 Nov 2022 01:16:22 +0400 Subject: [PATCH 393/537] wip: Update link tooltip styles --- src/shared/ui/design/link/link.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/design/link/link.tsx b/src/shared/ui/design/link/link.tsx index 2645ca1e..938696ff 100644 --- a/src/shared/ui/design/link/link.tsx +++ b/src/shared/ui/design/link/link.tsx @@ -1,4 +1,4 @@ -import { CopyAllOutlined } from "@mui/icons-material"; +import { ContentCopy } from "@mui/icons-material"; import { Button } from "@mui/material"; import { forwardRef, HTMLProps, MutableRefObject, useCallback } from "react"; @@ -40,7 +40,7 @@ export const Link = ({ href, label, noTooltip = false, ...props }: LinkProps) => classes={{ root: `${_Link}-tooltip-button` }} onClick={useCallback(() => void navigator.clipboard.writeText(text), [text])} startIcon={ - @@ -50,6 +50,7 @@ export const Link = ({ href, label, noTooltip = false, ...props }: LinkProps) => } leaveDelay={2000} + placement="right-end" > From 2e78d64df7f10466b28316546d0b3aad1773c5a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 17 Nov 2022 01:57:56 +0400 Subject: [PATCH 394/537] wip: Update link tooltip styles --- src/shared/ui/design/link/link.tsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/shared/ui/design/link/link.tsx b/src/shared/ui/design/link/link.tsx index 938696ff..4d102194 100644 --- a/src/shared/ui/design/link/link.tsx +++ b/src/shared/ui/design/link/link.tsx @@ -1,5 +1,5 @@ import { ContentCopy } from "@mui/icons-material"; -import { Button } from "@mui/material"; +import { Button, IconButton } from "@mui/material"; import { forwardRef, HTMLProps, MutableRefObject, useCallback } from "react"; import { Tooltip } from "../tooltip"; @@ -36,7 +36,7 @@ export const Link = ({ href, label, noTooltip = false, ...props }: LinkProps) => arrow classes={{ arrow: `${_Link}-tooltip-arrow`, tooltip: `${_Link}-tooltip` }} content={ - + */ + + void navigator.clipboard.writeText(text), [text])} + size="small" + > + + } leaveDelay={2000} - placement="right-end" + placement="right-start" > From e8393867255e61a10e8fc544bed19593e45ba5a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 17 Nov 2022 02:15:30 +0400 Subject: [PATCH 395/537] wip: Update link tooltip styles --- src/shared/ui/design/link/link.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/design/link/link.tsx b/src/shared/ui/design/link/link.tsx index 4d102194..3daff85f 100644 --- a/src/shared/ui/design/link/link.tsx +++ b/src/shared/ui/design/link/link.tsx @@ -60,7 +60,7 @@ export const Link = ({ href, label, noTooltip = false, ...props }: LinkProps) => /> } - leaveDelay={2000} + leaveDelay={0} placement="right-start" > From 84ccd74c2506d67287d87f5a67ebfaf11e660544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 17 Nov 2022 03:15:08 +0400 Subject: [PATCH 396/537] wip: Update link tooltip styles --- src/shared/ui/design/link/link.scss | 2 ++ src/shared/ui/design/link/link.tsx | 44 +++++++++++------------------ src/shared/ui/design/table/row.scss | 5 +--- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/src/shared/ui/design/link/link.scss b/src/shared/ui/design/link/link.scss index be2c10c2..0f51b631 100644 --- a/src/shared/ui/design/link/link.scss +++ b/src/shared/ui/design/link/link.scss @@ -2,6 +2,7 @@ @use "sass/size"; .Link { + line-height: 1; color: darken(color.$blue, 30%); text-decoration: none; cursor: pointer; @@ -10,6 +11,7 @@ background-color: color.$darkest; &.MuiTooltip-tooltip { + margin-left: size.$text !important; background-color: color.$darkest; } diff --git a/src/shared/ui/design/link/link.tsx b/src/shared/ui/design/link/link.tsx index 3daff85f..be8cf838 100644 --- a/src/shared/ui/design/link/link.tsx +++ b/src/shared/ui/design/link/link.tsx @@ -1,5 +1,6 @@ import { ContentCopy } from "@mui/icons-material"; import { Button, IconButton } from "@mui/material"; +import clsx from "clsx"; import { forwardRef, HTMLProps, MutableRefObject, useCallback } from "react"; import { Tooltip } from "../tooltip"; @@ -14,20 +15,22 @@ export interface LinkProps extends Omit, "children" const _Link = "Link"; -export const Link = ({ href, label, noTooltip = false, ...props }: LinkProps) => { +export const Link = ({ className, href, label, noTooltip = false, ...props }: LinkProps) => { const text = label && label.length > 0 ? label : href; - const Element = forwardRef((forwardedProps, ref) => ( - } - rel="noopener noreferrer" - {...{ ...forwardedProps, ...props, href }} - > - {text} - - )); + const Element = forwardRef( + ({ className: forwardedClassName, ...forwardedProps }: HTMLProps, ref) => ( + } + rel="noopener noreferrer" + {...{ ...forwardedProps, ...props, href }} + > + {text} + + ) + ); return noTooltip ? ( @@ -36,19 +39,6 @@ export const Link = ({ href, label, noTooltip = false, ...props }: LinkProps) => arrow classes={{ arrow: `${_Link}-tooltip-arrow`, tooltip: `${_Link}-tooltip` }} content={ - /**/ - void navigator.clipboard.writeText(text), [text])} @@ -60,8 +50,8 @@ export const Link = ({ href, label, noTooltip = false, ...props }: LinkProps) => /> } - leaveDelay={0} - placement="right-start" + leaveDelay={1000} + placement="right" > diff --git a/src/shared/ui/design/table/row.scss b/src/shared/ui/design/table/row.scss index 25da98f9..b279bfc9 100644 --- a/src/shared/ui/design/table/row.scss +++ b/src/shared/ui/design/table/row.scss @@ -170,10 +170,7 @@ &:not(:first-of-type) { padding: 0; - & > span > a, - & > span > p, - & > span > input, - & > span > span { + & > span { padding: size.$gap * 0.4 size.$gap * 0.6; } } From 314c5e922cea1f377ba97bd78e7d27345870f8d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 17 Nov 2022 03:17:24 +0400 Subject: [PATCH 397/537] wip: Update compact dense table row styles --- src/shared/ui/design/table/row.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/design/table/row.scss b/src/shared/ui/design/table/row.scss index b279bfc9..23253edd 100644 --- a/src/shared/ui/design/table/row.scss +++ b/src/shared/ui/design/table/row.scss @@ -171,7 +171,7 @@ padding: 0; & > span { - padding: size.$gap * 0.4 size.$gap * 0.6; + padding: size.$gap * 0.4; } } } From 38aa30ec3b4971cec96e83197a57039627f70292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 17 Nov 2022 22:54:14 +0400 Subject: [PATCH 398/537] wip: Finish `Link` address copy tooltip amendments --- src/shared/ui/design/link/link.scss | 10 +++++++- src/shared/ui/design/link/link.tsx | 38 ++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/shared/ui/design/link/link.scss b/src/shared/ui/design/link/link.scss index 0f51b631..4f226561 100644 --- a/src/shared/ui/design/link/link.scss +++ b/src/shared/ui/design/link/link.scss @@ -8,10 +8,12 @@ cursor: pointer; &-tooltip { + padding: 0; background-color: color.$darkest; &.MuiTooltip-tooltip { - margin-left: size.$text !important; + margin-left: size.$small-text !important; + padding: 0; background-color: color.$darkest; } @@ -22,8 +24,14 @@ &-button, &-button.MuiButtonBase-root { + background-color: color.$black; + border-radius: inherit; font-size: size.$small-text; color: color.$white; + + &.Mui-disabled { + color: color.$white; + } } } } diff --git a/src/shared/ui/design/link/link.tsx b/src/shared/ui/design/link/link.tsx index be8cf838..a95453d2 100644 --- a/src/shared/ui/design/link/link.tsx +++ b/src/shared/ui/design/link/link.tsx @@ -1,7 +1,7 @@ -import { ContentCopy } from "@mui/icons-material"; -import { Button, IconButton } from "@mui/material"; +import { CheckCircleRounded, ContentCopy } from "@mui/icons-material"; +import { IconButton } from "@mui/material"; import clsx from "clsx"; -import { forwardRef, HTMLProps, MutableRefObject, useCallback } from "react"; +import { forwardRef, HTMLProps, MutableRefObject, useCallback, useEffect, useState } from "react"; import { Tooltip } from "../tooltip"; @@ -32,6 +32,18 @@ export const Link = ({ className, href, label, noTooltip = false, ...props }: Li ) ); + const [copied, copiedStateUpdate] = useState(false); + + const onCopyButtonClick = useCallback( + async () => void copiedStateUpdate(!Boolean(await navigator.clipboard.writeText(text))), + [text] + ); + + useEffect( + () => void (copied ? setTimeout(() => void copiedStateUpdate(false), 2000) : null), + [copied, copiedStateUpdate] + ); + return noTooltip ? ( ) : ( @@ -41,16 +53,24 @@ export const Link = ({ className, href, label, noTooltip = false, ...props }: Li content={ void navigator.clipboard.writeText(text), [text])} + disabled={copied} + onClick={onCopyButtonClick} size="small" > - + {!copied ? ( + + ) : ( + + )} } - leaveDelay={1000} + leaveDelay={2000} placement="right" > From 1575f7b9106c3666fb7e1ed31257a578ec1a2406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 18 Nov 2022 21:36:01 +0400 Subject: [PATCH 399/537] chore: Rename alias --- src/entities/multicall-instance/config.ts | 4 ++-- src/shared/lib/contracts/multicall.ts | 4 ++-- src/shared/lib/contracts/sputnik-dao.ts | 2 +- src/widgets/multicall-config-editor/config.ts | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/config.ts index f5455dfb..1c0ccdc9 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/config.ts @@ -1,5 +1,5 @@ import { MulticallConfigParamKey } from "../../shared/lib/contracts/multicall"; -import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; +import { SputnikDAOAdapter } from "../../shared/lib/contracts/sputnik-dao"; import { toYocto } from "../../shared/lib/converter"; /** @@ -7,7 +7,7 @@ import { toYocto } from "../../shared/lib/converter"; */ namespace MulticallInstanceEntity { export interface Inputs { - daoContractAddress: SputnikDAOContract["address"]; + daoContractAddress: SputnikDAOAdapter["address"]; } export type ParamKey = MulticallConfigParamKey; diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 8578d67f..a51093ad 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -5,7 +5,7 @@ import { Big, toGas, dateToCron, toYocto } from "../converter"; import { FungibleToken } from "../standards/fungibleToken"; import { type Tx, viewAccount, viewState, view } from "../wallet"; -import type { FunctionCallAction as daoFunctionCallAction, SputnikDAOContract } from "./sputnik-dao"; +import type { FunctionCallAction as daoFunctionCallAction, SputnikDAOAdapter } from "./sputnik-dao"; const FACTORY_ADDRESS_SELECTOR: Record = { mainnet: "v1.multicall.near", @@ -149,7 +149,7 @@ class Multicall { * @param callback Stateful data fetch callback */ static instanceDataFetchFx = async ( - daoContractAddress: SputnikDAOContract["address"], + daoContractAddress: SputnikDAOAdapter["address"], callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void ) => callback( diff --git a/src/shared/lib/contracts/sputnik-dao.ts b/src/shared/lib/contracts/sputnik-dao.ts index 416f4976..5a12dd0e 100644 --- a/src/shared/lib/contracts/sputnik-dao.ts +++ b/src/shared/lib/contracts/sputnik-dao.ts @@ -622,5 +622,5 @@ class SputnikDAO { } } -export { SputnikDAO, SputnikDAO as SputnikDAOContract, SputnikUI, ProposalKindPolicyLabel, ProposalStatus }; +export { SputnikDAO, SputnikDAO as SputnikDAOAdapter, SputnikUI, ProposalKindPolicyLabel, ProposalStatus }; export type { FunctionCall, FunctionCallAction, ProposalOutput, ProposalKind, ProposalAction }; diff --git a/src/widgets/multicall-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts index d146cf86..c078cdd5 100644 --- a/src/widgets/multicall-config-editor/config.ts +++ b/src/widgets/multicall-config-editor/config.ts @@ -1,16 +1,16 @@ import { HTMLProps } from "react"; import { JobSettingsEdit, TokensWhitelistEdit } from "../../features"; import { MulticallConfigDiff, MulticallContract } from "../../shared/lib/contracts/multicall"; -import { SputnikDAOContract } from "../../shared/lib/contracts/sputnik-dao"; +import { SputnikDAOAdapter } from "../../shared/lib/contracts/sputnik-dao"; namespace MulticallConfigEditorWidget { export interface Inputs extends HTMLProps { - contracts: { dao: SputnikDAOContract; multicall: MulticallContract }; + contracts: { dao: SputnikDAOAdapter; multicall: MulticallContract }; } export type ChangesDiff = MulticallConfigDiff; - export type ProposalDescription = Parameters[0]; + export type ProposalDescription = Parameters[0]; } class MulticallConfigEditorConfig { From 7bfaaff055ca4163152d8c4b46cfff0e59ea019b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 20 Nov 2022 07:31:05 +0400 Subject: [PATCH 400/537] chore: Remove adapter aliases --- src/entities/multicall-instance/config.ts | 4 +-- .../multicall-instance/model/mi-admins.ts | 16 +++++------ .../multicall-instance/model/mi-tokens.ts | 16 +++++------ .../multicall-instance/ui/mi-admins.tsx | 4 +-- .../ui/mi-tokens-whitelist.tsx | 4 +-- src/features/job-settings-edit/config.ts | 6 ++-- .../ui/job-settings-form.tsx | 28 +++++++++---------- .../ui/tokens-whitelist-form.tsx | 4 +-- src/shared/lib/contracts/multicall.ts | 12 ++++---- src/shared/lib/contracts/sputnik-dao.ts | 2 +- src/widgets/multicall-config-editor/config.ts | 8 +++--- .../ui/multicall-config-editor.tsx | 12 ++++---- 12 files changed, 57 insertions(+), 59 deletions(-) diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/config.ts index 1c0ccdc9..16c64ad6 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/config.ts @@ -1,5 +1,5 @@ import { MulticallConfigParamKey } from "../../shared/lib/contracts/multicall"; -import { SputnikDAOAdapter } from "../../shared/lib/contracts/sputnik-dao"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; import { toYocto } from "../../shared/lib/converter"; /** @@ -7,7 +7,7 @@ import { toYocto } from "../../shared/lib/converter"; */ namespace MulticallInstanceEntity { export interface Inputs { - daoContractAddress: SputnikDAOAdapter["address"]; + daoAddress: SputnikDAO["address"]; } export type ParamKey = MulticallConfigParamKey; diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index 3954240d..46174089 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -1,28 +1,28 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; -import { MulticallContract } from "../../../shared/lib/contracts/multicall"; +import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; import { type MulticallInstanceEntity } from "../config"; export type MulticallInstanceAdminsAddressList = { - data: MulticallContract["admins"] | null; + data: Multicall["admins"] | null; error: Error | null; loading: boolean; }; export class MulticallInstanceAdminsModel { static addressListFetchFx = async ( - daoContractAddress: MulticallInstanceEntity.Inputs["daoContractAddress"], + daoAddress: MulticallInstanceEntity.Inputs["daoAddress"], callback: (result: MulticallInstanceAdminsAddressList) => void ) => - await MulticallContract.instanceDataFetchFx( - `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, + await Multicall.instanceDataFetchFx( + `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`, (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) ); - static useAddressList = (daoContractAddress: MulticallInstanceEntity.Inputs["daoContractAddress"]) => { + static useAddressList = (daoAddress: MulticallInstanceEntity.Inputs["daoAddress"]) => { const [state, stateUpdate] = useState({ data: null, error: null, @@ -30,8 +30,8 @@ export class MulticallInstanceAdminsModel { }); useEffect( - () => void MulticallInstanceAdminsModel.addressListFetchFx(daoContractAddress, stateUpdate), - [daoContractAddress, stateUpdate] + () => void MulticallInstanceAdminsModel.addressListFetchFx(daoAddress, stateUpdate), + [daoAddress, stateUpdate] ); return state; diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index 07db4ed9..6173cba0 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -1,30 +1,30 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; -import { MulticallContract } from "../../../shared/lib/contracts/multicall"; +import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; import { type MulticallInstanceEntity } from "../config"; export type MulticallInstanceTokensWhitelist = { - data: MulticallContract["tokensWhitelist"] | null; + data: Multicall["tokensWhitelist"] | null; error: Error | null; loading: boolean; }; export class MulticallInstanceTokensModel { static whitelistFetchFx = async ( - daoContractAddress: MulticallInstanceEntity.Inputs["daoContractAddress"], + daoAddress: MulticallInstanceEntity.Inputs["daoAddress"], callback: (result: MulticallInstanceTokensWhitelist) => void ) => - await MulticallContract.instanceDataFetchFx( - `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${MulticallContract.FACTORY_ADDRESS}`, + await Multicall.instanceDataFetchFx( + `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`, (multicallInstanceData) => callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) ); - static useWhitelist = (daoContractAddress: MulticallInstanceEntity.Inputs["daoContractAddress"]) => { + static useWhitelist = (daoAddress: MulticallInstanceEntity.Inputs["daoAddress"]) => { const [state, stateUpdate] = useState({ data: null, error: null, @@ -32,8 +32,8 @@ export class MulticallInstanceTokensModel { }); useEffect( - () => void MulticallInstanceTokensModel.whitelistFetchFx(daoContractAddress, stateUpdate), - [daoContractAddress, stateUpdate] + () => void MulticallInstanceTokensModel.whitelistFetchFx(daoAddress, stateUpdate), + [daoAddress, stateUpdate] ); return state; diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 5b964fb5..826986aa 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -8,8 +8,8 @@ interface MulticallInstanceAdminsTableProps extends MulticallInstanceEntity.Inpu className?: string; } -export const MulticallInstanceAdminsTable = ({ className, daoContractAddress }: MulticallInstanceAdminsTableProps) => { - const { data, error, loading } = MulticallInstanceAdminsModel.useAddressList(daoContractAddress); +export const MulticallInstanceAdminsTable = ({ className, daoAddress }: MulticallInstanceAdminsTableProps) => { + const { data, error, loading } = MulticallInstanceAdminsModel.useAddressList(daoAddress); return ( { - const { data, error, loading } = MulticallInstanceTokensModel.useWhitelist(daoContractAddress); + const { data, error, loading } = MulticallInstanceTokensModel.useWhitelist(daoAddress); return ( , "onChange">, - Pick { - multicallContract: MulticallContract; + Pick { + multicallInstance: Multicall; onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index b04f5a51..c28b1894 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -12,7 +12,7 @@ interface JobSettingsFormProps extends JobSettingsEditFeature.Inputs {} export const JobSettingsForm = ({ className, disabled, - multicallContract, + multicallInstance, onEdit, resetTrigger, }: JobSettingsFormProps) => { @@ -29,18 +29,18 @@ export const JobSettingsForm = ({ ]; const formFields = { - croncatManager: useMemo(() => new ArgsString(multicallContract.croncatManager), [multicallContract]), + croncatManager: useMemo(() => new ArgsString(multicallInstance.croncatManager), [multicallInstance]), jobBond: useMemo( - () => new ArgsString(multicallContract.jobBond !== "" ? toNEAR(multicallContract.jobBond) : ""), - [multicallContract] + () => new ArgsString(multicallInstance.jobBond !== "" ? toNEAR(multicallInstance.jobBond) : ""), + [multicallInstance] ), }; const onCroncatManagerChange = useCallback["onChange"]>( ({ target: { value } }) => void croncatManagerUpdate( - value !== multicallContract.croncatManager ? value : formInitialState.croncatManager + value !== multicallInstance.croncatManager ? value : formInitialState.croncatManager ), [croncatManagerUpdate] @@ -48,14 +48,14 @@ export const JobSettingsForm = ({ const onJobBondChange = useCallback["onChange"]>( ({ target: { value } }) => - void jobBondUpdate(value !== toNEAR(multicallContract.jobBond) ? toYocto(value) : formInitialState.jobBond), + void jobBondUpdate(value !== toNEAR(multicallInstance.jobBond) ? toYocto(value) : formInitialState.jobBond), [jobBondUpdate] ); const formReset = useCallback(() => { - formFields.croncatManager.value = multicallContract.croncatManager; - formFields.jobBond.value = toNEAR(multicallContract.jobBond); + formFields.croncatManager.value = multicallInstance.croncatManager; + formFields.jobBond.value = toNEAR(multicallInstance.jobBond); void croncatManagerUpdate(formInitialState.croncatManager); void jobBondUpdate(formInitialState.jobBond); @@ -105,7 +105,7 @@ export const JobSettingsForm = ({ ({ croncatManager, jobBond }[id] === formInitialState[id as JobSettingsEditFeature.ChangesDiffKey] || { croncatManager, jobBond }[id] === - multicallContract[id as JobSettingsEditFeature.ChangesDiffKey] + multicallInstance[id as JobSettingsEditFeature.ChangesDiffKey] ? null : "blue"), @@ -128,10 +128,10 @@ export const JobSettingsForm = ({ ) : ( - + ), ], }, @@ -151,14 +151,14 @@ export const JobSettingsForm = ({ fullWidth onChange={onJobBondChange} type="number" - value={toNEAR(jobBond || multicallContract.jobBond)} + value={toNEAR(jobBond || multicallInstance.jobBond)} /> ) : ( ); }; diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index a51093ad..fe3ba0e3 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -5,7 +5,7 @@ import { Big, toGas, dateToCron, toYocto } from "../converter"; import { FungibleToken } from "../standards/fungibleToken"; import { type Tx, viewAccount, viewState, view } from "../wallet"; -import type { FunctionCallAction as daoFunctionCallAction, SputnikDAOAdapter } from "./sputnik-dao"; +import type { FunctionCallAction as daoFunctionCallAction, SputnikDAO } from "./sputnik-dao"; const FACTORY_ADDRESS_SELECTOR: Record = { mainnet: "v1.multicall.near", @@ -145,17 +145,15 @@ class Multicall { * Calls the given callback with a result of multicall contract instantiation, * represented as stateful response. * - * @param daoContractAddress DAO contract address + * @param daoAddress DAO contract address * @param callback Stateful data fetch callback */ static instanceDataFetchFx = async ( - daoContractAddress: SputnikDAOAdapter["address"], + daoAddress: SputnikDAO["address"], callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void ) => callback( - await Multicall.init( - `${ArgsAccount.deconstructAddress(daoContractAddress).name}.${Multicall.FACTORY_ADDRESS}` - ) + await Multicall.init(`${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`) .then((multicallInstance) => ({ data: multicallInstance, error: null, @@ -326,5 +324,5 @@ class Multicall { } } -export { Multicall, Multicall as MulticallContract, MulticallConfigParamKey, MulticallTokensWhitelistChangesDiffKey }; +export { Multicall, MulticallConfigParamKey, MulticallTokensWhitelistChangesDiffKey }; export type { JobData, MulticallArgs, MulticallConfigDiff }; diff --git a/src/shared/lib/contracts/sputnik-dao.ts b/src/shared/lib/contracts/sputnik-dao.ts index 5a12dd0e..ef9ce06a 100644 --- a/src/shared/lib/contracts/sputnik-dao.ts +++ b/src/shared/lib/contracts/sputnik-dao.ts @@ -622,5 +622,5 @@ class SputnikDAO { } } -export { SputnikDAO, SputnikDAO as SputnikDAOAdapter, SputnikUI, ProposalKindPolicyLabel, ProposalStatus }; +export { SputnikDAO, SputnikUI, ProposalKindPolicyLabel, ProposalStatus }; export type { FunctionCall, FunctionCallAction, ProposalOutput, ProposalKind, ProposalAction }; diff --git a/src/widgets/multicall-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts index c078cdd5..318cb838 100644 --- a/src/widgets/multicall-config-editor/config.ts +++ b/src/widgets/multicall-config-editor/config.ts @@ -1,16 +1,16 @@ import { HTMLProps } from "react"; import { JobSettingsEdit, TokensWhitelistEdit } from "../../features"; -import { MulticallConfigDiff, MulticallContract } from "../../shared/lib/contracts/multicall"; -import { SputnikDAOAdapter } from "../../shared/lib/contracts/sputnik-dao"; +import { MulticallConfigDiff, Multicall } from "../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; namespace MulticallConfigEditorWidget { export interface Inputs extends HTMLProps { - contracts: { dao: SputnikDAOAdapter; multicall: MulticallContract }; + contracts: { dao: SputnikDAO; multicall: Multicall }; } export type ChangesDiff = MulticallConfigDiff; - export type ProposalDescription = Parameters[0]; + export type ProposalDescription = Parameters[0]; } class MulticallConfigEditorConfig { diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index b5d330fe..a57423f2 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -4,7 +4,7 @@ import { useCallback, useMemo, useState, FormEventHandler, useEffect, useContext import { MulticallInstance, Wallet } from "../../../entities"; import { JobSettingsEdit, TokensWhitelistEdit } from "../../../features"; import { ArgsString } from "../../../shared/lib/args-old"; -import { MulticallContract } from "../../../shared/lib/contracts/multicall"; +import { Multicall } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; import { MulticallConfigEditorConfig, MulticallConfigEditorWidget } from "../config"; @@ -71,7 +71,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi .proposeFunctionCall( proposalDescription, contracts.multicall.address, - MulticallContract.configDiffToProposalActions(changesDiff) + Multicall.configDiffToProposalActions(changesDiff) ) .then((someTx) => signAndSendTxs([someTx])) .catch(console.error); @@ -89,12 +89,12 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi
    From d969887713fff87ac326232f36d496d9d2e93dc5 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sun, 20 Nov 2022 14:51:01 +0100 Subject: [PATCH 401/537] Replace Account from near-api-js with string --- src/shared/lib/contracts/multicall.ts | 17 +++++------------ src/shared/ui/design/near-link/near-link.tsx | 4 +--- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index fe3ba0e3..9d3f08b8 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -1,8 +1,5 @@ -import { Account } from "near-api-js"; - import { ArgsAccount } from "../args-old"; import { Big, toGas, dateToCron, toYocto } from "../converter"; -import { FungibleToken } from "../standards/fungibleToken"; import { type Tx, viewAccount, viewState, view } from "../wallet"; import type { FunctionCallAction as daoFunctionCallAction, SputnikDAO } from "./sputnik-dao"; @@ -45,10 +42,6 @@ type JobData = { }; }; -type MulticallAdminData = Account["accountId"]; - -type WhitelistedTokenData = FungibleToken["address"]; - type FunctionCall = { func: string; args: string; // base64 encoded JSON args @@ -57,7 +50,7 @@ type FunctionCall = { }; type BatchCall = { - address: Account["accountId"]; + address: string; actions: FunctionCall[]; }; @@ -88,11 +81,11 @@ class Multicall { // 0.025 NEAR is the min required by croncat for a non-recurring task. Assume trigger of 270 Tgas and 0 NEAR. static CRONCAT_FEE: string = toYocto("0.0275"); - address: Account["accountId"]; - admins: MulticallAdminData[] = []; + address: string; + admins: string[] = []; [MulticallConfigParamKey.croncatManager]: string = ""; // only whitelisted tokens can be attached to multicalls or job activations. - tokensWhitelist: WhitelistedTokenData[] = []; + tokensWhitelist: string[] = []; // job bond amount must be attached as deposit when adding new jobs. // needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). [MulticallConfigParamKey.jobBond]: string = ""; @@ -172,7 +165,7 @@ class Multicall { * * @param accountId */ - static async isMulticall(accountId: Account["accountId"]): Promise { + static async isMulticall(accountId: string): Promise { const accountInfo = await viewAccount(accountId); const codeHash: string = accountInfo.code_hash; return Multicall.CONTRACT_CODE_HASHES.includes(codeHash); diff --git a/src/shared/ui/design/near-link/near-link.tsx b/src/shared/ui/design/near-link/near-link.tsx index dcb83dff..0ab1c9e8 100644 --- a/src/shared/ui/design/near-link/near-link.tsx +++ b/src/shared/ui/design/near-link/near-link.tsx @@ -1,10 +1,8 @@ -import { Account } from "near-api-js"; - import { ArgsAccount } from "../../../lib/args-old"; import { Link, LinkProps } from "../link"; export interface NearLinkProps extends Omit { - address: Account["accountId"]; + address: string; } export const NearLink = ({ address }: NearLinkProps) => { From 8f21d0dc8c66954b5f03c718a8da02de15d0c211 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sun, 20 Nov 2022 16:02:56 +0100 Subject: [PATCH 402/537] Fix: config changes callback dpeends on changesDiff --- .../multicall-config-editor/ui/multicall-config-editor.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx index a57423f2..4da3c000 100644 --- a/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx +++ b/src/widgets/multicall-config-editor/ui/multicall-config-editor.tsx @@ -77,7 +77,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi .catch(console.error); }, - [contracts, proposalDescription] + [changesDiff, contracts, proposalDescription] ); useEffect( From 656b2a8fa9015303ce8c15d3a4a60f38c3119239 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sun, 20 Nov 2022 22:18:25 +0100 Subject: [PATCH 403/537] reduce copy button icon change to 1 second --- src/shared/ui/design/link/link.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/design/link/link.tsx b/src/shared/ui/design/link/link.tsx index a95453d2..c94fc35e 100644 --- a/src/shared/ui/design/link/link.tsx +++ b/src/shared/ui/design/link/link.tsx @@ -40,7 +40,7 @@ export const Link = ({ className, href, label, noTooltip = false, ...props }: Li ); useEffect( - () => void (copied ? setTimeout(() => void copiedStateUpdate(false), 2000) : null), + () => void (copied ? setTimeout(() => void copiedStateUpdate(false), 1000) : null), [copied, copiedStateUpdate] ); From 74daa6a880ee73727507360b3851de295be6ccbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 22 Nov 2022 01:21:52 +0400 Subject: [PATCH 404/537] wip: Use types from `@near-wallet-selector/core` --- src/shared/lib/contracts/multicall.ts | 15 +++++++++++---- src/shared/lib/standards/fungibleToken.ts | 5 ++++- src/shared/ui/design/near-link/near-link.tsx | 4 +++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 9d3f08b8..2f2679dc 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -1,5 +1,8 @@ +import { Account } from "@near-wallet-selector/core"; + import { ArgsAccount } from "../args-old"; import { Big, toGas, dateToCron, toYocto } from "../converter"; +import { FungibleToken } from "../standards/fungibleToken"; import { type Tx, viewAccount, viewState, view } from "../wallet"; import type { FunctionCallAction as daoFunctionCallAction, SputnikDAO } from "./sputnik-dao"; @@ -42,6 +45,10 @@ type JobData = { }; }; +type MulticallAdminData = Account["accountId"]; + +type WhitelistedTokenData = FungibleToken["address"]; + type FunctionCall = { func: string; args: string; // base64 encoded JSON args @@ -50,7 +57,7 @@ type FunctionCall = { }; type BatchCall = { - address: string; + address: Account["accountId"]; actions: FunctionCall[]; }; @@ -81,11 +88,11 @@ class Multicall { // 0.025 NEAR is the min required by croncat for a non-recurring task. Assume trigger of 270 Tgas and 0 NEAR. static CRONCAT_FEE: string = toYocto("0.0275"); - address: string; - admins: string[] = []; + address: Account["accountId"]; + admins: MulticallAdminData[] = []; [MulticallConfigParamKey.croncatManager]: string = ""; // only whitelisted tokens can be attached to multicalls or job activations. - tokensWhitelist: string[] = []; + tokensWhitelist: WhitelistedTokenData[] = []; // job bond amount must be attached as deposit when adding new jobs. // needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). [MulticallConfigParamKey.jobBond]: string = ""; diff --git a/src/shared/lib/standards/fungibleToken.ts b/src/shared/lib/standards/fungibleToken.ts index a1dc1d10..ebbea32d 100644 --- a/src/shared/lib/standards/fungibleToken.ts +++ b/src/shared/lib/standards/fungibleToken.ts @@ -1,4 +1,7 @@ +import { Account } from "@near-wallet-selector/core"; + import { view } from "../wallet"; + import { StorageManagement } from "./storageManagement"; import type { StorageBalance, StorageBalanceBounds } from "./storageManagement"; @@ -16,7 +19,7 @@ type FungibleTokenMetadata = { // Fungible token core follow NEP-141. See: https://nomicon.io/Standards/Tokens/FungibleToken/Core // Also implements NEP-145 for storage management. See: https://nomicon.io/Standards/StorageManagement class FungibleToken extends StorageManagement { - address: string; + address: Account["accountId"]; // needs initialization, but start with empty metadata metadata: FungibleTokenMetadata = { spec: "", name: "", symbol: "", decimals: -1 }; // storage balance bounds. Needs initialization, but starts with "0" values diff --git a/src/shared/ui/design/near-link/near-link.tsx b/src/shared/ui/design/near-link/near-link.tsx index 0ab1c9e8..a35835dc 100644 --- a/src/shared/ui/design/near-link/near-link.tsx +++ b/src/shared/ui/design/near-link/near-link.tsx @@ -1,8 +1,10 @@ +import { Account } from "@near-wallet-selector/core"; + import { ArgsAccount } from "../../../lib/args-old"; import { Link, LinkProps } from "../link"; export interface NearLinkProps extends Omit { - address: string; + address: Account["accountId"]; } export const NearLink = ({ address }: NearLinkProps) => { From c5ed6fa50b70bb96c3cb28f71bc04a63a0766fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 22 Nov 2022 01:37:05 +0400 Subject: [PATCH 405/537] fix: Enable error handling for MI data fetch effect --- src/shared/lib/contracts/multicall.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 2f2679dc..8854296a 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -153,17 +153,13 @@ class Multicall { callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void ) => callback( - await Multicall.init(`${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`) - .then((multicallInstance) => ({ - data: multicallInstance, - error: null, - loading: false, - })) - .catch((error) => ({ - data: null, - error, - loading: false, - })) + await Multicall.init( + `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}` + ).then((multicallInstance) => ({ + data: multicallInstance.ready ? multicallInstance : null, + error: multicallInstance.ready ? null : new Error("Unable to connect to Multicall Instance"), + loading: false, + })) ); /** From 50a7b8eff251933597abb182d9ac67e1f9d07600 Mon Sep 17 00:00:00 2001 From: lennart Czardybon Date: Tue, 22 Nov 2022 00:46:31 +0100 Subject: [PATCH 406/537] added cosmetic types --- src/shared/lib/contracts/multicall.ts | 70 +++++++++++++-------------- src/shared/lib/types.d.ts | 8 +++ 2 files changed, 41 insertions(+), 37 deletions(-) create mode 100644 src/shared/lib/types.d.ts diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 8854296a..a84f18b3 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -2,12 +2,12 @@ import { Account } from "@near-wallet-selector/core"; import { ArgsAccount } from "../args-old"; import { Big, toGas, dateToCron, toYocto } from "../converter"; -import { FungibleToken } from "../standards/fungibleToken"; +import { AccountId, Base64String, BigString, U128String, U64String } from "../types"; import { type Tx, viewAccount, viewState, view } from "../wallet"; import type { FunctionCallAction as daoFunctionCallAction, SputnikDAO } from "./sputnik-dao"; -const FACTORY_ADDRESS_SELECTOR: Record = { +const FACTORY_ADDRESS_SELECTOR: Record = { mainnet: "v1.multicall.near", testnet: "v1_03.multicall.testnet", }; @@ -33,31 +33,27 @@ type JobData = { */ job: { croncat_hash: string; - creator: string; - bond: string; // string encoded number (u128) + creator: AccountId; + bond: U128String; // string encoded number (u128) cadence: string; - trigger_gas: string; // string encoded number (u64) - croncat_budget: string; // string encoded number (u128) - start_at: string; // string encoded number (u64) + trigger_gas: U64String; // string encoded number (u64) + croncat_budget: U128String; // string encoded number (u128) + start_at: U64String; // string encoded number (u64) run_count: number; is_active: boolean; multicalls: MulticallArgs[]; }; }; -type MulticallAdminData = Account["accountId"]; - -type WhitelistedTokenData = FungibleToken["address"]; - type FunctionCall = { func: string; - args: string; // base64 encoded JSON args - gas: string; // string encoded number (u64) - depo: string; // string encoded number (u128) + args: Base64String; // base64 encoded JSON args + gas: U64String; // string encoded number (u64) + depo: U128String; // string encoded number (u128) }; type BatchCall = { - address: Account["accountId"]; + address: AccountId; actions: FunctionCall[]; }; @@ -76,35 +72,35 @@ enum MulticallTokensWhitelistChangesDiffKey { } type MulticallConfigDiff = { - [MulticallTokensWhitelistChangesDiffKey.addTokens]: string[]; - [MulticallConfigParamKey.croncatManager]: string; - [MulticallConfigParamKey.jobBond]: string; - [MulticallTokensWhitelistChangesDiffKey.removeTokens]: string[]; + [MulticallTokensWhitelistChangesDiffKey.addTokens]: AccountId[]; + [MulticallConfigParamKey.croncatManager]: AccountId; + [MulticallConfigParamKey.jobBond]: U128String; + [MulticallTokensWhitelistChangesDiffKey.removeTokens]: AccountId[]; }; class Multicall { - static FACTORY_ADDRESS: string = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; - static CONTRACT_CODE_HASHES: string[] = CONTRACT_CODE_HASHES_SELECTOR[window.NEAR_ENV]; + static FACTORY_ADDRESS: AccountId = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; + static CONTRACT_CODE_HASHES: AccountId[] = CONTRACT_CODE_HASHES_SELECTOR[window.NEAR_ENV]; // 0.025 NEAR is the min required by croncat for a non-recurring task. Assume trigger of 270 Tgas and 0 NEAR. - static CRONCAT_FEE: string = toYocto("0.0275"); + static CRONCAT_FEE: BigString = toYocto("0.0275"); - address: Account["accountId"]; - admins: MulticallAdminData[] = []; - [MulticallConfigParamKey.croncatManager]: string = ""; + address: AccountId; + admins: AccountId[] = []; + [MulticallConfigParamKey.croncatManager]: AccountId = ""; // only whitelisted tokens can be attached to multicalls or job activations. - tokensWhitelist: WhitelistedTokenData[] = []; + tokensWhitelist: AccountId[] = []; // job bond amount must be attached as deposit when adding new jobs. // needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). - [MulticallConfigParamKey.jobBond]: string = ""; + [MulticallConfigParamKey.jobBond]: U128String = ""; // Multicall instance is ready when info (admins...) are fetched & assigned correctly. ready: boolean = false; - constructor(multicallAddress: string) { + constructor(multicallAddress: AccountId) { this.address = multicallAddress; } // used to create and initialize a Multicall instance - static async init(multicallAddress: string): Promise { + static async init(multicallAddress: AccountId): Promise { // verify address is a Multicall instance, fetch its info and mark it ready const newMulticall = new Multicall(multicallAddress); const [isMulticall, admins, croncatManager, tokensWhitelist, jobBond] = await Promise.all([ @@ -149,7 +145,7 @@ class Multicall { * @param callback Stateful data fetch callback */ static instanceDataFetchFx = async ( - daoAddress: SputnikDAO["address"], + daoAddress: AccountId, callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void ) => callback( @@ -168,7 +164,7 @@ class Multicall { * * @param accountId */ - static async isMulticall(accountId: string): Promise { + static async isMulticall(accountId: AccountId): Promise { const accountInfo = await viewAccount(accountId); const codeHash: string = accountInfo.code_hash; return Multicall.CONTRACT_CODE_HASHES.includes(codeHash); @@ -178,7 +174,7 @@ class Multicall { * Multicall's factory has an admin-controlled fee to be * paid upon creating a new multicall instance contract */ - static async getFactoryFee(): Promise { + static async getFactoryFee(): Promise { return view(this.FACTORY_ADDRESS, "get_fee", {}); } @@ -240,28 +236,28 @@ class Multicall { /** * get list of admins */ - async getAdmins(): Promise { + async getAdmins(): Promise { return view(this.address, "get_admins", {}); } /** * get whitelisted tokens */ - async getWhitelistedTokens(): Promise { + async getWhitelistedTokens(): Promise { return view(this.address, "get_tokens", {}); } /** * get croncat manager address that was registered on the multicall instance. */ - async getCroncatManager(): Promise { + async getCroncatManager(): Promise { return view(this.address, "get_croncat_manager", {}); } /** * get job bond */ - async getJobBond(): Promise { + async getJobBond(): Promise { return view(this.address, "get_job_bond", {}); } @@ -292,7 +288,7 @@ class Multicall { * @returns */ // TODO: currently budget is hard-coded for jobs with 1 multicall - async addJob(multicalls: MulticallArgs[], triggerDate: Date, triggerGas: string): Promise { + async addJob(multicalls: MulticallArgs[], triggerDate: Date, triggerGas: U64String): Promise { // crontab in CronCat format. See: https://github.com/CronCats/Schedule const cadence: string = dateToCron(triggerDate); // timestamp as required by NEAR chain (UTC, in nanoseconds) diff --git a/src/shared/lib/types.d.ts b/src/shared/lib/types.d.ts new file mode 100644 index 00000000..0673ba7e --- /dev/null +++ b/src/shared/lib/types.d.ts @@ -0,0 +1,8 @@ +export declare type AccountId = string; + +export declare type U128String = string; +export declare type U64String = string; +export declare type BigString = string; + +export declare type JsonString = string; +export declare type Base64String = string; From 23f55d5b17107327286aa993e5b6a132e67a56e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 09:32:29 +0400 Subject: [PATCH 407/537] chore: Remove unused module --- src/shared/lib/fn.ts | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/shared/lib/fn.ts diff --git a/src/shared/lib/fn.ts b/src/shared/lib/fn.ts deleted file mode 100644 index 3fed89cb..00000000 --- a/src/shared/lib/fn.ts +++ /dev/null @@ -1,5 +0,0 @@ -const returnVoid = (): void => void null; - -export const Fn = { - returnVoid, -}; From 5b59feb2124eb9e9d5ac6aa26e451fb1b0c384e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 09:34:03 +0400 Subject: [PATCH 408/537] chore: Rename `ui/forms` -> `ui/form` --- src/families/custom.tsx | 2 +- src/families/mintbase/add-minter.tsx | 2 +- src/families/mintbase/create-store.tsx | 4 ++-- src/families/mintbase/remove-minter.tsx | 2 +- src/families/mintbase/transfer-store-ownership.tsx | 2 +- src/families/multicall/transfer.tsx | 2 +- src/families/near/deposit-and-stake.tsx | 2 +- src/families/near/ft-transfer-call.tsx | 2 +- src/families/near/ft-transfer.tsx | 2 +- src/families/near/mft-transfer-call.tsx | 2 +- src/families/near/mft-transfer.tsx | 2 +- src/families/near/nft-approve.tsx | 2 +- src/families/near/nft-revoke.tsx | 2 +- src/families/near/nft-transfer-call.tsx | 2 +- src/families/near/nft-transfer.tsx | 2 +- src/families/near/storage-deposit.tsx | 2 +- src/families/near/storage-unregister.tsx | 2 +- src/families/near/storage-withdraw.tsx | 2 +- src/families/near/unstake.tsx | 4 ++-- src/families/near/withdraw.tsx | 2 +- src/pages/dao/dao.tsx | 2 +- src/shared/ui/{forms => form}/elements/form-control.tsx | 0 src/shared/ui/{forms => form}/elements/form-label.scss | 0 src/shared/ui/{forms => form}/elements/form-label.tsx | 0 src/shared/ui/{forms => form}/elements/form-radio-group.tsx | 0 src/shared/ui/{forms => form}/fields/checkbox-field.scss | 0 src/shared/ui/{forms => form}/fields/checkbox-field.tsx | 0 src/shared/ui/{forms => form}/fields/choice-field.scss | 0 src/shared/ui/{forms => form}/fields/choice-field.tsx | 0 src/shared/ui/{forms => form}/fields/file-field.scss | 0 src/shared/ui/{forms => form}/fields/file-field.tsx | 0 src/shared/ui/{forms => form}/fields/form-radio.scss | 0 src/shared/ui/{forms => form}/fields/form-radio.tsx | 0 src/shared/ui/{forms => form}/fields/info-field.scss | 0 src/shared/ui/{forms => form}/fields/info-field.tsx | 0 src/shared/ui/{forms => form}/fields/select-field.tsx | 0 src/shared/ui/{forms => form}/fields/text-field.scss | 0 src/shared/ui/{forms => form}/fields/text-field.tsx | 0 src/shared/ui/{forms => form}/fields/unit-field.scss | 0 src/shared/ui/{forms => form}/fields/unit-field.tsx | 0 src/shared/ui/{forms => form}/index.ts | 0 src/widgets/builder/builder.jsx | 2 +- src/widgets/export/export.tsx | 2 +- 43 files changed, 25 insertions(+), 25 deletions(-) rename src/shared/ui/{forms => form}/elements/form-control.tsx (100%) rename src/shared/ui/{forms => form}/elements/form-label.scss (100%) rename src/shared/ui/{forms => form}/elements/form-label.tsx (100%) rename src/shared/ui/{forms => form}/elements/form-radio-group.tsx (100%) rename src/shared/ui/{forms => form}/fields/checkbox-field.scss (100%) rename src/shared/ui/{forms => form}/fields/checkbox-field.tsx (100%) rename src/shared/ui/{forms => form}/fields/choice-field.scss (100%) rename src/shared/ui/{forms => form}/fields/choice-field.tsx (100%) rename src/shared/ui/{forms => form}/fields/file-field.scss (100%) rename src/shared/ui/{forms => form}/fields/file-field.tsx (100%) rename src/shared/ui/{forms => form}/fields/form-radio.scss (100%) rename src/shared/ui/{forms => form}/fields/form-radio.tsx (100%) rename src/shared/ui/{forms => form}/fields/info-field.scss (100%) rename src/shared/ui/{forms => form}/fields/info-field.tsx (100%) rename src/shared/ui/{forms => form}/fields/select-field.tsx (100%) rename src/shared/ui/{forms => form}/fields/text-field.scss (100%) rename src/shared/ui/{forms => form}/fields/text-field.tsx (100%) rename src/shared/ui/{forms => form}/fields/unit-field.scss (100%) rename src/shared/ui/{forms => form}/fields/unit-field.tsx (100%) rename src/shared/ui/{forms => form}/index.ts (100%) diff --git a/src/families/custom.tsx b/src/families/custom.tsx index 12e4f714..0aca8c44 100644 --- a/src/families/custom.tsx +++ b/src/families/custom.tsx @@ -3,7 +3,7 @@ import { useEffect } from "react"; import { args as arx } from "../shared/lib/args/args"; import { Call, CallError } from "../shared/lib/call"; import { toGas } from "../shared/lib/converter"; -import { TextField, UnitField } from "../shared/ui/forms"; +import { TextField, UnitField } from "../shared/ui/form"; import { BaseTask, BaseTaskProps, DefaultFormData, DisplayData } from "./base"; import "./custom.scss"; diff --git a/src/families/mintbase/add-minter.tsx b/src/families/mintbase/add-minter.tsx index 1f4a788a..f542a294 100644 --- a/src/families/mintbase/add-minter.tsx +++ b/src/families/mintbase/add-minter.tsx @@ -7,7 +7,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { MintbaseStore } from "../../shared/lib/contracts/mintbase"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; import "./mintbase.scss"; diff --git a/src/families/mintbase/create-store.tsx b/src/families/mintbase/create-store.tsx index aafd8c98..da568391 100644 --- a/src/families/mintbase/create-store.tsx +++ b/src/families/mintbase/create-store.tsx @@ -5,8 +5,8 @@ import { Call, CallError } from "../../shared/lib/call"; import { BASE_URI_ARWEAVE, MintbaseStore } from "../../shared/lib/contracts/mintbase"; import { dataUrlToFile, fileToDataUrl } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; -import { InfoField, TextField, UnitField } from "../../shared/ui/forms"; -import { FileField } from "../../shared/ui/forms/fields/file-field"; +import { InfoField, TextField, UnitField } from "../../shared/ui/form"; +import { FileField } from "../../shared/ui/form/fields/file-field"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "../base"; import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; import "./mintbase.scss"; diff --git a/src/families/mintbase/remove-minter.tsx b/src/families/mintbase/remove-minter.tsx index e09f8644..3cd06b83 100644 --- a/src/families/mintbase/remove-minter.tsx +++ b/src/families/mintbase/remove-minter.tsx @@ -7,7 +7,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { MintbaseStore } from "../../shared/lib/contracts/mintbase"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; import "./mintbase.scss"; diff --git a/src/families/mintbase/transfer-store-ownership.tsx b/src/families/mintbase/transfer-store-ownership.tsx index 7142af63..d7de90fb 100644 --- a/src/families/mintbase/transfer-store-ownership.tsx +++ b/src/families/mintbase/transfer-store-ownership.tsx @@ -7,7 +7,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { MintbaseStore } from "../../shared/lib/contracts/mintbase"; -import { CheckboxField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; import "./mintbase.scss"; diff --git a/src/families/multicall/transfer.tsx b/src/families/multicall/transfer.tsx index bb0ee56f..15bad7b7 100644 --- a/src/families/multicall/transfer.tsx +++ b/src/families/multicall/transfer.tsx @@ -5,7 +5,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { Multicall } from "../../shared/lib/contracts/multicall"; import { unit } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; -import { CheckboxField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, DefaultFormData } from "../base"; import { DynamicFeedOutlined } from "@mui/icons-material"; import "./multicall.scss"; diff --git a/src/families/near/deposit-and-stake.tsx b/src/families/near/deposit-and-stake.tsx index b14e9940..e6f3bd62 100644 --- a/src/families/near/deposit-and-stake.tsx +++ b/src/families/near/deposit-and-stake.tsx @@ -5,7 +5,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { StakingPool } from "../../shared/lib/contracts/staking-pool"; -import { InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { InfoField, TextField, UnitField } from "../../shared/ui/form"; import type { DefaultFormData } from "../base"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; diff --git a/src/families/near/ft-transfer-call.tsx b/src/families/near/ft-transfer-call.tsx index 5b72fdf8..7004d02d 100644 --- a/src/families/near/ft-transfer-call.tsx +++ b/src/families/near/ft-transfer-call.tsx @@ -6,7 +6,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { Big, toGas, unit } from "../../shared/lib/converter"; import { FungibleToken } from "../../shared/lib/standards/fungibleToken"; -import { TextField, UnitField, InfoField, CheckboxField } from "../../shared/ui/forms"; +import { TextField, UnitField, InfoField, CheckboxField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData, DisplayData } from "../base"; import "./near.scss"; diff --git a/src/families/near/ft-transfer.tsx b/src/families/near/ft-transfer.tsx index e8cd5955..f28fcf73 100644 --- a/src/families/near/ft-transfer.tsx +++ b/src/families/near/ft-transfer.tsx @@ -6,7 +6,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { Big, toGas, unit } from "../../shared/lib/converter"; import { FungibleToken } from "../../shared/lib/standards/fungibleToken"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import type { DefaultFormData, DisplayData } from "../base"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; diff --git a/src/families/near/mft-transfer-call.tsx b/src/families/near/mft-transfer-call.tsx index ba61ddb7..e96f76ee 100644 --- a/src/families/near/mft-transfer-call.tsx +++ b/src/families/near/mft-transfer-call.tsx @@ -6,7 +6,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { MultiFungibleToken } from "../../shared/lib/standards/multiFungibleToken"; -import { TextField, UnitField } from "../../shared/ui/forms"; +import { TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "../base"; import "./near.scss"; diff --git a/src/families/near/mft-transfer.tsx b/src/families/near/mft-transfer.tsx index d871b32b..111016de 100644 --- a/src/families/near/mft-transfer.tsx +++ b/src/families/near/mft-transfer.tsx @@ -6,7 +6,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { MultiFungibleToken } from "../../shared/lib/standards/multiFungibleToken"; -import { TextField, UnitField } from "../../shared/ui/forms"; +import { TextField, UnitField } from "../../shared/ui/form"; import type { DefaultFormData } from "../base"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; diff --git a/src/families/near/nft-approve.tsx b/src/families/near/nft-approve.tsx index 3d0d2bab..5182732c 100644 --- a/src/families/near/nft-approve.tsx +++ b/src/families/near/nft-approve.tsx @@ -7,7 +7,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { NonFungibleToken } from "../../shared/lib/standards/nonFungibleToken"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import type { DefaultFormData } from "../base"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; diff --git a/src/families/near/nft-revoke.tsx b/src/families/near/nft-revoke.tsx index a8a91def..25ec32cd 100644 --- a/src/families/near/nft-revoke.tsx +++ b/src/families/near/nft-revoke.tsx @@ -6,7 +6,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { NonFungibleToken } from "../../shared/lib/standards/nonFungibleToken"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import type { DefaultFormData } from "../base"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; diff --git a/src/families/near/nft-transfer-call.tsx b/src/families/near/nft-transfer-call.tsx index 95475e0d..f9d172c5 100644 --- a/src/families/near/nft-transfer-call.tsx +++ b/src/families/near/nft-transfer-call.tsx @@ -6,7 +6,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { NonFungibleToken } from "../../shared/lib/standards/nonFungibleToken"; -import { TextField, UnitField } from "../../shared/ui/forms"; +import { TextField, UnitField } from "../../shared/ui/form"; import type { DefaultFormData } from "../base"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; diff --git a/src/families/near/nft-transfer.tsx b/src/families/near/nft-transfer.tsx index 537d7446..09add64c 100644 --- a/src/families/near/nft-transfer.tsx +++ b/src/families/near/nft-transfer.tsx @@ -6,7 +6,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { toGas } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { NonFungibleToken } from "../../shared/lib/standards/nonFungibleToken"; -import { TextField, UnitField } from "../../shared/ui/forms"; +import { TextField, UnitField } from "../../shared/ui/form"; import type { DefaultFormData } from "../base"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; diff --git a/src/families/near/storage-deposit.tsx b/src/families/near/storage-deposit.tsx index 7c5b6d17..c4743994 100644 --- a/src/families/near/storage-deposit.tsx +++ b/src/families/near/storage-deposit.tsx @@ -6,7 +6,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { Big, unit } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { StorageManagement, StorageBalance, StorageBalanceBounds } from "../../shared/lib/standards/storageManagement"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "./../base"; import "./near.scss"; diff --git a/src/families/near/storage-unregister.tsx b/src/families/near/storage-unregister.tsx index 2d0712d8..39753a71 100644 --- a/src/families/near/storage-unregister.tsx +++ b/src/families/near/storage-unregister.tsx @@ -6,7 +6,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { unit } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { StorageManagement, StorageBalance } from "../../shared/lib/standards/storageManagement"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "../base"; import "./near.scss"; diff --git a/src/families/near/storage-withdraw.tsx b/src/families/near/storage-withdraw.tsx index d4af7e21..32785a44 100644 --- a/src/families/near/storage-withdraw.tsx +++ b/src/families/near/storage-withdraw.tsx @@ -6,7 +6,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { unit } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; import { StorageManagement, StorageBalance } from "../../shared/lib/standards/storageManagement"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "./../base"; import "./near.scss"; diff --git a/src/families/near/unstake.tsx b/src/families/near/unstake.tsx index cd3422a6..19de8f15 100644 --- a/src/families/near/unstake.tsx +++ b/src/families/near/unstake.tsx @@ -7,14 +7,14 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { toGas, unit, formatTokenAmount } from "../../shared/lib/converter"; import { StakingPool } from "../../shared/lib/contracts/staking-pool"; -import { CheckboxField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; import { STORAGE } from "../../shared/lib/persistent"; import type { DefaultFormData } from "../base"; import type { HumanReadableAccount } from "../../shared/lib/contracts/staking-pool"; -import { InfoField } from "../../shared/ui/forms/fields/info-field"; +import { InfoField } from "../../shared/ui/form/fields/info-field"; type FormData = DefaultFormData & { amount: string; diff --git a/src/families/near/withdraw.tsx b/src/families/near/withdraw.tsx index 818ee478..0144a994 100644 --- a/src/families/near/withdraw.tsx +++ b/src/families/near/withdraw.tsx @@ -7,7 +7,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { toGas, unit, formatTokenAmount } from "../../shared/lib/converter"; import { StakingPool } from "../../shared/lib/contracts/staking-pool"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/forms"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./near.scss"; import { STORAGE } from "../../shared/lib/persistent"; diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 981a0436..5ec4cec5 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -15,7 +15,7 @@ import { STORAGE } from "../../shared/lib/persistent"; import { signAndSendTxs } from "../../shared/lib/wallet"; import { Tabs } from "../../shared/ui/design"; -import { TextField } from "../../shared/ui/forms"; +import { TextField } from "../../shared/ui/form"; import { DaoConfigTab } from "./config/config"; import "./dao.scss"; import { DaoFundsTab } from "./funds/funds"; diff --git a/src/shared/ui/forms/elements/form-control.tsx b/src/shared/ui/form/elements/form-control.tsx similarity index 100% rename from src/shared/ui/forms/elements/form-control.tsx rename to src/shared/ui/form/elements/form-control.tsx diff --git a/src/shared/ui/forms/elements/form-label.scss b/src/shared/ui/form/elements/form-label.scss similarity index 100% rename from src/shared/ui/forms/elements/form-label.scss rename to src/shared/ui/form/elements/form-label.scss diff --git a/src/shared/ui/forms/elements/form-label.tsx b/src/shared/ui/form/elements/form-label.tsx similarity index 100% rename from src/shared/ui/forms/elements/form-label.tsx rename to src/shared/ui/form/elements/form-label.tsx diff --git a/src/shared/ui/forms/elements/form-radio-group.tsx b/src/shared/ui/form/elements/form-radio-group.tsx similarity index 100% rename from src/shared/ui/forms/elements/form-radio-group.tsx rename to src/shared/ui/form/elements/form-radio-group.tsx diff --git a/src/shared/ui/forms/fields/checkbox-field.scss b/src/shared/ui/form/fields/checkbox-field.scss similarity index 100% rename from src/shared/ui/forms/fields/checkbox-field.scss rename to src/shared/ui/form/fields/checkbox-field.scss diff --git a/src/shared/ui/forms/fields/checkbox-field.tsx b/src/shared/ui/form/fields/checkbox-field.tsx similarity index 100% rename from src/shared/ui/forms/fields/checkbox-field.tsx rename to src/shared/ui/form/fields/checkbox-field.tsx diff --git a/src/shared/ui/forms/fields/choice-field.scss b/src/shared/ui/form/fields/choice-field.scss similarity index 100% rename from src/shared/ui/forms/fields/choice-field.scss rename to src/shared/ui/form/fields/choice-field.scss diff --git a/src/shared/ui/forms/fields/choice-field.tsx b/src/shared/ui/form/fields/choice-field.tsx similarity index 100% rename from src/shared/ui/forms/fields/choice-field.tsx rename to src/shared/ui/form/fields/choice-field.tsx diff --git a/src/shared/ui/forms/fields/file-field.scss b/src/shared/ui/form/fields/file-field.scss similarity index 100% rename from src/shared/ui/forms/fields/file-field.scss rename to src/shared/ui/form/fields/file-field.scss diff --git a/src/shared/ui/forms/fields/file-field.tsx b/src/shared/ui/form/fields/file-field.tsx similarity index 100% rename from src/shared/ui/forms/fields/file-field.tsx rename to src/shared/ui/form/fields/file-field.tsx diff --git a/src/shared/ui/forms/fields/form-radio.scss b/src/shared/ui/form/fields/form-radio.scss similarity index 100% rename from src/shared/ui/forms/fields/form-radio.scss rename to src/shared/ui/form/fields/form-radio.scss diff --git a/src/shared/ui/forms/fields/form-radio.tsx b/src/shared/ui/form/fields/form-radio.tsx similarity index 100% rename from src/shared/ui/forms/fields/form-radio.tsx rename to src/shared/ui/form/fields/form-radio.tsx diff --git a/src/shared/ui/forms/fields/info-field.scss b/src/shared/ui/form/fields/info-field.scss similarity index 100% rename from src/shared/ui/forms/fields/info-field.scss rename to src/shared/ui/form/fields/info-field.scss diff --git a/src/shared/ui/forms/fields/info-field.tsx b/src/shared/ui/form/fields/info-field.tsx similarity index 100% rename from src/shared/ui/forms/fields/info-field.tsx rename to src/shared/ui/form/fields/info-field.tsx diff --git a/src/shared/ui/forms/fields/select-field.tsx b/src/shared/ui/form/fields/select-field.tsx similarity index 100% rename from src/shared/ui/forms/fields/select-field.tsx rename to src/shared/ui/form/fields/select-field.tsx diff --git a/src/shared/ui/forms/fields/text-field.scss b/src/shared/ui/form/fields/text-field.scss similarity index 100% rename from src/shared/ui/forms/fields/text-field.scss rename to src/shared/ui/form/fields/text-field.scss diff --git a/src/shared/ui/forms/fields/text-field.tsx b/src/shared/ui/form/fields/text-field.tsx similarity index 100% rename from src/shared/ui/forms/fields/text-field.tsx rename to src/shared/ui/form/fields/text-field.tsx diff --git a/src/shared/ui/forms/fields/unit-field.scss b/src/shared/ui/form/fields/unit-field.scss similarity index 100% rename from src/shared/ui/forms/fields/unit-field.scss rename to src/shared/ui/form/fields/unit-field.scss diff --git a/src/shared/ui/forms/fields/unit-field.tsx b/src/shared/ui/form/fields/unit-field.tsx similarity index 100% rename from src/shared/ui/forms/fields/unit-field.tsx rename to src/shared/ui/form/fields/unit-field.tsx diff --git a/src/shared/ui/forms/index.ts b/src/shared/ui/form/index.ts similarity index 100% rename from src/shared/ui/forms/index.ts rename to src/shared/ui/form/index.ts diff --git a/src/widgets/builder/builder.jsx b/src/widgets/builder/builder.jsx index 5a47f0f7..2927f7e8 100644 --- a/src/widgets/builder/builder.jsx +++ b/src/widgets/builder/builder.jsx @@ -1,7 +1,7 @@ import debounce from "lodash.debounce"; import { Component } from "react"; import { Droppable } from "react-beautiful-dnd"; -import { TextField } from "../../shared/ui/forms"; +import { TextField } from "../../shared/ui/form"; import { Column } from "../column/column.jsx"; import { keywords } from "../../keywords"; import { Formik, Form } from "formik"; diff --git a/src/widgets/export/export.tsx b/src/widgets/export/export.tsx index 9979e5bd..d4c26354 100644 --- a/src/widgets/export/export.tsx +++ b/src/widgets/export/export.tsx @@ -17,7 +17,7 @@ import { STORAGE } from "../../shared/lib/persistent"; import { FungibleToken } from "../../shared/lib/standards/fungibleToken"; import { signAndSendTxs } from "../../shared/lib/wallet"; import { DateTimePicker } from "../../shared/ui/design"; -import { ChoiceField, TextField, UnitField } from "../../shared/ui/forms"; +import { ChoiceField, TextField, UnitField } from "../../shared/ui/form"; import "./export.scss"; const Ctx = Wallet.trySelectorContext(); From 314647829ec76bacd8ab54557a5ebb375f582c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 09:39:18 +0400 Subject: [PATCH 409/537] chore: Rename property --- src/entities/job/ui/jobs-table.tsx | 2 +- src/entities/multicall-instance/ui/mi-admins.tsx | 2 +- .../multicall-instance/ui/mi-tokens-whitelist.tsx | 2 +- src/features/job-settings-edit/ui/job-settings-form.tsx | 2 +- src/shared/ui/design/table/row.scss | 6 +++--- src/shared/ui/design/table/row.tsx | 8 ++++---- src/shared/ui/design/table/table.tsx | 2 +- src/widgets/tokens-balances/ui/tokens-balances.tsx | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 5852e72d..736c0cbf 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -23,7 +23,7 @@ export const JobsTable = ({ className, contracts }: JobsTableProps) => { >
    span { &:first-of-type { @@ -166,7 +166,7 @@ } } - &--dense.TableRow-content--compact--entitled { + &--dense.TableRow-content--compact--withTitile { &:not(:first-of-type) { padding: 0; diff --git a/src/shared/ui/design/table/row.tsx b/src/shared/ui/design/table/row.tsx index ecec8bec..a5db2972 100644 --- a/src/shared/ui/design/table/row.tsx +++ b/src/shared/ui/design/table/row.tsx @@ -16,7 +16,7 @@ export interface TableRowProps { /** * Display first cell of each row as its title in `"compact"` table `displayMode` */ - entitled?: boolean; + withTitile?: boolean; header: TableHeader; id: string; idToHighlightColor?: (id: TableRowProps["id"]) => DesignKitConfigType.Color | null; @@ -43,7 +43,7 @@ export const TableRowCompact = ({ cells, centeredTitle, dense, - entitled, + withTitile, header, id, idToHighlightColor, @@ -68,8 +68,8 @@ export const TableRowCompact = ({
    , Pick
    From 5619ed314776a4c7ed5b3d27369ba01fea68ea7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 09:50:08 +0400 Subject: [PATCH 410/537] chore: Fix naming and labeling --- src/entities/job/ui/jobs-table.tsx | 2 +- src/entities/multicall-instance/ui/mi-admins.tsx | 2 +- .../multicall-instance/ui/mi-tokens-whitelist.tsx | 4 ++-- src/features/job-settings-edit/ui/job-settings-form.tsx | 4 ++-- src/shared/ui/design/table/row.scss | 6 +++--- src/shared/ui/design/table/row.tsx | 8 ++++---- src/widgets/tokens-balances/ui/tokens-balances.tsx | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 736c0cbf..6d1c7908 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -23,7 +23,7 @@ export const JobsTable = ({ className, contracts }: JobsTableProps) => { >
    @@ -109,7 +109,7 @@ export const JobSettingsForm = ({ ? null : "blue"), - withTitile: true, + withTitle: true, noKeys: true, }} displayMode="compact" diff --git a/src/shared/ui/design/table/row.scss b/src/shared/ui/design/table/row.scss index d003d21f..057aab20 100644 --- a/src/shared/ui/design/table/row.scss +++ b/src/shared/ui/design/table/row.scss @@ -75,7 +75,7 @@ } } - &:not(&--withTitile) { + &:not(&--withTitle) { padding: 0.5 * size.$gap size.$gap; background-color: rgba(color.$lightest, 0.7); @@ -120,7 +120,7 @@ } } - &--withTitile { + &--withTitle { &:first-of-type { & > span { &:first-of-type { @@ -166,7 +166,7 @@ } } - &--dense.TableRow-content--compact--withTitile { + &--dense.TableRow-content--compact--withTitle { &:not(:first-of-type) { padding: 0; diff --git a/src/shared/ui/design/table/row.tsx b/src/shared/ui/design/table/row.tsx index a5db2972..117e703b 100644 --- a/src/shared/ui/design/table/row.tsx +++ b/src/shared/ui/design/table/row.tsx @@ -16,7 +16,7 @@ export interface TableRowProps { /** * Display first cell of each row as its title in `"compact"` table `displayMode` */ - withTitile?: boolean; + withTitle?: boolean; header: TableHeader; id: string; idToHighlightColor?: (id: TableRowProps["id"]) => DesignKitConfigType.Color | null; @@ -43,7 +43,7 @@ export const TableRowCompact = ({ cells, centeredTitle, dense, - withTitile, + withTitle, header, id, idToHighlightColor, @@ -68,8 +68,8 @@ export const TableRowCompact = ({
    {(nearTokenBalances ?? fungibleTokensBalances) && (
    From 92ac7a55f64b3a47e2b113ed0de2aeee5037c9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 09:53:07 +0400 Subject: [PATCH 411/537] fix: Change link tooltip auto hide delay --- src/shared/ui/design/link/link.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/design/link/link.tsx b/src/shared/ui/design/link/link.tsx index c94fc35e..7fd5fd19 100644 --- a/src/shared/ui/design/link/link.tsx +++ b/src/shared/ui/design/link/link.tsx @@ -70,7 +70,7 @@ export const Link = ({ className, href, label, noTooltip = false, ...props }: Li )} } - leaveDelay={2000} + leaveDelay={400} placement="right" > From 421100d22b940693228bb391071c419b109762c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 10:13:38 +0400 Subject: [PATCH 412/537] wip: Shrink the gap between icon label elements --- src/shared/ui/design/icon-label/icon-label.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/design/icon-label/icon-label.scss b/src/shared/ui/design/icon-label/icon-label.scss index dd31d9f9..0be68814 100644 --- a/src/shared/ui/design/icon-label/icon-label.scss +++ b/src/shared/ui/design/icon-label/icon-label.scss @@ -5,7 +5,7 @@ display: flex; flex-direction: row; align-items: center; - gap: 0.6 * size.$gap; + gap: 0.3 * size.$gap; width: fit-content; line-height: 0; From dff1b1999afc21aeb3ce45d8e84f1384906c2fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 10:48:05 +0400 Subject: [PATCH 413/537] wip: Apply graphical design remarks --- src/global.scss | 4 ++++ src/shared/ui/design/icon-label/icon-label.tsx | 2 +- src/shared/ui/design/near-link/near-link.scss | 5 +++++ src/shared/ui/design/near-link/near-link.tsx | 5 +++++ .../multicall-config-editor/ui/mce-changes-proposal.tsx | 2 +- 5 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 src/shared/ui/design/near-link/near-link.scss diff --git a/src/global.scss b/src/global.scss index c79bff57..13bda999 100644 --- a/src/global.scss +++ b/src/global.scss @@ -74,3 +74,7 @@ button { .warn { color: color.$yellow; } + +.font--code { + font-family: font.$code; +} diff --git a/src/shared/ui/design/icon-label/icon-label.tsx b/src/shared/ui/design/icon-label/icon-label.tsx index 4e53734a..399a2c5c 100644 --- a/src/shared/ui/design/icon-label/icon-label.tsx +++ b/src/shared/ui/design/icon-label/icon-label.tsx @@ -30,6 +30,6 @@ export const IconLabel = ({ icon, label, reversed = false }: IconLabelProps) => )} - {label} + {label} ); diff --git a/src/shared/ui/design/near-link/near-link.scss b/src/shared/ui/design/near-link/near-link.scss new file mode 100644 index 00000000..62b38c24 --- /dev/null +++ b/src/shared/ui/design/near-link/near-link.scss @@ -0,0 +1,5 @@ +@use "sass/font"; + +.NearLink { + font-family: font.$code; +} diff --git a/src/shared/ui/design/near-link/near-link.tsx b/src/shared/ui/design/near-link/near-link.tsx index a35835dc..d9917840 100644 --- a/src/shared/ui/design/near-link/near-link.tsx +++ b/src/shared/ui/design/near-link/near-link.tsx @@ -3,15 +3,20 @@ import { Account } from "@near-wallet-selector/core"; import { ArgsAccount } from "../../../lib/args-old"; import { Link, LinkProps } from "../link"; +import "./near-link.scss"; + export interface NearLinkProps extends Omit { address: Account["accountId"]; } +const _NearLink = "NearLink"; + export const NearLink = ({ address }: NearLinkProps) => { const addr = new ArgsAccount(address); return ( - {!isNaN(parseInt(data as string)) && + {!Number.isNaN(data) && ChangesDiffKey === MulticallConfigEditorConfig.ChangesDiffKey.jobBond ? `${toNEAR(data as string)} ${NearIcon.NATIVE_TOKEN_CHARACTER}` : (data as string)} From 635d6be6958508f8f1ddf93c39ebc59d07d8722b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 14:27:42 +0400 Subject: [PATCH 414/537] wip: Fix tooltip --- src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index 466598f4..bfc29544 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -113,7 +113,7 @@ export const TokensWhitelistForm = ({ ) : ( - + void editModeSwitch(true)} From d893c2ba6218257e37febb6d516e627b804b81c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 23 Nov 2022 18:26:29 +0400 Subject: [PATCH 415/537] wip: Move data fetch effect away from multicall adapter --- .../multicall-instance/model/mi-admins.ts | 5 ++-- .../multicall-instance/model/mi-settings.ts | 26 +++++++++++++++++++ .../multicall-instance/model/mi-tokens.ts | 5 ++-- src/shared/lib/contracts/multicall.ts | 26 +------------------ 4 files changed, 33 insertions(+), 29 deletions(-) create mode 100644 src/entities/multicall-instance/model/mi-settings.ts diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index 46174089..a4c10e2f 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -3,9 +3,10 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; - import { type MulticallInstanceEntity } from "../config"; +import { MulticallInstanceSettingsModel } from "./mi-settings"; + export type MulticallInstanceAdminsAddressList = { data: Multicall["admins"] | null; error: Error | null; @@ -17,7 +18,7 @@ export class MulticallInstanceAdminsModel { daoAddress: MulticallInstanceEntity.Inputs["daoAddress"], callback: (result: MulticallInstanceAdminsAddressList) => void ) => - await Multicall.instanceDataFetchFx( + await MulticallInstanceSettingsModel.fetchFx( `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`, (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) ); diff --git a/src/entities/multicall-instance/model/mi-settings.ts b/src/entities/multicall-instance/model/mi-settings.ts new file mode 100644 index 00000000..4c6788e9 --- /dev/null +++ b/src/entities/multicall-instance/model/mi-settings.ts @@ -0,0 +1,26 @@ +import { ArgsAccount } from "../../../shared/lib/args-old"; +import { Multicall } from "../../../shared/lib/contracts/multicall"; +import { AccountId } from "../../../shared/lib/types"; + +export class MulticallInstanceSettingsModel { + /** + * Calls the given callback with a result of multicall contract instantiation, + * represented as stateful response. + * + * @param daoAddress DAO contract address + * @param callback Stateful data fetch callback + */ + static fetchFx = async ( + daoAddress: AccountId, + callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void + ) => + callback( + await Multicall.init( + `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}` + ).then((multicallInstance) => ({ + data: multicallInstance.ready ? multicallInstance : null, + error: multicallInstance.ready ? null : new Error("Unable to connect to Multicall Instance"), + loading: false, + })) + ); +} diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index 6173cba0..4f693b84 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -3,9 +3,10 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; - import { type MulticallInstanceEntity } from "../config"; +import { MulticallInstanceSettingsModel } from "./mi-settings"; + export type MulticallInstanceTokensWhitelist = { data: Multicall["tokensWhitelist"] | null; error: Error | null; @@ -17,7 +18,7 @@ export class MulticallInstanceTokensModel { daoAddress: MulticallInstanceEntity.Inputs["daoAddress"], callback: (result: MulticallInstanceTokensWhitelist) => void ) => - await Multicall.instanceDataFetchFx( + await MulticallInstanceSettingsModel.fetchFx( `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`, (multicallInstanceData) => diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index a84f18b3..90e9e75e 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -1,11 +1,8 @@ -import { Account } from "@near-wallet-selector/core"; - -import { ArgsAccount } from "../args-old"; import { Big, toGas, dateToCron, toYocto } from "../converter"; import { AccountId, Base64String, BigString, U128String, U64String } from "../types"; import { type Tx, viewAccount, viewState, view } from "../wallet"; -import type { FunctionCallAction as daoFunctionCallAction, SputnikDAO } from "./sputnik-dao"; +import type { FunctionCallAction as daoFunctionCallAction } from "./sputnik-dao"; const FACTORY_ADDRESS_SELECTOR: Record = { mainnet: "v1.multicall.near", @@ -137,27 +134,6 @@ class Multicall { return newMulticall; } - /** - * Calls the given callback with a result of multicall contract instantiation, - * represented as stateful response. - * - * @param daoAddress DAO contract address - * @param callback Stateful data fetch callback - */ - static instanceDataFetchFx = async ( - daoAddress: AccountId, - callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void - ) => - callback( - await Multicall.init( - `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}` - ).then((multicallInstance) => ({ - data: multicallInstance.ready ? multicallInstance : null, - error: multicallInstance.ready ? null : new Error("Unable to connect to Multicall Instance"), - loading: false, - })) - ); - /** * check of given accountId is a multicall instance. * uses code_hash of the contract deployed on accountId. From 5acba171d96278636de889df9f6e93548055224f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 24 Nov 2022 11:10:26 +0400 Subject: [PATCH 416/537] wip: Apply post code review remarks --- src/entities/fungible-token/config.ts | 6 +- src/entities/fungible-token/index.ts | 10 +-- src/entities/fungible-token/lib/ft-format.ts | 8 +-- .../fungible-token/model/ft-balances.ts | 67 ------------------- src/entities/fungible-token/model/ft-info.ts | 64 ++++++++++++++++++ .../fungible-token/ui/ft-balances.tsx | 19 +++--- src/entities/index.ts | 6 +- src/entities/multicall-instance/config.ts | 14 ++-- src/entities/multicall-instance/index.ts | 14 ++-- .../multicall-instance/model/mi-admins.ts | 23 +++---- .../multicall-instance/model/mi-settings.ts | 4 +- .../multicall-instance/model/mi-tokens.ts | 23 +++---- .../multicall-instance/ui/mi-admin.tsx | 8 +-- .../multicall-instance/ui/mi-admins.tsx | 14 ++-- ...s-whitelist.tsx => mi-token-whitelist.tsx} | 23 +++---- .../ui/mi-whitelisted-token.tsx | 10 ++- src/entities/near-token/index.ts | 8 --- src/entities/{near-token => near}/config.ts | 6 +- src/entities/near/index.ts | 8 +++ .../model/near-balances.ts | 22 +++--- .../{near-token => near}/ui/near-balances.tsx | 10 +-- src/features/index.ts | 2 +- src/features/job-settings-edit/config.ts | 20 +++--- .../ui/job-settings-form.tsx | 22 +++--- src/features/tokens-whitelist-edit/config.ts | 28 ++++---- src/features/tokens-whitelist-edit/index.ts | 10 +-- .../ui/tokens-whitelist-form.tsx | 20 +++--- src/pages/dao/config/config.tsx | 6 +- src/pages/dao/dao.tsx | 4 +- src/pages/dao/funds/funds.scss | 4 +- src/pages/dao/funds/funds.tsx | 6 +- src/shared/lib/contracts/multicall.ts | 24 +++---- src/shared/lib/converter.ts | 9 ++- src/widgets/index.ts | 4 +- src/widgets/multicall-config-editor/config.ts | 28 -------- src/widgets/multicall-config-editor/index.ts | 8 --- src/widgets/settings-editor/config.ts | 27 ++++++++ src/widgets/settings-editor/index.ts | 8 +++ .../ui/se-proposal-form.scss} | 4 +- .../ui/se-proposal-form.tsx} | 53 +++++++-------- .../ui/settings-editor.scss} | 12 ++-- .../ui/settings-editor.tsx} | 45 ++++++------- src/widgets/tokens-balances/config.ts | 8 +-- src/widgets/tokens-balances/index.ts | 10 +-- .../tokens-balances/ui/tokens-balances.scss | 4 +- .../tokens-balances/ui/tokens-balances.tsx | 23 +++---- 46 files changed, 363 insertions(+), 393 deletions(-) delete mode 100644 src/entities/fungible-token/model/ft-balances.ts create mode 100644 src/entities/fungible-token/model/ft-info.ts rename src/entities/multicall-instance/ui/{mi-tokens-whitelist.tsx => mi-token-whitelist.tsx} (58%) delete mode 100644 src/entities/near-token/index.ts rename src/entities/{near-token => near}/config.ts (75%) create mode 100644 src/entities/near/index.ts rename src/entities/{near-token => near}/model/near-balances.ts (59%) rename src/entities/{near-token => near}/ui/near-balances.tsx (55%) delete mode 100644 src/widgets/multicall-config-editor/config.ts delete mode 100644 src/widgets/multicall-config-editor/index.ts create mode 100644 src/widgets/settings-editor/config.ts create mode 100644 src/widgets/settings-editor/index.ts rename src/widgets/{multicall-config-editor/ui/mce-changes-proposal.scss => settings-editor/ui/se-proposal-form.scss} (95%) rename src/widgets/{multicall-config-editor/ui/mce-changes-proposal.tsx => settings-editor/ui/se-proposal-form.tsx} (57%) rename src/widgets/{multicall-config-editor/ui/multicall-config-editor.scss => settings-editor/ui/settings-editor.scss} (58%) rename src/widgets/{multicall-config-editor/ui/multicall-config-editor.tsx => settings-editor/ui/settings-editor.tsx} (68%) diff --git a/src/entities/fungible-token/config.ts b/src/entities/fungible-token/config.ts index 4188a5cb..d12d8cc4 100644 --- a/src/entities/fungible-token/config.ts +++ b/src/entities/fungible-token/config.ts @@ -1,7 +1,7 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -namespace FungibleTokenEntity { +export namespace FT { export interface Inputs { contracts: { dao: SputnikDAO; @@ -10,8 +10,6 @@ namespace FungibleTokenEntity { } } -class FungibleTokenConfig { +export class FTConfig { static FRACTIONAL_PART_LENGTH = 5; } - -export { FungibleTokenConfig, type FungibleTokenEntity }; diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index d369e95f..d3cecad4 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,8 +1,8 @@ -import { FungibleTokenConfig, type FungibleTokenEntity } from "./config"; -import { fungibleTokensBalancesRender } from "./ui/ft-balances"; +import { FTConfig, FT as FTEntity } from "./config"; +import { ftBalances } from "./ui/ft-balances"; -class FungibleToken extends FungibleTokenConfig { - static allBalancesRender = fungibleTokensBalancesRender; +class FT extends FTConfig { + static balances = ftBalances; } -export { FungibleToken, FungibleTokenEntity }; +export { FT, type FTEntity }; diff --git a/src/entities/fungible-token/lib/ft-format.ts b/src/entities/fungible-token/lib/ft-format.ts index 0985b636..8a61788d 100644 --- a/src/entities/fungible-token/lib/ft-format.ts +++ b/src/entities/fungible-token/lib/ft-format.ts @@ -1,16 +1,16 @@ import { Big, formatTokenAmount } from "../../../shared/lib/converter"; -import { FungibleTokenConfig } from "../config"; +import { FTConfig } from "../config"; const amountToDisplayAmount = (amount: string, decimals: number): string => { const formattedAmount = formatTokenAmount(amount, decimals), - minimalDisplayAmount = Big("10").pow(-FungibleTokenConfig.FRACTIONAL_PART_LENGTH).toFixed(); + minimalDisplayAmount = Big("10").pow(-FTConfig.FRACTIONAL_PART_LENGTH).toFixed(); return Big(formattedAmount).gt("0") && Big(formattedAmount).lt(minimalDisplayAmount) ? "< " + minimalDisplayAmount - : formatTokenAmount(amount, decimals, FungibleTokenConfig.FRACTIONAL_PART_LENGTH); + : formatTokenAmount(amount, decimals, FTConfig.FRACTIONAL_PART_LENGTH); }; -export const FungibleTokenFormat = { +export const FTFormat = { amountToDisplayAmount, }; diff --git a/src/entities/fungible-token/model/ft-balances.ts b/src/entities/fungible-token/model/ft-balances.ts deleted file mode 100644 index 6b48d4e5..00000000 --- a/src/entities/fungible-token/model/ft-balances.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { useEffect, useState } from "react"; - -import { Big } from "../../../shared/lib/converter"; -import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; - -import { type FungibleTokenEntity } from "../config"; - -type FungibleTokensDataFxResponse = { - data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; - loading: boolean; -}; - -const fungibleTokensDataFx = async ( - { dao, multicall }: FungibleTokenEntity.Inputs["contracts"], - callback: (result: FungibleTokensDataFxResponse) => void -) => { - /* Get LikelyTokens list on DAO and its Multicall instance */ - const [daoLikelyTokensList, multicallLikelyTokensList] = await Promise.all([ - FungibleToken.getLikelyTokenContracts(dao.address), - FungibleToken.getLikelyTokenContracts(multicall.address), - ]); - - /* Merge and de-duplicate both token lists */ - const fullLikelyTokensAddressesList = [...new Set([...daoLikelyTokensList, ...multicallLikelyTokensList])]; - - const likelyTokensList = await Promise.all( - fullLikelyTokensAddressesList.map((address) => FungibleToken.init(address)) - ); - - const rawBalances = await Promise.all( - likelyTokensList - .filter((token) => token.ready === true) - .map(async (token) => { - const [daoRawBalance, multicallRawBalance] = await Promise.all([ - token.ftBalanceOf(dao.address), - token.ftBalanceOf(multicall.address), - ]); - - return { - metadata: token.metadata, - dao: daoRawBalance, - multicall: multicallRawBalance, - total: Big(multicallRawBalance).add(daoRawBalance).toFixed(), - }; - }) - ); - - // remove tokens with 0 total balance - const nonZeroBalances = rawBalances.filter(({ total }) => Big(total).gt("0")); - - return callback({ - data: nonZeroBalances.map(({ dao, metadata, multicall, total }) => ({ metadata, dao, multicall, total })), - loading: false, - }); -}; - -const useAllFungibleTokensData = (contracts: FungibleTokenEntity.Inputs["contracts"]) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); - - useEffect(() => void fungibleTokensDataFx(contracts, stateUpdate), [contracts, stateUpdate]); - - return state; -}; - -export class FungibleTokenBalancesModel { - static useAllTokensFrom = useAllFungibleTokensData; -} diff --git a/src/entities/fungible-token/model/ft-info.ts b/src/entities/fungible-token/model/ft-info.ts new file mode 100644 index 00000000..6fc1a147 --- /dev/null +++ b/src/entities/fungible-token/model/ft-info.ts @@ -0,0 +1,64 @@ +import { useEffect, useState } from "react"; + +import { Big } from "../../../shared/lib/converter"; +import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; +import { type FT } from "../config"; + +type FTInfo = { + data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; + loading: boolean; +}; + +export class FTInfoModel { + private static readonly nonZeroBalancesFetchFx = async ( + { dao, multicall }: FT.Inputs["contracts"], + callback: (result: FTInfo) => void + ) => { + /* Get LikelyTokens list on DAO and its Multicall instance */ + const [daoLikelyTokensList, multicallLikelyTokensList] = await Promise.all([ + FungibleToken.getLikelyTokenContracts(dao.address), + FungibleToken.getLikelyTokenContracts(multicall.address), + ]); + + /* Merge and de-duplicate both token lists */ + const likelyTokensAddressesList = [...new Set([...daoLikelyTokensList, ...multicallLikelyTokensList])]; + + const likelyTokensList = await Promise.all( + likelyTokensAddressesList.map((address) => FungibleToken.init(address)) + ); + + const rawBalances = await Promise.all( + likelyTokensList + .filter((token) => token.ready === true) + .map(async (token) => { + const [daoRawBalance, multicallRawBalance] = await Promise.all([ + token.ftBalanceOf(dao.address), + token.ftBalanceOf(multicall.address), + ]); + + return { + metadata: token.metadata, + dao: daoRawBalance, + multicall: multicallRawBalance, + total: Big(multicallRawBalance).add(daoRawBalance).toFixed(), + }; + }) + ); + + // remove tokens with 0 total balance + const nonZeroBalances = rawBalances.filter(({ total }) => Big(total).gt("0")); + + return callback({ + data: nonZeroBalances.map(({ dao, metadata, multicall, total }) => ({ metadata, dao, multicall, total })), + loading: false, + }); + }; + + public static readonly useNonZeroBalances = (contracts: FT.Inputs["contracts"]) => { + const [state, stateUpdate] = useState({ data: null, loading: true }); + + useEffect(() => void FTInfoModel.nonZeroBalancesFetchFx(contracts, stateUpdate), [contracts, stateUpdate]); + + return state; + }; +} diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index a2d1c362..6567c811 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -1,13 +1,12 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; +import { FTFormat } from "../lib/ft-format"; +import { FTInfoModel } from "../model/ft-info"; +import { type FT } from "../config"; -import { FungibleTokenFormat } from "../lib/ft-format"; -import { FungibleTokenBalancesModel } from "../model/ft-balances"; -import { type FungibleTokenEntity } from "../config"; +interface FTBalancesProps extends FT.Inputs {} -interface FungibleTokensBalancesRenderProps extends FungibleTokenEntity.Inputs {} - -export const fungibleTokensBalancesRender = ({ contracts }: FungibleTokensBalancesRenderProps) => { - const { data } = FungibleTokenBalancesModel.useAllTokensFrom(contracts); +export const ftBalances = ({ contracts }: FTBalancesProps) => { + const { data } = FTInfoModel.useNonZeroBalances(contracts); return !data ? null @@ -18,9 +17,9 @@ export const fungibleTokensBalancesRender = ({ contracts }: FungibleTokensBalanc label={metadata.symbol} />, - FungibleTokenFormat.amountToDisplayAmount(multicall, metadata.decimals), - FungibleTokenFormat.amountToDisplayAmount(dao, metadata.decimals), - FungibleTokenFormat.amountToDisplayAmount(total, metadata.decimals), + FTFormat.amountToDisplayAmount(multicall, metadata.decimals), + FTFormat.amountToDisplayAmount(dao, metadata.decimals), + FTFormat.amountToDisplayAmount(total, metadata.decimals), ], id: metadata.symbol, diff --git a/src/entities/index.ts b/src/entities/index.ts index bce08ae0..9851dcc1 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ export { Task } from "./task"; export { Job, type JobEntity } from "./job"; -export { FungibleToken, type FungibleTokenEntity } from "./fungible-token"; -export { MulticallInstance, type MulticallInstanceEntity } from "./multicall-instance"; -export { NearToken, type NearTokenEntity } from "./near-token"; +export { FT, type FTEntity } from "./fungible-token"; +export { MI, type MIEntity } from "./multicall-instance"; +export { NEAR, type NEAREntity } from "./near"; export { Wallet } from "./wallet"; diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/config.ts index 16c64ad6..c140dea7 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/config.ts @@ -1,28 +1,26 @@ -import { MulticallConfigParamKey } from "../../shared/lib/contracts/multicall"; +import { MulticallSettingsParamKey } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; import { toYocto } from "../../shared/lib/converter"; /** * Type declaration for Multicall Instance entity */ -namespace MulticallInstanceEntity { +export namespace MI { export interface Inputs { daoAddress: SputnikDAO["address"]; } - export type ParamKey = MulticallConfigParamKey; + export type ParamKey = MulticallSettingsParamKey; } /** * Multicall Instance entity config */ -class MulticallInstanceEntityConfig { - public static readonly ParamKey = MulticallConfigParamKey; +export class MIConfig { + public static readonly ParamKey = MulticallSettingsParamKey; /** * Minimum balance needed for storage + state. */ - public static readonly MIN_BALANCE = toYocto(1 /* NEAR */); + public static readonly MIN_BALANCE = toYocto(1); } - -export { MulticallInstanceEntityConfig, type MulticallInstanceEntity }; diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 3161e2a2..29b825a3 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,13 +1,13 @@ -import { type MulticallInstanceEntity, MulticallInstanceEntityConfig } from "./config"; -import { MulticallInstanceAdminsTable } from "./ui/mi-admins"; -import { MulticallInstanceTokensWhitelistTable } from "./ui/mi-tokens-whitelist"; +import { MI as MIEntity, MIConfig } from "./config"; +import { MIAdminsTable } from "./ui/mi-admins"; +import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; /** * Multicall Instance entity */ -class MulticallInstance extends MulticallInstanceEntityConfig { - static AdminsTable = MulticallInstanceAdminsTable; - static TokensWhitelistTable = MulticallInstanceTokensWhitelistTable; +class MI extends MIConfig { + static AdminsTable = MIAdminsTable; + static TokenWhitelistTable = MITokenWhitelistTable; } -export { MulticallInstance, MulticallInstanceEntity }; +export { MI, type MIEntity }; diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index a4c10e2f..5ec31ca1 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -3,37 +3,34 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { type MulticallInstanceEntity } from "../config"; +import { type MI } from "../config"; -import { MulticallInstanceSettingsModel } from "./mi-settings"; +import { MIInfoModel } from "./mi-settings"; -export type MulticallInstanceAdminsAddressList = { +export type MIAdminAddresses = { data: Multicall["admins"] | null; error: Error | null; loading: boolean; }; -export class MulticallInstanceAdminsModel { +export class MIAdminsModel { static addressListFetchFx = async ( - daoAddress: MulticallInstanceEntity.Inputs["daoAddress"], - callback: (result: MulticallInstanceAdminsAddressList) => void + daoAddress: MI.Inputs["daoAddress"], + callback: (result: MIAdminAddresses) => void ) => - await MulticallInstanceSettingsModel.fetchFx( + await MIInfoModel.dataFetchFx( `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`, (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) ); - static useAddressList = (daoAddress: MulticallInstanceEntity.Inputs["daoAddress"]) => { - const [state, stateUpdate] = useState({ + static useAddressList = (daoAddress: MI.Inputs["daoAddress"]) => { + const [state, stateUpdate] = useState({ data: null, error: null, loading: true, }); - useEffect( - () => void MulticallInstanceAdminsModel.addressListFetchFx(daoAddress, stateUpdate), - [daoAddress, stateUpdate] - ); + useEffect(() => void MIAdminsModel.addressListFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); return state; }; diff --git a/src/entities/multicall-instance/model/mi-settings.ts b/src/entities/multicall-instance/model/mi-settings.ts index 4c6788e9..e943f7a8 100644 --- a/src/entities/multicall-instance/model/mi-settings.ts +++ b/src/entities/multicall-instance/model/mi-settings.ts @@ -2,7 +2,7 @@ import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { AccountId } from "../../../shared/lib/types"; -export class MulticallInstanceSettingsModel { +export class MIInfoModel { /** * Calls the given callback with a result of multicall contract instantiation, * represented as stateful response. @@ -10,7 +10,7 @@ export class MulticallInstanceSettingsModel { * @param daoAddress DAO contract address * @param callback Stateful data fetch callback */ - static fetchFx = async ( + static dataFetchFx = async ( daoAddress: AccountId, callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void ) => diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index 4f693b84..d4dfb128 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -3,39 +3,36 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { type MulticallInstanceEntity } from "../config"; +import { type MI } from "../config"; -import { MulticallInstanceSettingsModel } from "./mi-settings"; +import { MIInfoModel } from "./mi-settings"; -export type MulticallInstanceTokensWhitelist = { +export type MITokenWhitelist = { data: Multicall["tokensWhitelist"] | null; error: Error | null; loading: boolean; }; -export class MulticallInstanceTokensModel { +export class MITokensModel { static whitelistFetchFx = async ( - daoAddress: MulticallInstanceEntity.Inputs["daoAddress"], - callback: (result: MulticallInstanceTokensWhitelist) => void + daoAddress: MI.Inputs["daoAddress"], + callback: (result: MITokenWhitelist) => void ) => - await MulticallInstanceSettingsModel.fetchFx( + await MIInfoModel.dataFetchFx( `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`, (multicallInstanceData) => callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) ); - static useWhitelist = (daoAddress: MulticallInstanceEntity.Inputs["daoAddress"]) => { - const [state, stateUpdate] = useState({ + static useWhitelist = (daoAddress: MI.Inputs["daoAddress"]) => { + const [state, stateUpdate] = useState({ data: null, error: null, loading: true, }); - useEffect( - () => void MulticallInstanceTokensModel.whitelistFetchFx(daoAddress, stateUpdate), - [daoAddress, stateUpdate] - ); + useEffect(() => void MITokensModel.whitelistFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); return state; }; diff --git a/src/entities/multicall-instance/ui/mi-admin.tsx b/src/entities/multicall-instance/ui/mi-admin.tsx index 03db128c..8719afab 100644 --- a/src/entities/multicall-instance/ui/mi-admin.tsx +++ b/src/entities/multicall-instance/ui/mi-admin.tsx @@ -1,14 +1,14 @@ import { NearLink, type NearLinkProps } from "../../../shared/ui/design"; -interface MulticallInstanceAdminProps extends NearLinkProps {} +interface MIAdminProps extends NearLinkProps {} -const MulticallInstanceAdmin = ({ address }: MulticallInstanceAdminProps) => ( +const MIAdmin = ({ address }: MIAdminProps) => ( ); -export const multicallInstanceAdminToTableRow = (item: MulticallInstanceAdminProps["address"]) => ({ - content: [], +export const miAdminAsTableRow = (item: MIAdminProps["address"]) => ({ + content: [], id: item, }); diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 57ae4dc9..7a7d15eb 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,15 +1,15 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { MulticallInstanceAdminsModel } from "../model/mi-admins"; -import { type MulticallInstanceEntity } from "../config"; +import { MIAdminsModel } from "../model/mi-admins"; +import { type MI } from "../config"; -import { multicallInstanceAdminToTableRow } from "./mi-admin"; +import { miAdminAsTableRow } from "./mi-admin"; -interface MulticallInstanceAdminsTableProps extends MulticallInstanceEntity.Inputs { +interface MIAdminsTableProps extends MI.Inputs { className?: string; } -export const MulticallInstanceAdminsTable = ({ className, daoAddress }: MulticallInstanceAdminsTableProps) => { - const { data, error, loading } = MulticallInstanceAdminsModel.useAddressList(daoAddress); +export const MIAdminsTable = ({ className, daoAddress }: MIAdminsTableProps) => { + const { data, error, loading } = MIAdminsModel.useAddressList(daoAddress); return ( diff --git a/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx similarity index 58% rename from src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx rename to src/entities/multicall-instance/ui/mi-token-whitelist.tsx index 12804800..fdbda029 100644 --- a/src/entities/multicall-instance/ui/mi-tokens-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,22 +1,17 @@ import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; -import { MulticallInstanceTokensModel } from "../model/mi-tokens"; -import { type MulticallInstanceEntity } from "../config"; +import { MITokensModel } from "../model/mi-tokens"; +import { type MI } from "../config"; -import { - type MulticallInstanceWhitelistedTokenProps, - multicallInstanceWhitelistedTokenToTableRow, -} from "./mi-whitelisted-token"; +import { type MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; -interface MulticallInstanceTokensWhitelistTableProps - extends MulticallInstanceEntity.Inputs, - Pick { +interface MITokenWhitelistTableProps extends MI.Inputs, Pick { ItemProps?: TableProps["RowProps"]; className?: string; - itemsAdditional?: MulticallInstanceWhitelistedTokenProps["address"][]; + itemsAdditional?: MIWhitelistedTokenProps["address"][]; onItemsSelected?: TableProps["onRowsSelected"]; } -export const MulticallInstanceTokensWhitelistTable = ({ +export const MITokenWhitelistTable = ({ ItemProps, className, daoAddress, @@ -24,8 +19,8 @@ export const MulticallInstanceTokensWhitelistTable = ({ headingCorners, itemsAdditional, onItemsSelected, -}: MulticallInstanceTokensWhitelistTableProps) => { - const { data, error, loading } = MulticallInstanceTokensModel.useWhitelist(daoAddress); +}: MITokenWhitelistTableProps) => { + const { data, error, loading } = MITokensModel.useWhitelist(daoAddress); return ( diff --git a/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx b/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx index 69bf9cf9..bb1ec3a3 100644 --- a/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx +++ b/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx @@ -1,19 +1,17 @@ import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; import { NearLink } from "../../../shared/ui/design"; -export interface MulticallInstanceWhitelistedTokenProps { +export interface MIWhitelistedTokenProps { address: FungibleToken["address"]; } -const MulticallInstanceWhitelistedToken = ({ address }: MulticallInstanceWhitelistedTokenProps) => ( +const MIWhitelistedToken = ({ address }: MIWhitelistedTokenProps) => ( ); -export const multicallInstanceWhitelistedTokenToTableRow = ( - item: MulticallInstanceWhitelistedTokenProps["address"] -) => ({ - content: [], +export const miWhitelistedTokenAsTableRow = (item: MIWhitelistedTokenProps["address"]) => ({ + content: [], id: item, }); diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts deleted file mode 100644 index b6aeb9d5..00000000 --- a/src/entities/near-token/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NearTokenConfig, type NearTokenEntity } from "./config"; -import { nearTokenBalancesRender } from "./ui/near-balances"; - -class NearToken extends NearTokenConfig { - static balancesRender = nearTokenBalancesRender; -} - -export { NearToken, type NearTokenEntity }; diff --git a/src/entities/near-token/config.ts b/src/entities/near/config.ts similarity index 75% rename from src/entities/near-token/config.ts rename to src/entities/near/config.ts index cdb28ad5..15d415a7 100644 --- a/src/entities/near-token/config.ts +++ b/src/entities/near/config.ts @@ -1,7 +1,7 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -namespace NearTokenEntity { +namespace NEAREntity { export interface Inputs { contracts: { dao: SputnikDAO; @@ -10,8 +10,8 @@ namespace NearTokenEntity { } } -class NearTokenConfig { +class NEARConfig { static FRACTIONAL_PART_LENGTH = 5; } -export { NearTokenConfig, type NearTokenEntity }; +export { NEARConfig, type NEAREntity }; diff --git a/src/entities/near/index.ts b/src/entities/near/index.ts new file mode 100644 index 00000000..8689fa82 --- /dev/null +++ b/src/entities/near/index.ts @@ -0,0 +1,8 @@ +import { NEARConfig, type NEAREntity } from "./config"; +import { nearTokenBalancesRender } from "./ui/near-balances"; + +class NEAR extends NEARConfig { + static balancesRender = nearTokenBalancesRender; +} + +export { NEAR, type NEAREntity }; diff --git a/src/entities/near-token/model/near-balances.ts b/src/entities/near/model/near-balances.ts similarity index 59% rename from src/entities/near-token/model/near-balances.ts rename to src/entities/near/model/near-balances.ts index e77dc57b..05225ee4 100644 --- a/src/entities/near-token/model/near-balances.ts +++ b/src/entities/near/model/near-balances.ts @@ -3,16 +3,16 @@ import { useEffect, useState } from "react"; import { Big, formatTokenAmount } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; -import { NearTokenConfig, type NearTokenEntity } from "../config"; +import { NEARConfig, type NEAREntity } from "../config"; -type NearTokenDataFxResponse = { +type NEARDataFxResponse = { data: { dao: string; multicall: string; total: string } | null; loading: boolean; }; const nearTokenDataFx = async ( - { dao, multicall }: NearTokenEntity.Inputs["contracts"], - callback: (result: NearTokenDataFxResponse) => void + { dao, multicall }: NEAREntity.Inputs["contracts"], + callback: (result: NEARDataFxResponse) => void ) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ viewAccount(dao.address), @@ -24,13 +24,13 @@ const nearTokenDataFx = async ( return callback({ data: { - dao: formatTokenAmount(daoRawBalance, 24, NearTokenConfig.FRACTIONAL_PART_LENGTH), - multicall: formatTokenAmount(multicallRawBalance, 24, NearTokenConfig.FRACTIONAL_PART_LENGTH), + dao: formatTokenAmount(daoRawBalance, 24, NEARConfig.FRACTIONAL_PART_LENGTH), + multicall: formatTokenAmount(multicallRawBalance, 24, NEARConfig.FRACTIONAL_PART_LENGTH), total: formatTokenAmount( Big(daoRawBalance).add(multicallRawBalance).toFixed(), 24, - NearTokenConfig.FRACTIONAL_PART_LENGTH + NEARConfig.FRACTIONAL_PART_LENGTH ), }, @@ -38,14 +38,14 @@ const nearTokenDataFx = async ( }); }; -const useNearTokenData = (contracts: NearTokenEntity.Inputs["contracts"]) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); +const useNEARData = (contracts: NEAREntity.Inputs["contracts"]) => { + const [state, stateUpdate] = useState({ data: null, loading: true }); useEffect(() => void nearTokenDataFx(contracts, stateUpdate), [contracts, stateUpdate]); return state; }; -export class NearTokenBalancesModel { - static useTokenFrom = useNearTokenData; +export class NEARBalancesModel { + static useTokenFrom = useNEARData; } diff --git a/src/entities/near-token/ui/near-balances.tsx b/src/entities/near/ui/near-balances.tsx similarity index 55% rename from src/entities/near-token/ui/near-balances.tsx rename to src/entities/near/ui/near-balances.tsx index 0f284b35..28ab2e30 100644 --- a/src/entities/near-token/ui/near-balances.tsx +++ b/src/entities/near/ui/near-balances.tsx @@ -1,12 +1,12 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; -import { NearTokenBalancesModel } from "../model/near-balances"; -import { type NearTokenEntity } from "../config"; +import { NEARBalancesModel } from "../model/near-balances"; +import { type NEAREntity } from "../config"; -interface NearTokenBalancesRenderProps extends NearTokenEntity.Inputs {} +interface NEARBalancesRenderProps extends NEAREntity.Inputs {} -export const nearTokenBalancesRender = ({ contracts }: NearTokenBalancesRenderProps) => { - const { data } = NearTokenBalancesModel.useTokenFrom(contracts); +export const nearTokenBalancesRender = ({ contracts }: NEARBalancesRenderProps) => { + const { data } = NEARBalancesModel.useTokenFrom(contracts); return !data ? null diff --git a/src/features/index.ts b/src/features/index.ts index 8045862f..8712807d 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,3 +1,3 @@ export { DappLogin } from "./dapp-login"; export { JobSettingsEdit, type JobSettingsEditFeature } from "./job-settings-edit"; -export { TokensWhitelistEdit, type TokensWhitelistEditFeature } from "./tokens-whitelist-edit"; +export { TokenWhitelistEdit, type TokenWhitelistEditFeature } from "./tokens-whitelist-edit"; diff --git a/src/features/job-settings-edit/config.ts b/src/features/job-settings-edit/config.ts index edfd1fcf..d397ad49 100644 --- a/src/features/job-settings-edit/config.ts +++ b/src/features/job-settings-edit/config.ts @@ -1,17 +1,15 @@ import { HTMLProps } from "react"; -import { MulticallInstance, MulticallInstanceEntity } from "../../entities"; -import { MulticallConfigDiff, Multicall } from "../../shared/lib/contracts/multicall"; +import { MI, MIEntity } from "../../entities"; +import { MulticallSettingsDiff, Multicall } from "../../shared/lib/contracts/multicall"; import { DesignKitConfigType } from "../../shared/ui/design"; namespace JobSettingsEditFeature { - export type ChangesDiffKey = MulticallInstanceEntity.ParamKey; + export type DiffKey = MIEntity.ParamKey; - export type FormState = Pick; + export type FormState = Pick; - export interface Inputs - extends Omit, "onChange">, - Pick { + export interface Inputs extends Omit, "onChange">, Pick { multicallInstance: Multicall; onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; @@ -19,15 +17,15 @@ namespace JobSettingsEditFeature { } class JobSettingsEditConfig { - public static readonly ChangesDiffKey = MulticallInstance.ParamKey; + public static readonly DiffKey = MI.ParamKey; - public static readonly ChangesDiffMetadata = { - [JobSettingsEditConfig.ChangesDiffKey.croncatManager]: { + public static readonly DiffMetadata = { + [JobSettingsEditConfig.DiffKey.croncatManager]: { color: "blue" as DesignKitConfigType.Color, description: "Croncat manager", }, - [JobSettingsEditConfig.ChangesDiffKey.jobBond]: { + [JobSettingsEditConfig.DiffKey.jobBond]: { color: "blue" as DesignKitConfigType.Color, description: "Job bond", }, diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/job-settings-edit/ui/job-settings-form.tsx index 2388fa0c..afbd57e3 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/job-settings-edit/ui/job-settings-form.tsx @@ -19,8 +19,8 @@ export const JobSettingsForm = ({ const [editModeEnabled, editModeSwitch] = useState(false); const formInitialState: JobSettingsEditFeature.FormState = { - [JobSettingsEditConfig.ChangesDiffKey.croncatManager]: "", - [JobSettingsEditConfig.ChangesDiffKey.jobBond]: "", + [JobSettingsEditConfig.DiffKey.croncatManager]: "", + [JobSettingsEditConfig.DiffKey.jobBond]: "", }; const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ @@ -102,10 +102,8 @@ export const JobSettingsForm = ({ centeredTitle: true, idToHighlightColor: (id) => - ({ croncatManager, jobBond }[id] === - formInitialState[id as JobSettingsEditFeature.ChangesDiffKey] || - { croncatManager, jobBond }[id] === - multicallInstance[id as JobSettingsEditFeature.ChangesDiffKey] + ({ croncatManager, jobBond }[id] === formInitialState[id as JobSettingsEditFeature.DiffKey] || + { croncatManager, jobBond }[id] === multicallInstance[id as JobSettingsEditFeature.DiffKey] ? null : "blue"), @@ -117,12 +115,11 @@ export const JobSettingsForm = ({ header={["Option", "Value"]} rows={[ { - id: JobSettingsEditConfig.ChangesDiffKey.croncatManager, + id: JobSettingsEditConfig.DiffKey.croncatManager, content: [ - JobSettingsEditConfig.ChangesDiffMetadata[ - JobSettingsEditConfig.ChangesDiffKey.croncatManager - ].description, + JobSettingsEditConfig.DiffMetadata[JobSettingsEditConfig.DiffKey.croncatManager] + .description, editModeEnabled ? ( , "onChange">, MulticallInstanceEntity.Inputs { - onEdit: (payload: Pick) => void; + export interface Inputs extends Omit, "onChange">, MIEntity.Inputs { + onEdit: (payload: Pick) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } export interface FormStates extends Record< - keyof Pick, - Set][number]> + keyof Pick, + Set][number]> > {} } -class TokensWhitelistEditConfig { - public static readonly ChangesDiffKey = MulticallTokensWhitelistChangesDiffKey; +class TokenWhitelistEditConfig { + public static readonly DiffKey = MulticallTokenWhitelistDiffKey; - public static readonly ChangesDiffMetadata = { - [TokensWhitelistEditConfig.ChangesDiffKey.addTokens]: { + public static readonly DiffMetadata = { + [TokenWhitelistEditConfig.DiffKey.addTokens]: { color: "green" as DesignKitConfigType.Color, description: "Tokens to add to whitelist", }, - [TokensWhitelistEditConfig.ChangesDiffKey.removeTokens]: { + [TokenWhitelistEditConfig.DiffKey.removeTokens]: { color: "red" as DesignKitConfigType.Color, description: "Tokens to remove from whitelist", }, }; } -export { TokensWhitelistEditConfig, type TokensWhitelistEditFeature }; +export { TokenWhitelistEditConfig, type TokenWhitelistEditFeature }; diff --git a/src/features/tokens-whitelist-edit/index.ts b/src/features/tokens-whitelist-edit/index.ts index 8970904e..aec98f52 100644 --- a/src/features/tokens-whitelist-edit/index.ts +++ b/src/features/tokens-whitelist-edit/index.ts @@ -1,8 +1,8 @@ -import { TokensWhitelistEditConfig, type TokensWhitelistEditFeature } from "./config"; -import { TokensWhitelistForm } from "./ui/tokens-whitelist-form"; +import { TokenWhitelistEditConfig, type TokenWhitelistEditFeature } from "./config"; +import { TokenWhitelistForm } from "./ui/tokens-whitelist-form"; -class TokensWhitelistEdit extends TokensWhitelistEditConfig { - static Form = TokensWhitelistForm; +class TokenWhitelistEdit extends TokenWhitelistEditConfig { + static Form = TokenWhitelistForm; } -export { TokensWhitelistEdit, type TokensWhitelistEditFeature }; +export { TokenWhitelistEdit, type TokenWhitelistEditFeature }; diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx index bfc29544..fc67e875 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx @@ -4,22 +4,22 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { TextInput, Tooltip } from "../../../shared/ui/design"; import { ArgsString } from "../../../shared/lib/args-old"; -import { MulticallInstance } from "../../../entities"; -import { TokensWhitelistEditConfig, type TokensWhitelistEditFeature } from "../config"; +import { MI } from "../../../entities"; +import { TokenWhitelistEditConfig, type TokenWhitelistEditFeature } from "../config"; -interface TokensWhitelistFormProps extends TokensWhitelistEditFeature.Inputs {} +interface TokenWhitelistFormProps extends TokenWhitelistEditFeature.Inputs {} -export const TokensWhitelistForm = ({ +export const TokenWhitelistForm = ({ className, daoAddress, disabled, onEdit, resetTrigger, -}: TokensWhitelistFormProps) => { +}: TokenWhitelistFormProps) => { const [editModeEnabled, editModeSwitch] = useState(false); - const [addTokens, markForAddition] = useState(new Set()), - [removeTokens, markForRemoval] = useState(new Set()); + const [addTokens, markForAddition] = useState(new Set()), + [removeTokens, markForRemoval] = useState(new Set()); const tokenToAddAddress = useMemo(() => new ArgsString(""), []); @@ -68,11 +68,11 @@ export const TokensWhitelistForm = ({ ); return ( - - (addTokens.has(id) && TokensWhitelistEditConfig.ChangesDiffMetadata.addTokens.color) || - (removeTokens.has(id) && TokensWhitelistEditConfig.ChangesDiffMetadata.removeTokens.color) || + (addTokens.has(id) && TokenWhitelistEditConfig.DiffMetadata.addTokens.color) || + (removeTokens.has(id) && TokenWhitelistEditConfig.DiffMetadata.removeTokens.color) || null, slots: { diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx index 9e1e7712..ce4adbe9 100644 --- a/src/pages/dao/config/config.tsx +++ b/src/pages/dao/config/config.tsx @@ -1,11 +1,11 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { MulticallConfigEditor, MulticallConfigEditorWidget } from "../../../widgets"; +import { SettingsEditor, SettingsEditorWidget } from "../../../widgets"; import "./config.scss"; -interface DaoConfigTabUIProps extends HTMLProps, MulticallConfigEditorWidget.Inputs {} +interface DaoConfigTabUIProps extends HTMLProps, SettingsEditorWidget.Inputs {} const _DaoConfigTab = "DaoConfigTab"; @@ -14,7 +14,7 @@ const DaoConfigTabUI = ({ className, contracts, ...props }: DaoConfigTabUIProps) className={clsx(_DaoConfigTab, className)} {...props} > - + ); diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 5ec4cec5..b62b1f75 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -3,7 +3,7 @@ import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component, ContextType } from "react"; -import { MulticallInstance, Wallet } from "../../entities"; +import { MI, Wallet } from "../../entities"; import { Form, Formik } from "formik"; import { args } from "../../shared/lib/args/args"; import { fields } from "../../shared/lib/args/args-types/args-object"; @@ -181,7 +181,7 @@ export class DaoPage extends Component { const multicallAddress = this.toMulticallAddress(formData.addr); - const depo = Big(this.fee).plus(MulticallInstance.MIN_BALANCE); + const depo = Big(this.fee).plus(MI.MIN_BALANCE); const daoSearchInput: HTMLInputElement = document.querySelector(".DaoSearch input")!; /** diff --git a/src/pages/dao/funds/funds.scss b/src/pages/dao/funds/funds.scss index d84793ef..645bcf50 100644 --- a/src/pages/dao/funds/funds.scss +++ b/src/pages/dao/funds/funds.scss @@ -4,6 +4,6 @@ grid-template-rows: 1fr 1fr; grid-template-areas: - "TokensBalances TokensBalances" - "TokensBalances TokensBalances"; + "TokenBalances TokenBalances" + "TokenBalances TokenBalances"; } diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index fe989286..95d0aab6 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -1,11 +1,11 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { TokensBalances, type TokensBalancesWidget } from "../../../widgets"; +import { TokenBalances, type TokenBalancesWidget } from "../../../widgets"; import "./funds.scss"; -interface DaoFundsTabUIProps extends HTMLProps, TokensBalancesWidget.Inputs {} +interface DaoFundsTabUIProps extends HTMLProps, TokenBalancesWidget.Inputs {} const _DaoFundsTab = "DaoFundsTab"; @@ -14,7 +14,7 @@ const DaoFundsTabUI = ({ className, contracts, ...props }: DaoFundsTabUIProps) = className={clsx(_DaoFundsTab, className)} {...props} > - + ); diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 90e9e75e..23966f46 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -58,21 +58,21 @@ type MulticallArgs = { calls: BatchCall[][]; }; -enum MulticallConfigParamKey { +enum MulticallSettingsParamKey { croncatManager = "croncatManager", jobBond = "jobBond", } -enum MulticallTokensWhitelistChangesDiffKey { +enum MulticallTokenWhitelistDiffKey { addTokens = "addTokens", removeTokens = "removeTokens", } -type MulticallConfigDiff = { - [MulticallTokensWhitelistChangesDiffKey.addTokens]: AccountId[]; - [MulticallConfigParamKey.croncatManager]: AccountId; - [MulticallConfigParamKey.jobBond]: U128String; - [MulticallTokensWhitelistChangesDiffKey.removeTokens]: AccountId[]; +type MulticallSettingsDiff = { + [MulticallTokenWhitelistDiffKey.addTokens]: AccountId[]; + [MulticallSettingsParamKey.croncatManager]: AccountId; + [MulticallSettingsParamKey.jobBond]: U128String; + [MulticallTokenWhitelistDiffKey.removeTokens]: AccountId[]; }; class Multicall { @@ -83,12 +83,12 @@ class Multicall { address: AccountId; admins: AccountId[] = []; - [MulticallConfigParamKey.croncatManager]: AccountId = ""; + [MulticallSettingsParamKey.croncatManager]: AccountId = ""; // only whitelisted tokens can be attached to multicalls or job activations. tokensWhitelist: AccountId[] = []; // job bond amount must be attached as deposit when adding new jobs. // needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). - [MulticallConfigParamKey.jobBond]: U128String = ""; + [MulticallSettingsParamKey.jobBond]: U128String = ""; // Multicall instance is ready when info (admins...) are fetched & assigned correctly. ready: boolean = false; @@ -166,7 +166,7 @@ class Multicall { addTokens = [], jobBond = "", croncatManager = "", - }: MulticallConfigDiff): daoFunctionCallAction[] { + }: MulticallSettingsDiff): daoFunctionCallAction[] { const actions: daoFunctionCallAction[] = []; // action: change croncat manager address @@ -292,5 +292,5 @@ class Multicall { } } -export { Multicall, MulticallConfigParamKey, MulticallTokensWhitelistChangesDiffKey }; -export type { JobData, MulticallArgs, MulticallConfigDiff }; +export { Multicall, MulticallSettingsParamKey, MulticallTokenWhitelistDiffKey }; +export type { JobData, MulticallArgs, MulticallSettingsDiff }; diff --git a/src/shared/lib/converter.ts b/src/shared/lib/converter.ts index 51ccfca1..6d4de1fd 100644 --- a/src/shared/lib/converter.ts +++ b/src/shared/lib/converter.ts @@ -30,9 +30,14 @@ const formatTokenAmount = (amount: BigSource, decimals: number = 0, precision: n const toTGas = (amount: string): string => formatTokenAmount(amount, 12, 12); const toGas = (amount: string): string => parseTokenAmount(amount, 12); -// yocto -> NEAR +/** + * yocto -> NEAR + **/ const toNEAR = (amount: string | number): string => formatTokenAmount(amount.toString(), 24, 24); -// NEAR -> yocto + +/** + * NEAR -> yocto + **/ const toYocto = (amount: string | number): string => parseTokenAmount(amount.toString(), 24); const convert = (amount: string | number, unit: unit, decimals?: number): number | string => { diff --git a/src/widgets/index.ts b/src/widgets/index.ts index f9b8aa44..06f62f04 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -4,6 +4,6 @@ export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export"; -export { MulticallConfigEditor, type MulticallConfigEditorWidget } from "./multicall-config-editor"; +export { SettingsEditor, type SettingsEditorWidget } from "./settings-editor"; export { Sidebar } from "./sidebar/sidebar.jsx"; -export { TokensBalances, type TokensBalancesWidget } from "./tokens-balances"; +export { TokenBalances, type TokenBalancesWidget } from "./tokens-balances"; diff --git a/src/widgets/multicall-config-editor/config.ts b/src/widgets/multicall-config-editor/config.ts deleted file mode 100644 index 318cb838..00000000 --- a/src/widgets/multicall-config-editor/config.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { HTMLProps } from "react"; -import { JobSettingsEdit, TokensWhitelistEdit } from "../../features"; -import { MulticallConfigDiff, Multicall } from "../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; - -namespace MulticallConfigEditorWidget { - export interface Inputs extends HTMLProps { - contracts: { dao: SputnikDAO; multicall: Multicall }; - } - - export type ChangesDiff = MulticallConfigDiff; - - export type ProposalDescription = Parameters[0]; -} - -class MulticallConfigEditorConfig { - public static readonly ChangesDiffKey = { - ...JobSettingsEdit.ChangesDiffKey, - ...TokensWhitelistEdit.ChangesDiffKey, - }; - - public static readonly ChangesDiffMetadata = { - ...JobSettingsEdit.ChangesDiffMetadata, - ...TokensWhitelistEdit.ChangesDiffMetadata, - }; -} - -export { MulticallConfigEditorConfig, type MulticallConfigEditorWidget }; diff --git a/src/widgets/multicall-config-editor/index.ts b/src/widgets/multicall-config-editor/index.ts deleted file mode 100644 index a6579d03..00000000 --- a/src/widgets/multicall-config-editor/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { MulticallConfigEditorConfig, type MulticallConfigEditorWidget } from "./config"; -import { MulticallConfigEditorUI } from "./ui/multicall-config-editor"; - -class MulticallConfigEditor extends MulticallConfigEditorConfig { - static UI = MulticallConfigEditorUI; -} - -export { MulticallConfigEditor, type MulticallConfigEditorWidget }; diff --git a/src/widgets/settings-editor/config.ts b/src/widgets/settings-editor/config.ts new file mode 100644 index 00000000..6b9cf04e --- /dev/null +++ b/src/widgets/settings-editor/config.ts @@ -0,0 +1,27 @@ +import { HTMLProps } from "react"; + +import { JobSettingsEdit, TokenWhitelistEdit } from "../../features"; +import { MulticallSettingsDiff, Multicall } from "../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; + +export namespace Widget { + export interface Inputs extends HTMLProps { + contracts: { dao: SputnikDAO; multicall: Multicall }; + } + + export type Diff = MulticallSettingsDiff; + + export type ProposalDescription = Parameters[0]; +} + +export class Config { + public static readonly DiffKey = { + ...JobSettingsEdit.DiffKey, + ...TokenWhitelistEdit.DiffKey, + }; + + public static readonly DiffMetadata = { + ...JobSettingsEdit.DiffMetadata, + ...TokenWhitelistEdit.DiffMetadata, + }; +} diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts new file mode 100644 index 00000000..fd16ce8d --- /dev/null +++ b/src/widgets/settings-editor/index.ts @@ -0,0 +1,8 @@ +import { Config, Widget } from "./config"; +import { SettingsEditor as UI } from "./ui/settings-editor"; + +class SettingsEditor extends Config { + static UI = UI; +} + +export { SettingsEditor, type Widget as SettingsEditorWidget }; diff --git a/src/widgets/multicall-config-editor/ui/mce-changes-proposal.scss b/src/widgets/settings-editor/ui/se-proposal-form.scss similarity index 95% rename from src/widgets/multicall-config-editor/ui/mce-changes-proposal.scss rename to src/widgets/settings-editor/ui/se-proposal-form.scss index 23142eed..da6413ca 100644 --- a/src/widgets/multicall-config-editor/ui/mce-changes-proposal.scss +++ b/src/widgets/settings-editor/ui/se-proposal-form.scss @@ -2,8 +2,8 @@ @use "sass/mixin"; @use "sass/size"; -.MulticallConfigEditor-changesProposal { - grid-area: MCEChangesProposal; +.SettingsEditor-proposalForm { + grid-area: SEProposalForm; gap: size.$gap * 0.4; &-hint { diff --git a/src/widgets/multicall-config-editor/ui/mce-changes-proposal.tsx b/src/widgets/settings-editor/ui/se-proposal-form.tsx similarity index 57% rename from src/widgets/multicall-config-editor/ui/mce-changes-proposal.tsx rename to src/widgets/settings-editor/ui/se-proposal-form.tsx index d55270de..7b60376c 100644 --- a/src/widgets/multicall-config-editor/ui/mce-changes-proposal.tsx +++ b/src/widgets/settings-editor/ui/se-proposal-form.tsx @@ -4,14 +4,14 @@ import { FormEventHandler, HTMLProps } from "react"; import { ArgsString } from "../../../shared/lib/args-old"; import { toNEAR } from "../../../shared/lib/converter"; import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; -import { MulticallConfigEditorConfig, MulticallConfigEditorWidget } from "../config"; +import { Config, Widget } from "../config"; -import "./mce-changes-proposal.scss"; +import "./se-proposal-form.scss"; -export interface MCEChangesProposalProps extends HTMLProps { - changesDiff: MulticallConfigEditorWidget.ChangesDiff; +export interface SEProposalFormProps extends HTMLProps { + changesDiff: Widget.Diff; classNameRoot: Required>["className"]; - description: MulticallConfigEditorWidget.ProposalDescription; + description: Widget.ProposalDescription; formValues: { proposalDescription: ArgsString }; editMode: boolean; onCancel: FormEventHandler; @@ -19,7 +19,7 @@ export interface MCEChangesProposalProps extends HTMLProps { onSubmit: FormEventHandler; } -export const MCEChangesProposal = ({ +export const SEProposalForm = ({ changesDiff, className, classNameRoot, @@ -30,48 +30,47 @@ export const MCEChangesProposal = ({ onCancel, onDescriptionUpdate, onSubmit, -}: MCEChangesProposalProps) => ( +}: SEProposalFormProps) => ( -

    +

    {disabled ? "Current account has no permission to propose changes" : "Start editing to create config changes proposal template"}

    -
    - {Object.values(MulticallConfigEditorConfig.ChangesDiffKey).map( - (ChangesDiffKey) => - changesDiff[ChangesDiffKey].length > 0 && ( +
    + {Object.values(Config.DiffKey).map( + (DiffKey) => + changesDiff[DiffKey].length > 0 && (
    -

    - {MulticallConfigEditorConfig.ChangesDiffMetadata[ChangesDiffKey].description + ":"} +

    + {Config.DiffMetadata[DiffKey].description + ":"}

    -
      - {(Array.isArray(changesDiff[ChangesDiffKey]) - ? Array.from(changesDiff[ChangesDiffKey]) - : [changesDiff[ChangesDiffKey]] +
        + {(Array.isArray(changesDiff[DiffKey]) + ? Array.from(changesDiff[DiffKey]) + : [changesDiff[DiffKey]] ).map((data) => (
      • - {!Number.isNaN(data) && - ChangesDiffKey === MulticallConfigEditorConfig.ChangesDiffKey.jobBond + {!Number.isNaN(data) && DiffKey === Config.DiffKey.jobBond ? `${toNEAR(data as string)} ${NearIcon.NATIVE_TOKEN_CHARACTER}` : (data as string)}
      • @@ -82,7 +81,7 @@ export const MCEChangesProposal = ({ )}
    -
    +
    { +export const SettingsEditor = ({ className, contracts }: Widget.Inputs) => { const wallet = useContext(Wallet.SelectorContext); const proposalCreationPermitted = @@ -21,14 +21,14 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi const [editMode, editModeSwitch] = useState(false); - const changesDiffInitialState: MulticallConfigEditorWidget.ChangesDiff = { - [MulticallConfigEditorConfig.ChangesDiffKey.removeTokens]: [], - [MulticallConfigEditorConfig.ChangesDiffKey.addTokens]: [], - [MulticallConfigEditorConfig.ChangesDiffKey.jobBond]: "", - [MulticallConfigEditorConfig.ChangesDiffKey.croncatManager]: "", + const changesDiffInitialState: Widget.Diff = { + [Config.DiffKey.removeTokens]: [], + [Config.DiffKey.addTokens]: [], + [Config.DiffKey.jobBond]: "", + [Config.DiffKey.croncatManager]: "", }; - const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), + const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), formValues = { proposalDescription: useMemo(() => new ArgsString(""), []) }, [proposalDescription, proposalDescriptionUpdate] = useState(formValues.proposalDescription.value), _childFormsResetRequested = "childFormsResetRequested"; @@ -57,8 +57,7 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( - (update: Partial) => - void changesDiffUpdate((latestState) => ({ ...latestState, ...update })), + (update: Partial) => void changesDiffUpdate((latestState) => ({ ...latestState, ...update })), [changesDiffUpdate] ); @@ -86,14 +85,14 @@ export const MulticallConfigEditorUI = ({ className, contracts }: MulticallConfi ); return ( -
    - + - - { - const nearTokenBalances = NearToken.balancesRender({ contracts }), - fungibleTokensBalances = FungibleToken.allBalancesRender({ contracts }); +export const TokenBalances = ({ className, contracts }: TokenBalancesWidget.Inputs) => { + const nearTokenBalances = NEAR.balancesRender({ contracts }), + fungibleTokenBalances = FT.balances({ contracts }); return ( - {(nearTokenBalances ?? fungibleTokensBalances) && ( + {(nearTokenBalances ?? fungibleTokenBalances) && (
    )} - {(!nearTokenBalances || !fungibleTokensBalances) &&
    } + {(!nearTokenBalances || !fungibleTokenBalances) &&
    } ); }; From 609f563ebef7f7e7eb2c751d1e3cc71084084048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 24 Nov 2022 11:17:59 +0400 Subject: [PATCH 417/537] fix: Use correct import paths --- src/families/mintbase/buy-nft.tsx | 2 +- src/families/paras/buy-nft.tsx | 2 +- src/families/token-farm/create-token.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/families/mintbase/buy-nft.tsx b/src/families/mintbase/buy-nft.tsx index fda5f9ee..f74865b4 100644 --- a/src/families/mintbase/buy-nft.tsx +++ b/src/families/mintbase/buy-nft.tsx @@ -6,7 +6,7 @@ import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; import { MintbaseStore } from "../../shared/lib/contracts/mintbase"; import { toGas } from "../../shared/lib/converter"; -import { InfoField, TextField, UnitField } from "../../shared/ui/form-fields"; +import { InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./mintbase.scss"; diff --git a/src/families/paras/buy-nft.tsx b/src/families/paras/buy-nft.tsx index 6546fb99..7a64a968 100644 --- a/src/families/paras/buy-nft.tsx +++ b/src/families/paras/buy-nft.tsx @@ -7,7 +7,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { Paras, type MarketDataJson } from "../../shared/lib/contracts/paras"; import { NonFungibleToken } from "../../shared/lib/standards/nonFungibleToken"; import { Big, formatTokenAmount, toGas } from "../../shared/lib/converter"; -import { InfoField, TextField, UnitField } from "../../shared/ui/form-fields"; +import { InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; import "./paras.scss"; diff --git a/src/families/token-farm/create-token.tsx b/src/families/token-farm/create-token.tsx index 23a18399..f5c8ebac 100644 --- a/src/families/token-farm/create-token.tsx +++ b/src/families/token-farm/create-token.tsx @@ -8,8 +8,8 @@ import { Call, CallError } from "../../shared/lib/call"; import { TknFarm, TokenArgs } from "../../shared/lib/contracts/token-farm"; import { dataUrlToFile, fileToDataUrl } from "../../shared/lib/converter"; import { STORAGE } from "../../shared/lib/persistent"; -import { InfoField, TextField, UnitField } from "../../shared/ui/form-fields"; -import { FileField } from "../../shared/ui/form-fields/file-field/file-field"; +import { InfoField, TextField, UnitField } from "../../shared/ui/form"; +import { FileField } from "../../shared/ui/form/fields/file-field"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "../base"; import "./token-farm.scss"; From ba7dbf7ca6ae9232b8d25fe7272fb1f06b5ce82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 24 Nov 2022 11:36:47 +0400 Subject: [PATCH 418/537] wip: Apply post code review remarks --- src/entities/fungible-token/config.ts | 2 +- src/entities/fungible-token/index.ts | 6 +++--- src/entities/fungible-token/lib/ft-format.ts | 6 +++--- src/widgets/index.ts | 2 +- src/widgets/settings-editor/config.ts | 2 +- src/widgets/settings-editor/index.ts | 10 +++++----- src/widgets/settings-editor/ui/se-proposal-form.tsx | 6 +++--- src/widgets/settings-editor/ui/settings-editor.tsx | 11 ++++++----- .../{tokens-balances => token-balances}/config.ts | 2 +- src/widgets/token-balances/index.ts | 8 ++++++++ .../ui/token-balances.scss} | 0 .../ui/token-balances.tsx} | 6 +++--- src/widgets/tokens-balances/index.ts | 8 -------- 13 files changed, 35 insertions(+), 34 deletions(-) rename src/widgets/{tokens-balances => token-balances}/config.ts (83%) create mode 100644 src/widgets/token-balances/index.ts rename src/widgets/{tokens-balances/ui/tokens-balances.scss => token-balances/ui/token-balances.scss} (100%) rename src/widgets/{tokens-balances/ui/tokens-balances.tsx => token-balances/ui/token-balances.tsx} (85%) delete mode 100644 src/widgets/tokens-balances/index.ts diff --git a/src/entities/fungible-token/config.ts b/src/entities/fungible-token/config.ts index d12d8cc4..883598de 100644 --- a/src/entities/fungible-token/config.ts +++ b/src/entities/fungible-token/config.ts @@ -10,6 +10,6 @@ export namespace FT { } } -export class FTConfig { +export class Config { static FRACTIONAL_PART_LENGTH = 5; } diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index d3cecad4..5bd2e6e9 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,8 +1,8 @@ -import { FTConfig, FT as FTEntity } from "./config"; +import { Config, FT as FTEntity } from "./config"; import { ftBalances } from "./ui/ft-balances"; -class FT extends FTConfig { +export class FT extends Config { static balances = ftBalances; } -export { FT, type FTEntity }; +export { type FTEntity }; diff --git a/src/entities/fungible-token/lib/ft-format.ts b/src/entities/fungible-token/lib/ft-format.ts index 8a61788d..1e80274b 100644 --- a/src/entities/fungible-token/lib/ft-format.ts +++ b/src/entities/fungible-token/lib/ft-format.ts @@ -1,14 +1,14 @@ import { Big, formatTokenAmount } from "../../../shared/lib/converter"; -import { FTConfig } from "../config"; +import { Config } from "../config"; const amountToDisplayAmount = (amount: string, decimals: number): string => { const formattedAmount = formatTokenAmount(amount, decimals), - minimalDisplayAmount = Big("10").pow(-FTConfig.FRACTIONAL_PART_LENGTH).toFixed(); + minimalDisplayAmount = Big("10").pow(-Config.FRACTIONAL_PART_LENGTH).toFixed(); return Big(formattedAmount).gt("0") && Big(formattedAmount).lt(minimalDisplayAmount) ? "< " + minimalDisplayAmount - : formatTokenAmount(amount, decimals, FTConfig.FRACTIONAL_PART_LENGTH); + : formatTokenAmount(amount, decimals, Config.FRACTIONAL_PART_LENGTH); }; export const FTFormat = { diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 06f62f04..76205905 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -6,4 +6,4 @@ export { Editor } from "./editor/editor.jsx"; export { Export } from "./export"; export { SettingsEditor, type SettingsEditorWidget } from "./settings-editor"; export { Sidebar } from "./sidebar/sidebar.jsx"; -export { TokenBalances, type TokenBalancesWidget } from "./tokens-balances"; +export { TokenBalances, type TokenBalancesWidget } from "./token-balances"; diff --git a/src/widgets/settings-editor/config.ts b/src/widgets/settings-editor/config.ts index 6b9cf04e..727004eb 100644 --- a/src/widgets/settings-editor/config.ts +++ b/src/widgets/settings-editor/config.ts @@ -4,7 +4,7 @@ import { JobSettingsEdit, TokenWhitelistEdit } from "../../features"; import { MulticallSettingsDiff, Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -export namespace Widget { +export namespace SettingsEditor { export interface Inputs extends HTMLProps { contracts: { dao: SputnikDAO; multicall: Multicall }; } diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts index fd16ce8d..a0c72792 100644 --- a/src/widgets/settings-editor/index.ts +++ b/src/widgets/settings-editor/index.ts @@ -1,8 +1,8 @@ -import { Config, Widget } from "./config"; -import { SettingsEditor as UI } from "./ui/settings-editor"; +import { Config, SettingsEditor as SettingsEditorWidget } from "./config"; +import { SettingsEditorUI } from "./ui/settings-editor"; -class SettingsEditor extends Config { - static UI = UI; +export class SettingsEditor extends Config { + static UI = SettingsEditorUI; } -export { SettingsEditor, type Widget as SettingsEditorWidget }; +export { type SettingsEditorWidget }; diff --git a/src/widgets/settings-editor/ui/se-proposal-form.tsx b/src/widgets/settings-editor/ui/se-proposal-form.tsx index 7b60376c..f4e11d86 100644 --- a/src/widgets/settings-editor/ui/se-proposal-form.tsx +++ b/src/widgets/settings-editor/ui/se-proposal-form.tsx @@ -4,14 +4,14 @@ import { FormEventHandler, HTMLProps } from "react"; import { ArgsString } from "../../../shared/lib/args-old"; import { toNEAR } from "../../../shared/lib/converter"; import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; -import { Config, Widget } from "../config"; +import { Config, SettingsEditor } from "../config"; import "./se-proposal-form.scss"; export interface SEProposalFormProps extends HTMLProps { - changesDiff: Widget.Diff; + changesDiff: SettingsEditor.Diff; classNameRoot: Required>["className"]; - description: Widget.ProposalDescription; + description: SettingsEditor.ProposalDescription; formValues: { proposalDescription: ArgsString }; editMode: boolean; onCancel: FormEventHandler; diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index b613e9d8..d1a64a6e 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -6,14 +6,14 @@ import { JobSettingsEdit, TokenWhitelistEdit } from "../../../features"; import { ArgsString } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { Config, Widget } from "../config"; +import { Config, SettingsEditor } from "../config"; import { SEProposalForm } from "./se-proposal-form"; import "./settings-editor.scss"; const _SettingsEditor = "SettingsEditor"; -export const SettingsEditor = ({ className, contracts }: Widget.Inputs) => { +export const SettingsEditorUI = ({ className, contracts }: SettingsEditor.Inputs) => { const wallet = useContext(Wallet.SelectorContext); const proposalCreationPermitted = @@ -21,14 +21,14 @@ export const SettingsEditor = ({ className, contracts }: Widget.Inputs) => { const [editMode, editModeSwitch] = useState(false); - const changesDiffInitialState: Widget.Diff = { + const changesDiffInitialState: SettingsEditor.Diff = { [Config.DiffKey.removeTokens]: [], [Config.DiffKey.addTokens]: [], [Config.DiffKey.jobBond]: "", [Config.DiffKey.croncatManager]: "", }; - const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), + const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), formValues = { proposalDescription: useMemo(() => new ArgsString(""), []) }, [proposalDescription, proposalDescriptionUpdate] = useState(formValues.proposalDescription.value), _childFormsResetRequested = "childFormsResetRequested"; @@ -57,7 +57,8 @@ export const SettingsEditor = ({ className, contracts }: Widget.Inputs) => { }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( - (update: Partial) => void changesDiffUpdate((latestState) => ({ ...latestState, ...update })), + (update: Partial) => + void changesDiffUpdate((latestState) => ({ ...latestState, ...update })), [changesDiffUpdate] ); diff --git a/src/widgets/tokens-balances/config.ts b/src/widgets/token-balances/config.ts similarity index 83% rename from src/widgets/tokens-balances/config.ts rename to src/widgets/token-balances/config.ts index 5f0021eb..e32a7135 100644 --- a/src/widgets/tokens-balances/config.ts +++ b/src/widgets/token-balances/config.ts @@ -1,6 +1,6 @@ import { NEAREntity, FTEntity } from "../../entities"; -export namespace Widget { +export namespace TokenBalances { export interface Inputs extends NEAREntity.Inputs, FTEntity.Inputs { className?: string; } diff --git a/src/widgets/token-balances/index.ts b/src/widgets/token-balances/index.ts new file mode 100644 index 00000000..f8b86236 --- /dev/null +++ b/src/widgets/token-balances/index.ts @@ -0,0 +1,8 @@ +import { TokenBalancesUI } from "./ui/token-balances"; +import { TokenBalances as TokenBalancesWidget } from "./config"; + +class TokenBalances { + static UI = TokenBalancesUI; +} + +export { TokenBalances, type TokenBalancesWidget }; diff --git a/src/widgets/tokens-balances/ui/tokens-balances.scss b/src/widgets/token-balances/ui/token-balances.scss similarity index 100% rename from src/widgets/tokens-balances/ui/tokens-balances.scss rename to src/widgets/token-balances/ui/token-balances.scss diff --git a/src/widgets/tokens-balances/ui/tokens-balances.tsx b/src/widgets/token-balances/ui/token-balances.tsx similarity index 85% rename from src/widgets/tokens-balances/ui/tokens-balances.tsx rename to src/widgets/token-balances/ui/token-balances.tsx index 612fe12d..104f448e 100644 --- a/src/widgets/tokens-balances/ui/tokens-balances.tsx +++ b/src/widgets/token-balances/ui/token-balances.tsx @@ -2,13 +2,13 @@ import clsx from "clsx"; import { Tile, Scrollable, Table } from "../../../shared/ui/design"; import { FT, NEAR } from "../../../entities"; -import { type TokenBalancesWidget } from "../config"; +import { type TokenBalances } from "../config"; -import "./tokens-balances.scss"; +import "./token-balances.scss"; const _TokenBalances = "TokenBalances"; -export const TokenBalances = ({ className, contracts }: TokenBalancesWidget.Inputs) => { +export const TokenBalancesUI = ({ className, contracts }: TokenBalances.Inputs) => { const nearTokenBalances = NEAR.balancesRender({ contracts }), fungibleTokenBalances = FT.balances({ contracts }); diff --git a/src/widgets/tokens-balances/index.ts b/src/widgets/tokens-balances/index.ts deleted file mode 100644 index 42c8aa79..00000000 --- a/src/widgets/tokens-balances/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { TokenBalances as UI } from "./ui/tokens-balances"; -import { Widget } from "./config"; - -class TokenBalances { - static UI = UI; -} - -export { TokenBalances, type Widget as TokenBalancesWidget }; From 703db2b14f3561f0cf9fdddeb89906b5fd74c47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 24 Nov 2022 11:46:56 +0400 Subject: [PATCH 419/537] wip: Apply post code review remarks --- src/pages/dao/config/config.tsx | 26 ------------------- src/pages/dao/dao.tsx | 4 +-- .../config.scss => settings/settings.scss} | 2 +- src/pages/dao/settings/settings.tsx | 26 +++++++++++++++++++ 4 files changed, 29 insertions(+), 29 deletions(-) delete mode 100644 src/pages/dao/config/config.tsx rename src/pages/dao/{config/config.scss => settings/settings.scss} (91%) create mode 100644 src/pages/dao/settings/settings.tsx diff --git a/src/pages/dao/config/config.tsx b/src/pages/dao/config/config.tsx deleted file mode 100644 index ce4adbe9..00000000 --- a/src/pages/dao/config/config.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import clsx from "clsx"; -import { HTMLProps } from "react"; - -import { SettingsEditor, SettingsEditorWidget } from "../../../widgets"; - -import "./config.scss"; - -interface DaoConfigTabUIProps extends HTMLProps, SettingsEditorWidget.Inputs {} - -const _DaoConfigTab = "DaoConfigTab"; - -const DaoConfigTabUI = ({ className, contracts, ...props }: DaoConfigTabUIProps) => ( -
    - -
    -); - -export const DaoConfigTab = { - uiConnect: (props: DaoConfigTabUIProps) => ({ - content: , - name: "Config", - }), -}; diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index b62b1f75..c7c3b721 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -16,7 +16,7 @@ import { signAndSendTxs } from "../../shared/lib/wallet"; import { Tabs } from "../../shared/ui/design"; import { TextField } from "../../shared/ui/form"; -import { DaoConfigTab } from "./config/config"; +import { DaoSettingsTab } from "./settings/settings"; import "./dao.scss"; import { DaoFundsTab } from "./funds/funds"; import { DaoJobsTab } from "./jobs/jobs"; @@ -508,7 +508,7 @@ export class DaoPage extends Component { , SettingsEditorWidget.Inputs {} + +const _DaoSettingsTab = "DaoSettingsTab"; + +const DaoSettingsTabUI = ({ className, contracts, ...props }: DaoSettingsTabUIProps) => ( +
    + +
    +); + +export const DaoSettingsTab = { + uiConnect: (props: DaoSettingsTabUIProps) => ({ + content: , + name: "Settings", + }), +}; From 95f1e8c8213bbd47fbbbadde592704a5318b5ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 25 Nov 2022 04:19:57 +0400 Subject: [PATCH 420/537] wip: Apply post code review remarks --- src/features/dapp-login/index.ts | 8 --- .../dapp-login/model/dapp-login-dialogs.ts | 57 ---------------- .../dapp-login/ui/dapp-login-menu.tsx | 25 ------- .../{dapp-login => external-login}/config.ts | 4 +- src/features/external-login/index.ts | 8 +++ .../external-login/model/el-dialogs.ts | 59 ++++++++++++++++ .../ui/el-dialog.scss} | 2 +- .../ui/el-dialogs.tsx} | 23 ++++--- src/features/external-login/ui/el-menu.tsx | 25 +++++++ src/features/index.ts | 6 +- src/features/job-settings-edit/index.ts | 8 --- .../settings-change}/config.ts | 16 ++--- .../scheduling/settings-change/index.ts | 8 +++ .../ui/scheduling-settings-form.tsx} | 67 +++++++++---------- src/features/tokens-whitelist-edit/index.ts | 8 --- .../whitelist-change}/config.ts | 16 ++--- src/features/tokens/whitelist-change/index.ts | 8 +++ .../ui/tokens-whitelist-form.tsx | 44 ++++++------ .../dialogs-layer/ui/dialogs-layer.tsx | 4 +- src/widgets/settings-editor/config.ts | 10 +-- .../settings-editor/ui/settings-editor.tsx | 6 +- src/widgets/sidebar/sidebar.jsx | 22 +++--- 22 files changed, 215 insertions(+), 219 deletions(-) delete mode 100644 src/features/dapp-login/index.ts delete mode 100644 src/features/dapp-login/model/dapp-login-dialogs.ts delete mode 100644 src/features/dapp-login/ui/dapp-login-menu.tsx rename src/features/{dapp-login => external-login}/config.ts (92%) create mode 100644 src/features/external-login/index.ts create mode 100644 src/features/external-login/model/el-dialogs.ts rename src/features/{dapp-login/ui/dapp-login-dialog.scss => external-login/ui/el-dialog.scss} (96%) rename src/features/{dapp-login/ui/dapp-login-dialogs.tsx => external-login/ui/el-dialogs.tsx} (78%) create mode 100644 src/features/external-login/ui/el-menu.tsx delete mode 100644 src/features/job-settings-edit/index.ts rename src/features/{job-settings-edit => scheduling/settings-change}/config.ts (63%) create mode 100644 src/features/scheduling/settings-change/index.ts rename src/features/{job-settings-edit/ui/job-settings-form.tsx => scheduling/settings-change/ui/scheduling-settings-form.tsx} (75%) delete mode 100644 src/features/tokens-whitelist-edit/index.ts rename src/features/{tokens-whitelist-edit => tokens/whitelist-change}/config.ts (71%) create mode 100644 src/features/tokens/whitelist-change/index.ts rename src/features/{tokens-whitelist-edit => tokens/whitelist-change}/ui/tokens-whitelist-form.tsx (75%) diff --git a/src/features/dapp-login/index.ts b/src/features/dapp-login/index.ts deleted file mode 100644 index 81b36280..00000000 --- a/src/features/dapp-login/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { DappLoginConfig } from "./config"; -import { DappLoginDialogs } from "./ui/dapp-login-dialogs"; -import { DappLoginMenu } from "./ui/dapp-login-menu"; - -export class DappLogin extends DappLoginConfig { - static Dialogs = DappLoginDialogs; - static Menu = DappLoginMenu; -} diff --git a/src/features/dapp-login/model/dapp-login-dialogs.ts b/src/features/dapp-login/model/dapp-login-dialogs.ts deleted file mode 100644 index 4fa7a766..00000000 --- a/src/features/dapp-login/model/dapp-login-dialogs.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; - -import { DappLoginConfig as Config } from "../config"; - -/** - * !TODO: Use 3rd party solution for dialogs management - */ - -const _dialogOpenRequested = "dialogopenrequested"; - -const dialogOpenRequested = { - dispatch: (dialogKey: keyof typeof Config.METHODS) => - document.dispatchEvent(new CustomEvent(_dialogOpenRequested, { detail: { dialogKey } })), - - subscribe: (callback: EventListener) => { - document.addEventListener(_dialogOpenRequested, callback); - - return () => document.removeEventListener(_dialogOpenRequested, callback); - }, -}; - -const useDappLoginDialogsVisibilityState = () => { - const [dialogsVisibility, dialogVisibilitySwitch] = useState | {}>( - Object.values(Config.METHODS).reduce((visibilityState, { type }) => ({ ...visibilityState, [type]: false }), {}) - ); - - useEffect( - () => - dialogOpenRequested.subscribe(({ detail }) => - dialogVisibilitySwitch( - Object.keys(dialogsVisibility).reduce( - (visibilityState, someDialogKey) => ({ - ...visibilityState, - [someDialogKey]: someDialogKey === detail.dialogKey ? true : false, - }), - - dialogsVisibility - ) - ) - ), - [] - ); - - return { - dialogsVisibility, - - closeHandlerBinding: useCallback( - (dialogKey: string) => () => dialogVisibilitySwitch({ ...dialogsVisibility, [dialogKey]: false }), - [dialogVisibilitySwitch] - ), - }; -}; - -export class DappLoginDialogsModel { - static dialogOpenRequested = dialogOpenRequested.dispatch; - static useVisibilityState = useDappLoginDialogsVisibilityState; -} diff --git a/src/features/dapp-login/ui/dapp-login-menu.tsx b/src/features/dapp-login/ui/dapp-login-menu.tsx deleted file mode 100644 index 55e616fc..00000000 --- a/src/features/dapp-login/ui/dapp-login-menu.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { PreviewOutlined } from "@mui/icons-material"; -import { ComponentProps } from "react"; - -import { PopupMenu } from "../../../shared/ui/design"; -import { DappLoginConfig as Config } from "../config"; -import { DappLoginDialogsModel } from "../model/dapp-login-dialogs"; - -interface DappLoginMenuProps extends Pick, "triggerClassName"> { - FeatureFlags: { - DappLogin: Record; - }; -} - -export const DappLoginMenu = ({ FeatureFlags, triggerClassName }: DappLoginMenuProps) => ( - } - items={Object.values(Config.METHODS).map(({ title, type }) => ({ - disabled: !FeatureFlags.DappLogin[type], - key: type, - onClick: () => DappLoginDialogsModel.dialogOpenRequested(type), - title, - }))} - {...{ triggerClassName }} - /> -); diff --git a/src/features/dapp-login/config.ts b/src/features/external-login/config.ts similarity index 92% rename from src/features/dapp-login/config.ts rename to src/features/external-login/config.ts index e475a3ac..7f2807be 100644 --- a/src/features/dapp-login/config.ts +++ b/src/features/external-login/config.ts @@ -1,10 +1,10 @@ -export class DappLoginConfig { +export class Config { static KEYS = { all: "ed25519%3A9jeqkc8ybv7aYSA7uLNFUEn8cgKo759yue4771bBWsSr", public: "ed25519%3ADEaoD65LomNHAMzhNZva15LC85ntwBHdcTbCnZRXciZH", }; - static METHODS: Record<"dao" | "multicall", { title: string; type: keyof typeof DappLoginConfig.METHODS }> = { + static METHODS: Record<"dao" | "multicall", { title: string; type: keyof typeof Config.METHODS }> = { dao: { title: "Login in dApps as DAO", type: "dao" }, multicall: { title: "Login in dApps as Multicall", type: "multicall" }, }; diff --git a/src/features/external-login/index.ts b/src/features/external-login/index.ts new file mode 100644 index 00000000..676f9a96 --- /dev/null +++ b/src/features/external-login/index.ts @@ -0,0 +1,8 @@ +import { Config } from "./config"; +import { ELDialogs } from "./ui/el-dialogs"; +import { ELMenu } from "./ui/el-menu"; + +export class ExternalLogin extends Config { + static Dialogs = ELDialogs; + static Menu = ELMenu; +} diff --git a/src/features/external-login/model/el-dialogs.ts b/src/features/external-login/model/el-dialogs.ts new file mode 100644 index 00000000..b303ed12 --- /dev/null +++ b/src/features/external-login/model/el-dialogs.ts @@ -0,0 +1,59 @@ +/** + * !TODO: Use 3rd party solution for dialogs management + */ + +import { useCallback, useEffect, useState } from "react"; + +import { Config } from "../config"; + +const _dialogOpenRequested = "dialogOpenRequested"; + +const dialogOpenRequested = { + dispatch: (dialogKey: keyof typeof Config.METHODS) => + document.dispatchEvent(new CustomEvent(_dialogOpenRequested, { detail: { dialogKey } })), + + subscribe: (callback: EventListener) => { + document.addEventListener(_dialogOpenRequested, callback); + + return () => document.removeEventListener(_dialogOpenRequested, callback); + }, +}; + +export class ELDialogsModel { + static dialogOpenRequested = dialogOpenRequested.dispatch; + + static useVisibilityState = () => { + const [dialogsVisibility, dialogVisibilitySwitch] = useState | {}>( + Object.values(Config.METHODS).reduce( + (visibilityState, { type }) => ({ ...visibilityState, [type]: false }), + {} + ) + ); + + useEffect( + () => + dialogOpenRequested.subscribe(({ detail }) => + dialogVisibilitySwitch( + Object.keys(dialogsVisibility).reduce( + (visibilityState, someDialogKey) => ({ + ...visibilityState, + [someDialogKey]: someDialogKey === detail.dialogKey ? true : false, + }), + + dialogsVisibility + ) + ) + ), + [] + ); + + return { + dialogsVisibility, + + closeHandlerBinding: useCallback( + (dialogKey: string) => () => dialogVisibilitySwitch({ ...dialogsVisibility, [dialogKey]: false }), + [dialogVisibilitySwitch] + ), + }; + }; +} diff --git a/src/features/dapp-login/ui/dapp-login-dialog.scss b/src/features/external-login/ui/el-dialog.scss similarity index 96% rename from src/features/dapp-login/ui/dapp-login-dialog.scss rename to src/features/external-login/ui/el-dialog.scss index 7178993c..d2cf6c96 100644 --- a/src/features/dapp-login/ui/dapp-login-dialog.scss +++ b/src/features/external-login/ui/el-dialog.scss @@ -1,7 +1,7 @@ @use "sass/size"; @use "sass/mixin"; -.DappLoginDialog { +.ExternalLoginDialog { &-stepByStepGuide { padding: 0 size.$gap; list-style-type: decimal; diff --git a/src/features/dapp-login/ui/dapp-login-dialogs.tsx b/src/features/external-login/ui/el-dialogs.tsx similarity index 78% rename from src/features/dapp-login/ui/dapp-login-dialogs.tsx rename to src/features/external-login/ui/el-dialogs.tsx index 1f59952c..8f40c95b 100644 --- a/src/features/dapp-login/ui/dapp-login-dialogs.tsx +++ b/src/features/external-login/ui/el-dialogs.tsx @@ -6,18 +6,19 @@ import { ArgsError, ArgsString } from "../../../shared/lib/args-old"; import { STORAGE } from "../../../shared/lib/persistent"; import { Validation } from "../../../shared/lib/validation"; import { Dialog, TextInput, Tooltip } from "../../../shared/ui/design"; -import { DappLoginConfig as Config } from "../config"; -import { DappLoginDialogsModel } from "../model/dapp-login-dialogs"; +import { Config as Config } from "../config"; +import { ELDialogsModel } from "../model/el-dialogs"; -import "./dapp-login-dialog.scss"; +import "./el-dialog.scss"; -interface DappLoginDialogProps extends Pick, "className" | "onClose" | "open" | "title"> { +interface ExternalLoginDialogProps + extends Pick, "className" | "onClose" | "open" | "title"> { method: "dao" | "multicall"; } -const _DappLoginDialog = "DappLoginDialog"; +const _ExternalLoginDialog = "ExternalLoginDialog"; -const DappLoginDialog = ({ className, method, onClose, open, title }: DappLoginDialogProps) => { +const ExternalLoginDialog = ({ className, method, onClose, open, title }: ExternalLoginDialogProps) => { const dAppURL = useMemo(() => new ArgsString(""), []); const URLInvalid = ArgsError.useInstance("Invalid URL", Validation.isUrl, true); @@ -39,13 +40,13 @@ const DappLoginDialog = ({ className, method, onClose, open, title }: DappLoginD return ( window.open(requestURL, "_blank")} {...{ onClose, open, title }} > -
      +
        {Config.STEP_BY_STEP_GUIDE.map((step) => (
      • @@ -76,11 +77,11 @@ const DappLoginDialog = ({ className, method, onClose, open, title }: DappLoginD ); }; -export const DappLoginDialogs = () => { - const { dialogsVisibility, closeHandlerBinding } = DappLoginDialogsModel.useVisibilityState(); +export const ELDialogs = () => { + const { dialogsVisibility, closeHandlerBinding } = ELDialogsModel.useVisibilityState(); return Object.values(Config.METHODS).map((loginMethod) => ( - , "triggerClassName"> { + FeatureFlags: { + ExternalLogin: Record; + }; +} + +export const ELMenu = ({ FeatureFlags, triggerClassName }: ELMenuProps) => ( + } + items={Object.values(Config.METHODS).map(({ title, type }) => ({ + disabled: !FeatureFlags.ExternalLogin[type], + key: type, + onClick: () => ELDialogsModel.dialogOpenRequested(type), + title, + }))} + {...{ triggerClassName }} + /> +); diff --git a/src/features/index.ts b/src/features/index.ts index 8712807d..c8188cd5 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,3 +1,3 @@ -export { DappLogin } from "./dapp-login"; -export { JobSettingsEdit, type JobSettingsEditFeature } from "./job-settings-edit"; -export { TokenWhitelistEdit, type TokenWhitelistEditFeature } from "./tokens-whitelist-edit"; +export { ExternalLogin } from "./external-login"; +export { SchedulingSettingsChange, type SSChangeFeature } from "./scheduling/settings-change"; +export { TokensWhitelistChange, type TWChangeFeature } from "./tokens/whitelist-change"; diff --git a/src/features/job-settings-edit/index.ts b/src/features/job-settings-edit/index.ts deleted file mode 100644 index d8b39e7b..00000000 --- a/src/features/job-settings-edit/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { JobSettingsEditConfig, type JobSettingsEditFeature } from "./config"; -import { JobSettingsForm } from "./ui/job-settings-form"; - -class JobSettingsEdit extends JobSettingsEditConfig { - static Form = JobSettingsForm; -} - -export { JobSettingsEdit, type JobSettingsEditFeature }; diff --git a/src/features/job-settings-edit/config.ts b/src/features/scheduling/settings-change/config.ts similarity index 63% rename from src/features/job-settings-edit/config.ts rename to src/features/scheduling/settings-change/config.ts index d397ad49..b98aa291 100644 --- a/src/features/job-settings-edit/config.ts +++ b/src/features/scheduling/settings-change/config.ts @@ -1,10 +1,10 @@ import { HTMLProps } from "react"; -import { MI, MIEntity } from "../../entities"; -import { MulticallSettingsDiff, Multicall } from "../../shared/lib/contracts/multicall"; -import { DesignKitConfigType } from "../../shared/ui/design"; +import { MI, MIEntity } from "../../../entities"; +import { MulticallSettingsDiff, Multicall } from "../../../shared/lib/contracts/multicall"; +import { DesignKitConfigType } from "../../../shared/ui/design"; -namespace JobSettingsEditFeature { +export namespace SchedulingSettingsChange { export type DiffKey = MIEntity.ParamKey; export type FormState = Pick; @@ -16,20 +16,18 @@ namespace JobSettingsEditFeature { } } -class JobSettingsEditConfig { +export class Config { public static readonly DiffKey = MI.ParamKey; public static readonly DiffMetadata = { - [JobSettingsEditConfig.DiffKey.croncatManager]: { + [Config.DiffKey.croncatManager]: { color: "blue" as DesignKitConfigType.Color, description: "Croncat manager", }, - [JobSettingsEditConfig.DiffKey.jobBond]: { + [Config.DiffKey.jobBond]: { color: "blue" as DesignKitConfigType.Color, description: "Job bond", }, }; } - -export { JobSettingsEditConfig, type JobSettingsEditFeature }; diff --git a/src/features/scheduling/settings-change/index.ts b/src/features/scheduling/settings-change/index.ts new file mode 100644 index 00000000..222e074f --- /dev/null +++ b/src/features/scheduling/settings-change/index.ts @@ -0,0 +1,8 @@ +import { Config, type SchedulingSettingsChange as SSChangeFeature } from "./config"; +import { SchedulingSettingsForm } from "./ui/scheduling-settings-form"; + +export class SchedulingSettingsChange extends Config { + static Form = SchedulingSettingsForm; +} + +export { type SSChangeFeature }; diff --git a/src/features/job-settings-edit/ui/job-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx similarity index 75% rename from src/features/job-settings-edit/ui/job-settings-form.tsx rename to src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx index afbd57e3..4f5581dd 100644 --- a/src/features/job-settings-edit/ui/job-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx @@ -2,30 +2,28 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-mat import { IconButton, TextField, TextFieldProps } from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { ArgsString } from "../../../shared/lib/args-old"; -import { toNEAR, toYocto } from "../../../shared/lib/converter"; -import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../shared/ui/design"; -import { JobSettingsEditConfig, type JobSettingsEditFeature } from "../config"; +import { ArgsString } from "../../../../shared/lib/args-old"; +import { toNEAR, toYocto } from "../../../../shared/lib/converter"; +import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../../shared/ui/design"; +import { Config, SchedulingSettingsChange } from "../config"; -interface JobSettingsFormProps extends JobSettingsEditFeature.Inputs {} - -export const JobSettingsForm = ({ +export const SchedulingSettingsForm = ({ className, disabled, multicallInstance, onEdit, resetTrigger, -}: JobSettingsFormProps) => { +}: SchedulingSettingsChange.Inputs) => { const [editModeEnabled, editModeSwitch] = useState(false); - const formInitialState: JobSettingsEditFeature.FormState = { - [JobSettingsEditConfig.DiffKey.croncatManager]: "", - [JobSettingsEditConfig.DiffKey.jobBond]: "", + const formInitialState: SchedulingSettingsChange.FormState = { + [Config.DiffKey.croncatManager]: "", + [Config.DiffKey.jobBond]: "", }; const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ - useState(formInitialState.croncatManager), - useState(formInitialState.jobBond), + useState(formInitialState.croncatManager), + useState(formInitialState.jobBond), ]; const formFields = { @@ -69,30 +67,32 @@ export const JobSettingsForm = ({ return ( - {(croncatManager.length > 0 || jobBond.length > 0) && ( + void editModeSwitch(false)}> - )} + - - - + {(croncatManager.length > 0 || jobBond.length > 0) && ( + + + + + + )} ) : ( - - void editModeSwitch(true)} - {...{ disabled }} - > - - - + void editModeSwitch(true)} + {...{ disabled }} + > + + ), }} @@ -102,8 +102,8 @@ export const JobSettingsForm = ({ centeredTitle: true, idToHighlightColor: (id) => - ({ croncatManager, jobBond }[id] === formInitialState[id as JobSettingsEditFeature.DiffKey] || - { croncatManager, jobBond }[id] === multicallInstance[id as JobSettingsEditFeature.DiffKey] + ({ croncatManager, jobBond }[id] === formInitialState[id as SchedulingSettingsChange.DiffKey] || + { croncatManager, jobBond }[id] === multicallInstance[id as SchedulingSettingsChange.DiffKey] ? null : "blue"), @@ -115,11 +115,10 @@ export const JobSettingsForm = ({ header={["Option", "Value"]} rows={[ { - id: JobSettingsEditConfig.DiffKey.croncatManager, + id: Config.DiffKey.croncatManager, content: [ - JobSettingsEditConfig.DiffMetadata[JobSettingsEditConfig.DiffKey.croncatManager] - .description, + Config.DiffMetadata[Config.DiffKey.croncatManager].description, editModeEnabled ? ( , "onChange">, MIEntity.Inputs { @@ -19,20 +19,18 @@ namespace TokenWhitelistEditFeature { > {} } -class TokenWhitelistEditConfig { +export class Config { public static readonly DiffKey = MulticallTokenWhitelistDiffKey; public static readonly DiffMetadata = { - [TokenWhitelistEditConfig.DiffKey.addTokens]: { + [Config.DiffKey.addTokens]: { color: "green" as DesignKitConfigType.Color, description: "Tokens to add to whitelist", }, - [TokenWhitelistEditConfig.DiffKey.removeTokens]: { + [Config.DiffKey.removeTokens]: { color: "red" as DesignKitConfigType.Color, description: "Tokens to remove from whitelist", }, }; } - -export { TokenWhitelistEditConfig, type TokenWhitelistEditFeature }; diff --git a/src/features/tokens/whitelist-change/index.ts b/src/features/tokens/whitelist-change/index.ts new file mode 100644 index 00000000..97048de8 --- /dev/null +++ b/src/features/tokens/whitelist-change/index.ts @@ -0,0 +1,8 @@ +import { Config, type TokensWhitelistChange as TWChangeFeature } from "./config"; +import { TokensWhitelistForm } from "./ui/tokens-whitelist-form"; + +export class TokensWhitelistChange extends Config { + static Form = TokensWhitelistForm; +} + +export { type TWChangeFeature }; diff --git a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx similarity index 75% rename from src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx rename to src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx index fc67e875..9f3dfb10 100644 --- a/src/features/tokens-whitelist-edit/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx @@ -2,24 +2,22 @@ import { CancelOutlined, DeleteOutlined, EditOutlined, SettingsBackupRestoreOutl import { IconButton } from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { TextInput, Tooltip } from "../../../shared/ui/design"; -import { ArgsString } from "../../../shared/lib/args-old"; -import { MI } from "../../../entities"; -import { TokenWhitelistEditConfig, type TokenWhitelistEditFeature } from "../config"; +import { TextInput, Tooltip } from "../../../../shared/ui/design"; +import { ArgsString } from "../../../../shared/lib/args-old"; +import { MI } from "../../../../entities"; +import { Config, TokensWhitelistChange } from "../config"; -interface TokenWhitelistFormProps extends TokenWhitelistEditFeature.Inputs {} - -export const TokenWhitelistForm = ({ +export const TokensWhitelistForm = ({ className, daoAddress, disabled, onEdit, resetTrigger, -}: TokenWhitelistFormProps) => { +}: TokensWhitelistChange.Inputs) => { const [editModeEnabled, editModeSwitch] = useState(false); - const [addTokens, markForAddition] = useState(new Set()), - [removeTokens, markForRemoval] = useState(new Set()); + const [addTokens, markForAddition] = useState(new Set()), + [removeTokens, markForRemoval] = useState(new Set()); const tokenToAddAddress = useMemo(() => new ArgsString(""), []); @@ -71,8 +69,8 @@ export const TokenWhitelistForm = ({ - (addTokens.has(id) && TokenWhitelistEditConfig.DiffMetadata.addTokens.color) || - (removeTokens.has(id) && TokenWhitelistEditConfig.DiffMetadata.removeTokens.color) || + (addTokens.has(id) && Config.DiffMetadata.addTokens.color) || + (removeTokens.has(id) && Config.DiffMetadata.removeTokens.color) || null, slots: { @@ -109,19 +107,19 @@ export const TokenWhitelistForm = ({ } headingCorners={{ end: editModeEnabled ? ( - - - + + + + + ) : ( - - void editModeSwitch(true)} - {...{ disabled }} - > - - - + void editModeSwitch(true)} + {...{ disabled }} + > + + ), }} diff --git a/src/widgets/dialogs-layer/ui/dialogs-layer.tsx b/src/widgets/dialogs-layer/ui/dialogs-layer.tsx index 294cae0f..e8494095 100644 --- a/src/widgets/dialogs-layer/ui/dialogs-layer.tsx +++ b/src/widgets/dialogs-layer/ui/dialogs-layer.tsx @@ -1,7 +1,7 @@ -import { DappLogin } from "../../../features/dapp-login"; +import { ExternalLogin } from "../../../features/external-login"; export const DialogsLayer = () => ( <> - + ); diff --git a/src/widgets/settings-editor/config.ts b/src/widgets/settings-editor/config.ts index 727004eb..41edef75 100644 --- a/src/widgets/settings-editor/config.ts +++ b/src/widgets/settings-editor/config.ts @@ -1,6 +1,6 @@ import { HTMLProps } from "react"; -import { JobSettingsEdit, TokenWhitelistEdit } from "../../features"; +import { SchedulingSettingsChange, TokensWhitelistChange } from "../../features"; import { MulticallSettingsDiff, Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; @@ -16,12 +16,12 @@ export namespace SettingsEditor { export class Config { public static readonly DiffKey = { - ...JobSettingsEdit.DiffKey, - ...TokenWhitelistEdit.DiffKey, + ...SchedulingSettingsChange.DiffKey, + ...TokensWhitelistChange.DiffKey, }; public static readonly DiffMetadata = { - ...JobSettingsEdit.DiffMetadata, - ...TokenWhitelistEdit.DiffMetadata, + ...SchedulingSettingsChange.DiffMetadata, + ...TokensWhitelistChange.DiffMetadata, }; } diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index d1a64a6e..6603bd7c 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { useCallback, useMemo, useState, FormEventHandler, useEffect, useContext } from "react"; import { MI, Wallet } from "../../../entities"; -import { JobSettingsEdit, TokenWhitelistEdit } from "../../../features"; +import { SchedulingSettingsChange, TokensWhitelistChange } from "../../../features"; import { ArgsString } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; @@ -92,7 +92,7 @@ export const SettingsEditorUI = ({ className, contracts }: SettingsEditor.Inputs daoAddress={contracts.dao.address} /> - -
        - From 86df89f8f30de467e82b3d6eb7b183b50c593ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 25 Nov 2022 04:24:50 +0400 Subject: [PATCH 421/537] Merge branch 'main' of https://github.com/near-multicall/ui into feature/shopping-cart --- src/families/meta-pool/nslp-add-liquidity.tsx | 2 +- src/families/meta-pool/nslp-remove-liquidity.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/families/meta-pool/nslp-add-liquidity.tsx b/src/families/meta-pool/nslp-add-liquidity.tsx index 8a53305e..e4bff274 100644 --- a/src/families/meta-pool/nslp-add-liquidity.tsx +++ b/src/families/meta-pool/nslp-add-liquidity.tsx @@ -3,7 +3,7 @@ import { useEffect } from "react"; import { args as arx } from "../../shared/lib/args/args"; import { Call, CallError } from "../../shared/lib/call"; import { GetAccountInfoResult, MetaPool } from "../../shared/lib/contracts/meta-pool"; -import { InfoField, TextField, UnitField } from "../../shared/ui/form-fields"; +import { InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "../base"; import * as MetaPoolLogo from "../../app/static/meta-pool/MetaPool_logo.png"; import "./meta-pool.scss"; diff --git a/src/families/meta-pool/nslp-remove-liquidity.tsx b/src/families/meta-pool/nslp-remove-liquidity.tsx index 428aded4..c950a136 100644 --- a/src/families/meta-pool/nslp-remove-liquidity.tsx +++ b/src/families/meta-pool/nslp-remove-liquidity.tsx @@ -3,7 +3,7 @@ import { useEffect } from "react"; import { args as arx } from "../../shared/lib/args/args"; import { Call, CallError } from "../../shared/lib/call"; import { GetAccountInfoResult, MetaPool } from "../../shared/lib/contracts/meta-pool"; -import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form-fields"; +import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "../base"; import * as MetaPoolLogo from "../../app/static/meta-pool/MetaPool_logo.png"; import "./meta-pool.scss"; From 67c3e2b8a202ad0d91d075b3af6fb9a3fbdb2dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 25 Nov 2022 07:47:48 +0400 Subject: [PATCH 422/537] wip: Apply post code review remarks --- .../ui/mi-token-whitelist.tsx | 6 ++--- .../ui/scheduling-settings-form.tsx | 2 +- .../ui/tokens-whitelist-form.tsx | 2 +- src/shared/ui/design/tile/tile.scss | 4 +-- src/shared/ui/design/tile/tile.tsx | 25 ++++++++----------- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index fdbda029..d9ea603c 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -4,7 +4,7 @@ import { type MI } from "../config"; import { type MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; -interface MITokenWhitelistTableProps extends MI.Inputs, Pick { +interface MITokenWhitelistTableProps extends MI.Inputs, Pick { ItemProps?: TableProps["RowProps"]; className?: string; itemsAdditional?: MIWhitelistedTokenProps["address"][]; @@ -16,7 +16,7 @@ export const MITokenWhitelistTable = ({ className, daoAddress, footer, - headingCorners, + headerSlots, itemsAdditional, onItemsSelected, }: MITokenWhitelistTableProps) => { @@ -27,7 +27,7 @@ export const MITokenWhitelistTable = ({ classes={{ root: className }} heading="Token whitelist" noData={data !== null && data.length === 0} - {...{ error, footer, headingCorners, loading }} + {...{ error, footer, headerSlots, loading }} >
    diff --git a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx index 9f3dfb10..20d2d7f2 100644 --- a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx @@ -105,7 +105,7 @@ export const TokensWhitelistForm = ({ void null ) } - headingCorners={{ + headerSlots={{ end: editModeEnabled ? ( diff --git a/src/shared/ui/design/tile/tile.scss b/src/shared/ui/design/tile/tile.scss index 297626cd..31fc65c6 100644 --- a/src/shared/ui/design/tile/tile.scss +++ b/src/shared/ui/design/tile/tile.scss @@ -10,7 +10,7 @@ background-color: color.$lightest; font-size: size.$small-text; - &-heading { + &-header { display: flex; flex-flow: row nowrap; align-items: center; @@ -22,7 +22,7 @@ font-size: size.$large-text; } - &-corner { + &-slot { &--start, &--end { .MuiButtonBase-root { diff --git a/src/shared/ui/design/tile/tile.tsx b/src/shared/ui/design/tile/tile.tsx index 8ec899a6..d903b75e 100644 --- a/src/shared/ui/design/tile/tile.tsx +++ b/src/shared/ui/design/tile/tile.tsx @@ -8,13 +8,14 @@ import "./tile.scss"; const _Tile = "Tile"; export interface TileProps extends PropsWithChildren, Omit, "className"> { - classes?: Partial["className"]>>; + classes?: Partial["className"]>>; error?: Error | null; footer?: JSX.Element; heading?: string | null; - headingCorners?: { start?: JSX.Element; end?: JSX.Element }; + headerSlots?: { start?: JSX.Element; end?: JSX.Element }; loading?: boolean; noData?: boolean; + order?: "default" | "swapped"; } export const Tile = ({ @@ -23,21 +24,17 @@ export const Tile = ({ error, footer, heading, - headingCorners, + headerSlots, loading = false, noData = false, + order = "default", }: TileProps) => ( -
    - {heading && ( - - {headingCorners?.start && ( - {headingCorners?.start} - )} - -

    {heading}

    - {headingCorners?.end && {headingCorners?.end}} -
    - )} +
    + + {headerSlots?.start && {headerSlots?.start}} + {heading &&

    {heading}

    } + {headerSlots?.end && {headerSlots?.end}} +
    {loading &&
    } From 0ddaf5d30620aa2af991d2c22160d01f5fa3e2aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 25 Nov 2022 08:18:00 +0400 Subject: [PATCH 423/537] wip: Apply post code review remarks --- .../ui/mi-token-whitelist.tsx | 5 ++- src/features/index.ts | 2 +- .../tokens/whitelist-change/config.ts | 2 +- src/features/tokens/whitelist-change/index.ts | 8 ++-- .../ui/tokens-whitelist-form.tsx | 42 +++++++++---------- src/shared/ui/design/tile/tile.scss | 16 +++++-- src/shared/ui/design/tile/tile.tsx | 8 +++- src/widgets/settings-editor/config.ts | 6 +-- .../settings-editor/ui/settings-editor.tsx | 4 +- 9 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index d9ea603c..3254f3c9 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -4,7 +4,7 @@ import { type MI } from "../config"; import { type MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; -interface MITokenWhitelistTableProps extends MI.Inputs, Pick { +interface MITokenWhitelistTableProps extends MI.Inputs, Pick { ItemProps?: TableProps["RowProps"]; className?: string; itemsAdditional?: MIWhitelistedTokenProps["address"][]; @@ -19,6 +19,7 @@ export const MITokenWhitelistTable = ({ headerSlots, itemsAdditional, onItemsSelected, + subheader, }: MITokenWhitelistTableProps) => { const { data, error, loading } = MITokensModel.useWhitelist(daoAddress); @@ -27,7 +28,7 @@ export const MITokenWhitelistTable = ({ classes={{ root: className }} heading="Token whitelist" noData={data !== null && data.length === 0} - {...{ error, footer, headerSlots, loading }} + {...{ error, footer, headerSlots, loading, subheader }} >
    , "onChange">, MIEntity.Inputs { diff --git a/src/features/tokens/whitelist-change/index.ts b/src/features/tokens/whitelist-change/index.ts index 97048de8..19d6e12a 100644 --- a/src/features/tokens/whitelist-change/index.ts +++ b/src/features/tokens/whitelist-change/index.ts @@ -1,8 +1,8 @@ -import { Config, type TokensWhitelistChange as TWChangeFeature } from "./config"; -import { TokensWhitelistForm } from "./ui/tokens-whitelist-form"; +import { Config, type TokenWhitelistChange as TWChangeFeature } from "./config"; +import { TokenWhitelistForm } from "./ui/tokens-whitelist-form"; -export class TokensWhitelistChange extends Config { - static Form = TokensWhitelistForm; +export class TokenWhitelistChange extends Config { + static Form = TokenWhitelistForm; } export { type TWChangeFeature }; diff --git a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx index 20d2d7f2..546b5c29 100644 --- a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx @@ -5,19 +5,19 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { TextInput, Tooltip } from "../../../../shared/ui/design"; import { ArgsString } from "../../../../shared/lib/args-old"; import { MI } from "../../../../entities"; -import { Config, TokensWhitelistChange } from "../config"; +import { Config, TokenWhitelistChange } from "../config"; -export const TokensWhitelistForm = ({ +export const TokenWhitelistForm = ({ className, daoAddress, disabled, onEdit, resetTrigger, -}: TokensWhitelistChange.Inputs) => { +}: TokenWhitelistChange.Inputs) => { const [editModeEnabled, editModeSwitch] = useState(false); - const [addTokens, markForAddition] = useState(new Set()), - [removeTokens, markForRemoval] = useState(new Set()); + const [addTokens, markForAddition] = useState(new Set()), + [removeTokens, markForRemoval] = useState(new Set()); const tokenToAddAddress = useMemo(() => new ArgsString(""), []); @@ -89,22 +89,6 @@ export const TokensWhitelistForm = ({ void null, }, }} - footer={ - editModeEnabled ? ( - - void (key === "Enter" && Object.hasOwn(target, "value") - ? onAdditionRequest((target as HTMLInputElement).value) - : null) - } - value={tokenToAddAddress} - /> - ) : ( - void null - ) - } headerSlots={{ end: editModeEnabled ? ( @@ -124,6 +108,22 @@ export const TokensWhitelistForm = ({ ), }} itemsAdditional={Array.from(addTokens)} + subheader={ + editModeEnabled ? ( + + void (key === "Enter" && Object.hasOwn(target, "value") + ? onAdditionRequest((target as HTMLInputElement).value) + : null) + } + value={tokenToAddAddress} + /> + ) : ( + void null + ) + } {...{ className, daoAddress }} /> ); diff --git a/src/shared/ui/design/tile/tile.scss b/src/shared/ui/design/tile/tile.scss index 31fc65c6..d98038fe 100644 --- a/src/shared/ui/design/tile/tile.scss +++ b/src/shared/ui/design/tile/tile.scss @@ -6,7 +6,8 @@ flex-flow: column nowrap; position: relative; border-radius: size.$task-radius; - padding: size.$gap * 0.6; + padding: size.$gap * 0.5; + gap: size.$gap * 0.5; background-color: color.$lightest; font-size: size.$small-text; @@ -14,8 +15,8 @@ display: flex; flex-flow: row nowrap; align-items: center; + padding: size.$gap * 0.2 size.$gap * 0.2 size.$gap * 0.5; gap: size.$gap; - padding: size.$gap * 0.2 size.$gap * 0.2 size.$gap * 0.8; &-text, svg { @@ -36,6 +37,10 @@ } } + &-subheader { + margin-bottom: auto; + } + &-content { display: flex; flex-flow: column nowrap; @@ -45,9 +50,14 @@ overflow: hidden; } + &-footer { + margin-top: auto; + } + + &-subheader, &-footer { display: flex; + flex-flow: row nowrap; justify-content: center; - margin-top: auto; } } diff --git a/src/shared/ui/design/tile/tile.tsx b/src/shared/ui/design/tile/tile.tsx index d903b75e..db1f3beb 100644 --- a/src/shared/ui/design/tile/tile.tsx +++ b/src/shared/ui/design/tile/tile.tsx @@ -8,7 +8,9 @@ import "./tile.scss"; const _Tile = "Tile"; export interface TileProps extends PropsWithChildren, Omit, "className"> { - classes?: Partial["className"]>>; + classes?: Partial< + Record<"root" | "content" | "footer" | "header" | "subheader", HTMLAttributes["className"]> + >; error?: Error | null; footer?: JSX.Element; heading?: string | null; @@ -16,6 +18,7 @@ export interface TileProps extends PropsWithChildren, Omit (
    @@ -36,6 +40,8 @@ export const Tile = ({ {headerSlots?.end && {headerSlots?.end}} + {subheader &&
    {subheader}
    } +
    {loading &&
    } {!loading && noData && } diff --git a/src/widgets/settings-editor/config.ts b/src/widgets/settings-editor/config.ts index 41edef75..2e9cb77f 100644 --- a/src/widgets/settings-editor/config.ts +++ b/src/widgets/settings-editor/config.ts @@ -1,6 +1,6 @@ import { HTMLProps } from "react"; -import { SchedulingSettingsChange, TokensWhitelistChange } from "../../features"; +import { SchedulingSettingsChange, TokenWhitelistChange } from "../../features"; import { MulticallSettingsDiff, Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; @@ -17,11 +17,11 @@ export namespace SettingsEditor { export class Config { public static readonly DiffKey = { ...SchedulingSettingsChange.DiffKey, - ...TokensWhitelistChange.DiffKey, + ...TokenWhitelistChange.DiffKey, }; public static readonly DiffMetadata = { ...SchedulingSettingsChange.DiffMetadata, - ...TokensWhitelistChange.DiffMetadata, + ...TokenWhitelistChange.DiffMetadata, }; } diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 6603bd7c..d107b24e 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { useCallback, useMemo, useState, FormEventHandler, useEffect, useContext } from "react"; import { MI, Wallet } from "../../../entities"; -import { SchedulingSettingsChange, TokensWhitelistChange } from "../../../features"; +import { SchedulingSettingsChange, TokenWhitelistChange } from "../../../features"; import { ArgsString } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; @@ -92,7 +92,7 @@ export const SettingsEditorUI = ({ className, contracts }: SettingsEditor.Inputs daoAddress={contracts.dao.address} /> - Date: Sat, 26 Nov 2022 04:11:22 +0400 Subject: [PATCH 424/537] wip: Apply post code review remarks --- .../fungible-token/{config.ts => context.ts} | 2 +- src/entities/fungible-token/index.ts | 4 ++-- src/entities/fungible-token/lib/ft-format.ts | 6 ++--- src/entities/fungible-token/model/ft-info.ts | 2 +- .../fungible-token/ui/ft-balances.tsx | 2 +- src/entities/index.ts | 2 +- src/entities/job/{config.ts => context.ts} | 4 ++-- src/entities/job/index.ts | 4 ++-- src/entities/job/lib/job-normalized.ts | 12 +++++----- src/entities/job/model/job.ts | 2 +- src/entities/job/ui/job.tsx | 10 +++++---- src/entities/job/ui/jobs-table.tsx | 2 +- .../{config.ts => context.ts} | 2 +- src/entities/multicall-instance/index.ts | 4 ++-- .../multicall-instance/model/mi-admins.ts | 2 +- .../multicall-instance/model/mi-tokens.ts | 2 +- .../multicall-instance/ui/mi-admins.tsx | 2 +- .../ui/mi-token-whitelist.tsx | 2 +- src/entities/near/{config.ts => context.ts} | 6 ++--- src/entities/near/index.ts | 6 ++--- src/entities/near/model/near-balances.ts | 22 +++++++++---------- src/entities/near/ui/near-balances.tsx | 10 ++++----- .../external-login/{config.ts => context.ts} | 4 ++-- src/features/external-login/index.ts | 4 ++-- .../external-login/model/el-dialogs.ts | 10 +++++---- src/features/external-login/ui/el-dialogs.tsx | 12 +++++----- src/features/external-login/ui/el-menu.tsx | 6 ++--- .../settings-change/{config.ts => context.ts} | 12 +++++----- .../scheduling/settings-change/index.ts | 4 ++-- .../ui/scheduling-settings-form.tsx | 20 +++++++++-------- .../{config.ts => context.ts} | 12 +++++----- src/features/tokens/whitelist-change/index.ts | 4 ++-- .../ui/tokens-whitelist-form.tsx | 6 ++--- src/pages/dao/dao.tsx | 2 +- src/shared/lib/contracts/sputnik-dao.ts | 2 +- src/shared/ui/design/config.ts | 5 ----- src/shared/ui/design/context.ts | 3 +++ .../data-inspector/{config.ts => context.ts} | 2 +- .../design/data-inspector/data-inspector.tsx | 4 ++-- src/shared/ui/design/index.ts | 2 +- src/shared/ui/design/table/row.tsx | 4 ++-- .../settings-editor/{config.ts => context.ts} | 2 +- src/widgets/settings-editor/index.ts | 4 ++-- .../settings-editor/ui/se-proposal-form.tsx | 10 ++++----- .../settings-editor/ui/settings-editor.tsx | 10 ++++----- src/widgets/token-balances/config.ts | 7 ------ src/widgets/token-balances/context.ts | 7 ++++++ src/widgets/token-balances/index.ts | 2 +- .../token-balances/ui/token-balances.tsx | 6 ++--- 49 files changed, 140 insertions(+), 136 deletions(-) rename src/entities/fungible-token/{config.ts => context.ts} (91%) rename src/entities/job/{config.ts => context.ts} (92%) rename src/entities/multicall-instance/{config.ts => context.ts} (95%) rename src/entities/near/{config.ts => context.ts} (72%) rename src/features/external-login/{config.ts => context.ts} (92%) rename src/features/scheduling/settings-change/{config.ts => context.ts} (75%) rename src/features/tokens/whitelist-change/{config.ts => context.ts} (78%) delete mode 100644 src/shared/ui/design/config.ts create mode 100644 src/shared/ui/design/context.ts rename src/shared/ui/design/data-inspector/{config.ts => context.ts} (81%) rename src/widgets/settings-editor/{config.ts => context.ts} (96%) delete mode 100644 src/widgets/token-balances/config.ts create mode 100644 src/widgets/token-balances/context.ts diff --git a/src/entities/fungible-token/config.ts b/src/entities/fungible-token/context.ts similarity index 91% rename from src/entities/fungible-token/config.ts rename to src/entities/fungible-token/context.ts index 883598de..d626077b 100644 --- a/src/entities/fungible-token/config.ts +++ b/src/entities/fungible-token/context.ts @@ -10,6 +10,6 @@ export namespace FT { } } -export class Config { +export class ModuleContext { static FRACTIONAL_PART_LENGTH = 5; } diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 5bd2e6e9..44f9ca82 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,7 +1,7 @@ -import { Config, FT as FTEntity } from "./config"; +import { ModuleContext, FT as FTEntity } from "./context"; import { ftBalances } from "./ui/ft-balances"; -export class FT extends Config { +export class FT extends ModuleContext { static balances = ftBalances; } diff --git a/src/entities/fungible-token/lib/ft-format.ts b/src/entities/fungible-token/lib/ft-format.ts index 1e80274b..d4229a46 100644 --- a/src/entities/fungible-token/lib/ft-format.ts +++ b/src/entities/fungible-token/lib/ft-format.ts @@ -1,14 +1,14 @@ import { Big, formatTokenAmount } from "../../../shared/lib/converter"; -import { Config } from "../config"; +import { ModuleContext } from "../context"; const amountToDisplayAmount = (amount: string, decimals: number): string => { const formattedAmount = formatTokenAmount(amount, decimals), - minimalDisplayAmount = Big("10").pow(-Config.FRACTIONAL_PART_LENGTH).toFixed(); + minimalDisplayAmount = Big("10").pow(-ModuleContext.FRACTIONAL_PART_LENGTH).toFixed(); return Big(formattedAmount).gt("0") && Big(formattedAmount).lt(minimalDisplayAmount) ? "< " + minimalDisplayAmount - : formatTokenAmount(amount, decimals, Config.FRACTIONAL_PART_LENGTH); + : formatTokenAmount(amount, decimals, ModuleContext.FRACTIONAL_PART_LENGTH); }; export const FTFormat = { diff --git a/src/entities/fungible-token/model/ft-info.ts b/src/entities/fungible-token/model/ft-info.ts index 6fc1a147..da3c4526 100644 --- a/src/entities/fungible-token/model/ft-info.ts +++ b/src/entities/fungible-token/model/ft-info.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { Big } from "../../../shared/lib/converter"; import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; -import { type FT } from "../config"; +import { type FT } from "../context"; type FTInfo = { data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index 6567c811..0f7ead41 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -1,7 +1,7 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { FTFormat } from "../lib/ft-format"; import { FTInfoModel } from "../model/ft-info"; -import { type FT } from "../config"; +import { type FT } from "../context"; interface FTBalancesProps extends FT.Inputs {} diff --git a/src/entities/index.ts b/src/entities/index.ts index 9851dcc1..10471b4e 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -2,5 +2,5 @@ export { Task } from "./task"; export { Job, type JobEntity } from "./job"; export { FT, type FTEntity } from "./fungible-token"; export { MI, type MIEntity } from "./multicall-instance"; -export { NEAR, type NEAREntity } from "./near"; +export { NEARToken, type NEARTokenEntity } from "./near"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/config.ts b/src/entities/job/context.ts similarity index 92% rename from src/entities/job/config.ts rename to src/entities/job/context.ts index 7810dd8e..0c341597 100644 --- a/src/entities/job/config.ts +++ b/src/entities/job/context.ts @@ -21,7 +21,7 @@ namespace JobEntity { }; } -class JobConfig { +class JobModuleContext { static readonly Status = JobEntity.Status; static StatusIcons = { @@ -33,4 +33,4 @@ class JobConfig { }; } -export { JobConfig, type JobEntity }; +export { JobModuleContext, type JobEntity }; diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index 8e8afb4e..b0d810fc 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,7 +1,7 @@ -import { JobConfig, type JobEntity } from "./config"; +import { JobModuleContext, type JobEntity } from "./context"; import { JobsTable } from "./ui/jobs-table"; -class Job extends JobConfig { +class Job extends JobModuleContext { static EntriesTable = JobsTable; } diff --git a/src/entities/job/lib/job-normalized.ts b/src/entities/job/lib/job-normalized.ts index 5b2e2efd..1d13763b 100644 --- a/src/entities/job/lib/job-normalized.ts +++ b/src/entities/job/lib/job-normalized.ts @@ -3,7 +3,7 @@ import { Base64 } from "js-base64"; import { JobData } from "../../../shared/lib/contracts/multicall"; import { Big } from "../../../shared/lib/converter"; -import { JobConfig, type JobEntity } from "../config"; +import { JobModuleContext, type JobEntity } from "../context"; /** * Job status is: @@ -14,14 +14,14 @@ import { JobConfig, type JobEntity } from "../config"; */ const jobToStatus = ({ job }: JobData): JobEntity.Status => { if (job.is_active) { - if (job.run_count > -1) return JobConfig.Status.Running; - else return JobConfig.Status.Active; + if (job.run_count > -1) return JobModuleContext.Status.Running; + else return JobModuleContext.Status.Active; } else { // Date.now() returns timestamp in milliseconds, we use nanoseconds const currentTime = Big(Date.now()).times("1000000"); const jobTime = job.start_at; - if (currentTime.gt(jobTime)) return JobConfig.Status.Expired; - else return JobConfig.Status.Inactive; + if (currentTime.gt(jobTime)) return JobModuleContext.Status.Expired; + else return JobModuleContext.Status.Inactive; } }; @@ -65,7 +65,7 @@ const jobToJobWithMulticallsDataDecoded = ({ id, job }: JobData): JobData => ({ */ const jobToJobWithStatus = (job: JobData): JobEntity.DataWithStatus => ({ ...job, - job: { ...job.job, status: JobConfig.Status[jobToStatus(job)] }, + job: { ...job.job, status: JobModuleContext.Status[jobToStatus(job)] }, }); export const JobNormalized = { diff --git a/src/entities/job/model/job.ts b/src/entities/job/model/job.ts index ed42ab17..6224ce9f 100644 --- a/src/entities/job/model/job.ts +++ b/src/entities/job/model/job.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import { type JobEntity } from "../config"; +import { type JobEntity } from "../context"; import { JobNormalized } from "../lib/job-normalized"; type JobAllEntries = { diff --git a/src/entities/job/ui/job.tsx b/src/entities/job/ui/job.tsx index 2daa67fa..ec193f79 100644 --- a/src/entities/job/ui/job.tsx +++ b/src/entities/job/ui/job.tsx @@ -3,7 +3,7 @@ import { NavLink } from "react-router-dom"; import { Big, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/design"; -import { JobConfig, type JobEntity } from "../config"; +import { JobModuleContext, type JobEntity } from "../context"; import "./job.scss"; interface JobEntryProps extends JobEntity.DataWithStatus {} @@ -12,13 +12,15 @@ const _Job = "Job"; const JobDisplayStatus = ({ job }: Pick) => { const statusTextByStatus = { - ...JobConfig.Status, - [JobConfig.Status.Running]: `${JobConfig.Status.Running}: ${job.run_count + 1}/${job.multicalls.length}`, + ...JobModuleContext.Status, + [JobModuleContext.Status.Running]: `${JobModuleContext.Status.Running}: ${job.run_count + 1}/${ + job.multicalls.length + }`, }; return ( ); diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 6d1c7908..c339d0ec 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { JobModel } from "../model/job"; -import { type JobEntity } from "../config"; +import { type JobEntity } from "../context"; import { jobTableRowRender } from "./job"; import "./jobs-table.scss"; diff --git a/src/entities/multicall-instance/config.ts b/src/entities/multicall-instance/context.ts similarity index 95% rename from src/entities/multicall-instance/config.ts rename to src/entities/multicall-instance/context.ts index c140dea7..943f9cec 100644 --- a/src/entities/multicall-instance/config.ts +++ b/src/entities/multicall-instance/context.ts @@ -16,7 +16,7 @@ export namespace MI { /** * Multicall Instance entity config */ -export class MIConfig { +export class MIModuleContext { public static readonly ParamKey = MulticallSettingsParamKey; /** diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 29b825a3..2281d0cc 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,11 +1,11 @@ -import { MI as MIEntity, MIConfig } from "./config"; +import { MI as MIEntity, MIModuleContext } from "./context"; import { MIAdminsTable } from "./ui/mi-admins"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; /** * Multicall Instance entity */ -class MI extends MIConfig { +class MI extends MIModuleContext { static AdminsTable = MIAdminsTable; static TokenWhitelistTable = MITokenWhitelistTable; } diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index 5ec31ca1..dc1e5dec 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { type MI } from "../config"; +import { type MI } from "../context"; import { MIInfoModel } from "./mi-settings"; diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index d4dfb128..58292a32 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { type MI } from "../config"; +import { type MI } from "../context"; import { MIInfoModel } from "./mi-settings"; diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 7a7d15eb..57f074af 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,6 +1,6 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { MIAdminsModel } from "../model/mi-admins"; -import { type MI } from "../config"; +import { type MI } from "../context"; import { miAdminAsTableRow } from "./mi-admin"; diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index 3254f3c9..5600bfb5 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,6 +1,6 @@ import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; import { MITokensModel } from "../model/mi-tokens"; -import { type MI } from "../config"; +import { type MI } from "../context"; import { type MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; diff --git a/src/entities/near/config.ts b/src/entities/near/context.ts similarity index 72% rename from src/entities/near/config.ts rename to src/entities/near/context.ts index 15d415a7..88355c6e 100644 --- a/src/entities/near/config.ts +++ b/src/entities/near/context.ts @@ -1,7 +1,7 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -namespace NEAREntity { +namespace NEARTokenEntity { export interface Inputs { contracts: { dao: SputnikDAO; @@ -10,8 +10,8 @@ namespace NEAREntity { } } -class NEARConfig { +class NEARTokenModuleContext { static FRACTIONAL_PART_LENGTH = 5; } -export { NEARConfig, type NEAREntity }; +export { NEARTokenModuleContext, type NEARTokenEntity }; diff --git a/src/entities/near/index.ts b/src/entities/near/index.ts index 8689fa82..61a6bfce 100644 --- a/src/entities/near/index.ts +++ b/src/entities/near/index.ts @@ -1,8 +1,8 @@ -import { NEARConfig, type NEAREntity } from "./config"; +import { NEARTokenModuleContext, type NEARTokenEntity } from "./context"; import { nearTokenBalancesRender } from "./ui/near-balances"; -class NEAR extends NEARConfig { +class NEARToken extends NEARTokenModuleContext { static balancesRender = nearTokenBalancesRender; } -export { NEAR, type NEAREntity }; +export { NEARToken, type NEARTokenEntity }; diff --git a/src/entities/near/model/near-balances.ts b/src/entities/near/model/near-balances.ts index 05225ee4..ab3ea7ae 100644 --- a/src/entities/near/model/near-balances.ts +++ b/src/entities/near/model/near-balances.ts @@ -3,16 +3,16 @@ import { useEffect, useState } from "react"; import { Big, formatTokenAmount } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; -import { NEARConfig, type NEAREntity } from "../config"; +import { NEARTokenModuleContext, type NEARTokenEntity } from "../context"; -type NEARDataFxResponse = { +type NEARTokenDataFxResponse = { data: { dao: string; multicall: string; total: string } | null; loading: boolean; }; const nearTokenDataFx = async ( - { dao, multicall }: NEAREntity.Inputs["contracts"], - callback: (result: NEARDataFxResponse) => void + { dao, multicall }: NEARTokenEntity.Inputs["contracts"], + callback: (result: NEARTokenDataFxResponse) => void ) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ viewAccount(dao.address), @@ -24,13 +24,13 @@ const nearTokenDataFx = async ( return callback({ data: { - dao: formatTokenAmount(daoRawBalance, 24, NEARConfig.FRACTIONAL_PART_LENGTH), - multicall: formatTokenAmount(multicallRawBalance, 24, NEARConfig.FRACTIONAL_PART_LENGTH), + dao: formatTokenAmount(daoRawBalance, 24, NEARTokenModuleContext.FRACTIONAL_PART_LENGTH), + multicall: formatTokenAmount(multicallRawBalance, 24, NEARTokenModuleContext.FRACTIONAL_PART_LENGTH), total: formatTokenAmount( Big(daoRawBalance).add(multicallRawBalance).toFixed(), 24, - NEARConfig.FRACTIONAL_PART_LENGTH + NEARTokenModuleContext.FRACTIONAL_PART_LENGTH ), }, @@ -38,14 +38,14 @@ const nearTokenDataFx = async ( }); }; -const useNEARData = (contracts: NEAREntity.Inputs["contracts"]) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); +const useNEARTokenData = (contracts: NEARTokenEntity.Inputs["contracts"]) => { + const [state, stateUpdate] = useState({ data: null, loading: true }); useEffect(() => void nearTokenDataFx(contracts, stateUpdate), [contracts, stateUpdate]); return state; }; -export class NEARBalancesModel { - static useTokenFrom = useNEARData; +export class NEARTokenBalancesModel { + static useTokenFrom = useNEARTokenData; } diff --git a/src/entities/near/ui/near-balances.tsx b/src/entities/near/ui/near-balances.tsx index 28ab2e30..04b091c0 100644 --- a/src/entities/near/ui/near-balances.tsx +++ b/src/entities/near/ui/near-balances.tsx @@ -1,12 +1,12 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; -import { NEARBalancesModel } from "../model/near-balances"; -import { type NEAREntity } from "../config"; +import { NEARTokenBalancesModel } from "../model/near-balances"; +import { type NEARTokenEntity } from "../context"; -interface NEARBalancesRenderProps extends NEAREntity.Inputs {} +interface NEARTokenBalancesRenderProps extends NEARTokenEntity.Inputs {} -export const nearTokenBalancesRender = ({ contracts }: NEARBalancesRenderProps) => { - const { data } = NEARBalancesModel.useTokenFrom(contracts); +export const nearTokenBalancesRender = ({ contracts }: NEARTokenBalancesRenderProps) => { + const { data } = NEARTokenBalancesModel.useTokenFrom(contracts); return !data ? null diff --git a/src/features/external-login/config.ts b/src/features/external-login/context.ts similarity index 92% rename from src/features/external-login/config.ts rename to src/features/external-login/context.ts index 7f2807be..84e6232f 100644 --- a/src/features/external-login/config.ts +++ b/src/features/external-login/context.ts @@ -1,10 +1,10 @@ -export class Config { +export class ModuleContext { static KEYS = { all: "ed25519%3A9jeqkc8ybv7aYSA7uLNFUEn8cgKo759yue4771bBWsSr", public: "ed25519%3ADEaoD65LomNHAMzhNZva15LC85ntwBHdcTbCnZRXciZH", }; - static METHODS: Record<"dao" | "multicall", { title: string; type: keyof typeof Config.METHODS }> = { + static METHODS: Record<"dao" | "multicall", { title: string; type: keyof typeof ModuleContext.METHODS }> = { dao: { title: "Login in dApps as DAO", type: "dao" }, multicall: { title: "Login in dApps as Multicall", type: "multicall" }, }; diff --git a/src/features/external-login/index.ts b/src/features/external-login/index.ts index 676f9a96..fb5ea29a 100644 --- a/src/features/external-login/index.ts +++ b/src/features/external-login/index.ts @@ -1,8 +1,8 @@ -import { Config } from "./config"; +import { ModuleContext } from "./context"; import { ELDialogs } from "./ui/el-dialogs"; import { ELMenu } from "./ui/el-menu"; -export class ExternalLogin extends Config { +export class ExternalLogin extends ModuleContext { static Dialogs = ELDialogs; static Menu = ELMenu; } diff --git a/src/features/external-login/model/el-dialogs.ts b/src/features/external-login/model/el-dialogs.ts index b303ed12..33be7f59 100644 --- a/src/features/external-login/model/el-dialogs.ts +++ b/src/features/external-login/model/el-dialogs.ts @@ -4,12 +4,12 @@ import { useCallback, useEffect, useState } from "react"; -import { Config } from "../config"; +import { ModuleContext } from "../context"; const _dialogOpenRequested = "dialogOpenRequested"; const dialogOpenRequested = { - dispatch: (dialogKey: keyof typeof Config.METHODS) => + dispatch: (dialogKey: keyof typeof ModuleContext.METHODS) => document.dispatchEvent(new CustomEvent(_dialogOpenRequested, { detail: { dialogKey } })), subscribe: (callback: EventListener) => { @@ -23,8 +23,10 @@ export class ELDialogsModel { static dialogOpenRequested = dialogOpenRequested.dispatch; static useVisibilityState = () => { - const [dialogsVisibility, dialogVisibilitySwitch] = useState | {}>( - Object.values(Config.METHODS).reduce( + const [dialogsVisibility, dialogVisibilitySwitch] = useState< + Record | {} + >( + Object.values(ModuleContext.METHODS).reduce( (visibilityState, { type }) => ({ ...visibilityState, [type]: false }), {} ) diff --git a/src/features/external-login/ui/el-dialogs.tsx b/src/features/external-login/ui/el-dialogs.tsx index 8f40c95b..d46bfe78 100644 --- a/src/features/external-login/ui/el-dialogs.tsx +++ b/src/features/external-login/ui/el-dialogs.tsx @@ -1,12 +1,12 @@ import { InfoOutlined } from "@mui/icons-material"; import clsx from "clsx"; -import { ComponentProps, useCallback, useMemo, useReducer, useState } from "react"; +import { ComponentProps, useMemo, useReducer } from "react"; import { ArgsError, ArgsString } from "../../../shared/lib/args-old"; import { STORAGE } from "../../../shared/lib/persistent"; import { Validation } from "../../../shared/lib/validation"; import { Dialog, TextInput, Tooltip } from "../../../shared/ui/design"; -import { Config as Config } from "../config"; +import { ModuleContext } from "../context"; import { ELDialogsModel } from "../model/el-dialogs"; import "./el-dialog.scss"; @@ -30,8 +30,8 @@ const ExternalLoginDialog = ({ className, method, onClose, open, title }: Extern } else { const url = new URL(value); url.searchParams.set("account_id", STORAGE.addresses[method]); - url.searchParams.set("public_key", Config.KEYS.public); - url.searchParams.set("all_keys", Config.KEYS.all); + url.searchParams.set("public_key", ModuleContext.KEYS.public); + url.searchParams.set("all_keys", ModuleContext.KEYS.all); return url.toString(); } }, @@ -47,7 +47,7 @@ const ExternalLoginDialog = ({ className, method, onClose, open, title }: Extern {...{ onClose, open, title }} >
      - {Config.STEP_BY_STEP_GUIDE.map((step) => ( + {ModuleContext.STEP_BY_STEP_GUIDE.map((step) => (
    • {step.text} @@ -80,7 +80,7 @@ const ExternalLoginDialog = ({ className, method, onClose, open, title }: Extern export const ELDialogs = () => { const { dialogsVisibility, closeHandlerBinding } = ELDialogsModel.useVisibilityState(); - return Object.values(Config.METHODS).map((loginMethod) => ( + return Object.values(ModuleContext.METHODS).map((loginMethod) => ( , "triggerClassName"> { FeatureFlags: { - ExternalLogin: Record; + ExternalLogin: Record; }; } export const ELMenu = ({ FeatureFlags, triggerClassName }: ELMenuProps) => ( } - items={Object.values(Config.METHODS).map(({ title, type }) => ({ + items={Object.values(ModuleContext.METHODS).map(({ title, type }) => ({ disabled: !FeatureFlags.ExternalLogin[type], key: type, onClick: () => ELDialogsModel.dialogOpenRequested(type), diff --git a/src/features/scheduling/settings-change/config.ts b/src/features/scheduling/settings-change/context.ts similarity index 75% rename from src/features/scheduling/settings-change/config.ts rename to src/features/scheduling/settings-change/context.ts index b98aa291..c7b1d2d2 100644 --- a/src/features/scheduling/settings-change/config.ts +++ b/src/features/scheduling/settings-change/context.ts @@ -2,7 +2,7 @@ import { HTMLProps } from "react"; import { MI, MIEntity } from "../../../entities"; import { MulticallSettingsDiff, Multicall } from "../../../shared/lib/contracts/multicall"; -import { DesignKitConfigType } from "../../../shared/ui/design"; +import { DesignContext } from "../../../shared/ui/design"; export namespace SchedulingSettingsChange { export type DiffKey = MIEntity.ParamKey; @@ -16,17 +16,17 @@ export namespace SchedulingSettingsChange { } } -export class Config { +export class ModuleContext { public static readonly DiffKey = MI.ParamKey; public static readonly DiffMetadata = { - [Config.DiffKey.croncatManager]: { - color: "blue" as DesignKitConfigType.Color, + [ModuleContext.DiffKey.croncatManager]: { + color: "blue" as DesignContext.Color, description: "Croncat manager", }, - [Config.DiffKey.jobBond]: { - color: "blue" as DesignKitConfigType.Color, + [ModuleContext.DiffKey.jobBond]: { + color: "blue" as DesignContext.Color, description: "Job bond", }, }; diff --git a/src/features/scheduling/settings-change/index.ts b/src/features/scheduling/settings-change/index.ts index 222e074f..05651071 100644 --- a/src/features/scheduling/settings-change/index.ts +++ b/src/features/scheduling/settings-change/index.ts @@ -1,7 +1,7 @@ -import { Config, type SchedulingSettingsChange as SSChangeFeature } from "./config"; +import { ModuleContext, type SchedulingSettingsChange as SSChangeFeature } from "./context"; import { SchedulingSettingsForm } from "./ui/scheduling-settings-form"; -export class SchedulingSettingsChange extends Config { +export class SchedulingSettingsChange extends ModuleContext { static Form = SchedulingSettingsForm; } diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx index b4cb1a90..492c6a73 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx @@ -5,7 +5,7 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { ArgsString } from "../../../../shared/lib/args-old"; import { toNEAR, toYocto } from "../../../../shared/lib/converter"; import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../../shared/ui/design"; -import { Config, SchedulingSettingsChange } from "../config"; +import { ModuleContext, SchedulingSettingsChange } from "../context"; export const SchedulingSettingsForm = ({ className, @@ -17,8 +17,8 @@ export const SchedulingSettingsForm = ({ const [editModeEnabled, editModeSwitch] = useState(false); const formInitialState: SchedulingSettingsChange.FormState = { - [Config.DiffKey.croncatManager]: "", - [Config.DiffKey.jobBond]: "", + [ModuleContext.DiffKey.croncatManager]: "", + [ModuleContext.DiffKey.jobBond]: "", }; const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ @@ -27,14 +27,16 @@ export const SchedulingSettingsForm = ({ ]; const formFields = { - croncatManager: useMemo(() => new ArgsString(multicallInstance.croncatManager), [multicallInstance]), + croncatManager: useMemo(() => new ArgsString(multicallInstance.croncatManager), []), jobBond: useMemo( () => new ArgsString(multicallInstance.jobBond !== "" ? toNEAR(multicallInstance.jobBond) : ""), - [multicallInstance] + [] ), }; + console.table(croncatManager); + const onCroncatManagerChange = useCallback["onChange"]>( ({ target: { value } }) => void croncatManagerUpdate( @@ -115,10 +117,10 @@ export const SchedulingSettingsForm = ({ header={["Option", "Value"]} rows={[ { - id: Config.DiffKey.croncatManager, + id: ModuleContext.DiffKey.croncatManager, content: [ - Config.DiffMetadata[Config.DiffKey.croncatManager].description, + ModuleContext.DiffMetadata[ModuleContext.DiffKey.croncatManager].description, editModeEnabled ? ( {} } -export class Config { +export class ModuleContext { public static readonly DiffKey = MulticallTokenWhitelistDiffKey; public static readonly DiffMetadata = { - [Config.DiffKey.addTokens]: { - color: "green" as DesignKitConfigType.Color, + [ModuleContext.DiffKey.addTokens]: { + color: "green" as DesignContext.Color, description: "Tokens to add to whitelist", }, - [Config.DiffKey.removeTokens]: { - color: "red" as DesignKitConfigType.Color, + [ModuleContext.DiffKey.removeTokens]: { + color: "red" as DesignContext.Color, description: "Tokens to remove from whitelist", }, }; diff --git a/src/features/tokens/whitelist-change/index.ts b/src/features/tokens/whitelist-change/index.ts index 19d6e12a..e0a32080 100644 --- a/src/features/tokens/whitelist-change/index.ts +++ b/src/features/tokens/whitelist-change/index.ts @@ -1,7 +1,7 @@ -import { Config, type TokenWhitelistChange as TWChangeFeature } from "./config"; +import { ModuleContext, type TokenWhitelistChange as TWChangeFeature } from "./context"; import { TokenWhitelistForm } from "./ui/tokens-whitelist-form"; -export class TokenWhitelistChange extends Config { +export class TokenWhitelistChange extends ModuleContext { static Form = TokenWhitelistForm; } diff --git a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx index 546b5c29..4522653b 100644 --- a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx @@ -5,7 +5,7 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { TextInput, Tooltip } from "../../../../shared/ui/design"; import { ArgsString } from "../../../../shared/lib/args-old"; import { MI } from "../../../../entities"; -import { Config, TokenWhitelistChange } from "../config"; +import { ModuleContext, TokenWhitelistChange } from "../context"; export const TokenWhitelistForm = ({ className, @@ -69,8 +69,8 @@ export const TokenWhitelistForm = ({ - (addTokens.has(id) && Config.DiffMetadata.addTokens.color) || - (removeTokens.has(id) && Config.DiffMetadata.removeTokens.color) || + (addTokens.has(id) && ModuleContext.DiffMetadata.addTokens.color) || + (removeTokens.has(id) && ModuleContext.DiffMetadata.removeTokens.color) || null, slots: { diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index c7c3b721..a00aa42e 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -208,7 +208,7 @@ export class DaoPage extends Component { JSON.stringify({ multicall_init_args: { admin_accounts: [dao.address], - croncat_manager: window.nearConfig.CRONCAT_MANAGER_ADDRESS, + croncat_manager: window.nearModuleContext.CRONCAT_MANAGER_ADDRESS, job_bond: dao.policy.proposal_bond, }, diff --git a/src/shared/lib/contracts/sputnik-dao.ts b/src/shared/lib/contracts/sputnik-dao.ts index c0953d42..d06e2f1b 100644 --- a/src/shared/lib/contracts/sputnik-dao.ts +++ b/src/shared/lib/contracts/sputnik-dao.ts @@ -134,7 +134,7 @@ type Proposal = { }; const ProposalKindPolicyLabel: Record = { - ChangeConfig: "config", + ChangeConfig: "context", ChangePolicy: "policy", AddMemberToRole: "add_member_to_role", RemoveMemberFromRole: "remove_member_from_role", diff --git a/src/shared/ui/design/config.ts b/src/shared/ui/design/config.ts deleted file mode 100644 index 33796e4b..00000000 --- a/src/shared/ui/design/config.ts +++ /dev/null @@ -1,5 +0,0 @@ -namespace DesignKitConfigType { - export type Color = "blue" | "green" | "red" | "yellow"; -} - -export { type DesignKitConfigType }; diff --git a/src/shared/ui/design/context.ts b/src/shared/ui/design/context.ts new file mode 100644 index 00000000..1acca136 --- /dev/null +++ b/src/shared/ui/design/context.ts @@ -0,0 +1,3 @@ +export namespace DesignContext { + export type Color = "blue" | "green" | "red" | "yellow"; +} diff --git a/src/shared/ui/design/data-inspector/config.ts b/src/shared/ui/design/data-inspector/context.ts similarity index 81% rename from src/shared/ui/design/data-inspector/config.ts rename to src/shared/ui/design/data-inspector/context.ts index b73aec39..28a4212d 100644 --- a/src/shared/ui/design/data-inspector/config.ts +++ b/src/shared/ui/design/data-inspector/context.ts @@ -1,6 +1,6 @@ import { chromeLight } from "react-inspector"; -export class DataInspectorConfig { +export class ModuleContext { static readonly theme = { ...chromeLight, BASE_BACKGROUND_COLOR: "transparent", diff --git a/src/shared/ui/design/data-inspector/data-inspector.tsx b/src/shared/ui/design/data-inspector/data-inspector.tsx index 1e2232c6..9c8f2011 100644 --- a/src/shared/ui/design/data-inspector/data-inspector.tsx +++ b/src/shared/ui/design/data-inspector/data-inspector.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { MouseEvent, useCallback, useState, type ComponentProps } from "react"; import { ObjectInspector } from "react-inspector"; -import { DataInspectorConfig as Config } from "./config"; +import { ModuleContext as ModuleContext } from "./context"; import { DataInspectorNode } from "./data-inspector-node"; import "./data-inspector.scss"; @@ -46,7 +46,7 @@ export const DataInspector = ({ classes, expanded = false, expandLevel = 1, labe expandLevel={expandLevel < 1 ? 1 : expandLevel} nodeRenderer={DataInspectorNode} // @ts-ignore Built-in typings seems broken - theme={Config.theme} + theme={ModuleContext.theme} {...props} />
    diff --git a/src/shared/ui/design/index.ts b/src/shared/ui/design/index.ts index db650bbd..92f56168 100644 --- a/src/shared/ui/design/index.ts +++ b/src/shared/ui/design/index.ts @@ -1,4 +1,4 @@ -export { type DesignKitConfigType } from "./config"; +export { type DesignContext } from "./context"; /** Atoms */ export { Button } from "./button"; diff --git a/src/shared/ui/design/table/row.tsx b/src/shared/ui/design/table/row.tsx index 117e703b..00cb2f4c 100644 --- a/src/shared/ui/design/table/row.tsx +++ b/src/shared/ui/design/table/row.tsx @@ -1,7 +1,7 @@ import { Checkbox, TableCell, TableRow as MuiTableRow } from "@mui/material"; import clsx from "clsx"; import { ChangeEvent, useCallback } from "react"; -import { DesignKitConfigType } from "../config"; +import { DesignContext } from "../context"; import "./row.scss"; @@ -19,7 +19,7 @@ export interface TableRowProps { withTitle?: boolean; header: TableHeader; id: string; - idToHighlightColor?: (id: TableRowProps["id"]) => DesignKitConfigType.Color | null; + idToHighlightColor?: (id: TableRowProps["id"]) => DesignContext.Color | null; noKeys?: boolean; onSelect?: (selectedRow: { id: TableRowProps["id"]; checked: boolean }) => void; selectable: boolean; diff --git a/src/widgets/settings-editor/config.ts b/src/widgets/settings-editor/context.ts similarity index 96% rename from src/widgets/settings-editor/config.ts rename to src/widgets/settings-editor/context.ts index 2e9cb77f..20ab9266 100644 --- a/src/widgets/settings-editor/config.ts +++ b/src/widgets/settings-editor/context.ts @@ -14,7 +14,7 @@ export namespace SettingsEditor { export type ProposalDescription = Parameters[0]; } -export class Config { +export class ModuleContext { public static readonly DiffKey = { ...SchedulingSettingsChange.DiffKey, ...TokenWhitelistChange.DiffKey, diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts index a0c72792..ce6929c3 100644 --- a/src/widgets/settings-editor/index.ts +++ b/src/widgets/settings-editor/index.ts @@ -1,7 +1,7 @@ -import { Config, SettingsEditor as SettingsEditorWidget } from "./config"; +import { ModuleContext, SettingsEditor as SettingsEditorWidget } from "./context"; import { SettingsEditorUI } from "./ui/settings-editor"; -export class SettingsEditor extends Config { +export class SettingsEditor extends ModuleContext { static UI = SettingsEditorUI; } diff --git a/src/widgets/settings-editor/ui/se-proposal-form.tsx b/src/widgets/settings-editor/ui/se-proposal-form.tsx index f4e11d86..e5a91a1e 100644 --- a/src/widgets/settings-editor/ui/se-proposal-form.tsx +++ b/src/widgets/settings-editor/ui/se-proposal-form.tsx @@ -4,7 +4,7 @@ import { FormEventHandler, HTMLProps } from "react"; import { ArgsString } from "../../../shared/lib/args-old"; import { toNEAR } from "../../../shared/lib/converter"; import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; -import { Config, SettingsEditor } from "../config"; +import { ModuleContext, SettingsEditor } from "../context"; import "./se-proposal-form.scss"; @@ -44,7 +44,7 @@ export const SEProposalForm = ({

    - {Object.values(Config.DiffKey).map( + {Object.values(ModuleContext.DiffKey).map( (DiffKey) => changesDiff[DiffKey].length > 0 && (

    - {Config.DiffMetadata[DiffKey].description + ":"} + {ModuleContext.DiffMetadata[DiffKey].description + ":"}

      @@ -66,11 +66,11 @@ export const SEProposalForm = ({ `${classNameRoot}-proposalForm-summary-entry-data-chip` + "--" + - Config.DiffMetadata[DiffKey].color + ModuleContext.DiffMetadata[DiffKey].color )} key={data as string} > - {!Number.isNaN(data) && DiffKey === Config.DiffKey.jobBond + {!Number.isNaN(data) && DiffKey === ModuleContext.DiffKey.jobBond ? `${toNEAR(data as string)} ${NearIcon.NATIVE_TOKEN_CHARACTER}` : (data as string)} diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index d107b24e..05f8336f 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -6,7 +6,7 @@ import { SchedulingSettingsChange, TokenWhitelistChange } from "../../../feature import { ArgsString } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { Config, SettingsEditor } from "../config"; +import { ModuleContext, SettingsEditor } from "../context"; import { SEProposalForm } from "./se-proposal-form"; import "./settings-editor.scss"; @@ -22,10 +22,10 @@ export const SettingsEditorUI = ({ className, contracts }: SettingsEditor.Inputs const [editMode, editModeSwitch] = useState(false); const changesDiffInitialState: SettingsEditor.Diff = { - [Config.DiffKey.removeTokens]: [], - [Config.DiffKey.addTokens]: [], - [Config.DiffKey.jobBond]: "", - [Config.DiffKey.croncatManager]: "", + [ModuleContext.DiffKey.removeTokens]: [], + [ModuleContext.DiffKey.addTokens]: [], + [ModuleContext.DiffKey.jobBond]: "", + [ModuleContext.DiffKey.croncatManager]: "", }; const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), diff --git a/src/widgets/token-balances/config.ts b/src/widgets/token-balances/config.ts deleted file mode 100644 index e32a7135..00000000 --- a/src/widgets/token-balances/config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { NEAREntity, FTEntity } from "../../entities"; - -export namespace TokenBalances { - export interface Inputs extends NEAREntity.Inputs, FTEntity.Inputs { - className?: string; - } -} diff --git a/src/widgets/token-balances/context.ts b/src/widgets/token-balances/context.ts new file mode 100644 index 00000000..7647ce10 --- /dev/null +++ b/src/widgets/token-balances/context.ts @@ -0,0 +1,7 @@ +import { NEARTokenEntity, FTEntity } from "../../entities"; + +export namespace TokenBalances { + export interface Inputs extends NEARTokenEntity.Inputs, FTEntity.Inputs { + className?: string; + } +} diff --git a/src/widgets/token-balances/index.ts b/src/widgets/token-balances/index.ts index f8b86236..417d97cc 100644 --- a/src/widgets/token-balances/index.ts +++ b/src/widgets/token-balances/index.ts @@ -1,5 +1,5 @@ import { TokenBalancesUI } from "./ui/token-balances"; -import { TokenBalances as TokenBalancesWidget } from "./config"; +import { TokenBalances as TokenBalancesWidget } from "./context"; class TokenBalances { static UI = TokenBalancesUI; diff --git a/src/widgets/token-balances/ui/token-balances.tsx b/src/widgets/token-balances/ui/token-balances.tsx index 104f448e..4021fcb1 100644 --- a/src/widgets/token-balances/ui/token-balances.tsx +++ b/src/widgets/token-balances/ui/token-balances.tsx @@ -1,15 +1,15 @@ import clsx from "clsx"; import { Tile, Scrollable, Table } from "../../../shared/ui/design"; -import { FT, NEAR } from "../../../entities"; -import { type TokenBalances } from "../config"; +import { FT, NEARToken } from "../../../entities"; +import { type TokenBalances } from "../context"; import "./token-balances.scss"; const _TokenBalances = "TokenBalances"; export const TokenBalancesUI = ({ className, contracts }: TokenBalances.Inputs) => { - const nearTokenBalances = NEAR.balancesRender({ contracts }), + const nearTokenBalances = NEARToken.balancesRender({ contracts }), fungibleTokenBalances = FT.balances({ contracts }); return ( From da50825aac76849501e48abed0b38f8b5d32fa01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 26 Nov 2022 04:15:35 +0400 Subject: [PATCH 425/537] chore: Move configs to `shared/config` --- src/{ => shared/config}/keywords.ts | 0 src/{near-config.ts => shared/config/near-protocol.ts} | 0 src/shared/lib/wallet.ts | 2 +- src/widgets/builder/builder.jsx | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename src/{ => shared/config}/keywords.ts (100%) rename src/{near-config.ts => shared/config/near-protocol.ts} (100%) diff --git a/src/keywords.ts b/src/shared/config/keywords.ts similarity index 100% rename from src/keywords.ts rename to src/shared/config/keywords.ts diff --git a/src/near-config.ts b/src/shared/config/near-protocol.ts similarity index 100% rename from src/near-config.ts rename to src/shared/config/near-protocol.ts diff --git a/src/shared/lib/wallet.ts b/src/shared/lib/wallet.ts index 18774b0d..43fbc87c 100644 --- a/src/shared/lib/wallet.ts +++ b/src/shared/lib/wallet.ts @@ -1,6 +1,6 @@ // TODO: de-deprecate near-wallet on wallet selector. Use patch import { providers } from "near-api-js"; -import { getConfig } from "../../near-config"; +import { getConfig } from "../config/near-protocol"; import { Base64 } from "js-base64"; import type { AccountView, ViewStateResult } from "near-api-js/lib/providers/provider"; diff --git a/src/widgets/builder/builder.jsx b/src/widgets/builder/builder.jsx index 2927f7e8..bcd78457 100644 --- a/src/widgets/builder/builder.jsx +++ b/src/widgets/builder/builder.jsx @@ -3,7 +3,7 @@ import { Component } from "react"; import { Droppable } from "react-beautiful-dnd"; import { TextField } from "../../shared/ui/form"; import { Column } from "../column/column.jsx"; -import { keywords } from "../../keywords"; +import { keywords } from "../../shared/config/keywords"; import { Formik, Form } from "formik"; import "./builder.scss"; From 737ab078420ac1905622f1ff1f035cc97bd2e533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 26 Nov 2022 04:28:10 +0400 Subject: [PATCH 426/537] wip: Update icon label styles --- src/shared/ui/design/icon-label/icon-label.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/ui/design/icon-label/icon-label.scss b/src/shared/ui/design/icon-label/icon-label.scss index 0be68814..281c69b6 100644 --- a/src/shared/ui/design/icon-label/icon-label.scss +++ b/src/shared/ui/design/icon-label/icon-label.scss @@ -5,7 +5,7 @@ display: flex; flex-direction: row; align-items: center; - gap: 0.3 * size.$gap; + gap: 0.5 * size.$gap; width: fit-content; line-height: 0; From 684d1ebc298188a4954838f8a0bf83ccadd929c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 26 Nov 2022 04:37:20 +0400 Subject: [PATCH 427/537] wip: Apply post code review remarks --- src/entities/fungible-token/index.ts | 4 ++-- src/entities/index.ts | 8 ++++---- src/entities/job/context.ts | 16 ++++++++-------- src/entities/job/index.ts | 4 ++-- src/entities/job/lib/job-normalized.ts | 6 +++--- src/entities/job/model/job.ts | 8 ++++---- src/entities/job/ui/job.tsx | 6 +++--- src/entities/job/ui/jobs-table.tsx | 4 ++-- src/entities/multicall-instance/index.ts | 4 ++-- src/entities/near/context.ts | 4 ++-- src/entities/near/index.ts | 4 ++-- src/entities/near/model/near-balances.ts | 6 +++--- src/entities/near/ui/near-balances.tsx | 4 ++-- src/features/index.ts | 4 ++-- .../scheduling/settings-change/context.ts | 10 +++++----- src/features/scheduling/settings-change/index.ts | 4 ++-- .../ui/scheduling-settings-form.tsx | 4 ++-- src/features/tokens/whitelist-change/context.ts | 6 +++--- src/features/tokens/whitelist-change/index.ts | 4 ++-- .../ui/tokens-whitelist-form.tsx | 4 ++-- src/pages/dao/funds/funds.tsx | 4 ++-- src/pages/dao/settings/settings.tsx | 4 ++-- src/widgets/index.ts | 4 ++-- src/widgets/settings-editor/context.ts | 6 +++--- src/widgets/settings-editor/index.ts | 4 ++-- .../settings-editor/ui/se-proposal-form.tsx | 4 ++-- src/widgets/token-balances/context.ts | 4 ++-- src/widgets/token-balances/index.ts | 4 ++-- 28 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 44f9ca82..9243357e 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,8 +1,8 @@ -import { ModuleContext, FT as FTEntity } from "./context"; +import { ModuleContext, FT as FTModule } from "./context"; import { ftBalances } from "./ui/ft-balances"; export class FT extends ModuleContext { static balances = ftBalances; } -export { type FTEntity }; +export { type FTModule }; diff --git a/src/entities/index.ts b/src/entities/index.ts index 10471b4e..e2a61457 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ export { Task } from "./task"; -export { Job, type JobEntity } from "./job"; -export { FT, type FTEntity } from "./fungible-token"; -export { MI, type MIEntity } from "./multicall-instance"; -export { NEARToken, type NEARTokenEntity } from "./near"; +export { Job, type JobModule } from "./job"; +export { FT, type FTModule } from "./fungible-token"; +export { MI, type MIModule } from "./multicall-instance"; +export { NEARToken, type NEARTokenModule } from "./near"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/context.ts b/src/entities/job/context.ts index 0c341597..297ae0e0 100644 --- a/src/entities/job/context.ts +++ b/src/entities/job/context.ts @@ -1,6 +1,6 @@ import { type JobData, type Multicall } from "../../shared/lib/contracts/multicall"; -namespace JobEntity { +namespace JobModule { export interface Inputs { className?: string; contracts: { multicall: Multicall }; @@ -22,15 +22,15 @@ namespace JobEntity { } class JobModuleContext { - static readonly Status = JobEntity.Status; + static readonly Status = JobModule.Status; static StatusIcons = { - [JobEntity.Status.Inactive]: "🟡", - [JobEntity.Status.Expired]: "🔴", - [JobEntity.Status.Active]: "🟢", - [JobEntity.Status.Running]: "🟣", - [JobEntity.Status.Unknown]: "❔", + [JobModule.Status.Inactive]: "🟡", + [JobModule.Status.Expired]: "🔴", + [JobModule.Status.Active]: "🟢", + [JobModule.Status.Running]: "🟣", + [JobModule.Status.Unknown]: "❔", }; } -export { JobModuleContext, type JobEntity }; +export { JobModuleContext, type JobModule }; diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index b0d810fc..de7744e3 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,8 +1,8 @@ -import { JobModuleContext, type JobEntity } from "./context"; +import { JobModuleContext, type JobModule } from "./context"; import { JobsTable } from "./ui/jobs-table"; class Job extends JobModuleContext { static EntriesTable = JobsTable; } -export { Job, type JobEntity }; +export { Job, type JobModule }; diff --git a/src/entities/job/lib/job-normalized.ts b/src/entities/job/lib/job-normalized.ts index 1d13763b..cc1022a8 100644 --- a/src/entities/job/lib/job-normalized.ts +++ b/src/entities/job/lib/job-normalized.ts @@ -3,7 +3,7 @@ import { Base64 } from "js-base64"; import { JobData } from "../../../shared/lib/contracts/multicall"; import { Big } from "../../../shared/lib/converter"; -import { JobModuleContext, type JobEntity } from "../context"; +import { JobModuleContext, type JobModule } from "../context"; /** * Job status is: @@ -12,7 +12,7 @@ import { JobModuleContext, type JobEntity } from "../context"; * - Expired: job not active, and execution moment is in the past. * - Inactive: job not active, but execution moment in the future. */ -const jobToStatus = ({ job }: JobData): JobEntity.Status => { +const jobToStatus = ({ job }: JobData): JobModule.Status => { if (job.is_active) { if (job.run_count > -1) return JobModuleContext.Status.Running; else return JobModuleContext.Status.Active; @@ -63,7 +63,7 @@ const jobToJobWithMulticallsDataDecoded = ({ id, job }: JobData): JobData => ({ * * @returns Extended job data structure. */ -const jobToJobWithStatus = (job: JobData): JobEntity.DataWithStatus => ({ +const jobToJobWithStatus = (job: JobData): JobModule.DataWithStatus => ({ ...job, job: { ...job.job, status: JobModuleContext.Status[jobToStatus(job)] }, }); diff --git a/src/entities/job/model/job.ts b/src/entities/job/model/job.ts index 6224ce9f..3bffc7ea 100644 --- a/src/entities/job/model/job.ts +++ b/src/entities/job/model/job.ts @@ -1,18 +1,18 @@ import { useEffect, useState } from "react"; -import { type JobEntity } from "../context"; +import { type JobModule } from "../context"; import { JobNormalized } from "../lib/job-normalized"; type JobAllEntries = { /** Jobs indexed by ID for easy access to each particular job */ - data: Record | null; + data: Record | null; error?: Error | null; loading: boolean; }; export class JobModel { static allEntriesFetchFx = async ( - { multicall }: JobEntity.Inputs["contracts"], + { multicall }: JobModule.Inputs["contracts"], callback: (result: JobAllEntries) => void ) => callback( @@ -37,7 +37,7 @@ export class JobModel { })) ); - static useAllEntries = (contracts: JobEntity.Inputs["contracts"]) => { + static useAllEntries = (contracts: JobModule.Inputs["contracts"]) => { const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); useEffect(() => void JobModel.allEntriesFetchFx(contracts, stateUpdate), [contracts, stateUpdate]); diff --git a/src/entities/job/ui/job.tsx b/src/entities/job/ui/job.tsx index ec193f79..77172d29 100644 --- a/src/entities/job/ui/job.tsx +++ b/src/entities/job/ui/job.tsx @@ -3,14 +3,14 @@ import { NavLink } from "react-router-dom"; import { Big, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/design"; -import { JobModuleContext, type JobEntity } from "../context"; +import { JobModuleContext, type JobModule } from "../context"; import "./job.scss"; -interface JobEntryProps extends JobEntity.DataWithStatus {} +interface JobEntryProps extends JobModule.DataWithStatus {} const _Job = "Job"; -const JobDisplayStatus = ({ job }: Pick) => { +const JobDisplayStatus = ({ job }: Pick) => { const statusTextByStatus = { ...JobModuleContext.Status, [JobModuleContext.Status.Running]: `${JobModuleContext.Status.Running}: ${job.run_count + 1}/${ diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index c339d0ec..23621a12 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -2,12 +2,12 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { JobModel } from "../model/job"; -import { type JobEntity } from "../context"; +import { type JobModule } from "../context"; import { jobTableRowRender } from "./job"; import "./jobs-table.scss"; -interface JobsTableProps extends JobEntity.Inputs {} +interface JobsTableProps extends JobModule.Inputs {} const _JobsTable = "JobsTable"; diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 2281d0cc..dd9cd7b9 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,4 +1,4 @@ -import { MI as MIEntity, MIModuleContext } from "./context"; +import { MI as MIModule, MIModuleContext } from "./context"; import { MIAdminsTable } from "./ui/mi-admins"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; @@ -10,4 +10,4 @@ class MI extends MIModuleContext { static TokenWhitelistTable = MITokenWhitelistTable; } -export { MI, type MIEntity }; +export { MI, type MIModule }; diff --git a/src/entities/near/context.ts b/src/entities/near/context.ts index 88355c6e..931c6954 100644 --- a/src/entities/near/context.ts +++ b/src/entities/near/context.ts @@ -1,7 +1,7 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -namespace NEARTokenEntity { +namespace NEARTokenModule { export interface Inputs { contracts: { dao: SputnikDAO; @@ -14,4 +14,4 @@ class NEARTokenModuleContext { static FRACTIONAL_PART_LENGTH = 5; } -export { NEARTokenModuleContext, type NEARTokenEntity }; +export { NEARTokenModuleContext, type NEARTokenModule }; diff --git a/src/entities/near/index.ts b/src/entities/near/index.ts index 61a6bfce..875d1580 100644 --- a/src/entities/near/index.ts +++ b/src/entities/near/index.ts @@ -1,8 +1,8 @@ -import { NEARTokenModuleContext, type NEARTokenEntity } from "./context"; +import { NEARTokenModuleContext, type NEARTokenModule } from "./context"; import { nearTokenBalancesRender } from "./ui/near-balances"; class NEARToken extends NEARTokenModuleContext { static balancesRender = nearTokenBalancesRender; } -export { NEARToken, type NEARTokenEntity }; +export { NEARToken, type NEARTokenModule }; diff --git a/src/entities/near/model/near-balances.ts b/src/entities/near/model/near-balances.ts index ab3ea7ae..059d67aa 100644 --- a/src/entities/near/model/near-balances.ts +++ b/src/entities/near/model/near-balances.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { Big, formatTokenAmount } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; -import { NEARTokenModuleContext, type NEARTokenEntity } from "../context"; +import { NEARTokenModuleContext, type NEARTokenModule } from "../context"; type NEARTokenDataFxResponse = { data: { dao: string; multicall: string; total: string } | null; @@ -11,7 +11,7 @@ type NEARTokenDataFxResponse = { }; const nearTokenDataFx = async ( - { dao, multicall }: NEARTokenEntity.Inputs["contracts"], + { dao, multicall }: NEARTokenModule.Inputs["contracts"], callback: (result: NEARTokenDataFxResponse) => void ) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ @@ -38,7 +38,7 @@ const nearTokenDataFx = async ( }); }; -const useNEARTokenData = (contracts: NEARTokenEntity.Inputs["contracts"]) => { +const useNEARTokenData = (contracts: NEARTokenModule.Inputs["contracts"]) => { const [state, stateUpdate] = useState({ data: null, loading: true }); useEffect(() => void nearTokenDataFx(contracts, stateUpdate), [contracts, stateUpdate]); diff --git a/src/entities/near/ui/near-balances.tsx b/src/entities/near/ui/near-balances.tsx index 04b091c0..253834b2 100644 --- a/src/entities/near/ui/near-balances.tsx +++ b/src/entities/near/ui/near-balances.tsx @@ -1,9 +1,9 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { NEARTokenBalancesModel } from "../model/near-balances"; -import { type NEARTokenEntity } from "../context"; +import { type NEARTokenModule } from "../context"; -interface NEARTokenBalancesRenderProps extends NEARTokenEntity.Inputs {} +interface NEARTokenBalancesRenderProps extends NEARTokenModule.Inputs {} export const nearTokenBalancesRender = ({ contracts }: NEARTokenBalancesRenderProps) => { const { data } = NEARTokenBalancesModel.useTokenFrom(contracts); diff --git a/src/features/index.ts b/src/features/index.ts index a1974bbb..15e1a763 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,3 +1,3 @@ export { ExternalLogin } from "./external-login"; -export { SchedulingSettingsChange, type SSChangeFeature } from "./scheduling/settings-change"; -export { TokenWhitelistChange, type TWChangeFeature } from "./tokens/whitelist-change"; +export { SchedulingSettingsChange, type SchedulingSettingsChangeModule } from "./scheduling/settings-change"; +export { TokenWhitelistChange, type TokenWhitelistChangeModule } from "./tokens/whitelist-change"; diff --git a/src/features/scheduling/settings-change/context.ts b/src/features/scheduling/settings-change/context.ts index c7b1d2d2..27bd027e 100644 --- a/src/features/scheduling/settings-change/context.ts +++ b/src/features/scheduling/settings-change/context.ts @@ -1,15 +1,15 @@ import { HTMLProps } from "react"; -import { MI, MIEntity } from "../../../entities"; +import { MI, MIModule } from "../../../entities"; import { MulticallSettingsDiff, Multicall } from "../../../shared/lib/contracts/multicall"; import { DesignContext } from "../../../shared/ui/design"; export namespace SchedulingSettingsChange { - export type DiffKey = MIEntity.ParamKey; + export type DiffKey = MIModule.ParamKey; - export type FormState = Pick; + export type FormState = Pick; - export interface Inputs extends Omit, "onChange">, Pick { + export interface Inputs extends Omit, "onChange">, Pick { multicallInstance: Multicall; onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; @@ -19,7 +19,7 @@ export namespace SchedulingSettingsChange { export class ModuleContext { public static readonly DiffKey = MI.ParamKey; - public static readonly DiffMetadata = { + public static readonly DiffMeta = { [ModuleContext.DiffKey.croncatManager]: { color: "blue" as DesignContext.Color, description: "Croncat manager", diff --git a/src/features/scheduling/settings-change/index.ts b/src/features/scheduling/settings-change/index.ts index 05651071..9698ac05 100644 --- a/src/features/scheduling/settings-change/index.ts +++ b/src/features/scheduling/settings-change/index.ts @@ -1,8 +1,8 @@ -import { ModuleContext, type SchedulingSettingsChange as SSChangeFeature } from "./context"; +import { ModuleContext, type SchedulingSettingsChange as SchedulingSettingsChangeModule } from "./context"; import { SchedulingSettingsForm } from "./ui/scheduling-settings-form"; export class SchedulingSettingsChange extends ModuleContext { static Form = SchedulingSettingsForm; } -export { type SSChangeFeature }; +export { type SchedulingSettingsChangeModule }; diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx index 492c6a73..77e2ffdd 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx @@ -120,7 +120,7 @@ export const SchedulingSettingsForm = ({ id: ModuleContext.DiffKey.croncatManager, content: [ - ModuleContext.DiffMetadata[ModuleContext.DiffKey.croncatManager].description, + ModuleContext.DiffMeta[ModuleContext.DiffKey.croncatManager].description, editModeEnabled ? ( , "onChange">, MIEntity.Inputs { + export interface Inputs extends Omit, "onChange">, MIModule.Inputs { onEdit: (payload: Pick) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } @@ -22,7 +22,7 @@ export namespace TokenWhitelistChange { export class ModuleContext { public static readonly DiffKey = MulticallTokenWhitelistDiffKey; - public static readonly DiffMetadata = { + public static readonly DiffMeta = { [ModuleContext.DiffKey.addTokens]: { color: "green" as DesignContext.Color, description: "Tokens to add to whitelist", diff --git a/src/features/tokens/whitelist-change/index.ts b/src/features/tokens/whitelist-change/index.ts index e0a32080..caa85cad 100644 --- a/src/features/tokens/whitelist-change/index.ts +++ b/src/features/tokens/whitelist-change/index.ts @@ -1,8 +1,8 @@ -import { ModuleContext, type TokenWhitelistChange as TWChangeFeature } from "./context"; +import { ModuleContext, type TokenWhitelistChange as TokenWhitelistChangeModule } from "./context"; import { TokenWhitelistForm } from "./ui/tokens-whitelist-form"; export class TokenWhitelistChange extends ModuleContext { static Form = TokenWhitelistForm; } -export { type TWChangeFeature }; +export { type TokenWhitelistChangeModule }; diff --git a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx index 4522653b..3e0d1d4c 100644 --- a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx @@ -69,8 +69,8 @@ export const TokenWhitelistForm = ({ - (addTokens.has(id) && ModuleContext.DiffMetadata.addTokens.color) || - (removeTokens.has(id) && ModuleContext.DiffMetadata.removeTokens.color) || + (addTokens.has(id) && ModuleContext.DiffMeta.addTokens.color) || + (removeTokens.has(id) && ModuleContext.DiffMeta.removeTokens.color) || null, slots: { diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index 95d0aab6..c562d02e 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -1,11 +1,11 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { TokenBalances, type TokenBalancesWidget } from "../../../widgets"; +import { TokenBalances, type TokenBalancesModule } from "../../../widgets"; import "./funds.scss"; -interface DaoFundsTabUIProps extends HTMLProps, TokenBalancesWidget.Inputs {} +interface DaoFundsTabUIProps extends HTMLProps, TokenBalancesModule.Inputs {} const _DaoFundsTab = "DaoFundsTab"; diff --git a/src/pages/dao/settings/settings.tsx b/src/pages/dao/settings/settings.tsx index 3e7316a7..a6db32be 100644 --- a/src/pages/dao/settings/settings.tsx +++ b/src/pages/dao/settings/settings.tsx @@ -1,11 +1,11 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { SettingsEditor, SettingsEditorWidget } from "../../../widgets"; +import { SettingsEditor, SettingsEditorModule } from "../../../widgets"; import "./settings.scss"; -interface DaoSettingsTabUIProps extends HTMLProps, SettingsEditorWidget.Inputs {} +interface DaoSettingsTabUIProps extends HTMLProps, SettingsEditorModule.Inputs {} const _DaoSettingsTab = "DaoSettingsTab"; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 76205905..31e81016 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -4,6 +4,6 @@ export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export"; -export { SettingsEditor, type SettingsEditorWidget } from "./settings-editor"; +export { SettingsEditor, type SettingsEditorModule } from "./settings-editor"; export { Sidebar } from "./sidebar/sidebar.jsx"; -export { TokenBalances, type TokenBalancesWidget } from "./token-balances"; +export { TokenBalances, type TokenBalancesModule } from "./token-balances"; diff --git a/src/widgets/settings-editor/context.ts b/src/widgets/settings-editor/context.ts index 20ab9266..e5f26019 100644 --- a/src/widgets/settings-editor/context.ts +++ b/src/widgets/settings-editor/context.ts @@ -20,8 +20,8 @@ export class ModuleContext { ...TokenWhitelistChange.DiffKey, }; - public static readonly DiffMetadata = { - ...SchedulingSettingsChange.DiffMetadata, - ...TokenWhitelistChange.DiffMetadata, + public static readonly DiffMeta = { + ...SchedulingSettingsChange.DiffMeta, + ...TokenWhitelistChange.DiffMeta, }; } diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts index ce6929c3..26b320c9 100644 --- a/src/widgets/settings-editor/index.ts +++ b/src/widgets/settings-editor/index.ts @@ -1,8 +1,8 @@ -import { ModuleContext, SettingsEditor as SettingsEditorWidget } from "./context"; +import { ModuleContext, SettingsEditor as SettingsEditorModule } from "./context"; import { SettingsEditorUI } from "./ui/settings-editor"; export class SettingsEditor extends ModuleContext { static UI = SettingsEditorUI; } -export { type SettingsEditorWidget }; +export { type SettingsEditorModule }; diff --git a/src/widgets/settings-editor/ui/se-proposal-form.tsx b/src/widgets/settings-editor/ui/se-proposal-form.tsx index e5a91a1e..70c40487 100644 --- a/src/widgets/settings-editor/ui/se-proposal-form.tsx +++ b/src/widgets/settings-editor/ui/se-proposal-form.tsx @@ -52,7 +52,7 @@ export const SEProposalForm = ({ key={DiffKey} >

      - {ModuleContext.DiffMetadata[DiffKey].description + ":"} + {ModuleContext.DiffMeta[DiffKey].description + ":"}

        @@ -66,7 +66,7 @@ export const SEProposalForm = ({ `${classNameRoot}-proposalForm-summary-entry-data-chip` + "--" + - ModuleContext.DiffMetadata[DiffKey].color + ModuleContext.DiffMeta[DiffKey].color )} key={data as string} > diff --git a/src/widgets/token-balances/context.ts b/src/widgets/token-balances/context.ts index 7647ce10..b1f5fcb8 100644 --- a/src/widgets/token-balances/context.ts +++ b/src/widgets/token-balances/context.ts @@ -1,7 +1,7 @@ -import { NEARTokenEntity, FTEntity } from "../../entities"; +import { NEARTokenModule, FTModule } from "../../entities"; export namespace TokenBalances { - export interface Inputs extends NEARTokenEntity.Inputs, FTEntity.Inputs { + export interface Inputs extends NEARTokenModule.Inputs, FTModule.Inputs { className?: string; } } diff --git a/src/widgets/token-balances/index.ts b/src/widgets/token-balances/index.ts index 417d97cc..eb6794bc 100644 --- a/src/widgets/token-balances/index.ts +++ b/src/widgets/token-balances/index.ts @@ -1,8 +1,8 @@ import { TokenBalancesUI } from "./ui/token-balances"; -import { TokenBalances as TokenBalancesWidget } from "./context"; +import { TokenBalances as TokenBalancesModule } from "./context"; class TokenBalances { static UI = TokenBalancesUI; } -export { TokenBalances, type TokenBalancesWidget }; +export { TokenBalances, type TokenBalancesModule }; From 0436ed870fc6cda575ea808087a789c295c84ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 26 Nov 2022 05:12:49 +0400 Subject: [PATCH 428/537] wip: Apply post code review remarks --- src/entities/fungible-token/context.ts | 2 +- src/entities/fungible-token/index.ts | 4 ++-- src/entities/fungible-token/model/ft-info.ts | 8 ++++---- .../fungible-token/ui/ft-balances.tsx | 6 +++--- src/entities/index.ts | 2 +- src/entities/job/context.ts | 20 +++++++++---------- src/entities/job/index.ts | 8 ++++---- src/entities/job/lib/job-normalized.ts | 20 +++++++++---------- src/entities/job/model/job.ts | 10 +++++----- src/entities/job/ui/job.tsx | 14 ++++++------- src/entities/job/ui/jobs-table.tsx | 12 +++++------ src/entities/multicall-instance/context.ts | 2 +- src/entities/multicall-instance/index.ts | 8 ++++---- .../multicall-instance/model/mi-admins.ts | 2 +- .../multicall-instance/model/mi-tokens.ts | 2 +- .../multicall-instance/ui/mi-admin.tsx | 2 +- .../multicall-instance/ui/mi-admins.tsx | 2 +- .../ui/mi-token-whitelist.tsx | 4 ++-- src/entities/{near => near-token}/context.ts | 8 +++----- src/entities/near-token/index.ts | 8 ++++++++ .../model/near-balances.ts | 15 +++++++------- .../ui/nt-balances.tsx} | 8 ++++---- src/entities/near/index.ts | 8 -------- src/pages/dao/dao.tsx | 6 +++--- src/pages/dao/funds/funds.tsx | 4 ++-- src/pages/dao/jobs/jobs.tsx | 4 ++-- src/pages/dao/settings/settings.tsx | 4 ++-- src/widgets/settings-editor/context.ts | 2 +- .../settings-editor/ui/settings-editor.tsx | 18 ++++++++--------- .../token-balances/ui/token-balances.tsx | 6 +++--- 30 files changed, 105 insertions(+), 114 deletions(-) rename src/entities/{near => near-token}/context.ts (67%) create mode 100644 src/entities/near-token/index.ts rename src/entities/{near => near-token}/model/near-balances.ts (68%) rename src/entities/{near/ui/near-balances.tsx => near-token/ui/nt-balances.tsx} (63%) delete mode 100644 src/entities/near/index.ts diff --git a/src/entities/fungible-token/context.ts b/src/entities/fungible-token/context.ts index d626077b..362fe2c3 100644 --- a/src/entities/fungible-token/context.ts +++ b/src/entities/fungible-token/context.ts @@ -3,7 +3,7 @@ import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; export namespace FT { export interface Inputs { - contracts: { + adapters: { dao: SputnikDAO; multicall: Multicall; }; diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 9243357e..1f07f2d5 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,8 +1,8 @@ import { ModuleContext, FT as FTModule } from "./context"; import { ftBalances } from "./ui/ft-balances"; +export { type FTModule }; + export class FT extends ModuleContext { static balances = ftBalances; } - -export { type FTModule }; diff --git a/src/entities/fungible-token/model/ft-info.ts b/src/entities/fungible-token/model/ft-info.ts index da3c4526..34548edf 100644 --- a/src/entities/fungible-token/model/ft-info.ts +++ b/src/entities/fungible-token/model/ft-info.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { Big } from "../../../shared/lib/converter"; import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; -import { type FT } from "../context"; +import { FT } from "../context"; type FTInfo = { data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; @@ -11,7 +11,7 @@ type FTInfo = { export class FTInfoModel { private static readonly nonZeroBalancesFetchFx = async ( - { dao, multicall }: FT.Inputs["contracts"], + { dao, multicall }: FT.Inputs["adapters"], callback: (result: FTInfo) => void ) => { /* Get LikelyTokens list on DAO and its Multicall instance */ @@ -54,10 +54,10 @@ export class FTInfoModel { }); }; - public static readonly useNonZeroBalances = (contracts: FT.Inputs["contracts"]) => { + public static readonly useNonZeroBalances = (adapters: FT.Inputs["adapters"]) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void FTInfoModel.nonZeroBalancesFetchFx(contracts, stateUpdate), [contracts, stateUpdate]); + useEffect(() => void FTInfoModel.nonZeroBalancesFetchFx(adapters, stateUpdate), [adapters, stateUpdate]); return state; }; diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index 0f7ead41..b112d529 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -1,12 +1,12 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { FTFormat } from "../lib/ft-format"; import { FTInfoModel } from "../model/ft-info"; -import { type FT } from "../context"; +import { FT } from "../context"; interface FTBalancesProps extends FT.Inputs {} -export const ftBalances = ({ contracts }: FTBalancesProps) => { - const { data } = FTInfoModel.useNonZeroBalances(contracts); +export const ftBalances = ({ adapters }: FTBalancesProps) => { + const { data } = FTInfoModel.useNonZeroBalances(adapters); return !data ? null diff --git a/src/entities/index.ts b/src/entities/index.ts index e2a61457..abb1d70e 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -2,5 +2,5 @@ export { Task } from "./task"; export { Job, type JobModule } from "./job"; export { FT, type FTModule } from "./fungible-token"; export { MI, type MIModule } from "./multicall-instance"; -export { NEARToken, type NEARTokenModule } from "./near"; +export { NEARToken, type NEARTokenModule } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/context.ts b/src/entities/job/context.ts index 297ae0e0..be9f4883 100644 --- a/src/entities/job/context.ts +++ b/src/entities/job/context.ts @@ -1,9 +1,9 @@ import { type JobData, type Multicall } from "../../shared/lib/contracts/multicall"; -namespace JobModule { +export namespace Job { export interface Inputs { className?: string; - contracts: { multicall: Multicall }; + adapters: { multicall: Multicall }; } export type Data = JobData; @@ -21,16 +21,14 @@ namespace JobModule { }; } -class JobModuleContext { - static readonly Status = JobModule.Status; +export class ModuleContext { + static readonly Status = Job.Status; static StatusIcons = { - [JobModule.Status.Inactive]: "🟡", - [JobModule.Status.Expired]: "🔴", - [JobModule.Status.Active]: "🟢", - [JobModule.Status.Running]: "🟣", - [JobModule.Status.Unknown]: "❔", + [Job.Status.Inactive]: "🟡", + [Job.Status.Expired]: "🔴", + [Job.Status.Active]: "🟢", + [Job.Status.Running]: "🟣", + [Job.Status.Unknown]: "❔", }; } - -export { JobModuleContext, type JobModule }; diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index de7744e3..33ab72a9 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,8 +1,8 @@ -import { JobModuleContext, type JobModule } from "./context"; +import { ModuleContext, Job as JobModule } from "./context"; import { JobsTable } from "./ui/jobs-table"; -class Job extends JobModuleContext { +export { type JobModule }; + +export class Job extends ModuleContext { static EntriesTable = JobsTable; } - -export { Job, type JobModule }; diff --git a/src/entities/job/lib/job-normalized.ts b/src/entities/job/lib/job-normalized.ts index cc1022a8..9a82e810 100644 --- a/src/entities/job/lib/job-normalized.ts +++ b/src/entities/job/lib/job-normalized.ts @@ -1,9 +1,7 @@ import { Base64 } from "js-base64"; -import { JobData } from "../../../shared/lib/contracts/multicall"; import { Big } from "../../../shared/lib/converter"; - -import { JobModuleContext, type JobModule } from "../context"; +import { ModuleContext, Job } from "../context"; /** * Job status is: @@ -12,16 +10,16 @@ import { JobModuleContext, type JobModule } from "../context"; * - Expired: job not active, and execution moment is in the past. * - Inactive: job not active, but execution moment in the future. */ -const jobToStatus = ({ job }: JobData): JobModule.Status => { +const jobToStatus = ({ job }: Job.Data): Job.Status => { if (job.is_active) { - if (job.run_count > -1) return JobModuleContext.Status.Running; - else return JobModuleContext.Status.Active; + if (job.run_count > -1) return ModuleContext.Status.Running; + else return ModuleContext.Status.Active; } else { // Date.now() returns timestamp in milliseconds, we use nanoseconds const currentTime = Big(Date.now()).times("1000000"); const jobTime = job.start_at; - if (currentTime.gt(jobTime)) return JobModuleContext.Status.Expired; - else return JobModuleContext.Status.Inactive; + if (currentTime.gt(jobTime)) return ModuleContext.Status.Expired; + else return ModuleContext.Status.Inactive; } }; @@ -31,7 +29,7 @@ const jobToStatus = ({ job }: JobData): JobModule.Status => { * * @returns Updated job data structure. */ -const jobToJobWithMulticallsDataDecoded = ({ id, job }: JobData): JobData => ({ +const jobToJobWithMulticallsDataDecoded = ({ id, job }: Job.Data): Job.Data => ({ id, job: { @@ -63,9 +61,9 @@ const jobToJobWithMulticallsDataDecoded = ({ id, job }: JobData): JobData => ({ * * @returns Extended job data structure. */ -const jobToJobWithStatus = (job: JobData): JobModule.DataWithStatus => ({ +const jobToJobWithStatus = (job: Job.Data): Job.DataWithStatus => ({ ...job, - job: { ...job.job, status: JobModuleContext.Status[jobToStatus(job)] }, + job: { ...job.job, status: ModuleContext.Status[jobToStatus(job)] }, }); export const JobNormalized = { diff --git a/src/entities/job/model/job.ts b/src/entities/job/model/job.ts index 3bffc7ea..e943103d 100644 --- a/src/entities/job/model/job.ts +++ b/src/entities/job/model/job.ts @@ -1,18 +1,18 @@ import { useEffect, useState } from "react"; -import { type JobModule } from "../context"; +import { Job } from "../context"; import { JobNormalized } from "../lib/job-normalized"; type JobAllEntries = { /** Jobs indexed by ID for easy access to each particular job */ - data: Record | null; + data: Record | null; error?: Error | null; loading: boolean; }; export class JobModel { static allEntriesFetchFx = async ( - { multicall }: JobModule.Inputs["contracts"], + { multicall }: Job.Inputs["adapters"], callback: (result: JobAllEntries) => void ) => callback( @@ -37,10 +37,10 @@ export class JobModel { })) ); - static useAllEntries = (contracts: JobModule.Inputs["contracts"]) => { + static useAllEntries = (adapters: Job.Inputs["adapters"]) => { const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - useEffect(() => void JobModel.allEntriesFetchFx(contracts, stateUpdate), [contracts, stateUpdate]); + useEffect(() => void JobModel.allEntriesFetchFx(adapters, stateUpdate), [adapters, stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/job/ui/job.tsx b/src/entities/job/ui/job.tsx index 77172d29..68b6cdac 100644 --- a/src/entities/job/ui/job.tsx +++ b/src/entities/job/ui/job.tsx @@ -2,31 +2,29 @@ import { NavLink } from "react-router-dom"; import { Big, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/design"; +import { ModuleContext, Job } from "../context"; -import { JobModuleContext, type JobModule } from "../context"; import "./job.scss"; -interface JobEntryProps extends JobModule.DataWithStatus {} - const _Job = "Job"; -const JobDisplayStatus = ({ job }: Pick) => { +const JobDisplayStatus = ({ job }: Pick) => { const statusTextByStatus = { - ...JobModuleContext.Status, - [JobModuleContext.Status.Running]: `${JobModuleContext.Status.Running}: ${job.run_count + 1}/${ + ...ModuleContext.Status, + [ModuleContext.Status.Running]: `${ModuleContext.Status.Running}: ${job.run_count + 1}/${ job.multicalls.length }`, }; return ( ); }; -export const jobTableRowRender = ({ id, job }: JobEntryProps) => ({ +export const jobAsTableRow = ({ id, job }: Job.DataWithStatus) => ({ content: [ , id, diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 23621a12..2243edd4 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -2,17 +2,17 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { JobModel } from "../model/job"; -import { type JobModule } from "../context"; +import { type Job } from "../context"; -import { jobTableRowRender } from "./job"; +import { jobAsTableRow } from "./job"; import "./jobs-table.scss"; -interface JobsTableProps extends JobModule.Inputs {} +interface JobsTableProps extends Job.Inputs {} const _JobsTable = "JobsTable"; -export const JobsTable = ({ className, contracts }: JobsTableProps) => { - const { data, error, loading } = JobModel.useAllEntries(contracts); +export const JobsTable = ({ className, adapters }: JobsTableProps) => { + const { data, error, loading } = JobModel.useAllEntries(adapters); return ( { displayMode="compact" header={["Status", "ID", "Start at", "Croncat hash", "Creator", "Trigger gas", "Multicalls"]} rows={Object.values(data ?? {}) - .map(jobTableRowRender) + .map(jobAsTableRow) .reverse()} /> diff --git a/src/entities/multicall-instance/context.ts b/src/entities/multicall-instance/context.ts index 943f9cec..b183684c 100644 --- a/src/entities/multicall-instance/context.ts +++ b/src/entities/multicall-instance/context.ts @@ -16,7 +16,7 @@ export namespace MI { /** * Multicall Instance entity config */ -export class MIModuleContext { +export class ModuleContext { public static readonly ParamKey = MulticallSettingsParamKey; /** diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index dd9cd7b9..eea145f6 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,13 +1,13 @@ -import { MI as MIModule, MIModuleContext } from "./context"; +import { MI as MIModule, ModuleContext } from "./context"; import { MIAdminsTable } from "./ui/mi-admins"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; +export { type MIModule }; + /** * Multicall Instance entity */ -class MI extends MIModuleContext { +export class MI extends ModuleContext { static AdminsTable = MIAdminsTable; static TokenWhitelistTable = MITokenWhitelistTable; } - -export { MI, type MIModule }; diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index dc1e5dec..738a877e 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { type MI } from "../context"; +import { MI } from "../context"; import { MIInfoModel } from "./mi-settings"; diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index 58292a32..2f321d26 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { type MI } from "../context"; +import { MI } from "../context"; import { MIInfoModel } from "./mi-settings"; diff --git a/src/entities/multicall-instance/ui/mi-admin.tsx b/src/entities/multicall-instance/ui/mi-admin.tsx index 8719afab..6f9a88a9 100644 --- a/src/entities/multicall-instance/ui/mi-admin.tsx +++ b/src/entities/multicall-instance/ui/mi-admin.tsx @@ -1,4 +1,4 @@ -import { NearLink, type NearLinkProps } from "../../../shared/ui/design"; +import { NearLink, NearLinkProps } from "../../../shared/ui/design"; interface MIAdminProps extends NearLinkProps {} diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 57f074af..64dc40bf 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,6 +1,6 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { MIAdminsModel } from "../model/mi-admins"; -import { type MI } from "../context"; +import { MI } from "../context"; import { miAdminAsTableRow } from "./mi-admin"; diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index 5600bfb5..4f015959 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,8 +1,8 @@ import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; import { MITokensModel } from "../model/mi-tokens"; -import { type MI } from "../context"; +import { MI } from "../context"; -import { type MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; +import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; interface MITokenWhitelistTableProps extends MI.Inputs, Pick { ItemProps?: TableProps["RowProps"]; diff --git a/src/entities/near/context.ts b/src/entities/near-token/context.ts similarity index 67% rename from src/entities/near/context.ts rename to src/entities/near-token/context.ts index 931c6954..0e01f847 100644 --- a/src/entities/near/context.ts +++ b/src/entities/near-token/context.ts @@ -1,17 +1,15 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -namespace NEARTokenModule { +export namespace NEARToken { export interface Inputs { - contracts: { + adapters: { dao: SputnikDAO; multicall: Multicall; }; } } -class NEARTokenModuleContext { +export class ModuleContext { static FRACTIONAL_PART_LENGTH = 5; } - -export { NEARTokenModuleContext, type NEARTokenModule }; diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts new file mode 100644 index 00000000..8ee9e5a5 --- /dev/null +++ b/src/entities/near-token/index.ts @@ -0,0 +1,8 @@ +import { ModuleContext, type NEARToken as NEARTokenModule } from "./context"; +import { ntBalancesRender } from "./ui/nt-balances"; + +export { type NEARTokenModule }; + +export class NEARToken extends ModuleContext { + static balancesRender = ntBalancesRender; +} diff --git a/src/entities/near/model/near-balances.ts b/src/entities/near-token/model/near-balances.ts similarity index 68% rename from src/entities/near/model/near-balances.ts rename to src/entities/near-token/model/near-balances.ts index 059d67aa..2c0c59f1 100644 --- a/src/entities/near/model/near-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -2,8 +2,7 @@ import { useEffect, useState } from "react"; import { Big, formatTokenAmount } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; - -import { NEARTokenModuleContext, type NEARTokenModule } from "../context"; +import { ModuleContext, type NEARToken } from "../context"; type NEARTokenDataFxResponse = { data: { dao: string; multicall: string; total: string } | null; @@ -11,7 +10,7 @@ type NEARTokenDataFxResponse = { }; const nearTokenDataFx = async ( - { dao, multicall }: NEARTokenModule.Inputs["contracts"], + { dao, multicall }: NEARToken.Inputs["adapters"], callback: (result: NEARTokenDataFxResponse) => void ) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ @@ -24,13 +23,13 @@ const nearTokenDataFx = async ( return callback({ data: { - dao: formatTokenAmount(daoRawBalance, 24, NEARTokenModuleContext.FRACTIONAL_PART_LENGTH), - multicall: formatTokenAmount(multicallRawBalance, 24, NEARTokenModuleContext.FRACTIONAL_PART_LENGTH), + dao: formatTokenAmount(daoRawBalance, 24, ModuleContext.FRACTIONAL_PART_LENGTH), + multicall: formatTokenAmount(multicallRawBalance, 24, ModuleContext.FRACTIONAL_PART_LENGTH), total: formatTokenAmount( Big(daoRawBalance).add(multicallRawBalance).toFixed(), 24, - NEARTokenModuleContext.FRACTIONAL_PART_LENGTH + ModuleContext.FRACTIONAL_PART_LENGTH ), }, @@ -38,10 +37,10 @@ const nearTokenDataFx = async ( }); }; -const useNEARTokenData = (contracts: NEARTokenModule.Inputs["contracts"]) => { +const useNEARTokenData = (adapters: NEARToken.Inputs["adapters"]) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void nearTokenDataFx(contracts, stateUpdate), [contracts, stateUpdate]); + useEffect(() => void nearTokenDataFx(adapters, stateUpdate), [adapters, stateUpdate]); return state; }; diff --git a/src/entities/near/ui/near-balances.tsx b/src/entities/near-token/ui/nt-balances.tsx similarity index 63% rename from src/entities/near/ui/near-balances.tsx rename to src/entities/near-token/ui/nt-balances.tsx index 253834b2..d76801dd 100644 --- a/src/entities/near/ui/near-balances.tsx +++ b/src/entities/near-token/ui/nt-balances.tsx @@ -1,12 +1,12 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { NEARTokenBalancesModel } from "../model/near-balances"; -import { type NEARTokenModule } from "../context"; +import { type NEARToken } from "../context"; -interface NEARTokenBalancesRenderProps extends NEARTokenModule.Inputs {} +interface NTBalancesRenderProps extends NEARToken.Inputs {} -export const nearTokenBalancesRender = ({ contracts }: NEARTokenBalancesRenderProps) => { - const { data } = NEARTokenBalancesModel.useTokenFrom(contracts); +export const ntBalancesRender = ({ adapters }: NTBalancesRenderProps) => { + const { data } = NEARTokenBalancesModel.useTokenFrom(adapters); return !data ? null diff --git a/src/entities/near/index.ts b/src/entities/near/index.ts deleted file mode 100644 index 875d1580..00000000 --- a/src/entities/near/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NEARTokenModuleContext, type NEARTokenModule } from "./context"; -import { nearTokenBalancesRender } from "./ui/near-balances"; - -class NEARToken extends NEARTokenModuleContext { - static balancesRender = nearTokenBalancesRender; -} - -export { NEARToken, type NEARTokenModule }; diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index a00aa42e..6e7437a9 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -508,9 +508,9 @@ export class DaoPage extends Component { ); diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index c562d02e..849e392f 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -9,12 +9,12 @@ interface DaoFundsTabUIProps extends HTMLProps, TokenBalancesMod const _DaoFundsTab = "DaoFundsTab"; -const DaoFundsTabUI = ({ className, contracts, ...props }: DaoFundsTabUIProps) => ( +const DaoFundsTabUI = ({ className, adapters, ...props }: DaoFundsTabUIProps) => (
        - +
        ); diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 7e3fef00..14d9b09e 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -9,12 +9,12 @@ interface DaoJobsTabUIProps extends HTMLProps, ComponentProps ( +const DaoJobsTabUI = ({ className, adapters, ...props }: DaoJobsTabUIProps) => (
        - +
        ); diff --git a/src/pages/dao/settings/settings.tsx b/src/pages/dao/settings/settings.tsx index a6db32be..f2bf3425 100644 --- a/src/pages/dao/settings/settings.tsx +++ b/src/pages/dao/settings/settings.tsx @@ -9,12 +9,12 @@ interface DaoSettingsTabUIProps extends HTMLProps, SettingsEdito const _DaoSettingsTab = "DaoSettingsTab"; -const DaoSettingsTabUI = ({ className, contracts, ...props }: DaoSettingsTabUIProps) => ( +const DaoSettingsTabUI = ({ className, adapters, ...props }: DaoSettingsTabUIProps) => (
        - +
        ); diff --git a/src/widgets/settings-editor/context.ts b/src/widgets/settings-editor/context.ts index e5f26019..6d8223c7 100644 --- a/src/widgets/settings-editor/context.ts +++ b/src/widgets/settings-editor/context.ts @@ -6,7 +6,7 @@ import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; export namespace SettingsEditor { export interface Inputs extends HTMLProps { - contracts: { dao: SputnikDAO; multicall: Multicall }; + adapters: { dao: SputnikDAO; multicall: Multicall }; } export type Diff = MulticallSettingsDiff; diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 05f8336f..e73faa2f 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -13,11 +13,11 @@ import "./settings-editor.scss"; const _SettingsEditor = "SettingsEditor"; -export const SettingsEditorUI = ({ className, contracts }: SettingsEditor.Inputs) => { +export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) => { const wallet = useContext(Wallet.SelectorContext); const proposalCreationPermitted = - !wallet?.accountId || contracts.dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); + !wallet?.accountId || adapters.dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); const [editMode, editModeSwitch] = useState(false); @@ -67,17 +67,17 @@ export const SettingsEditorUI = ({ className, contracts }: SettingsEditor.Inputs (event) => { void event.preventDefault(); - void contracts.dao + void adapters.dao .proposeFunctionCall( proposalDescription, - contracts.multicall.address, + adapters.multicall.address, Multicall.configDiffToProposalActions(changesDiff) ) .then((someTx) => signAndSendTxs([someTx])) .catch(console.error); }, - [changesDiff, contracts, proposalDescription] + [changesDiff, adapters, proposalDescription] ); useEffect( @@ -89,12 +89,12 @@ export const SettingsEditorUI = ({ className, contracts }: SettingsEditor.Inputs
        diff --git a/src/widgets/token-balances/ui/token-balances.tsx b/src/widgets/token-balances/ui/token-balances.tsx index 4021fcb1..31e79e23 100644 --- a/src/widgets/token-balances/ui/token-balances.tsx +++ b/src/widgets/token-balances/ui/token-balances.tsx @@ -8,9 +8,9 @@ import "./token-balances.scss"; const _TokenBalances = "TokenBalances"; -export const TokenBalancesUI = ({ className, contracts }: TokenBalances.Inputs) => { - const nearTokenBalances = NEARToken.balancesRender({ contracts }), - fungibleTokenBalances = FT.balances({ contracts }); +export const TokenBalancesUI = ({ className, adapters }: TokenBalances.Inputs) => { + const nearTokenBalances = NEARToken.balancesRender({ adapters }), + fungibleTokenBalances = FT.balances({ adapters }); return ( Date: Sat, 26 Nov 2022 05:41:33 +0400 Subject: [PATCH 429/537] wip: Apply post code review remarks --- .../settings-change/ui/scheduling-settings-form.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx index 77e2ffdd..2db6686e 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx @@ -27,16 +27,14 @@ export const SchedulingSettingsForm = ({ ]; const formFields = { - croncatManager: useMemo(() => new ArgsString(multicallInstance.croncatManager), []), + croncatManager: useMemo(() => new ArgsString(multicallInstance.croncatManager), [multicallInstance]), jobBond: useMemo( () => new ArgsString(multicallInstance.jobBond !== "" ? toNEAR(multicallInstance.jobBond) : ""), - [] + [multicallInstance] ), }; - console.table(croncatManager); - const onCroncatManagerChange = useCallback["onChange"]>( ({ target: { value } }) => void croncatManagerUpdate( From 4a15d027c5311f00483324ac9b90e8b856abf855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 30 Nov 2022 18:31:22 +0400 Subject: [PATCH 430/537] wip: Reverse token whitelist items order --- src/entities/job/ui/jobs-table.tsx | 9 ++++----- .../multicall-instance/ui/mi-token-whitelist.tsx | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 2243edd4..4230f800 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -12,13 +12,14 @@ interface JobsTableProps extends Job.Inputs {} const _JobsTable = "JobsTable"; export const JobsTable = ({ className, adapters }: JobsTableProps) => { - const { data, error, loading } = JobModel.useAllEntries(adapters); + const { data, error, loading } = JobModel.useAllEntries(adapters), + items = Object.values(data ?? {}); return ( @@ -27,9 +28,7 @@ export const JobsTable = ({ className, adapters }: JobsTableProps) => { className={`${_JobsTable}-body`} displayMode="compact" header={["Status", "ID", "Start at", "Croncat hash", "Creator", "Trigger gas", "Multicalls"]} - rows={Object.values(data ?? {}) - .map(jobAsTableRow) - .reverse()} + rows={items.map(jobAsTableRow).reverse()} /> diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index 4674c932..fba18658 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -22,13 +22,13 @@ export const MITokenWhitelistTable = ({ subheader, }: MITokenWhitelistTableProps) => { const { data, error, loading } = MITokensModel.useWhitelist(daoAddress), - allItems = data?.concat(itemsAdditional ?? []); + items = data?.concat(itemsAdditional ?? []); return ( @@ -38,7 +38,7 @@ export const MITokenWhitelistTable = ({ displayMode="compact" header={["Contract address"]} onRowsSelected={onItemsSelected} - rows={allItems?.map(miWhitelistedTokenAsTableRow)} + rows={items?.map(miWhitelistedTokenAsTableRow).reverse()} /> From 6a037eea1e83f3f11867f0cb5a8ad74598c37436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 30 Nov 2022 18:40:30 +0400 Subject: [PATCH 431/537] wip: Remove debugging artifact --- .../scheduling/settings-change/ui/scheduling-settings-form.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx index 4e68ec1d..2db6686e 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx @@ -35,8 +35,6 @@ export const SchedulingSettingsForm = ({ ), }; - console.table(croncatManager); - const onCroncatManagerChange = useCallback["onChange"]>( ({ target: { value } }) => void croncatManagerUpdate( From 0522942ee3c73aa5de0e08d4b278b9899fe5980a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 1 Dec 2022 00:39:05 +0400 Subject: [PATCH 432/537] chore: Use more accurate definition --- src/entities/fungible-token/context.ts | 2 +- src/entities/fungible-token/model/ft-info.ts | 6 ++-- src/entities/job/context.ts | 4 +-- .../job/model/{job.ts => job-model.ts} | 4 +-- src/entities/job/ui/jobs-table.tsx | 4 +-- src/entities/near-token/context.ts | 2 +- .../near-token/model/near-balances.ts | 4 +-- src/entities/wallet/ui/wallet.tsx | 4 +-- .../scheduling/settings-change/context.ts | 5 ++- .../ui/scheduling-settings-form.tsx | 2 +- src/pages/dao/dao.tsx | 35 ++++++++++--------- src/shared/lib/contracts/multicall.ts | 24 ++++++------- src/widgets/settings-editor/context.ts | 2 +- .../settings-editor/ui/settings-editor.tsx | 5 ++- 14 files changed, 54 insertions(+), 49 deletions(-) rename src/entities/job/model/{job.ts => job-model.ts} (94%) diff --git a/src/entities/fungible-token/context.ts b/src/entities/fungible-token/context.ts index 362fe2c3..d9d07793 100644 --- a/src/entities/fungible-token/context.ts +++ b/src/entities/fungible-token/context.ts @@ -5,7 +5,7 @@ export namespace FT { export interface Inputs { adapters: { dao: SputnikDAO; - multicall: Multicall; + multicallInstance: Multicall; }; } } diff --git a/src/entities/fungible-token/model/ft-info.ts b/src/entities/fungible-token/model/ft-info.ts index 34548edf..40c8f6b9 100644 --- a/src/entities/fungible-token/model/ft-info.ts +++ b/src/entities/fungible-token/model/ft-info.ts @@ -11,13 +11,13 @@ type FTInfo = { export class FTInfoModel { private static readonly nonZeroBalancesFetchFx = async ( - { dao, multicall }: FT.Inputs["adapters"], + { dao, multicallInstance }: FT.Inputs["adapters"], callback: (result: FTInfo) => void ) => { /* Get LikelyTokens list on DAO and its Multicall instance */ const [daoLikelyTokensList, multicallLikelyTokensList] = await Promise.all([ FungibleToken.getLikelyTokenContracts(dao.address), - FungibleToken.getLikelyTokenContracts(multicall.address), + FungibleToken.getLikelyTokenContracts(multicallInstance.address), ]); /* Merge and de-duplicate both token lists */ @@ -33,7 +33,7 @@ export class FTInfoModel { .map(async (token) => { const [daoRawBalance, multicallRawBalance] = await Promise.all([ token.ftBalanceOf(dao.address), - token.ftBalanceOf(multicall.address), + token.ftBalanceOf(multicallInstance.address), ]); return { diff --git a/src/entities/job/context.ts b/src/entities/job/context.ts index be9f4883..f88ba349 100644 --- a/src/entities/job/context.ts +++ b/src/entities/job/context.ts @@ -1,9 +1,9 @@ -import { type JobData, type Multicall } from "../../shared/lib/contracts/multicall"; +import { JobData, Multicall } from "../../shared/lib/contracts/multicall"; export namespace Job { export interface Inputs { className?: string; - adapters: { multicall: Multicall }; + adapters: { multicallInstance: Multicall }; } export type Data = JobData; diff --git a/src/entities/job/model/job.ts b/src/entities/job/model/job-model.ts similarity index 94% rename from src/entities/job/model/job.ts rename to src/entities/job/model/job-model.ts index e943103d..c41c7b47 100644 --- a/src/entities/job/model/job.ts +++ b/src/entities/job/model/job-model.ts @@ -12,11 +12,11 @@ type JobAllEntries = { export class JobModel { static allEntriesFetchFx = async ( - { multicall }: Job.Inputs["adapters"], + { multicallInstance }: Job.Inputs["adapters"], callback: (result: JobAllEntries) => void ) => callback( - await multicall + await multicallInstance .getJobs() .then((data) => ({ data: data.reduce( diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 4230f800..b85da400 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -1,8 +1,8 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { JobModel } from "../model/job"; -import { type Job } from "../context"; +import { JobModel } from "../model/job-model"; +import { Job } from "../context"; import { jobAsTableRow } from "./job"; import "./jobs-table.scss"; diff --git a/src/entities/near-token/context.ts b/src/entities/near-token/context.ts index 0e01f847..0b6ba9ed 100644 --- a/src/entities/near-token/context.ts +++ b/src/entities/near-token/context.ts @@ -5,7 +5,7 @@ export namespace NEARToken { export interface Inputs { adapters: { dao: SputnikDAO; - multicall: Multicall; + multicallInstance: Multicall; }; } } diff --git a/src/entities/near-token/model/near-balances.ts b/src/entities/near-token/model/near-balances.ts index 2c0c59f1..343498b6 100644 --- a/src/entities/near-token/model/near-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -10,12 +10,12 @@ type NEARTokenDataFxResponse = { }; const nearTokenDataFx = async ( - { dao, multicall }: NEARToken.Inputs["adapters"], + { dao, multicallInstance }: NEARToken.Inputs["adapters"], callback: (result: NEARTokenDataFxResponse) => void ) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ viewAccount(dao.address), - viewAccount(multicall.address), + viewAccount(multicallInstance.address), ]); const daoRawBalance = daoAccInfo.amount, diff --git a/src/entities/wallet/ui/wallet.tsx b/src/entities/wallet/ui/wallet.tsx index 1c956459..4d78bdf9 100644 --- a/src/entities/wallet/ui/wallet.tsx +++ b/src/entities/wallet/ui/wallet.tsx @@ -146,12 +146,12 @@ export class WalletComponent extends Component { }), Multicall.init(multicallAddress).catch((e) => new Multicall(multicallAddress)), ]) - .then(([newDao, newMulticall]) => { + .then(([newDao, multicallInstance]) => { if (!newDao?.ready) return; this.setState({ currentDao: newDao, - currentMulticall: newMulticall, + currentMulticall: multicallInstance, }); }) .finally(async () => { diff --git a/src/features/scheduling/settings-change/context.ts b/src/features/scheduling/settings-change/context.ts index 27bd027e..aded758b 100644 --- a/src/features/scheduling/settings-change/context.ts +++ b/src/features/scheduling/settings-change/context.ts @@ -10,7 +10,10 @@ export namespace SchedulingSettingsChange { export type FormState = Pick; export interface Inputs extends Omit, "onChange">, Pick { - multicallInstance: Multicall; + adapters: { + multicallInstance: Multicall; + }; + onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx index 2db6686e..eca56ee1 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx @@ -8,9 +8,9 @@ import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../.. import { ModuleContext, SchedulingSettingsChange } from "../context"; export const SchedulingSettingsForm = ({ + adapters: { multicallInstance }, className, disabled, - multicallInstance, onEdit, resetTrigger, }: SchedulingSettingsChange.Inputs) => { diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 932fd7e3..6e95cd59 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -30,13 +30,14 @@ interface State { addr: string; }; dao: SputnikDAO; - multicall: Multicall; + multicallInstance: Multicall; loading: boolean; proposed: number; proposedInfo: ProposalOutput | null; } const _DaoPage = "DaoPage"; + export class DaoPage extends Component { static contextType = Ctx; declare context: ContextType; @@ -80,8 +81,7 @@ export class DaoPage extends Component { }, dao: new SputnikDAO(addr), - multicall: new Multicall(this.toMulticallAddress(addr)), - + multicallInstance: new Multicall(this.toMulticallAddress(addr)), loading: false, proposed: -1, proposedInfo: null, @@ -160,7 +160,7 @@ export class DaoPage extends Component { onAddressesUpdated(e: CustomEvent<{ dao: string }>) { if (e.detail.dao !== this.state.formData.addr) { this.setState({ - multicall: new Multicall(this.toMulticallAddress(e.detail.dao)), + multicallInstance: new Multicall(this.toMulticallAddress(e.detail.dao)), }); this.formikSetValues?.({ addr: e.detail.dao }); } @@ -406,7 +406,7 @@ export class DaoPage extends Component { if (!newDao.ready) { this.setState({ dao: newDao, - multicall: new Multicall(multicallAddress), + multicallInstance: new Multicall(multicallAddress), loading: false, }); return; @@ -416,7 +416,7 @@ export class DaoPage extends Component { .then((proposalData) => this.setState({ dao: newDao, - multicall: new Multicall(multicallAddress), + multicallInstance: new Multicall(multicallAddress), loading: false, proposed: proposalData?.proposal_id ?? -1, proposedInfo: (proposalData?.proposal_info as ProposalOutput) ?? null, @@ -436,12 +436,12 @@ export class DaoPage extends Component { Promise.all([ SputnikDAO.init(daoAddress).catch((e) => new SputnikDAO(daoAddress)), Multicall.init(multicallAddress).catch((e) => new Multicall(multicallAddress)), - ]).then(([newDao, newMulticall]) => { + ]).then(([newDao, multicallInstance]) => { // some error happened during DAO object init. - if (!newDao.ready || !newMulticall.ready) { + if (!newDao.ready || !multicallInstance.ready) { this.setState({ dao: newDao, - multicall: newMulticall, + multicallInstance, loading: false, }); } else { @@ -450,7 +450,7 @@ export class DaoPage extends Component { .then((proposalData) => this.setState({ dao: newDao, - multicall: newMulticall, + multicallInstance, loading: false, proposed: proposalData?.proposal_id ?? -1, proposedInfo: (proposalData?.proposal_info as ProposalOutput) ?? null, @@ -462,7 +462,7 @@ export class DaoPage extends Component { getContent() { const { selector: walletSelector } = this.context!; - const { dao, loading, multicall } = this.state; + const { dao, loading, multicallInstance } = this.state; // if user not logged in, remind them to sign in. // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) @@ -499,8 +499,8 @@ export class DaoPage extends Component { /* * Everything should be loaded */ - if (!multicall.admins || !multicall.tokensWhitelist || !multicall.jobBond) { - console.error("multicall infos incomplete", multicall); + if (!multicallInstance.admins || !multicallInstance.tokensWhitelist || !multicallInstance.jobBond) { + console.error("multicall infos incomplete", multicallInstance); return
        Unexpected error! Multicall might be outdated.
        ; } @@ -512,9 +512,12 @@ export class DaoPage extends Component { contentSpace: "DaoPage-tabs-contentSpace", }} items={[ - DaoSettingsTab.uiConnect({ className: `${_DaoPage}-content`, adapters: { dao, multicall } }), - DaoFundsTab.uiConnect({ className: `${_DaoPage}-content`, adapters: { dao, multicall } }), - DaoJobsTab.uiConnect({ className: `${_DaoPage}-content`, adapters: { multicall } }), + DaoSettingsTab.uiConnect({ + className: `${_DaoPage}-content`, + adapters: { dao, multicallInstance }, + }), + DaoFundsTab.uiConnect({ className: `${_DaoPage}-content`, adapters: { dao, multicallInstance } }), + DaoJobsTab.uiConnect({ className: `${_DaoPage}-content`, adapters: { multicallInstance } }), ]} /> ); diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index c41f24e5..83d54743 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -99,39 +99,39 @@ class Multicall { // used to create and initialize a Multicall instance static async init(multicallAddress: AccountId): Promise { // verify address is a Multicall instance, fetch its info and mark it ready - const newMulticall = new Multicall(multicallAddress); + const multicallInstance = new Multicall(multicallAddress); const [isMulticall, admins, croncatManager, tokensWhitelist, jobBond] = await Promise.all([ // on failure set isMulticall to false Multicall.isMulticall(multicallAddress).catch((err) => { return false; }), // on failure set admins list to be empty - newMulticall.getAdmins().catch((err) => { + multicallInstance.getAdmins().catch((err) => { return []; }), //on failure set manager list to be empty - newMulticall.getCroncatManager().catch((err) => { + multicallInstance.getCroncatManager().catch((err) => { return ""; }), // on failure set tokens whitelist to be empty - newMulticall.getWhitelistedTokens().catch((err) => { + multicallInstance.getWhitelistedTokens().catch((err) => { return []; }), // on failure set job bond to "" - newMulticall.getJobBond().catch((err) => { + multicallInstance.getJobBond().catch((err) => { return ""; }), ]); - newMulticall.admins = admins; - newMulticall.croncatManager = croncatManager; - newMulticall.tokensWhitelist = tokensWhitelist; - newMulticall.jobBond = jobBond; + multicallInstance.admins = admins; + multicallInstance.croncatManager = croncatManager; + multicallInstance.tokensWhitelist = tokensWhitelist; + multicallInstance.jobBond = jobBond; // set ready to true if address is a Multicall instance and it has at least 1 admin. - if (isMulticall === true && newMulticall.admins.length >= 1) { - newMulticall.ready = true; + if (isMulticall === true && multicallInstance.admins.length >= 1) { + multicallInstance.ready = true; } - return newMulticall; + return multicallInstance; } /** diff --git a/src/widgets/settings-editor/context.ts b/src/widgets/settings-editor/context.ts index 6d8223c7..1533b495 100644 --- a/src/widgets/settings-editor/context.ts +++ b/src/widgets/settings-editor/context.ts @@ -6,7 +6,7 @@ import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; export namespace SettingsEditor { export interface Inputs extends HTMLProps { - adapters: { dao: SputnikDAO; multicall: Multicall }; + adapters: { dao: SputnikDAO; multicallInstance: Multicall }; } export type Diff = MulticallSettingsDiff; diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index e73faa2f..2253391d 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -70,7 +70,7 @@ export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) void adapters.dao .proposeFunctionCall( proposalDescription, - adapters.multicall.address, + adapters.multicallInstance.address, Multicall.configDiffToProposalActions(changesDiff) ) .then((someTx) => signAndSendTxs([someTx])) @@ -104,9 +104,8 @@ export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) className={`${_SettingsEditor}-jobsSettings`} daoAddress={adapters.dao.address} disabled={!proposalCreationPermitted} - multicallInstance={adapters.multicall} resetTrigger={childFormsResetRequested} - {...{ onEdit }} + {...{ adapters, onEdit }} /> Date: Thu, 1 Dec 2022 01:04:50 +0400 Subject: [PATCH 433/537] wip: Swap buttons --- .../settings-change/ui/scheduling-settings-form.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx index eca56ee1..2c39dd34 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx @@ -71,16 +71,16 @@ export const SchedulingSettingsForm = ({ headerSlots={{ end: editModeEnabled ? ( <> - - void editModeSwitch(false)}> - + + + {(croncatManager.length > 0 || jobBond.length > 0) && ( - - - + + void editModeSwitch(false)}> + )} From a64773cd808748004ca3a56b0f9394083652fb2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 2 Dec 2022 13:22:41 +0400 Subject: [PATCH 434/537] chore: Rename module context files --- src/entities/fungible-token/index.ts | 2 +- src/entities/fungible-token/lib/ft-format.ts | 2 +- src/entities/fungible-token/model/ft-info.ts | 2 +- src/entities/fungible-token/{context.ts => module-context.ts} | 0 src/entities/fungible-token/ui/ft-balances.tsx | 2 +- src/entities/job/index.ts | 2 +- src/entities/job/lib/job-normalized.ts | 2 +- src/entities/job/model/job-model.ts | 2 +- src/entities/job/{context.ts => module-context.ts} | 0 src/entities/job/ui/job.tsx | 2 +- src/entities/job/ui/jobs-table.tsx | 2 +- src/entities/multicall-instance/index.ts | 2 +- src/entities/multicall-instance/model/mi-admins.ts | 2 +- src/entities/multicall-instance/model/mi-tokens.ts | 2 +- .../multicall-instance/{context.ts => module-context.ts} | 0 src/entities/multicall-instance/ui/mi-admins.tsx | 2 +- src/entities/multicall-instance/ui/mi-token-whitelist.tsx | 2 +- src/entities/near-token/index.ts | 2 +- src/entities/near-token/model/near-balances.ts | 2 +- src/entities/near-token/{context.ts => module-context.ts} | 0 src/entities/near-token/ui/nt-balances.tsx | 2 +- src/features/external-login/index.ts | 2 +- src/features/external-login/model/el-dialogs.ts | 2 +- src/features/external-login/{context.ts => module-context.ts} | 0 src/features/external-login/ui/el-dialogs.tsx | 2 +- src/features/external-login/ui/el-menu.tsx | 2 +- src/features/scheduling/settings-change/index.ts | 2 +- .../settings-change/{context.ts => module-context.ts} | 0 .../scheduling/settings-change/ui/scheduling-settings-form.tsx | 2 +- src/features/tokens/whitelist-change/index.ts | 2 +- .../tokens/whitelist-change/{context.ts => module-context.ts} | 0 .../tokens/whitelist-change/ui/tokens-whitelist-form.tsx | 2 +- src/shared/ui/design/data-inspector/data-inspector.tsx | 2 +- .../ui/design/data-inspector/{context.ts => module-context.ts} | 0 src/shared/ui/design/index.ts | 2 +- src/shared/ui/design/{context.ts => module-context.ts} | 0 src/shared/ui/design/table/row.tsx | 2 +- src/widgets/settings-editor/index.ts | 2 +- src/widgets/settings-editor/{context.ts => module-context.ts} | 0 src/widgets/settings-editor/ui/se-proposal-form.tsx | 2 +- src/widgets/settings-editor/ui/settings-editor.tsx | 2 +- src/widgets/token-balances/index.ts | 2 +- src/widgets/token-balances/{context.ts => module-context.ts} | 0 src/widgets/token-balances/ui/token-balances.tsx | 2 +- 44 files changed, 33 insertions(+), 33 deletions(-) rename src/entities/fungible-token/{context.ts => module-context.ts} (100%) rename src/entities/job/{context.ts => module-context.ts} (100%) rename src/entities/multicall-instance/{context.ts => module-context.ts} (100%) rename src/entities/near-token/{context.ts => module-context.ts} (100%) rename src/features/external-login/{context.ts => module-context.ts} (100%) rename src/features/scheduling/settings-change/{context.ts => module-context.ts} (100%) rename src/features/tokens/whitelist-change/{context.ts => module-context.ts} (100%) rename src/shared/ui/design/data-inspector/{context.ts => module-context.ts} (100%) rename src/shared/ui/design/{context.ts => module-context.ts} (100%) rename src/widgets/settings-editor/{context.ts => module-context.ts} (100%) rename src/widgets/token-balances/{context.ts => module-context.ts} (100%) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 1f07f2d5..766e8fcb 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,4 +1,4 @@ -import { ModuleContext, FT as FTModule } from "./context"; +import { ModuleContext, FT as FTModule } from "./module-context"; import { ftBalances } from "./ui/ft-balances"; export { type FTModule }; diff --git a/src/entities/fungible-token/lib/ft-format.ts b/src/entities/fungible-token/lib/ft-format.ts index d4229a46..b11e8e64 100644 --- a/src/entities/fungible-token/lib/ft-format.ts +++ b/src/entities/fungible-token/lib/ft-format.ts @@ -1,6 +1,6 @@ import { Big, formatTokenAmount } from "../../../shared/lib/converter"; -import { ModuleContext } from "../context"; +import { ModuleContext } from "../module-context"; const amountToDisplayAmount = (amount: string, decimals: number): string => { const formattedAmount = formatTokenAmount(amount, decimals), diff --git a/src/entities/fungible-token/model/ft-info.ts b/src/entities/fungible-token/model/ft-info.ts index 40c8f6b9..cdea15c9 100644 --- a/src/entities/fungible-token/model/ft-info.ts +++ b/src/entities/fungible-token/model/ft-info.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { Big } from "../../../shared/lib/converter"; import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; -import { FT } from "../context"; +import { FT } from "../module-context"; type FTInfo = { data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; diff --git a/src/entities/fungible-token/context.ts b/src/entities/fungible-token/module-context.ts similarity index 100% rename from src/entities/fungible-token/context.ts rename to src/entities/fungible-token/module-context.ts diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index b112d529..07ecc526 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -1,7 +1,7 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { FTFormat } from "../lib/ft-format"; import { FTInfoModel } from "../model/ft-info"; -import { FT } from "../context"; +import { FT } from "../module-context"; interface FTBalancesProps extends FT.Inputs {} diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index 33ab72a9..640709f9 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,4 +1,4 @@ -import { ModuleContext, Job as JobModule } from "./context"; +import { ModuleContext, Job as JobModule } from "./module-context"; import { JobsTable } from "./ui/jobs-table"; export { type JobModule }; diff --git a/src/entities/job/lib/job-normalized.ts b/src/entities/job/lib/job-normalized.ts index 9a82e810..57170594 100644 --- a/src/entities/job/lib/job-normalized.ts +++ b/src/entities/job/lib/job-normalized.ts @@ -1,7 +1,7 @@ import { Base64 } from "js-base64"; import { Big } from "../../../shared/lib/converter"; -import { ModuleContext, Job } from "../context"; +import { ModuleContext, Job } from "../module-context"; /** * Job status is: diff --git a/src/entities/job/model/job-model.ts b/src/entities/job/model/job-model.ts index c41c7b47..0d6409c2 100644 --- a/src/entities/job/model/job-model.ts +++ b/src/entities/job/model/job-model.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import { Job } from "../context"; +import { Job } from "../module-context"; import { JobNormalized } from "../lib/job-normalized"; type JobAllEntries = { diff --git a/src/entities/job/context.ts b/src/entities/job/module-context.ts similarity index 100% rename from src/entities/job/context.ts rename to src/entities/job/module-context.ts diff --git a/src/entities/job/ui/job.tsx b/src/entities/job/ui/job.tsx index 68b6cdac..1d75d266 100644 --- a/src/entities/job/ui/job.tsx +++ b/src/entities/job/ui/job.tsx @@ -2,7 +2,7 @@ import { NavLink } from "react-router-dom"; import { Big, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/design"; -import { ModuleContext, Job } from "../context"; +import { ModuleContext, Job } from "../module-context"; import "./job.scss"; diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index b85da400..77097eaf 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { JobModel } from "../model/job-model"; -import { Job } from "../context"; +import { Job } from "../module-context"; import { jobAsTableRow } from "./job"; import "./jobs-table.scss"; diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index eea145f6..2cf1086d 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,4 +1,4 @@ -import { MI as MIModule, ModuleContext } from "./context"; +import { MI as MIModule, ModuleContext } from "./module-context"; import { MIAdminsTable } from "./ui/mi-admins"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts index 738a877e..913cfb06 100644 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ b/src/entities/multicall-instance/model/mi-admins.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { MI } from "../context"; +import { MI } from "../module-context"; import { MIInfoModel } from "./mi-settings"; diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts index 2f321d26..75524236 100644 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ b/src/entities/multicall-instance/model/mi-tokens.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Props } from "../../../shared/lib/props"; -import { MI } from "../context"; +import { MI } from "../module-context"; import { MIInfoModel } from "./mi-settings"; diff --git a/src/entities/multicall-instance/context.ts b/src/entities/multicall-instance/module-context.ts similarity index 100% rename from src/entities/multicall-instance/context.ts rename to src/entities/multicall-instance/module-context.ts diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 64dc40bf..313f05b9 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,6 +1,6 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { MIAdminsModel } from "../model/mi-admins"; -import { MI } from "../context"; +import { MI } from "../module-context"; import { miAdminAsTableRow } from "./mi-admin"; diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index fba18658..c5ab4e4b 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,6 +1,6 @@ import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; import { MITokensModel } from "../model/mi-tokens"; -import { MI } from "../context"; +import { MI } from "../module-context"; import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts index 8ee9e5a5..1ba78708 100644 --- a/src/entities/near-token/index.ts +++ b/src/entities/near-token/index.ts @@ -1,4 +1,4 @@ -import { ModuleContext, type NEARToken as NEARTokenModule } from "./context"; +import { ModuleContext, type NEARToken as NEARTokenModule } from "./module-context"; import { ntBalancesRender } from "./ui/nt-balances"; export { type NEARTokenModule }; diff --git a/src/entities/near-token/model/near-balances.ts b/src/entities/near-token/model/near-balances.ts index 343498b6..52c86f17 100644 --- a/src/entities/near-token/model/near-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { Big, formatTokenAmount } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; -import { ModuleContext, type NEARToken } from "../context"; +import { ModuleContext, type NEARToken } from "../module-context"; type NEARTokenDataFxResponse = { data: { dao: string; multicall: string; total: string } | null; diff --git a/src/entities/near-token/context.ts b/src/entities/near-token/module-context.ts similarity index 100% rename from src/entities/near-token/context.ts rename to src/entities/near-token/module-context.ts diff --git a/src/entities/near-token/ui/nt-balances.tsx b/src/entities/near-token/ui/nt-balances.tsx index d76801dd..efc7edab 100644 --- a/src/entities/near-token/ui/nt-balances.tsx +++ b/src/entities/near-token/ui/nt-balances.tsx @@ -1,7 +1,7 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { NEARTokenBalancesModel } from "../model/near-balances"; -import { type NEARToken } from "../context"; +import { type NEARToken } from "../module-context"; interface NTBalancesRenderProps extends NEARToken.Inputs {} diff --git a/src/features/external-login/index.ts b/src/features/external-login/index.ts index fb5ea29a..136d5b9c 100644 --- a/src/features/external-login/index.ts +++ b/src/features/external-login/index.ts @@ -1,4 +1,4 @@ -import { ModuleContext } from "./context"; +import { ModuleContext } from "./module-context"; import { ELDialogs } from "./ui/el-dialogs"; import { ELMenu } from "./ui/el-menu"; diff --git a/src/features/external-login/model/el-dialogs.ts b/src/features/external-login/model/el-dialogs.ts index 33be7f59..56a4bf71 100644 --- a/src/features/external-login/model/el-dialogs.ts +++ b/src/features/external-login/model/el-dialogs.ts @@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from "react"; -import { ModuleContext } from "../context"; +import { ModuleContext } from "../module-context"; const _dialogOpenRequested = "dialogOpenRequested"; diff --git a/src/features/external-login/context.ts b/src/features/external-login/module-context.ts similarity index 100% rename from src/features/external-login/context.ts rename to src/features/external-login/module-context.ts diff --git a/src/features/external-login/ui/el-dialogs.tsx b/src/features/external-login/ui/el-dialogs.tsx index d46bfe78..2cf705a9 100644 --- a/src/features/external-login/ui/el-dialogs.tsx +++ b/src/features/external-login/ui/el-dialogs.tsx @@ -6,7 +6,7 @@ import { ArgsError, ArgsString } from "../../../shared/lib/args-old"; import { STORAGE } from "../../../shared/lib/persistent"; import { Validation } from "../../../shared/lib/validation"; import { Dialog, TextInput, Tooltip } from "../../../shared/ui/design"; -import { ModuleContext } from "../context"; +import { ModuleContext } from "../module-context"; import { ELDialogsModel } from "../model/el-dialogs"; import "./el-dialog.scss"; diff --git a/src/features/external-login/ui/el-menu.tsx b/src/features/external-login/ui/el-menu.tsx index 05e8686d..8a0c825e 100644 --- a/src/features/external-login/ui/el-menu.tsx +++ b/src/features/external-login/ui/el-menu.tsx @@ -2,7 +2,7 @@ import { PreviewOutlined } from "@mui/icons-material"; import { ComponentProps } from "react"; import { PopupMenu } from "../../../shared/ui/design"; -import { ModuleContext as ModuleContext } from "../context"; +import { ModuleContext as ModuleContext } from "../module-context"; import { ELDialogsModel } from "../model/el-dialogs"; interface ELMenuProps extends Pick, "triggerClassName"> { diff --git a/src/features/scheduling/settings-change/index.ts b/src/features/scheduling/settings-change/index.ts index 9698ac05..71b43b90 100644 --- a/src/features/scheduling/settings-change/index.ts +++ b/src/features/scheduling/settings-change/index.ts @@ -1,4 +1,4 @@ -import { ModuleContext, type SchedulingSettingsChange as SchedulingSettingsChangeModule } from "./context"; +import { ModuleContext, type SchedulingSettingsChange as SchedulingSettingsChangeModule } from "./module-context"; import { SchedulingSettingsForm } from "./ui/scheduling-settings-form"; export class SchedulingSettingsChange extends ModuleContext { diff --git a/src/features/scheduling/settings-change/context.ts b/src/features/scheduling/settings-change/module-context.ts similarity index 100% rename from src/features/scheduling/settings-change/context.ts rename to src/features/scheduling/settings-change/module-context.ts diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx index 2c39dd34..de147166 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx @@ -5,7 +5,7 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { ArgsString } from "../../../../shared/lib/args-old"; import { toNEAR, toYocto } from "../../../../shared/lib/converter"; import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../../shared/ui/design"; -import { ModuleContext, SchedulingSettingsChange } from "../context"; +import { ModuleContext, SchedulingSettingsChange } from "../module-context"; export const SchedulingSettingsForm = ({ adapters: { multicallInstance }, diff --git a/src/features/tokens/whitelist-change/index.ts b/src/features/tokens/whitelist-change/index.ts index caa85cad..b276a4bd 100644 --- a/src/features/tokens/whitelist-change/index.ts +++ b/src/features/tokens/whitelist-change/index.ts @@ -1,4 +1,4 @@ -import { ModuleContext, type TokenWhitelistChange as TokenWhitelistChangeModule } from "./context"; +import { ModuleContext, type TokenWhitelistChange as TokenWhitelistChangeModule } from "./module-context"; import { TokenWhitelistForm } from "./ui/tokens-whitelist-form"; export class TokenWhitelistChange extends ModuleContext { diff --git a/src/features/tokens/whitelist-change/context.ts b/src/features/tokens/whitelist-change/module-context.ts similarity index 100% rename from src/features/tokens/whitelist-change/context.ts rename to src/features/tokens/whitelist-change/module-context.ts diff --git a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx index 3e0d1d4c..b8701211 100644 --- a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx +++ b/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx @@ -5,7 +5,7 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { TextInput, Tooltip } from "../../../../shared/ui/design"; import { ArgsString } from "../../../../shared/lib/args-old"; import { MI } from "../../../../entities"; -import { ModuleContext, TokenWhitelistChange } from "../context"; +import { ModuleContext, TokenWhitelistChange } from "../module-context"; export const TokenWhitelistForm = ({ className, diff --git a/src/shared/ui/design/data-inspector/data-inspector.tsx b/src/shared/ui/design/data-inspector/data-inspector.tsx index 9c8f2011..482b51ea 100644 --- a/src/shared/ui/design/data-inspector/data-inspector.tsx +++ b/src/shared/ui/design/data-inspector/data-inspector.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { MouseEvent, useCallback, useState, type ComponentProps } from "react"; import { ObjectInspector } from "react-inspector"; -import { ModuleContext as ModuleContext } from "./context"; +import { ModuleContext as ModuleContext } from "./module-context"; import { DataInspectorNode } from "./data-inspector-node"; import "./data-inspector.scss"; diff --git a/src/shared/ui/design/data-inspector/context.ts b/src/shared/ui/design/data-inspector/module-context.ts similarity index 100% rename from src/shared/ui/design/data-inspector/context.ts rename to src/shared/ui/design/data-inspector/module-context.ts diff --git a/src/shared/ui/design/index.ts b/src/shared/ui/design/index.ts index 92f56168..f36509a5 100644 --- a/src/shared/ui/design/index.ts +++ b/src/shared/ui/design/index.ts @@ -1,4 +1,4 @@ -export { type DesignContext } from "./context"; +export { type DesignContext } from "./module-context"; /** Atoms */ export { Button } from "./button"; diff --git a/src/shared/ui/design/context.ts b/src/shared/ui/design/module-context.ts similarity index 100% rename from src/shared/ui/design/context.ts rename to src/shared/ui/design/module-context.ts diff --git a/src/shared/ui/design/table/row.tsx b/src/shared/ui/design/table/row.tsx index 00cb2f4c..67dea921 100644 --- a/src/shared/ui/design/table/row.tsx +++ b/src/shared/ui/design/table/row.tsx @@ -1,7 +1,7 @@ import { Checkbox, TableCell, TableRow as MuiTableRow } from "@mui/material"; import clsx from "clsx"; import { ChangeEvent, useCallback } from "react"; -import { DesignContext } from "../context"; +import { DesignContext } from "../module-context"; import "./row.scss"; diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts index 26b320c9..15b99dc8 100644 --- a/src/widgets/settings-editor/index.ts +++ b/src/widgets/settings-editor/index.ts @@ -1,4 +1,4 @@ -import { ModuleContext, SettingsEditor as SettingsEditorModule } from "./context"; +import { ModuleContext, SettingsEditor as SettingsEditorModule } from "./module-context"; import { SettingsEditorUI } from "./ui/settings-editor"; export class SettingsEditor extends ModuleContext { diff --git a/src/widgets/settings-editor/context.ts b/src/widgets/settings-editor/module-context.ts similarity index 100% rename from src/widgets/settings-editor/context.ts rename to src/widgets/settings-editor/module-context.ts diff --git a/src/widgets/settings-editor/ui/se-proposal-form.tsx b/src/widgets/settings-editor/ui/se-proposal-form.tsx index 70c40487..3a545708 100644 --- a/src/widgets/settings-editor/ui/se-proposal-form.tsx +++ b/src/widgets/settings-editor/ui/se-proposal-form.tsx @@ -4,7 +4,7 @@ import { FormEventHandler, HTMLProps } from "react"; import { ArgsString } from "../../../shared/lib/args-old"; import { toNEAR } from "../../../shared/lib/converter"; import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; -import { ModuleContext, SettingsEditor } from "../context"; +import { ModuleContext, SettingsEditor } from "../module-context"; import "./se-proposal-form.scss"; diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 2253391d..4fbf7c14 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -6,7 +6,7 @@ import { SchedulingSettingsChange, TokenWhitelistChange } from "../../../feature import { ArgsString } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { ModuleContext, SettingsEditor } from "../context"; +import { ModuleContext, SettingsEditor } from "../module-context"; import { SEProposalForm } from "./se-proposal-form"; import "./settings-editor.scss"; diff --git a/src/widgets/token-balances/index.ts b/src/widgets/token-balances/index.ts index eb6794bc..001c2776 100644 --- a/src/widgets/token-balances/index.ts +++ b/src/widgets/token-balances/index.ts @@ -1,5 +1,5 @@ import { TokenBalancesUI } from "./ui/token-balances"; -import { TokenBalances as TokenBalancesModule } from "./context"; +import { TokenBalances as TokenBalancesModule } from "./module-context"; class TokenBalances { static UI = TokenBalancesUI; diff --git a/src/widgets/token-balances/context.ts b/src/widgets/token-balances/module-context.ts similarity index 100% rename from src/widgets/token-balances/context.ts rename to src/widgets/token-balances/module-context.ts diff --git a/src/widgets/token-balances/ui/token-balances.tsx b/src/widgets/token-balances/ui/token-balances.tsx index 31e79e23..8464cf7a 100644 --- a/src/widgets/token-balances/ui/token-balances.tsx +++ b/src/widgets/token-balances/ui/token-balances.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { Tile, Scrollable, Table } from "../../../shared/ui/design"; import { FT, NEARToken } from "../../../entities"; -import { type TokenBalances } from "../context"; +import { type TokenBalances } from "../module-context"; import "./token-balances.scss"; From 048ec2fba571d8107fb50199343e890cf47060dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 2 Dec 2022 14:57:59 +0400 Subject: [PATCH 435/537] wip: Conditionally hide tile header --- src/shared/ui/design/tile/tile.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/shared/ui/design/tile/tile.tsx b/src/shared/ui/design/tile/tile.tsx index db1f3beb..0b0b7981 100644 --- a/src/shared/ui/design/tile/tile.tsx +++ b/src/shared/ui/design/tile/tile.tsx @@ -34,11 +34,13 @@ export const Tile = ({ subheader, }: TileProps) => (
        - - {headerSlots?.start && {headerSlots?.start}} - {heading &&

        {heading}

        } - {headerSlots?.end && {headerSlots?.end}} -
        + {(headerSlots?.start ?? heading ?? headerSlots?.end ?? null) !== null && ( + + {headerSlots?.start && {headerSlots?.start}} + {heading &&

        {heading}

        } + {headerSlots?.end && {headerSlots?.end}} +
        + )} {subheader &&
        {subheader}
        } From dcc0a571156be5902d56bfa3d0907552af359874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Dec 2022 23:47:47 +0400 Subject: [PATCH 436/537] Fix: Move away from deprecated React API --- src/index.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 0c83cb4a..ddf20302 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,5 +1,5 @@ import "@near-wallet-selector/modal-ui/styles.css"; -import ReactDOM from "react-dom"; +import { createRoot } from "react-dom/client"; import { HashRouter, Routes, Route, Navigate } from "react-router-dom"; import { AppPage } from "./pages/app"; @@ -8,7 +8,11 @@ import { Wallet } from "./entities"; import { DialogsLayer, Sidebar } from "./widgets"; import "./shared/lib/persistent"; -ReactDOM.render( +const appMountPoint = document.querySelector("#root") ?? document.createElement("div"); + +appMountPoint.setAttribute("id", "root"); + +createRoot(appMountPoint).render( @@ -45,7 +49,5 @@ ReactDOM.render( /> - , - - document.querySelector("#root") + ); From 6b16f44940e7c7ff3ae87ce14946c0afdb45597a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Dec 2022 23:52:00 +0400 Subject: [PATCH 437/537] Fix: Hide MI admins table properly --- src/widgets/settings-editor/ui/settings-editor.scss | 1 - src/widgets/settings-editor/ui/settings-editor.tsx | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/widgets/settings-editor/ui/settings-editor.scss b/src/widgets/settings-editor/ui/settings-editor.scss index db040e1c..a3a4d920 100644 --- a/src/widgets/settings-editor/ui/settings-editor.scss +++ b/src/widgets/settings-editor/ui/settings-editor.scss @@ -14,7 +14,6 @@ &-admins { grid-area: admins; - display: none; } &-jobsSettings { diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 4fbf7c14..ec8460b6 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -87,10 +87,12 @@ export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) return (
        - + {/* + + */} Date: Thu, 8 Dec 2022 23:52:40 +0400 Subject: [PATCH 438/537] chore: Format --- src/shared/lib/contracts/multicall.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 83d54743..8bb4f782 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -2,7 +2,7 @@ import { Big, toGas, dateToCron, toYocto } from "../converter"; import { AccountId, Base64String, U128String, U64String } from "../types"; import { viewAccount, viewState, view } from "../wallet"; -import type { FunctionCallAction as daoFunctionCallAction } from "./sputnik-dao"; +import { FunctionCallAction as daoFunctionCallAction } from "./sputnik-dao"; const FACTORY_ADDRESS_SELECTOR: Record = { mainnet: "v1.multicall.near", From 64476548d89b01579f9e98da8578e83284195271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 8 Dec 2022 23:53:48 +0400 Subject: [PATCH 439/537] wip: Rework MI data model --- .../multicall-instance/model/mi-admins.ts | 37 --------------- .../model/mi-settings-provider.tsx | 13 ++++++ .../multicall-instance/model/mi-settings.ts | 33 ++++++++++++-- .../multicall-instance/model/mi-tokens.ts | 39 ---------------- .../multicall-instance/ui/mi-admin.tsx | 2 +- .../multicall-instance/ui/mi-admins.tsx | 45 ++++++++++--------- .../ui/mi-token-whitelist.tsx | 43 +++++++++--------- 7 files changed, 92 insertions(+), 120 deletions(-) delete mode 100644 src/entities/multicall-instance/model/mi-admins.ts create mode 100644 src/entities/multicall-instance/model/mi-settings-provider.tsx delete mode 100644 src/entities/multicall-instance/model/mi-tokens.ts diff --git a/src/entities/multicall-instance/model/mi-admins.ts b/src/entities/multicall-instance/model/mi-admins.ts deleted file mode 100644 index 913cfb06..00000000 --- a/src/entities/multicall-instance/model/mi-admins.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { useEffect, useState } from "react"; - -import { ArgsAccount } from "../../../shared/lib/args-old"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { Props } from "../../../shared/lib/props"; -import { MI } from "../module-context"; - -import { MIInfoModel } from "./mi-settings"; - -export type MIAdminAddresses = { - data: Multicall["admins"] | null; - error: Error | null; - loading: boolean; -}; - -export class MIAdminsModel { - static addressListFetchFx = async ( - daoAddress: MI.Inputs["daoAddress"], - callback: (result: MIAdminAddresses) => void - ) => - await MIInfoModel.dataFetchFx( - `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`, - (multicallInstanceData) => callback(Props.evolve({ data: ({ admins }) => admins }, multicallInstanceData)) - ); - - static useAddressList = (daoAddress: MI.Inputs["daoAddress"]) => { - const [state, stateUpdate] = useState({ - data: null, - error: null, - loading: true, - }); - - useEffect(() => void MIAdminsModel.addressListFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); - - return state; - }; -} diff --git a/src/entities/multicall-instance/model/mi-settings-provider.tsx b/src/entities/multicall-instance/model/mi-settings-provider.tsx new file mode 100644 index 00000000..fe1391b7 --- /dev/null +++ b/src/entities/multicall-instance/model/mi-settings-provider.tsx @@ -0,0 +1,13 @@ +import { PropsWithChildren } from "react"; + +import { MI } from "../module-context"; + +import { MISettingsModel } from "./mi-settings"; + +interface MISettingsProviderProps extends PropsWithChildren, Pick {} + +export const MISettingsProvider = ({ children, daoAddress }: MISettingsProviderProps) => ( + + {children} + +); diff --git a/src/entities/multicall-instance/model/mi-settings.ts b/src/entities/multicall-instance/model/mi-settings.ts index e943f7a8..11caabd0 100644 --- a/src/entities/multicall-instance/model/mi-settings.ts +++ b/src/entities/multicall-instance/model/mi-settings.ts @@ -1,8 +1,21 @@ +import { createContext, useContext, useEffect, useState } from "react"; + import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { AccountId } from "../../../shared/lib/types"; +import { MI } from "../module-context"; + +export class MISettingsModel { + public static readonly data: { + data: Multicall | null; + error: Error | null; + loading: boolean; + } = { + data: null, + error: null, + loading: true, + }; -export class MIInfoModel { /** * Calls the given callback with a result of multicall contract instantiation, * represented as stateful response. @@ -10,9 +23,9 @@ export class MIInfoModel { * @param daoAddress DAO contract address * @param callback Stateful data fetch callback */ - static dataFetchFx = async ( + private static readonly dataFetchFx = async ( daoAddress: AccountId, - callback: (result: { data: Multicall | null; error: Error | null; loading: boolean }) => void + callback: (result: typeof MISettingsModel.data) => void ) => callback( await Multicall.init( @@ -23,4 +36,18 @@ export class MIInfoModel { loading: false, })) ); + + /** + * For context provider usage only. + */ + public static readonly useData = (daoAddress: MI.Inputs["daoAddress"]) => { + const [state, stateUpdate] = useState(MISettingsModel.data); + + useEffect(() => void MISettingsModel.dataFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); + + return state; + }; + + public static readonly Context = createContext(MISettingsModel.data); + public static readonly useContext = () => useContext(MISettingsModel.Context); } diff --git a/src/entities/multicall-instance/model/mi-tokens.ts b/src/entities/multicall-instance/model/mi-tokens.ts deleted file mode 100644 index 75524236..00000000 --- a/src/entities/multicall-instance/model/mi-tokens.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { useEffect, useState } from "react"; - -import { ArgsAccount } from "../../../shared/lib/args-old"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { Props } from "../../../shared/lib/props"; -import { MI } from "../module-context"; - -import { MIInfoModel } from "./mi-settings"; - -export type MITokenWhitelist = { - data: Multicall["tokensWhitelist"] | null; - error: Error | null; - loading: boolean; -}; - -export class MITokensModel { - static whitelistFetchFx = async ( - daoAddress: MI.Inputs["daoAddress"], - callback: (result: MITokenWhitelist) => void - ) => - await MIInfoModel.dataFetchFx( - `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}`, - - (multicallInstanceData) => - callback(Props.evolve({ data: ({ tokensWhitelist }) => tokensWhitelist }, multicallInstanceData)) - ); - - static useWhitelist = (daoAddress: MI.Inputs["daoAddress"]) => { - const [state, stateUpdate] = useState({ - data: null, - error: null, - loading: true, - }); - - useEffect(() => void MITokensModel.whitelistFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); - - return state; - }; -} diff --git a/src/entities/multicall-instance/ui/mi-admin.tsx b/src/entities/multicall-instance/ui/mi-admin.tsx index 6f9a88a9..ac1d1d3b 100644 --- a/src/entities/multicall-instance/ui/mi-admin.tsx +++ b/src/entities/multicall-instance/ui/mi-admin.tsx @@ -1,6 +1,6 @@ import { NearLink, NearLinkProps } from "../../../shared/ui/design"; -interface MIAdminProps extends NearLinkProps {} +export interface MIAdminProps extends NearLinkProps {} const MIAdmin = ({ address }: MIAdminProps) => ( diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 313f05b9..de2aca73 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,32 +1,37 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { MIAdminsModel } from "../model/mi-admins"; +import { MISettingsModel } from "../model/mi-settings"; +import { MISettingsProvider } from "../model/mi-settings-provider"; import { MI } from "../module-context"; -import { miAdminAsTableRow } from "./mi-admin"; +import { miAdminAsTableRow, MIAdminProps } from "./mi-admin"; interface MIAdminsTableProps extends MI.Inputs { className?: string; + itemsAdditional?: MIAdminProps["address"][]; } -export const MIAdminsTable = ({ className, daoAddress }: MIAdminsTableProps) => { - const { data, error, loading } = MIAdminsModel.useAddressList(daoAddress); +export const MIAdminsTable = ({ className, daoAddress, itemsAdditional }: MIAdminsTableProps) => { + const { data, error, loading } = MISettingsModel.useContext(), + items = (data?.admins ?? []).concat(itemsAdditional ?? []); return ( - - -
    - - + + + +
    + + + ); }; diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index c5ab4e4b..8a602aa0 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,5 +1,6 @@ import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; -import { MITokensModel } from "../model/mi-tokens"; +import { MISettingsModel } from "../model/mi-settings"; +import { MISettingsProvider } from "../model/mi-settings-provider"; import { MI } from "../module-context"; import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; @@ -21,26 +22,28 @@ export const MITokenWhitelistTable = ({ onItemsSelected, subheader, }: MITokenWhitelistTableProps) => { - const { data, error, loading } = MITokensModel.useWhitelist(daoAddress), - items = data?.concat(itemsAdditional ?? []); + const { data, error, loading } = MISettingsModel.useContext(), + items = (data?.tokensWhitelist ?? []).concat(itemsAdditional ?? []); return ( - - -
    - - + + + +
    + + + ); }; From 6b5306a5b04157e0cf7c8b9fd9ce348f6421ea71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 9 Dec 2022 00:15:13 +0400 Subject: [PATCH 440/537] wip: Connect MI settings provider properly --- src/entities/multicall-instance/index.ts | 2 + .../multicall-instance/model/mi-settings.ts | 3 +- .../multicall-instance/ui/mi-admins.tsx | 37 +++++------ .../{model => ui}/mi-settings-provider.tsx | 3 +- .../ui/mi-token-whitelist.tsx | 37 +++++------ .../settings-editor/ui/settings-editor.tsx | 66 ++++++++++--------- 6 files changed, 72 insertions(+), 76 deletions(-) rename src/entities/multicall-instance/{model => ui}/mi-settings-provider.tsx (88%) diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 2cf1086d..e49fc169 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,5 +1,6 @@ import { MI as MIModule, ModuleContext } from "./module-context"; import { MIAdminsTable } from "./ui/mi-admins"; +import { MISettingsProvider } from "./ui/mi-settings-provider"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; export { type MIModule }; @@ -10,4 +11,5 @@ export { type MIModule }; export class MI extends ModuleContext { static AdminsTable = MIAdminsTable; static TokenWhitelistTable = MITokenWhitelistTable; + static SettingsProvider = MISettingsProvider; } diff --git a/src/entities/multicall-instance/model/mi-settings.ts b/src/entities/multicall-instance/model/mi-settings.ts index 11caabd0..2543b822 100644 --- a/src/entities/multicall-instance/model/mi-settings.ts +++ b/src/entities/multicall-instance/model/mi-settings.ts @@ -2,7 +2,6 @@ import { createContext, useContext, useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { AccountId } from "../../../shared/lib/types"; import { MI } from "../module-context"; export class MISettingsModel { @@ -24,7 +23,7 @@ export class MISettingsModel { * @param callback Stateful data fetch callback */ private static readonly dataFetchFx = async ( - daoAddress: AccountId, + daoAddress: MI.Inputs["daoAddress"], callback: (result: typeof MISettingsModel.data) => void ) => callback( diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index de2aca73..ee696590 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,6 +1,5 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { MISettingsModel } from "../model/mi-settings"; -import { MISettingsProvider } from "../model/mi-settings-provider"; import { MI } from "../module-context"; import { miAdminAsTableRow, MIAdminProps } from "./mi-admin"; @@ -10,28 +9,26 @@ interface MIAdminsTableProps extends MI.Inputs { itemsAdditional?: MIAdminProps["address"][]; } -export const MIAdminsTable = ({ className, daoAddress, itemsAdditional }: MIAdminsTableProps) => { +export const MIAdminsTable = ({ className, itemsAdditional }: MIAdminsTableProps) => { const { data, error, loading } = MISettingsModel.useContext(), items = (data?.admins ?? []).concat(itemsAdditional ?? []); return ( - - - -
    - - - + + +
    + + ); }; diff --git a/src/entities/multicall-instance/model/mi-settings-provider.tsx b/src/entities/multicall-instance/ui/mi-settings-provider.tsx similarity index 88% rename from src/entities/multicall-instance/model/mi-settings-provider.tsx rename to src/entities/multicall-instance/ui/mi-settings-provider.tsx index fe1391b7..8578ffdb 100644 --- a/src/entities/multicall-instance/model/mi-settings-provider.tsx +++ b/src/entities/multicall-instance/ui/mi-settings-provider.tsx @@ -1,8 +1,7 @@ import { PropsWithChildren } from "react"; import { MI } from "../module-context"; - -import { MISettingsModel } from "./mi-settings"; +import { MISettingsModel } from "../model/mi-settings"; interface MISettingsProviderProps extends PropsWithChildren, Pick {} diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index 8a602aa0..e8215add 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,6 +1,5 @@ import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; import { MISettingsModel } from "../model/mi-settings"; -import { MISettingsProvider } from "../model/mi-settings-provider"; import { MI } from "../module-context"; import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; @@ -26,24 +25,22 @@ export const MITokenWhitelistTable = ({ items = (data?.tokensWhitelist ?? []).concat(itemsAdditional ?? []); return ( - - - -
    - - - + + +
    + + ); }; diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index ec8460b6..709d1a76 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -86,37 +86,39 @@ export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) ); return ( -
    - {/* - - */} - - - - - - -
    + +
    + {false && ( + + )} + + + + + + +
    +
    ); }; From be38cae2edc7d0e5071fe37783d3537606a67463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 9 Dec 2022 03:32:25 +0400 Subject: [PATCH 441/537] wip: Apply code review and naming remarks --- src/entities/index.ts | 4 +-- src/entities/job/index.ts | 4 +-- src/entities/job/lib/job-normalized.ts | 8 ++--- src/entities/job/model/job-model.ts | 14 ++++----- src/entities/job/module-context.ts | 14 ++++----- src/entities/job/ui/job.tsx | 6 ++-- src/entities/multicall-instance/index.ts | 4 +-- .../multicall-instance/model/mi-settings.ts | 6 ++-- .../multicall-instance/module-context.ts | 2 +- .../multicall-instance/ui/mi-admins.tsx | 3 +- .../ui/mi-settings-provider.tsx | 4 +-- .../ui/mi-token-whitelist.tsx | 4 +-- src/features/external-login/index.ts | 8 ++--- ...l-dialogs.ts => external-login-dialogs.ts} | 2 +- ...dialog.scss => external-login-dialog.scss} | 0 ...dialogs.tsx => external-login-dialogs.tsx} | 10 ++++--- .../{el-menu.tsx => external-login-menu.tsx} | 14 +++++---- src/features/index.ts | 4 +-- .../scheduling/settings-change/index.ts | 10 +++---- .../settings-change/module-context.ts | 10 +++---- .../ui/scheduling-settings-change.scss | 3 ++ ...orm.tsx => scheduling-settings-change.tsx} | 30 +++++++++---------- src/features/token/whitelist-change/index.ts | 8 +++++ .../whitelist-change/module-context.ts | 7 ++--- .../ui/token-whitelist-change.scss | 3 ++ .../ui/token-whitelist-change.tsx} | 24 +++++++-------- src/features/tokens/whitelist-change/index.ts | 8 ----- .../settings-editor/ui/settings-editor.scss | 16 ++-------- .../settings-editor/ui/settings-editor.tsx | 15 ++-------- ...orm.scss => settings-proposal-create.scss} | 4 +-- ...-form.tsx => settings-proposal-create.tsx} | 30 +++++++++---------- 31 files changed, 133 insertions(+), 146 deletions(-) rename src/features/external-login/model/{el-dialogs.ts => external-login-dialogs.ts} (97%) rename src/features/external-login/ui/{el-dialog.scss => external-login-dialog.scss} (100%) rename src/features/external-login/ui/{el-dialogs.tsx => external-login-dialogs.tsx} (91%) rename src/features/external-login/ui/{el-menu.tsx => external-login-menu.tsx} (54%) create mode 100644 src/features/scheduling/settings-change/ui/scheduling-settings-change.scss rename src/features/scheduling/settings-change/ui/{scheduling-settings-form.tsx => scheduling-settings-change.tsx} (90%) create mode 100644 src/features/token/whitelist-change/index.ts rename src/features/{tokens => token}/whitelist-change/module-context.ts (81%) create mode 100644 src/features/token/whitelist-change/ui/token-whitelist-change.scss rename src/features/{tokens/whitelist-change/ui/tokens-whitelist-form.tsx => token/whitelist-change/ui/token-whitelist-change.tsx} (90%) delete mode 100644 src/features/tokens/whitelist-change/index.ts rename src/widgets/settings-editor/ui/{se-proposal-form.scss => settings-proposal-create.scss} (96%) rename src/widgets/settings-editor/ui/{se-proposal-form.tsx => settings-proposal-create.tsx} (77%) diff --git a/src/entities/index.ts b/src/entities/index.ts index abb1d70e..a6920cc0 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ export { Task } from "./task"; -export { Job, type JobModule } from "./job"; +export { Job, type JobEntity } from "./job"; export { FT, type FTModule } from "./fungible-token"; -export { MI, type MIModule } from "./multicall-instance"; +export { MI, type MIEntity } from "./multicall-instance"; export { NEARToken, type NEARTokenModule } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index 640709f9..1e53de43 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,7 +1,7 @@ -import { ModuleContext, Job as JobModule } from "./module-context"; +import { ModuleContext, Entity as JobEntity } from "./module-context"; import { JobsTable } from "./ui/jobs-table"; -export { type JobModule }; +export { type JobEntity }; export class Job extends ModuleContext { static EntriesTable = JobsTable; diff --git a/src/entities/job/lib/job-normalized.ts b/src/entities/job/lib/job-normalized.ts index 57170594..db0cf3c5 100644 --- a/src/entities/job/lib/job-normalized.ts +++ b/src/entities/job/lib/job-normalized.ts @@ -1,7 +1,7 @@ import { Base64 } from "js-base64"; import { Big } from "../../../shared/lib/converter"; -import { ModuleContext, Job } from "../module-context"; +import { ModuleContext, Entity } from "../module-context"; /** * Job status is: @@ -10,7 +10,7 @@ import { ModuleContext, Job } from "../module-context"; * - Expired: job not active, and execution moment is in the past. * - Inactive: job not active, but execution moment in the future. */ -const jobToStatus = ({ job }: Job.Data): Job.Status => { +const jobToStatus = ({ job }: Entity.Data): Entity.Status => { if (job.is_active) { if (job.run_count > -1) return ModuleContext.Status.Running; else return ModuleContext.Status.Active; @@ -29,7 +29,7 @@ const jobToStatus = ({ job }: Job.Data): Job.Status => { * * @returns Updated job data structure. */ -const jobToJobWithMulticallsDataDecoded = ({ id, job }: Job.Data): Job.Data => ({ +const jobToJobWithMulticallsDataDecoded = ({ id, job }: Entity.Data): Entity.Data => ({ id, job: { @@ -61,7 +61,7 @@ const jobToJobWithMulticallsDataDecoded = ({ id, job }: Job.Data): Job.Data => ( * * @returns Extended job data structure. */ -const jobToJobWithStatus = (job: Job.Data): Job.DataWithStatus => ({ +const jobToJobWithStatus = (job: Entity.Data): Entity.DataWithStatus => ({ ...job, job: { ...job.job, status: ModuleContext.Status[jobToStatus(job)] }, }); diff --git a/src/entities/job/model/job-model.ts b/src/entities/job/model/job-model.ts index 0d6409c2..c304b96c 100644 --- a/src/entities/job/model/job-model.ts +++ b/src/entities/job/model/job-model.ts @@ -1,19 +1,19 @@ import { useEffect, useState } from "react"; -import { Job } from "../module-context"; +import { Entity } from "../module-context"; import { JobNormalized } from "../lib/job-normalized"; -type JobAllEntries = { +type Jobs = { /** Jobs indexed by ID for easy access to each particular job */ - data: Record | null; + data: Record | null; error?: Error | null; loading: boolean; }; export class JobModel { static allEntriesFetchFx = async ( - { multicallInstance }: Job.Inputs["adapters"], - callback: (result: JobAllEntries) => void + { multicallInstance }: Entity.Inputs["adapters"], + callback: (result: Jobs) => void ) => callback( await multicallInstance @@ -37,8 +37,8 @@ export class JobModel { })) ); - static useAllEntries = (adapters: Job.Inputs["adapters"]) => { - const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); + static useAllEntries = (adapters: Entity.Inputs["adapters"]) => { + const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); useEffect(() => void JobModel.allEntriesFetchFx(adapters, stateUpdate), [adapters, stateUpdate]); diff --git a/src/entities/job/module-context.ts b/src/entities/job/module-context.ts index f88ba349..e6fb6f76 100644 --- a/src/entities/job/module-context.ts +++ b/src/entities/job/module-context.ts @@ -1,6 +1,6 @@ import { JobData, Multicall } from "../../shared/lib/contracts/multicall"; -export namespace Job { +export namespace Entity { export interface Inputs { className?: string; adapters: { multicallInstance: Multicall }; @@ -22,13 +22,13 @@ export namespace Job { } export class ModuleContext { - static readonly Status = Job.Status; + static readonly Status = Entity.Status; static StatusIcons = { - [Job.Status.Inactive]: "🟡", - [Job.Status.Expired]: "🔴", - [Job.Status.Active]: "🟢", - [Job.Status.Running]: "🟣", - [Job.Status.Unknown]: "❔", + [Entity.Status.Inactive]: "🟡", + [Entity.Status.Expired]: "🔴", + [Entity.Status.Active]: "🟢", + [Entity.Status.Running]: "🟣", + [Entity.Status.Unknown]: "❔", }; } diff --git a/src/entities/job/ui/job.tsx b/src/entities/job/ui/job.tsx index 1d75d266..41c6d3a7 100644 --- a/src/entities/job/ui/job.tsx +++ b/src/entities/job/ui/job.tsx @@ -2,13 +2,13 @@ import { NavLink } from "react-router-dom"; import { Big, toTGas } from "../../../shared/lib/converter"; import { DataInspector, IconLabel } from "../../../shared/ui/design"; -import { ModuleContext, Job } from "../module-context"; +import { ModuleContext, Entity } from "../module-context"; import "./job.scss"; const _Job = "Job"; -const JobDisplayStatus = ({ job }: Pick) => { +const JobDisplayStatus = ({ job }: Pick) => { const statusTextByStatus = { ...ModuleContext.Status, [ModuleContext.Status.Running]: `${ModuleContext.Status.Running}: ${job.run_count + 1}/${ @@ -24,7 +24,7 @@ const JobDisplayStatus = ({ job }: Pick) => { ); }; -export const jobAsTableRow = ({ id, job }: Job.DataWithStatus) => ({ +export const jobAsTableRow = ({ id, job }: Entity.DataWithStatus) => ({ content: [ , id, diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index e49fc169..92baab6e 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,9 +1,9 @@ -import { MI as MIModule, ModuleContext } from "./module-context"; +import { Entity as MIEntity, ModuleContext } from "./module-context"; import { MIAdminsTable } from "./ui/mi-admins"; import { MISettingsProvider } from "./ui/mi-settings-provider"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; -export { type MIModule }; +export { type MIEntity }; /** * Multicall Instance entity diff --git a/src/entities/multicall-instance/model/mi-settings.ts b/src/entities/multicall-instance/model/mi-settings.ts index 2543b822..cec22b18 100644 --- a/src/entities/multicall-instance/model/mi-settings.ts +++ b/src/entities/multicall-instance/model/mi-settings.ts @@ -2,7 +2,7 @@ import { createContext, useContext, useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { MI } from "../module-context"; +import { Entity } from "../module-context"; export class MISettingsModel { public static readonly data: { @@ -23,7 +23,7 @@ export class MISettingsModel { * @param callback Stateful data fetch callback */ private static readonly dataFetchFx = async ( - daoAddress: MI.Inputs["daoAddress"], + daoAddress: Entity.Inputs["daoAddress"], callback: (result: typeof MISettingsModel.data) => void ) => callback( @@ -39,7 +39,7 @@ export class MISettingsModel { /** * For context provider usage only. */ - public static readonly useData = (daoAddress: MI.Inputs["daoAddress"]) => { + public static readonly useData = (daoAddress: Entity.Inputs["daoAddress"]) => { const [state, stateUpdate] = useState(MISettingsModel.data); useEffect(() => void MISettingsModel.dataFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); diff --git a/src/entities/multicall-instance/module-context.ts b/src/entities/multicall-instance/module-context.ts index b183684c..fc404d94 100644 --- a/src/entities/multicall-instance/module-context.ts +++ b/src/entities/multicall-instance/module-context.ts @@ -5,7 +5,7 @@ import { toYocto } from "../../shared/lib/converter"; /** * Type declaration for Multicall Instance entity */ -export namespace MI { +export namespace Entity { export interface Inputs { daoAddress: SputnikDAO["address"]; } diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index ee696590..980084e5 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,10 +1,9 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { MISettingsModel } from "../model/mi-settings"; -import { MI } from "../module-context"; import { miAdminAsTableRow, MIAdminProps } from "./mi-admin"; -interface MIAdminsTableProps extends MI.Inputs { +interface MIAdminsTableProps { className?: string; itemsAdditional?: MIAdminProps["address"][]; } diff --git a/src/entities/multicall-instance/ui/mi-settings-provider.tsx b/src/entities/multicall-instance/ui/mi-settings-provider.tsx index 8578ffdb..fbe5ad64 100644 --- a/src/entities/multicall-instance/ui/mi-settings-provider.tsx +++ b/src/entities/multicall-instance/ui/mi-settings-provider.tsx @@ -1,9 +1,9 @@ import { PropsWithChildren } from "react"; -import { MI } from "../module-context"; +import { Entity } from "../module-context"; import { MISettingsModel } from "../model/mi-settings"; -interface MISettingsProviderProps extends PropsWithChildren, Pick {} +interface MISettingsProviderProps extends PropsWithChildren, Pick {} export const MISettingsProvider = ({ children, daoAddress }: MISettingsProviderProps) => ( diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index e8215add..10280bd7 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,10 +1,9 @@ import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; import { MISettingsModel } from "../model/mi-settings"; -import { MI } from "../module-context"; import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; -interface MITokenWhitelistTableProps extends MI.Inputs, Pick { +interface MITokenWhitelistTableProps extends Pick { ItemProps?: TableProps["RowProps"]; className?: string; itemsAdditional?: MIWhitelistedTokenProps["address"][]; @@ -14,7 +13,6 @@ interface MITokenWhitelistTableProps extends MI.Inputs, Pick { diff --git a/src/features/external-login/ui/el-dialog.scss b/src/features/external-login/ui/external-login-dialog.scss similarity index 100% rename from src/features/external-login/ui/el-dialog.scss rename to src/features/external-login/ui/external-login-dialog.scss diff --git a/src/features/external-login/ui/el-dialogs.tsx b/src/features/external-login/ui/external-login-dialogs.tsx similarity index 91% rename from src/features/external-login/ui/el-dialogs.tsx rename to src/features/external-login/ui/external-login-dialogs.tsx index 2cf705a9..10fa6d06 100644 --- a/src/features/external-login/ui/el-dialogs.tsx +++ b/src/features/external-login/ui/external-login-dialogs.tsx @@ -7,9 +7,9 @@ import { STORAGE } from "../../../shared/lib/persistent"; import { Validation } from "../../../shared/lib/validation"; import { Dialog, TextInput, Tooltip } from "../../../shared/ui/design"; import { ModuleContext } from "../module-context"; -import { ELDialogsModel } from "../model/el-dialogs"; +import { ExternalLoginDialogsModel } from "../model/external-login-dialogs"; -import "./el-dialog.scss"; +import "./external-login-dialog.scss"; interface ExternalLoginDialogProps extends Pick, "className" | "onClose" | "open" | "title"> { @@ -77,8 +77,8 @@ const ExternalLoginDialog = ({ className, method, onClose, open, title }: Extern ); }; -export const ELDialogs = () => { - const { dialogsVisibility, closeHandlerBinding } = ELDialogsModel.useVisibilityState(); +export const Dialogs = () => { + const { dialogsVisibility, closeHandlerBinding } = ExternalLoginDialogsModel.useVisibilityState(); return Object.values(ModuleContext.METHODS).map((loginMethod) => ( { /> )); }; + +Dialogs.displayName = `${_ExternalLoginDialog}s`; diff --git a/src/features/external-login/ui/el-menu.tsx b/src/features/external-login/ui/external-login-menu.tsx similarity index 54% rename from src/features/external-login/ui/el-menu.tsx rename to src/features/external-login/ui/external-login-menu.tsx index 8a0c825e..06488e00 100644 --- a/src/features/external-login/ui/el-menu.tsx +++ b/src/features/external-login/ui/external-login-menu.tsx @@ -2,24 +2,28 @@ import { PreviewOutlined } from "@mui/icons-material"; import { ComponentProps } from "react"; import { PopupMenu } from "../../../shared/ui/design"; -import { ModuleContext as ModuleContext } from "../module-context"; -import { ELDialogsModel } from "../model/el-dialogs"; +import { ModuleContext } from "../module-context"; +import { ExternalLoginDialogsModel } from "../model/external-login-dialogs"; -interface ELMenuProps extends Pick, "triggerClassName"> { +interface MenuProps extends Pick, "triggerClassName"> { FeatureFlags: { ExternalLogin: Record; }; } -export const ELMenu = ({ FeatureFlags, triggerClassName }: ELMenuProps) => ( +const _ExternalLoginMenu = "ExternalLoginMenu"; + +export const Menu = ({ FeatureFlags, triggerClassName }: MenuProps) => ( } items={Object.values(ModuleContext.METHODS).map(({ title, type }) => ({ disabled: !FeatureFlags.ExternalLogin[type], key: type, - onClick: () => ELDialogsModel.dialogOpenRequested(type), + onClick: () => ExternalLoginDialogsModel.dialogOpenRequested(type), title, }))} {...{ triggerClassName }} /> ); + +Menu.displayName = _ExternalLoginMenu; diff --git a/src/features/index.ts b/src/features/index.ts index 15e1a763..1e40fac1 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,3 +1,3 @@ export { ExternalLogin } from "./external-login"; -export { SchedulingSettingsChange, type SchedulingSettingsChangeModule } from "./scheduling/settings-change"; -export { TokenWhitelistChange, type TokenWhitelistChangeModule } from "./tokens/whitelist-change"; +export { SchedulingSettingsChange, type SchedulingSettingsChangeFeature } from "./scheduling/settings-change"; +export { TokenWhitelistChange, type TokenWhitelistChangeFeature } from "./token/whitelist-change"; diff --git a/src/features/scheduling/settings-change/index.ts b/src/features/scheduling/settings-change/index.ts index 71b43b90..3aeeb3b4 100644 --- a/src/features/scheduling/settings-change/index.ts +++ b/src/features/scheduling/settings-change/index.ts @@ -1,8 +1,8 @@ -import { ModuleContext, type SchedulingSettingsChange as SchedulingSettingsChangeModule } from "./module-context"; -import { SchedulingSettingsForm } from "./ui/scheduling-settings-form"; +import { ModuleContext, Feature as SchedulingSettingsChangeFeature } from "./module-context"; +import { Form } from "./ui/scheduling-settings-change"; + +export { type SchedulingSettingsChangeFeature }; export class SchedulingSettingsChange extends ModuleContext { - static Form = SchedulingSettingsForm; + public static readonly Form = Form; } - -export { type SchedulingSettingsChangeModule }; diff --git a/src/features/scheduling/settings-change/module-context.ts b/src/features/scheduling/settings-change/module-context.ts index aded758b..c1009801 100644 --- a/src/features/scheduling/settings-change/module-context.ts +++ b/src/features/scheduling/settings-change/module-context.ts @@ -1,15 +1,15 @@ import { HTMLProps } from "react"; -import { MI, MIModule } from "../../../entities"; +import { MI, MIEntity } from "../../../entities"; import { MulticallSettingsDiff, Multicall } from "../../../shared/lib/contracts/multicall"; import { DesignContext } from "../../../shared/ui/design"; -export namespace SchedulingSettingsChange { - export type DiffKey = MIModule.ParamKey; +export namespace Feature { + export type DiffKey = MIEntity.ParamKey; - export type FormState = Pick; + export type FormState = Pick; - export interface Inputs extends Omit, "onChange">, Pick { + export interface Inputs extends Omit, "onChange"> { adapters: { multicallInstance: Multicall; }; diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-change.scss b/src/features/scheduling/settings-change/ui/scheduling-settings-change.scss new file mode 100644 index 00000000..23a5d68e --- /dev/null +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-change.scss @@ -0,0 +1,3 @@ +.SchedulingSettingsChange { + grid-area: SchedulingSettingsChange; +} diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx similarity index 90% rename from src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx rename to src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx index de147166..f2820d20 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-form.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx @@ -5,25 +5,23 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { ArgsString } from "../../../../shared/lib/args-old"; import { toNEAR, toYocto } from "../../../../shared/lib/converter"; import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../../shared/ui/design"; -import { ModuleContext, SchedulingSettingsChange } from "../module-context"; - -export const SchedulingSettingsForm = ({ - adapters: { multicallInstance }, - className, - disabled, - onEdit, - resetTrigger, -}: SchedulingSettingsChange.Inputs) => { +import { ModuleContext, Feature } from "../module-context"; + +import "./scheduling-settings-change.scss"; + +const _SchedulingSettingsChange = "SchedulingSettingsChange"; + +export const Form = ({ adapters: { multicallInstance }, disabled, onEdit, resetTrigger }: Feature.Inputs) => { const [editModeEnabled, editModeSwitch] = useState(false); - const formInitialState: SchedulingSettingsChange.FormState = { + const formInitialState: Feature.FormState = { [ModuleContext.DiffKey.croncatManager]: "", [ModuleContext.DiffKey.jobBond]: "", }; const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ - useState(formInitialState.croncatManager), - useState(formInitialState.jobBond), + useState(formInitialState.croncatManager), + useState(formInitialState.jobBond), ]; const formFields = { @@ -66,7 +64,7 @@ export const SchedulingSettingsForm = ({ return ( - ({ croncatManager, jobBond }[id] === formInitialState[id as SchedulingSettingsChange.DiffKey] || - { croncatManager, jobBond }[id] === multicallInstance[id as SchedulingSettingsChange.DiffKey] + ({ croncatManager, jobBond }[id] === formInitialState[id as Feature.DiffKey] || + { croncatManager, jobBond }[id] === multicallInstance[id as Feature.DiffKey] ? null : "blue"), @@ -166,3 +164,5 @@ export const SchedulingSettingsForm = ({ ); }; + +Form.displayName = _SchedulingSettingsChange; diff --git a/src/features/token/whitelist-change/index.ts b/src/features/token/whitelist-change/index.ts new file mode 100644 index 00000000..594f75ca --- /dev/null +++ b/src/features/token/whitelist-change/index.ts @@ -0,0 +1,8 @@ +import { ModuleContext, Feature as TokenWhitelistChangeFeature } from "./module-context"; +import { Form } from "./ui/token-whitelist-change"; + +export { type TokenWhitelistChangeFeature }; + +export class TokenWhitelistChange extends ModuleContext { + public static readonly Form = Form; +} diff --git a/src/features/tokens/whitelist-change/module-context.ts b/src/features/token/whitelist-change/module-context.ts similarity index 81% rename from src/features/tokens/whitelist-change/module-context.ts rename to src/features/token/whitelist-change/module-context.ts index 746e12d3..271584fc 100644 --- a/src/features/tokens/whitelist-change/module-context.ts +++ b/src/features/token/whitelist-change/module-context.ts @@ -1,13 +1,12 @@ import { HTMLProps } from "react"; -import { MulticallTokenWhitelistDiffKey, type MulticallSettingsDiff } from "../../../shared/lib/contracts/multicall"; -import { MIModule } from "../../../entities"; +import { MulticallTokenWhitelistDiffKey, MulticallSettingsDiff } from "../../../shared/lib/contracts/multicall"; import { DesignContext } from "../../../shared/ui/design"; -export namespace TokenWhitelistChange { +export namespace Feature { export type DiffKey = MulticallTokenWhitelistDiffKey; - export interface Inputs extends Omit, "onChange">, MIModule.Inputs { + export interface Inputs extends Omit, "onChange"> { onEdit: (payload: Pick) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } diff --git a/src/features/token/whitelist-change/ui/token-whitelist-change.scss b/src/features/token/whitelist-change/ui/token-whitelist-change.scss new file mode 100644 index 00000000..f23bda3a --- /dev/null +++ b/src/features/token/whitelist-change/ui/token-whitelist-change.scss @@ -0,0 +1,3 @@ +.TokenWhitelistChange { + grid-area: TokenWhitelistChange; +} diff --git a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx b/src/features/token/whitelist-change/ui/token-whitelist-change.tsx similarity index 90% rename from src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx rename to src/features/token/whitelist-change/ui/token-whitelist-change.tsx index b8701211..d146adbc 100644 --- a/src/features/tokens/whitelist-change/ui/tokens-whitelist-form.tsx +++ b/src/features/token/whitelist-change/ui/token-whitelist-change.tsx @@ -5,19 +5,17 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { TextInput, Tooltip } from "../../../../shared/ui/design"; import { ArgsString } from "../../../../shared/lib/args-old"; import { MI } from "../../../../entities"; -import { ModuleContext, TokenWhitelistChange } from "../module-context"; - -export const TokenWhitelistForm = ({ - className, - daoAddress, - disabled, - onEdit, - resetTrigger, -}: TokenWhitelistChange.Inputs) => { +import { ModuleContext, Feature } from "../module-context"; + +import "./token-whitelist-change.scss"; + +const _TokenWhitelistChange = "TokenWhitelistChange"; + +export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { const [editModeEnabled, editModeSwitch] = useState(false); - const [addTokens, markForAddition] = useState(new Set()), - [removeTokens, markForRemoval] = useState(new Set()); + const [addTokens, markForAddition] = useState(new Set()), + [removeTokens, markForRemoval] = useState(new Set()); const tokenToAddAddress = useMemo(() => new ArgsString(""), []); @@ -89,6 +87,7 @@ export const TokenWhitelistForm = ({ void null, }, }} + className={_TokenWhitelistChange} headerSlots={{ end: editModeEnabled ? ( @@ -124,7 +123,8 @@ export const TokenWhitelistForm = ({ void null ) } - {...{ className, daoAddress }} /> ); }; + +Form.displayName = _TokenWhitelistChange; diff --git a/src/features/tokens/whitelist-change/index.ts b/src/features/tokens/whitelist-change/index.ts deleted file mode 100644 index b276a4bd..00000000 --- a/src/features/tokens/whitelist-change/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ModuleContext, type TokenWhitelistChange as TokenWhitelistChangeModule } from "./module-context"; -import { TokenWhitelistForm } from "./ui/tokens-whitelist-form"; - -export class TokenWhitelistChange extends ModuleContext { - static Form = TokenWhitelistForm; -} - -export { type TokenWhitelistChangeModule }; diff --git a/src/widgets/settings-editor/ui/settings-editor.scss b/src/widgets/settings-editor/ui/settings-editor.scss index a3a4d920..fcf179c0 100644 --- a/src/widgets/settings-editor/ui/settings-editor.scss +++ b/src/widgets/settings-editor/ui/settings-editor.scss @@ -9,18 +9,6 @@ height: 100%; grid-template-areas: - "tokenWhitelist jobsSettings" - "tokenWhitelist SEProposalForm"; - - &-admins { - grid-area: admins; - } - - &-jobsSettings { - grid-area: jobsSettings; - } - - &-tokenWhitelist { - grid-area: tokenWhitelist; - } + "TokenWhitelistChange SchedulingSettingsChange" + "TokenWhitelistChange SettingsProposalCreate"; } diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 709d1a76..0af5f0ad 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -8,7 +8,7 @@ import { Multicall } from "../../../shared/lib/contracts/multicall"; import { signAndSendTxs } from "../../../shared/lib/wallet"; import { ModuleContext, SettingsEditor } from "../module-context"; -import { SEProposalForm } from "./se-proposal-form"; +import { SettingsProposalCreate } from "./settings-proposal-create"; import "./settings-editor.scss"; const _SettingsEditor = "SettingsEditor"; @@ -88,31 +88,22 @@ export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) return (
    - {false && ( - - )} + {false && } - { +export interface SettingsProposalCreateProps extends HTMLProps { changesDiff: SettingsEditor.Diff; - classNameRoot: Required>["className"]; description: SettingsEditor.ProposalDescription; formValues: { proposalDescription: ArgsString }; editMode: boolean; @@ -19,10 +18,11 @@ export interface SEProposalFormProps extends HTMLProps { onSubmit: FormEventHandler; } -export const SEProposalForm = ({ +const _SettingsProposalCreate = "SettingsProposalCreate"; + +export const SettingsProposalCreate = ({ changesDiff, className, - classNameRoot, description, disabled, formValues, @@ -30,41 +30,41 @@ export const SEProposalForm = ({ onCancel, onDescriptionUpdate, onSubmit, -}: SEProposalFormProps) => ( +}: SettingsProposalCreateProps) => ( -

    +

    {disabled ? "Current account has no permission to propose changes" : "Start editing to create config changes proposal template"}

    -
    +
    {Object.values(ModuleContext.DiffKey).map( (DiffKey) => changesDiff[DiffKey].length > 0 && (
    -

    +

    {ModuleContext.DiffMeta[DiffKey].description + ":"}

    -
      +
        {(Array.isArray(changesDiff[DiffKey]) ? Array.from(changesDiff[DiffKey]) : [changesDiff[DiffKey]] ).map((data) => (
      • - +
        Date: Fri, 9 Dec 2022 03:35:05 +0400 Subject: [PATCH 442/537] wip: Apply code review and naming remarks --- src/entities/job/model/{job-model.ts => job-info.ts} | 4 ++-- src/entities/job/ui/jobs-table.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) rename src/entities/job/model/{job-model.ts => job-info.ts} (91%) diff --git a/src/entities/job/model/job-model.ts b/src/entities/job/model/job-info.ts similarity index 91% rename from src/entities/job/model/job-model.ts rename to src/entities/job/model/job-info.ts index c304b96c..d8bcd381 100644 --- a/src/entities/job/model/job-model.ts +++ b/src/entities/job/model/job-info.ts @@ -10,7 +10,7 @@ type Jobs = { loading: boolean; }; -export class JobModel { +export class JobInfoModel { static allEntriesFetchFx = async ( { multicallInstance }: Entity.Inputs["adapters"], callback: (result: Jobs) => void @@ -40,7 +40,7 @@ export class JobModel { static useAllEntries = (adapters: Entity.Inputs["adapters"]) => { const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - useEffect(() => void JobModel.allEntriesFetchFx(adapters, stateUpdate), [adapters, stateUpdate]); + useEffect(() => void JobInfoModel.allEntriesFetchFx(adapters, stateUpdate), [adapters, stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/jobs-table.tsx index 77097eaf..75bb1161 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/jobs-table.tsx @@ -1,18 +1,18 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { JobModel } from "../model/job-model"; -import { Job } from "../module-context"; +import { JobInfoModel } from "../model/job-info"; +import { Entity } from "../module-context"; import { jobAsTableRow } from "./job"; import "./jobs-table.scss"; -interface JobsTableProps extends Job.Inputs {} +interface JobsTableProps extends Entity.Inputs {} const _JobsTable = "JobsTable"; export const JobsTable = ({ className, adapters }: JobsTableProps) => { - const { data, error, loading } = JobModel.useAllEntries(adapters), + const { data, error, loading } = JobInfoModel.useAllEntries(adapters), items = Object.values(data ?? {}); return ( From 4c271d69320d7bea358f40ce0342fe00614f5fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 10 Dec 2022 23:40:34 +0400 Subject: [PATCH 443/537] wip: Apply code review and naming remarks --- src/entities/multicall-instance/index.ts | 4 +- ...mi-settings-provider.tsx => providers.tsx} | 0 .../ui/external-login-dialogs.tsx | 23 +++--- .../external-login/ui/external-login-menu.tsx | 4 +- src/pages/dao/dao.tsx | 8 +- src/pages/dao/funds/funds.tsx | 16 ++-- src/pages/dao/jobs/jobs.tsx | 12 +-- src/pages/dao/settings/settings.tsx | 29 ++++--- src/widgets/dialogs-layer/index.ts | 4 +- src/widgets/index.ts | 4 +- src/widgets/settings-editor/index.ts | 9 +-- src/widgets/settings-editor/module-context.ts | 14 ---- .../settings-editor/ui/settings-editor.scss | 18 +++++ .../settings-editor/ui/settings-editor.tsx | 76 +++++++++++-------- .../ui/settings-proposal-create.tsx | 12 +-- src/widgets/token-balances/index.ts | 9 +-- src/widgets/token-balances/module-context.ts | 7 -- .../token-balances/ui/token-balances.tsx | 9 ++- 18 files changed, 135 insertions(+), 123 deletions(-) rename src/entities/multicall-instance/ui/{mi-settings-provider.tsx => providers.tsx} (100%) delete mode 100644 src/widgets/token-balances/module-context.ts diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 92baab6e..bf44ea49 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,7 +1,8 @@ import { Entity as MIEntity, ModuleContext } from "./module-context"; import { MIAdminsTable } from "./ui/mi-admins"; -import { MISettingsProvider } from "./ui/mi-settings-provider"; +import { MISettingsProvider } from "./ui/providers"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; +import { MISettingsModel } from "./model/mi-settings"; export { type MIEntity }; @@ -12,4 +13,5 @@ export class MI extends ModuleContext { static AdminsTable = MIAdminsTable; static TokenWhitelistTable = MITokenWhitelistTable; static SettingsProvider = MISettingsProvider; + static useSettings = MISettingsModel.useContext; } diff --git a/src/entities/multicall-instance/ui/mi-settings-provider.tsx b/src/entities/multicall-instance/ui/providers.tsx similarity index 100% rename from src/entities/multicall-instance/ui/mi-settings-provider.tsx rename to src/entities/multicall-instance/ui/providers.tsx diff --git a/src/features/external-login/ui/external-login-dialogs.tsx b/src/features/external-login/ui/external-login-dialogs.tsx index 10fa6d06..fef03357 100644 --- a/src/features/external-login/ui/external-login-dialogs.tsx +++ b/src/features/external-login/ui/external-login-dialogs.tsx @@ -80,15 +80,20 @@ const ExternalLoginDialog = ({ className, method, onClose, open, title }: Extern export const Dialogs = () => { const { dialogsVisibility, closeHandlerBinding } = ExternalLoginDialogsModel.useVisibilityState(); - return Object.values(ModuleContext.METHODS).map((loginMethod) => ( - - )); + return ( + <> + {" "} + {Object.values(ModuleContext.METHODS).map((loginMethod) => ( + + ))} + + ); }; Dialogs.displayName = `${_ExternalLoginDialog}s`; diff --git a/src/features/external-login/ui/external-login-menu.tsx b/src/features/external-login/ui/external-login-menu.tsx index 06488e00..75fda15a 100644 --- a/src/features/external-login/ui/external-login-menu.tsx +++ b/src/features/external-login/ui/external-login-menu.tsx @@ -5,14 +5,14 @@ import { PopupMenu } from "../../../shared/ui/design"; import { ModuleContext } from "../module-context"; import { ExternalLoginDialogsModel } from "../model/external-login-dialogs"; +const _ExternalLoginMenu = "ExternalLoginMenu"; + interface MenuProps extends Pick, "triggerClassName"> { FeatureFlags: { ExternalLogin: Record; }; } -const _ExternalLoginMenu = "ExternalLoginMenu"; - export const Menu = ({ FeatureFlags, triggerClassName }: MenuProps) => ( } diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 6e95cd59..cc84ee60 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -501,7 +501,7 @@ export class DaoPage extends Component { */ if (!multicallInstance.admins || !multicallInstance.tokensWhitelist || !multicallInstance.jobBond) { console.error("multicall infos incomplete", multicallInstance); - return
        Unexpected error! Multicall might be outdated.
        ; + console.error("Unexpected error! Multicall might be outdated."); } return ( @@ -512,12 +512,12 @@ export class DaoPage extends Component { contentSpace: "DaoPage-tabs-contentSpace", }} items={[ - DaoSettingsTab.uiConnect({ + DaoSettingsTab.render({ className: `${_DaoPage}-content`, adapters: { dao, multicallInstance }, }), - DaoFundsTab.uiConnect({ className: `${_DaoPage}-content`, adapters: { dao, multicallInstance } }), - DaoJobsTab.uiConnect({ className: `${_DaoPage}-content`, adapters: { multicallInstance } }), + DaoFundsTab.render({ className: `${_DaoPage}-content`, adapters: { dao, multicallInstance } }), + DaoJobsTab.render({ className: `${_DaoPage}-content`, adapters: { multicallInstance } }), ]} /> ); diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index 849e392f..7cc93f0a 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -1,26 +1,28 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { TokenBalances, type TokenBalancesModule } from "../../../widgets"; +import { TokenBalances, type TokenBalancesProps } from "../../../widgets"; import "./funds.scss"; -interface DaoFundsTabUIProps extends HTMLProps, TokenBalancesModule.Inputs {} - const _DaoFundsTab = "DaoFundsTab"; -const DaoFundsTabUI = ({ className, adapters, ...props }: DaoFundsTabUIProps) => ( +interface DaoFundsTabProps extends HTMLProps, TokenBalancesProps {} + +const Content = ({ className, adapters, ...props }: DaoFundsTabProps) => (
        - +
        ); +Content.displayName = _DaoFundsTab; + export const DaoFundsTab = { - uiConnect: (props: DaoFundsTabUIProps) => ({ - content: , + render: (props: DaoFundsTabProps) => ({ + content: , lazy: true, name: "Funds", }), diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 14d9b09e..c9f72d2e 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -5,11 +5,11 @@ import { Job } from "../../../entities"; import "./jobs.scss"; -interface DaoJobsTabUIProps extends HTMLProps, ComponentProps {} - const _DaoJobsTab = "DaoJobsTab"; -const DaoJobsTabUI = ({ className, adapters, ...props }: DaoJobsTabUIProps) => ( +interface DaoJobsTabProps extends HTMLProps, ComponentProps {} + +const Content = ({ className, adapters, ...props }: DaoJobsTabProps) => (
        (
        ); +Content.displayName = _DaoJobsTab; + export const DaoJobsTab = { - uiConnect: (props: DaoJobsTabUIProps) => ({ - content: , + render: (props: DaoJobsTabProps) => ({ + content: , lazy: true, name: "Jobs", }), diff --git a/src/pages/dao/settings/settings.tsx b/src/pages/dao/settings/settings.tsx index f2bf3425..208b1a06 100644 --- a/src/pages/dao/settings/settings.tsx +++ b/src/pages/dao/settings/settings.tsx @@ -1,26 +1,31 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { SettingsEditor, SettingsEditorModule } from "../../../widgets"; +import { MI } from "../../../entities"; +import { SettingsEditor, SettingsEditorProps } from "../../../widgets"; import "./settings.scss"; -interface DaoSettingsTabUIProps extends HTMLProps, SettingsEditorModule.Inputs {} - const _DaoSettingsTab = "DaoSettingsTab"; -const DaoSettingsTabUI = ({ className, adapters, ...props }: DaoSettingsTabUIProps) => ( -
        - -
        +interface DaoSettingsTabProps extends HTMLProps, SettingsEditorProps {} + +const Content = ({ className, adapters, ...props }: DaoSettingsTabProps) => ( + +
        + +
        +
        ); +Content.displayName = _DaoSettingsTab; + export const DaoSettingsTab = { - uiConnect: (props: DaoSettingsTabUIProps) => ({ - content: , + render: (props: DaoSettingsTabProps) => ({ + content: , name: "Settings", }), }; diff --git a/src/widgets/dialogs-layer/index.ts b/src/widgets/dialogs-layer/index.ts index 36a365a8..62bc5a04 100644 --- a/src/widgets/dialogs-layer/index.ts +++ b/src/widgets/dialogs-layer/index.ts @@ -1,3 +1 @@ -import { DialogsLayer } from "./ui/dialogs-layer"; - -export { DialogsLayer }; +export { DialogsLayer } from "./ui/dialogs-layer"; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 31e81016..ddc8c7bb 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -4,6 +4,6 @@ export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export"; -export { SettingsEditor, type SettingsEditorModule } from "./settings-editor"; +export { SettingsEditor, type SettingsEditorProps } from "./settings-editor"; export { Sidebar } from "./sidebar/sidebar.jsx"; -export { TokenBalances, type TokenBalancesModule } from "./token-balances"; +export { TokenBalances, type TokenBalancesProps } from "./token-balances"; diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts index 15b99dc8..99796e30 100644 --- a/src/widgets/settings-editor/index.ts +++ b/src/widgets/settings-editor/index.ts @@ -1,8 +1 @@ -import { ModuleContext, SettingsEditor as SettingsEditorModule } from "./module-context"; -import { SettingsEditorUI } from "./ui/settings-editor"; - -export class SettingsEditor extends ModuleContext { - static UI = SettingsEditorUI; -} - -export { type SettingsEditorModule }; +export { SettingsEditor, type SettingsEditorProps } from "./ui/settings-editor"; diff --git a/src/widgets/settings-editor/module-context.ts b/src/widgets/settings-editor/module-context.ts index 1533b495..b3ba6920 100644 --- a/src/widgets/settings-editor/module-context.ts +++ b/src/widgets/settings-editor/module-context.ts @@ -1,18 +1,4 @@ -import { HTMLProps } from "react"; - import { SchedulingSettingsChange, TokenWhitelistChange } from "../../features"; -import { MulticallSettingsDiff, Multicall } from "../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; - -export namespace SettingsEditor { - export interface Inputs extends HTMLProps { - adapters: { dao: SputnikDAO; multicallInstance: Multicall }; - } - - export type Diff = MulticallSettingsDiff; - - export type ProposalDescription = Parameters[0]; -} export class ModuleContext { public static readonly DiffKey = { diff --git a/src/widgets/settings-editor/ui/settings-editor.scss b/src/widgets/settings-editor/ui/settings-editor.scss index fcf179c0..3b83e786 100644 --- a/src/widgets/settings-editor/ui/settings-editor.scss +++ b/src/widgets/settings-editor/ui/settings-editor.scss @@ -11,4 +11,22 @@ grid-template-areas: "TokenWhitelistChange SchedulingSettingsChange" "TokenWhitelistChange SettingsProposalCreate"; + + &-error { + grid-area: SettingsEditorError; + } + + &.is-displayingError { + grid-template-columns: 1fr; + grid-template-rows: 1fr; + grid-template-areas: "SettingsEditorError"; + } + + &.is-displayingError > *:not(&-error) { + display: none; + } + + &:not(&.is-displayingError) &-error { + display: none; + } } diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 0af5f0ad..724350c9 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -1,34 +1,41 @@ import clsx from "clsx"; -import { useCallback, useMemo, useState, FormEventHandler, useEffect, useContext } from "react"; +import { useCallback, useMemo, useState, FormEventHandler, useEffect, useContext, HTMLProps } from "react"; import { MI, Wallet } from "../../../entities"; import { SchedulingSettingsChange, TokenWhitelistChange } from "../../../features"; import { ArgsString } from "../../../shared/lib/args-old"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; +import { Multicall, MulticallSettingsDiff } from "../../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { ModuleContext, SettingsEditor } from "../module-context"; +import { ModuleContext } from "../module-context"; +import { Tile } from "../../../shared/ui/design"; import { SettingsProposalCreate } from "./settings-proposal-create"; import "./settings-editor.scss"; const _SettingsEditor = "SettingsEditor"; -export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) => { - const wallet = useContext(Wallet.SelectorContext); +export interface SettingsEditorProps extends HTMLProps { + adapters: { dao: SputnikDAO; multicallInstance: Multicall }; +} + +export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => { + const wallet = useContext(Wallet.SelectorContext), + settings = MI.useSettings(); const proposalCreationPermitted = !wallet?.accountId || adapters.dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); const [editMode, editModeSwitch] = useState(false); - const changesDiffInitialState: SettingsEditor.Diff = { + const changesDiffInitialState: MulticallSettingsDiff = { [ModuleContext.DiffKey.removeTokens]: [], [ModuleContext.DiffKey.addTokens]: [], [ModuleContext.DiffKey.jobBond]: "", [ModuleContext.DiffKey.croncatManager]: "", }; - const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), + const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), formValues = { proposalDescription: useMemo(() => new ArgsString(""), []) }, [proposalDescription, proposalDescriptionUpdate] = useState(formValues.proposalDescription.value), _childFormsResetRequested = "childFormsResetRequested"; @@ -57,7 +64,7 @@ export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( - (update: Partial) => + (update: Partial) => void changesDiffUpdate((latestState) => ({ ...latestState, ...update })), [changesDiffUpdate] @@ -86,30 +93,33 @@ export const SettingsEditorUI = ({ className, adapters }: SettingsEditor.Inputs) ); return ( - -
        - {false && } - - - - - - -
        -
        +
        + + + {false && } + + + + + + +
        ); }; diff --git a/src/widgets/settings-editor/ui/settings-proposal-create.tsx b/src/widgets/settings-editor/ui/settings-proposal-create.tsx index 459ef3f1..cad39299 100644 --- a/src/widgets/settings-editor/ui/settings-proposal-create.tsx +++ b/src/widgets/settings-editor/ui/settings-proposal-create.tsx @@ -2,15 +2,19 @@ import clsx from "clsx"; import { FormEventHandler, HTMLProps } from "react"; import { ArgsString } from "../../../shared/lib/args-old"; +import { MulticallSettingsDiff } from "../../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { toNEAR } from "../../../shared/lib/converter"; import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; -import { ModuleContext, SettingsEditor } from "../module-context"; +import { ModuleContext } from "../module-context"; import "./settings-proposal-create.scss"; +const _SettingsProposalCreate = "SettingsProposalCreate"; + export interface SettingsProposalCreateProps extends HTMLProps { - changesDiff: SettingsEditor.Diff; - description: SettingsEditor.ProposalDescription; + changesDiff: MulticallSettingsDiff; + description: Parameters[0]; formValues: { proposalDescription: ArgsString }; editMode: boolean; onCancel: FormEventHandler; @@ -18,8 +22,6 @@ export interface SettingsProposalCreateProps extends HTMLProps { onSubmit: FormEventHandler; } -const _SettingsProposalCreate = "SettingsProposalCreate"; - export const SettingsProposalCreate = ({ changesDiff, className, diff --git a/src/widgets/token-balances/index.ts b/src/widgets/token-balances/index.ts index 001c2776..8e0f8da5 100644 --- a/src/widgets/token-balances/index.ts +++ b/src/widgets/token-balances/index.ts @@ -1,8 +1 @@ -import { TokenBalancesUI } from "./ui/token-balances"; -import { TokenBalances as TokenBalancesModule } from "./module-context"; - -class TokenBalances { - static UI = TokenBalancesUI; -} - -export { TokenBalances, type TokenBalancesModule }; +export { TokenBalances, type TokenBalancesProps } from "./ui/token-balances"; diff --git a/src/widgets/token-balances/module-context.ts b/src/widgets/token-balances/module-context.ts deleted file mode 100644 index b1f5fcb8..00000000 --- a/src/widgets/token-balances/module-context.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { NEARTokenModule, FTModule } from "../../entities"; - -export namespace TokenBalances { - export interface Inputs extends NEARTokenModule.Inputs, FTModule.Inputs { - className?: string; - } -} diff --git a/src/widgets/token-balances/ui/token-balances.tsx b/src/widgets/token-balances/ui/token-balances.tsx index 8464cf7a..6913277d 100644 --- a/src/widgets/token-balances/ui/token-balances.tsx +++ b/src/widgets/token-balances/ui/token-balances.tsx @@ -1,14 +1,17 @@ import clsx from "clsx"; import { Tile, Scrollable, Table } from "../../../shared/ui/design"; -import { FT, NEARToken } from "../../../entities"; -import { type TokenBalances } from "../module-context"; +import { FT, FTModule, NEARToken, NEARTokenModule } from "../../../entities"; import "./token-balances.scss"; const _TokenBalances = "TokenBalances"; -export const TokenBalancesUI = ({ className, adapters }: TokenBalances.Inputs) => { +export interface TokenBalancesProps extends NEARTokenModule.Inputs, FTModule.Inputs { + className?: string; +} + +export const TokenBalances = ({ className, adapters }: TokenBalancesProps) => { const nearTokenBalances = NEARToken.balancesRender({ adapters }), fungibleTokenBalances = FT.balances({ adapters }); From 6b761952df4a79aea1c175e7e20775da2052fb68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 10 Dec 2022 23:45:10 +0400 Subject: [PATCH 444/537] wip: Fix React warning --- .../ui/scheduling-settings-change.tsx | 14 ++++++++------ .../whitelist-change/ui/token-whitelist-change.tsx | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx index f2820d20..330d604e 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx @@ -85,12 +85,14 @@ export const Form = ({ adapters: { multicallInstance }, disabled, onEdit, resetT ) : ( - void editModeSwitch(true)} - {...{ disabled }} - > - - + + void editModeSwitch(true)} + {...{ disabled }} + > + + + ), }} diff --git a/src/features/token/whitelist-change/ui/token-whitelist-change.tsx b/src/features/token/whitelist-change/ui/token-whitelist-change.tsx index d146adbc..1b2a6175 100644 --- a/src/features/token/whitelist-change/ui/token-whitelist-change.tsx +++ b/src/features/token/whitelist-change/ui/token-whitelist-change.tsx @@ -97,12 +97,14 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { ) : ( - void editModeSwitch(true)} - {...{ disabled }} - > - - + + void editModeSwitch(true)} + {...{ disabled }} + > + + + ), }} From fb56ebbe82e6e395b7524203169ed799e1650098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Dec 2022 00:07:06 +0400 Subject: [PATCH 445/537] wip: Use new `args` in NearLink --- src/shared/ui/design/near-link/near-link.tsx | 24 ++++++++------------ 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/shared/ui/design/near-link/near-link.tsx b/src/shared/ui/design/near-link/near-link.tsx index d9917840..1090e9ad 100644 --- a/src/shared/ui/design/near-link/near-link.tsx +++ b/src/shared/ui/design/near-link/near-link.tsx @@ -1,6 +1,6 @@ import { Account } from "@near-wallet-selector/core"; -import { ArgsAccount } from "../../../lib/args-old"; +import { args } from "../../../lib/args/args"; import { Link, LinkProps } from "../link"; import "./near-link.scss"; @@ -11,16 +11,12 @@ export interface NearLinkProps extends Omit { const _NearLink = "NearLink"; -export const NearLink = ({ address }: NearLinkProps) => { - const addr = new ArgsAccount(address); - - return ( - - ); -}; +export const NearLink = ({ address }: NearLinkProps) => ( + +); From d788e4fee17de2f364c5d64c82017ec2c030a551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Dec 2022 01:21:25 +0400 Subject: [PATCH 446/537] chore: Update NEAR config path in env config error --- src/shared/config/near-protocol.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/config/near-protocol.ts b/src/shared/config/near-protocol.ts index c8a8e448..8e22b417 100644 --- a/src/shared/config/near-protocol.ts +++ b/src/shared/config/near-protocol.ts @@ -55,7 +55,7 @@ function getConfig(env: string) { masterAccount: "test.near", }; default: - throw Error(`Unconfigured environment '${env}'. Can be configured in src/config.js.`); + throw Error(`Unconfigured environment '${env}'. Can be configured in src/shared/config/near-protocol.ts.`); } } From 48bc35b74c89d50974d1737c63a803397971187a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 11 Dec 2022 02:03:11 +0400 Subject: [PATCH 447/537] wip: Remove redundant / unused code & Fix errors --- .../multicall-instance/model/mi-settings.ts | 6 +- .../settings-change/module-context.ts | 4 - .../ui/scheduling-settings-change.tsx | 34 +++--- src/pages/dao/dao.scss | 1 + src/pages/dao/dao.tsx | 107 ++++++------------ .../settings-editor/ui/settings-editor.tsx | 10 +- 6 files changed, 63 insertions(+), 99 deletions(-) diff --git a/src/entities/multicall-instance/model/mi-settings.ts b/src/entities/multicall-instance/model/mi-settings.ts index cec22b18..38e036a2 100644 --- a/src/entities/multicall-instance/model/mi-settings.ts +++ b/src/entities/multicall-instance/model/mi-settings.ts @@ -6,11 +6,11 @@ import { Entity } from "../module-context"; export class MISettingsModel { public static readonly data: { - data: Multicall | null; + data: Multicall; error: Error | null; loading: boolean; } = { - data: null, + data: new Multicall(""), error: null, loading: true, }; @@ -30,7 +30,7 @@ export class MISettingsModel { await Multicall.init( `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}` ).then((multicallInstance) => ({ - data: multicallInstance.ready ? multicallInstance : null, + data: multicallInstance, error: multicallInstance.ready ? null : new Error("Unable to connect to Multicall Instance"), loading: false, })) diff --git a/src/features/scheduling/settings-change/module-context.ts b/src/features/scheduling/settings-change/module-context.ts index c1009801..c2468a36 100644 --- a/src/features/scheduling/settings-change/module-context.ts +++ b/src/features/scheduling/settings-change/module-context.ts @@ -10,10 +10,6 @@ export namespace Feature { export type FormState = Pick; export interface Inputs extends Omit, "onChange"> { - adapters: { - multicallInstance: Multicall; - }; - onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx index 330d604e..4a666882 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx @@ -2,6 +2,7 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-mat import { IconButton, TextField, TextFieldProps } from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; +import { MI } from "../../../../entities"; import { ArgsString } from "../../../../shared/lib/args-old"; import { toNEAR, toYocto } from "../../../../shared/lib/converter"; import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../../shared/ui/design"; @@ -11,7 +12,9 @@ import "./scheduling-settings-change.scss"; const _SchedulingSettingsChange = "SchedulingSettingsChange"; -export const Form = ({ adapters: { multicallInstance }, disabled, onEdit, resetTrigger }: Feature.Inputs) => { +export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { + const { data: MISettings } = MI.useSettings(); + const [editModeEnabled, editModeSwitch] = useState(false); const formInitialState: Feature.FormState = { @@ -25,33 +28,32 @@ export const Form = ({ adapters: { multicallInstance }, disabled, onEdit, resetT ]; const formFields = { - croncatManager: useMemo(() => new ArgsString(multicallInstance.croncatManager), [multicallInstance]), + croncatManager: useMemo(() => new ArgsString(MISettings.croncatManager), [MISettings]), jobBond: useMemo( - () => new ArgsString(multicallInstance.jobBond !== "" ? toNEAR(multicallInstance.jobBond) : ""), - [multicallInstance] + () => new ArgsString(MISettings.jobBond !== "" ? toNEAR(MISettings.jobBond) : ""), + + [MISettings] ), }; const onCroncatManagerChange = useCallback["onChange"]>( ({ target: { value } }) => - void croncatManagerUpdate( - value !== multicallInstance.croncatManager ? value : formInitialState.croncatManager - ), + void croncatManagerUpdate(value !== MISettings.croncatManager ? value : formInitialState.croncatManager), [croncatManagerUpdate] ); const onJobBondChange = useCallback["onChange"]>( ({ target: { value } }) => - void jobBondUpdate(value !== toNEAR(multicallInstance.jobBond) ? toYocto(value) : formInitialState.jobBond), + void jobBondUpdate(value !== toNEAR(MISettings.jobBond) ? toYocto(value) : formInitialState.jobBond), [jobBondUpdate] ); const formReset = useCallback(() => { - formFields.croncatManager.value = multicallInstance.croncatManager; - formFields.jobBond.value = toNEAR(multicallInstance.jobBond); + formFields.croncatManager.value = MISettings.croncatManager; + formFields.jobBond.value = toNEAR(MISettings.jobBond); void croncatManagerUpdate(formInitialState.croncatManager); void jobBondUpdate(formInitialState.jobBond); @@ -103,7 +105,7 @@ export const Form = ({ adapters: { multicallInstance }, disabled, onEdit, resetT idToHighlightColor: (id) => ({ croncatManager, jobBond }[id] === formInitialState[id as Feature.DiffKey] || - { croncatManager, jobBond }[id] === multicallInstance[id as Feature.DiffKey] + { croncatManager, jobBond }[id] === MISettings[id as Feature.DiffKey] ? null : "blue"), @@ -124,10 +126,10 @@ export const Form = ({ adapters: { multicallInstance }, disabled, onEdit, resetT ) : ( - + ), ], }, @@ -146,14 +148,14 @@ export const Form = ({ adapters: { multicallInstance }, disabled, onEdit, resetT fullWidth onChange={onJobBondChange} type="number" - value={toNEAR(jobBond || multicallInstance.jobBond)} + value={toNEAR(jobBond || MISettings.jobBond)} /> ) : ( { const multicallAddress = this.toMulticallAddress(formData.addr); const depo = Big(this.fee).plus(MI.MIN_BALANCE); - const daoSearchInput: HTMLInputElement = document.querySelector(".DaoSearch input")!; /** * Can user propose a FunctionCall to DAO? @@ -208,7 +207,7 @@ export class DaoPage extends Component { JSON.stringify({ multicall_init_args: { admin_accounts: [dao.address], - croncat_manager: window.nearModuleContext.CRONCAT_MANAGER_ADDRESS, + croncat_manager: window.nearConfig.CRONCAT_MANAGER_ADDRESS, job_bond: dao.policy.proposal_bond, }, @@ -230,7 +229,7 @@ export class DaoPage extends Component { !noDao.isBad() && // base.sputnik-dao.near does not exist !loading && // disappear while debouncing - this.lastAddr === daoSearchInput.value + this.lastAddr === formData.addr ) { if (proposed === -1) { // no create multicall proposal exists @@ -343,32 +342,6 @@ export class DaoPage extends Component { } } - toLink(address: string, deleteIcon = true) { - return ( - - - {address} - - {deleteIcon ? : null} - - ); - } - - job(job: any) { - return ( -
        - - - {job.is_active ? : } -
        {JSON.stringify(job, null, "  ")}
        -
        - ); - } - tryLoadInfo() { if (this.lastAddr === this.state.formData.addr) return; this.lastAddr = this.state.formData.addr; @@ -460,18 +433,27 @@ export class DaoPage extends Component { }); } - getContent() { + componentDidMount(): void { + window.SIDEBAR.switchPage("dao"); + document.addEventListener("onaddressesupdated", (event) => this.onAddressesUpdated(event as CustomEvent)); + } + + render() { const { selector: walletSelector } = this.context!; - const { dao, loading, multicallInstance } = this.state; + const { dao, multicallInstance } = this.state; // if user not logged in, remind them to sign in. // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) if (!walletSelector.isSignedIn()) { - return
        Please sign in to continue
        ; + return ( +
        +
        Please sign in to continue
        +
        + ); } - // errors to display const displayErrorsList = ["noAddress", "noDao", "noMulticall"]; + const displayErrors = Object.entries(fields(this.schema, "addr")) .filter(([k, v]) => v.isBad() && displayErrorsList.includes(k)) .map(([k, v]) => ( @@ -486,52 +468,24 @@ export class DaoPage extends Component { if (displayErrors.length > 0) return ( - <> -
        +
        +
        {displayErrors}
        {this.createMulticall()}
        - +
        ); - if (loading) return
        ; - /* * Everything should be loaded */ if (!multicallInstance.admins || !multicallInstance.tokensWhitelist || !multicallInstance.jobBond) { - console.error("multicall infos incomplete", multicallInstance); console.error("Unexpected error! Multicall might be outdated."); } return ( - - ); - } - - componentDidMount(): void { - window.SIDEBAR.switchPage("dao"); - document.addEventListener("onaddressesupdated", (event) => this.onAddressesUpdated(event as CustomEvent)); - } - - render() { - return ( -
        -
        +
        +
        {
        - {this.getContent()} +
        ); } diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 724350c9..6aebe337 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -16,12 +16,12 @@ import "./settings-editor.scss"; const _SettingsEditor = "SettingsEditor"; export interface SettingsEditorProps extends HTMLProps { - adapters: { dao: SputnikDAO; multicallInstance: Multicall }; + adapters: { dao: SputnikDAO }; } export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => { const wallet = useContext(Wallet.SelectorContext), - settings = MI.useSettings(); + { data: MISettings, error: MIError } = MI.useSettings(); const proposalCreationPermitted = !wallet?.accountId || adapters.dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); @@ -77,7 +77,7 @@ export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => void adapters.dao .proposeFunctionCall( proposalDescription, - adapters.multicallInstance.address, + MISettings.address, Multicall.configDiffToProposalActions(changesDiff) ) .then((someTx) => signAndSendTxs([someTx])) @@ -93,10 +93,10 @@ export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => ); return ( -
        +
        {false && } From 0a85ec486452ce4930c9af5b40b65faa3e04e5d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Dec 2022 00:11:46 +0400 Subject: [PATCH 448/537] chore: Rename MI settings -> properties --- src/entities/multicall-instance/index.ts | 8 +++--- .../{mi-settings.ts => mi-properties.ts} | 12 ++++---- .../multicall-instance/ui/mi-admins.tsx | 4 +-- .../ui/mi-token-whitelist.tsx | 4 +-- .../multicall-instance/ui/providers.tsx | 10 +++---- .../ui/scheduling-settings-change.tsx | 28 +++++++++---------- src/pages/dao/settings/settings.tsx | 4 +-- .../settings-editor/ui/settings-editor.tsx | 4 +-- 8 files changed, 37 insertions(+), 37 deletions(-) rename src/entities/multicall-instance/model/{mi-settings.ts => mi-properties.ts} (74%) diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index bf44ea49..07cc20a3 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,8 +1,8 @@ import { Entity as MIEntity, ModuleContext } from "./module-context"; import { MIAdminsTable } from "./ui/mi-admins"; -import { MISettingsProvider } from "./ui/providers"; +import { MIPropertiesProvider } from "./ui/providers"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; -import { MISettingsModel } from "./model/mi-settings"; +import { MIPropertiesModel } from "./model/mi-properties"; export { type MIEntity }; @@ -12,6 +12,6 @@ export { type MIEntity }; export class MI extends ModuleContext { static AdminsTable = MIAdminsTable; static TokenWhitelistTable = MITokenWhitelistTable; - static SettingsProvider = MISettingsProvider; - static useSettings = MISettingsModel.useContext; + static PropertiesProvider = MIPropertiesProvider; + static useProperties = MIPropertiesModel.useContext; } diff --git a/src/entities/multicall-instance/model/mi-settings.ts b/src/entities/multicall-instance/model/mi-properties.ts similarity index 74% rename from src/entities/multicall-instance/model/mi-settings.ts rename to src/entities/multicall-instance/model/mi-properties.ts index 38e036a2..5fd7e7a9 100644 --- a/src/entities/multicall-instance/model/mi-settings.ts +++ b/src/entities/multicall-instance/model/mi-properties.ts @@ -4,7 +4,7 @@ import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { Entity } from "../module-context"; -export class MISettingsModel { +export class MIPropertiesModel { public static readonly data: { data: Multicall; error: Error | null; @@ -24,7 +24,7 @@ export class MISettingsModel { */ private static readonly dataFetchFx = async ( daoAddress: Entity.Inputs["daoAddress"], - callback: (result: typeof MISettingsModel.data) => void + callback: (result: typeof MIPropertiesModel.data) => void ) => callback( await Multicall.init( @@ -40,13 +40,13 @@ export class MISettingsModel { * For context provider usage only. */ public static readonly useData = (daoAddress: Entity.Inputs["daoAddress"]) => { - const [state, stateUpdate] = useState(MISettingsModel.data); + const [state, stateUpdate] = useState(MIPropertiesModel.data); - useEffect(() => void MISettingsModel.dataFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); + useEffect(() => void MIPropertiesModel.dataFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); return state; }; - public static readonly Context = createContext(MISettingsModel.data); - public static readonly useContext = () => useContext(MISettingsModel.Context); + public static readonly Context = createContext(MIPropertiesModel.data); + public static readonly useContext = () => useContext(MIPropertiesModel.Context); } diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 980084e5..5ea1bc9a 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,5 +1,5 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { MISettingsModel } from "../model/mi-settings"; +import { MIPropertiesModel } from "../model/mi-properties"; import { miAdminAsTableRow, MIAdminProps } from "./mi-admin"; @@ -9,7 +9,7 @@ interface MIAdminsTableProps { } export const MIAdminsTable = ({ className, itemsAdditional }: MIAdminsTableProps) => { - const { data, error, loading } = MISettingsModel.useContext(), + const { data, error, loading } = MIPropertiesModel.useContext(), items = (data?.admins ?? []).concat(itemsAdditional ?? []); return ( diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index 10280bd7..2a8ebffa 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,5 +1,5 @@ import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; -import { MISettingsModel } from "../model/mi-settings"; +import { MIPropertiesModel } from "../model/mi-properties"; import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; @@ -19,7 +19,7 @@ export const MITokenWhitelistTable = ({ onItemsSelected, subheader, }: MITokenWhitelistTableProps) => { - const { data, error, loading } = MISettingsModel.useContext(), + const { data, error, loading } = MIPropertiesModel.useContext(), items = (data?.tokensWhitelist ?? []).concat(itemsAdditional ?? []); return ( diff --git a/src/entities/multicall-instance/ui/providers.tsx b/src/entities/multicall-instance/ui/providers.tsx index fbe5ad64..2ed94619 100644 --- a/src/entities/multicall-instance/ui/providers.tsx +++ b/src/entities/multicall-instance/ui/providers.tsx @@ -1,12 +1,12 @@ import { PropsWithChildren } from "react"; import { Entity } from "../module-context"; -import { MISettingsModel } from "../model/mi-settings"; +import { MIPropertiesModel } from "../model/mi-properties"; -interface MISettingsProviderProps extends PropsWithChildren, Pick {} +interface MIPropertiesProviderProps extends PropsWithChildren, Pick {} -export const MISettingsProvider = ({ children, daoAddress }: MISettingsProviderProps) => ( - +export const MIPropertiesProvider = ({ children, daoAddress }: MIPropertiesProviderProps) => ( + {children} - + ); diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx index 4a666882..3b9bee28 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx @@ -13,7 +13,7 @@ import "./scheduling-settings-change.scss"; const _SchedulingSettingsChange = "SchedulingSettingsChange"; export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { - const { data: MISettings } = MI.useSettings(); + const { data: MIProperties } = MI.useProperties(); const [editModeEnabled, editModeSwitch] = useState(false); @@ -28,32 +28,32 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { ]; const formFields = { - croncatManager: useMemo(() => new ArgsString(MISettings.croncatManager), [MISettings]), + croncatManager: useMemo(() => new ArgsString(MIProperties.croncatManager), [MIProperties]), jobBond: useMemo( - () => new ArgsString(MISettings.jobBond !== "" ? toNEAR(MISettings.jobBond) : ""), + () => new ArgsString(MIProperties.jobBond !== "" ? toNEAR(MIProperties.jobBond) : ""), - [MISettings] + [MIProperties] ), }; const onCroncatManagerChange = useCallback["onChange"]>( ({ target: { value } }) => - void croncatManagerUpdate(value !== MISettings.croncatManager ? value : formInitialState.croncatManager), + void croncatManagerUpdate(value !== MIProperties.croncatManager ? value : formInitialState.croncatManager), [croncatManagerUpdate] ); const onJobBondChange = useCallback["onChange"]>( ({ target: { value } }) => - void jobBondUpdate(value !== toNEAR(MISettings.jobBond) ? toYocto(value) : formInitialState.jobBond), + void jobBondUpdate(value !== toNEAR(MIProperties.jobBond) ? toYocto(value) : formInitialState.jobBond), [jobBondUpdate] ); const formReset = useCallback(() => { - formFields.croncatManager.value = MISettings.croncatManager; - formFields.jobBond.value = toNEAR(MISettings.jobBond); + formFields.croncatManager.value = MIProperties.croncatManager; + formFields.jobBond.value = toNEAR(MIProperties.jobBond); void croncatManagerUpdate(formInitialState.croncatManager); void jobBondUpdate(formInitialState.jobBond); @@ -105,7 +105,7 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { idToHighlightColor: (id) => ({ croncatManager, jobBond }[id] === formInitialState[id as Feature.DiffKey] || - { croncatManager, jobBond }[id] === MISettings[id as Feature.DiffKey] + { croncatManager, jobBond }[id] === MIProperties[id as Feature.DiffKey] ? null : "blue"), @@ -126,10 +126,10 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { ) : ( - + ), ], }, @@ -148,14 +148,14 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { fullWidth onChange={onJobBondChange} type="number" - value={toNEAR(jobBond || MISettings.jobBond)} + value={toNEAR(jobBond || MIProperties.jobBond)} /> ) : ( , SettingsEditorProps {} const Content = ({ className, adapters, ...props }: DaoSettingsTabProps) => ( - +
        -
        + ); Content.displayName = _DaoSettingsTab; diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 6aebe337..27f82a9d 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -21,7 +21,7 @@ export interface SettingsEditorProps extends HTMLProps { export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => { const wallet = useContext(Wallet.SelectorContext), - { data: MISettings, error: MIError } = MI.useSettings(); + { data: MIProperties, error: MIError } = MI.useProperties(); const proposalCreationPermitted = !wallet?.accountId || adapters.dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); @@ -77,7 +77,7 @@ export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => void adapters.dao .proposeFunctionCall( proposalDescription, - MISettings.address, + MIProperties.address, Multicall.configDiffToProposalActions(changesDiff) ) .then((someTx) => signAndSendTxs([someTx])) From 130f4c0225aea82a88de81b52573d91433ba26b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Dec 2022 00:13:39 +0400 Subject: [PATCH 449/537] chore: Prepend context to MI providers module filename --- src/entities/multicall-instance/index.ts | 4 ++-- .../multicall-instance/ui/{providers.tsx => mi-providers.tsx} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src/entities/multicall-instance/ui/{providers.tsx => mi-providers.tsx} (100%) diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 07cc20a3..de6a1a4e 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,8 +1,8 @@ import { Entity as MIEntity, ModuleContext } from "./module-context"; +import { MIPropertiesModel } from "./model/mi-properties"; import { MIAdminsTable } from "./ui/mi-admins"; -import { MIPropertiesProvider } from "./ui/providers"; +import { MIPropertiesProvider } from "./ui/mi-providers"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; -import { MIPropertiesModel } from "./model/mi-properties"; export { type MIEntity }; diff --git a/src/entities/multicall-instance/ui/providers.tsx b/src/entities/multicall-instance/ui/mi-providers.tsx similarity index 100% rename from src/entities/multicall-instance/ui/providers.tsx rename to src/entities/multicall-instance/ui/mi-providers.tsx From 0220207d7c40936ab41d45bbd462f3ab5898765d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 14 Dec 2022 01:31:00 +0400 Subject: [PATCH 450/537] wip: Apply code review and naming remarks --- src/entities/fungible-token/model/ft-info.ts | 4 +- src/entities/index.ts | 2 +- src/entities/job/model/job-info.ts | 4 +- src/entities/multicall-instance/index.ts | 13 ++---- .../model/{mi-properties.ts => mi-model.ts} | 31 +++++++------- .../multicall-instance/module-context.ts | 18 ++------ .../multicall-instance/ui/mi-admins.tsx | 4 +- .../multicall-instance/ui/mi-providers.tsx | 12 +++--- .../ui/mi-token-whitelist.tsx | 6 +-- .../near-token/model/near-balances.ts | 10 ++--- src/features/external-login/index.ts | 8 ++-- ...{external-login-dialogs.ts => el-model.ts} | 10 ++--- src/features/external-login/module-context.ts | 6 +-- ...ernal-login-dialog.scss => el-dialog.scss} | 2 +- ...ternal-login-dialogs.tsx => el-dialog.tsx} | 41 ++++--------------- src/features/external-login/ui/el-dialogs.tsx | 22 ++++++++++ src/features/external-login/ui/el-menu.tsx | 25 +++++++++++ .../external-login/ui/external-login-menu.tsx | 29 ------------- src/features/index.ts | 2 +- .../scheduling/settings-change/index.ts | 8 ++-- .../settings-change/module-context.ts | 18 +------- .../ui/scheduling-settings-change.tsx | 32 +++++++++------ src/features/token/whitelist-change/index.ts | 4 +- .../token/whitelist-change/module-context.ts | 8 ++-- .../ui/token-whitelist-change.tsx | 8 ++-- src/pages/dao/dao.tsx | 4 +- src/pages/dao/settings/settings.tsx | 6 +-- src/shared/lib/contracts/multicall.ts | 22 +++++----- .../settings-editor/ui/settings-editor.tsx | 18 ++++---- .../ui/settings-proposal-create.tsx | 4 +- src/widgets/sidebar/sidebar.jsx | 8 ++-- 31 files changed, 179 insertions(+), 210 deletions(-) rename src/entities/multicall-instance/model/{mi-properties.ts => mi-model.ts} (56%) rename src/features/external-login/model/{external-login-dialogs.ts => el-model.ts} (86%) rename src/features/external-login/ui/{external-login-dialog.scss => el-dialog.scss} (96%) rename src/features/external-login/ui/{external-login-dialogs.tsx => el-dialog.tsx} (62%) create mode 100644 src/features/external-login/ui/el-dialogs.tsx create mode 100644 src/features/external-login/ui/el-menu.tsx delete mode 100644 src/features/external-login/ui/external-login-menu.tsx diff --git a/src/entities/fungible-token/model/ft-info.ts b/src/entities/fungible-token/model/ft-info.ts index cdea15c9..ca32d81d 100644 --- a/src/entities/fungible-token/model/ft-info.ts +++ b/src/entities/fungible-token/model/ft-info.ts @@ -10,7 +10,7 @@ type FTInfo = { }; export class FTInfoModel { - private static readonly nonZeroBalancesFetchFx = async ( + private static readonly nonZeroBalancesFetch = async ( { dao, multicallInstance }: FT.Inputs["adapters"], callback: (result: FTInfo) => void ) => { @@ -57,7 +57,7 @@ export class FTInfoModel { public static readonly useNonZeroBalances = (adapters: FT.Inputs["adapters"]) => { const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void FTInfoModel.nonZeroBalancesFetchFx(adapters, stateUpdate), [adapters, stateUpdate]); + useEffect(() => void FTInfoModel.nonZeroBalancesFetch(adapters, stateUpdate), [adapters, stateUpdate]); return state; }; diff --git a/src/entities/index.ts b/src/entities/index.ts index a6920cc0..74c4f051 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ export { Task } from "./task"; export { Job, type JobEntity } from "./job"; export { FT, type FTModule } from "./fungible-token"; -export { MI, type MIEntity } from "./multicall-instance"; +export { MulticallInstance } from "./multicall-instance"; export { NEARToken, type NEARTokenModule } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/model/job-info.ts b/src/entities/job/model/job-info.ts index d8bcd381..ec8a2ccd 100644 --- a/src/entities/job/model/job-info.ts +++ b/src/entities/job/model/job-info.ts @@ -11,7 +11,7 @@ type Jobs = { }; export class JobInfoModel { - static allEntriesFetchFx = async ( + static allEntriesFetch = async ( { multicallInstance }: Entity.Inputs["adapters"], callback: (result: Jobs) => void ) => @@ -40,7 +40,7 @@ export class JobInfoModel { static useAllEntries = (adapters: Entity.Inputs["adapters"]) => { const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - useEffect(() => void JobInfoModel.allEntriesFetchFx(adapters, stateUpdate), [adapters, stateUpdate]); + useEffect(() => void JobInfoModel.allEntriesFetch(adapters, stateUpdate), [adapters, stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index de6a1a4e..8b792c75 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,17 +1,12 @@ -import { Entity as MIEntity, ModuleContext } from "./module-context"; -import { MIPropertiesModel } from "./model/mi-properties"; +import { ModuleContext } from "./module-context"; +import { MIModel } from "./model/mi-model"; import { MIAdminsTable } from "./ui/mi-admins"; import { MIPropertiesProvider } from "./ui/mi-providers"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; -export { type MIEntity }; - -/** - * Multicall Instance entity - */ -export class MI extends ModuleContext { +export class MulticallInstance extends ModuleContext { static AdminsTable = MIAdminsTable; static TokenWhitelistTable = MITokenWhitelistTable; static PropertiesProvider = MIPropertiesProvider; - static useProperties = MIPropertiesModel.useContext; + static useProperties = MIModel.useProperties; } diff --git a/src/entities/multicall-instance/model/mi-properties.ts b/src/entities/multicall-instance/model/mi-model.ts similarity index 56% rename from src/entities/multicall-instance/model/mi-properties.ts rename to src/entities/multicall-instance/model/mi-model.ts index 5fd7e7a9..f930566a 100644 --- a/src/entities/multicall-instance/model/mi-properties.ts +++ b/src/entities/multicall-instance/model/mi-model.ts @@ -2,10 +2,14 @@ import { createContext, useContext, useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { Entity } from "../module-context"; +import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; -export class MIPropertiesModel { - public static readonly data: { +export interface MIModelInputs { + daoAddress: SputnikDAO["address"]; +} + +export class MIModel { + public static readonly properties: { data: Multicall; error: Error | null; loading: boolean; @@ -15,6 +19,9 @@ export class MIPropertiesModel { loading: true, }; + public static readonly PropertiesContext = createContext(MIModel.properties); + public static readonly useProperties = () => useContext(MIModel.PropertiesContext); + /** * Calls the given callback with a result of multicall contract instantiation, * represented as stateful response. @@ -22,9 +29,9 @@ export class MIPropertiesModel { * @param daoAddress DAO contract address * @param callback Stateful data fetch callback */ - private static readonly dataFetchFx = async ( - daoAddress: Entity.Inputs["daoAddress"], - callback: (result: typeof MIPropertiesModel.data) => void + private static readonly propertiesFetch = async ( + daoAddress: MIModelInputs["daoAddress"], + callback: (result: typeof MIModel.properties) => void ) => callback( await Multicall.init( @@ -36,17 +43,11 @@ export class MIPropertiesModel { })) ); - /** - * For context provider usage only. - */ - public static readonly useData = (daoAddress: Entity.Inputs["daoAddress"]) => { - const [state, stateUpdate] = useState(MIPropertiesModel.data); + public static readonly usePropertiesState = (daoAddress: MIModelInputs["daoAddress"]) => { + const [state, stateUpdate] = useState(MIModel.properties); - useEffect(() => void MIPropertiesModel.dataFetchFx(daoAddress, stateUpdate), [daoAddress, stateUpdate]); + useEffect(() => void MIModel.propertiesFetch(daoAddress, stateUpdate), [daoAddress, stateUpdate]); return state; }; - - public static readonly Context = createContext(MIPropertiesModel.data); - public static readonly useContext = () => useContext(MIPropertiesModel.Context); } diff --git a/src/entities/multicall-instance/module-context.ts b/src/entities/multicall-instance/module-context.ts index fc404d94..5d62ff5e 100644 --- a/src/entities/multicall-instance/module-context.ts +++ b/src/entities/multicall-instance/module-context.ts @@ -1,23 +1,11 @@ -import { MulticallSettingsParamKey } from "../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; +import { MulticallPropertyKey } from "../../shared/lib/contracts/multicall"; import { toYocto } from "../../shared/lib/converter"; /** - * Type declaration for Multicall Instance entity - */ -export namespace Entity { - export interface Inputs { - daoAddress: SputnikDAO["address"]; - } - - export type ParamKey = MulticallSettingsParamKey; -} - -/** - * Multicall Instance entity config + * Multicall Instance entity context. */ export class ModuleContext { - public static readonly ParamKey = MulticallSettingsParamKey; + public static readonly ParamKey = MulticallPropertyKey; /** * Minimum balance needed for storage + state. diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 5ea1bc9a..30b78f9f 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,5 +1,5 @@ import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { MIPropertiesModel } from "../model/mi-properties"; +import { MIModel } from "../model/mi-model"; import { miAdminAsTableRow, MIAdminProps } from "./mi-admin"; @@ -9,7 +9,7 @@ interface MIAdminsTableProps { } export const MIAdminsTable = ({ className, itemsAdditional }: MIAdminsTableProps) => { - const { data, error, loading } = MIPropertiesModel.useContext(), + const { data, error, loading } = MIModel.useProperties(), items = (data?.admins ?? []).concat(itemsAdditional ?? []); return ( diff --git a/src/entities/multicall-instance/ui/mi-providers.tsx b/src/entities/multicall-instance/ui/mi-providers.tsx index 2ed94619..5364e9b1 100644 --- a/src/entities/multicall-instance/ui/mi-providers.tsx +++ b/src/entities/multicall-instance/ui/mi-providers.tsx @@ -1,12 +1,14 @@ import { PropsWithChildren } from "react"; -import { Entity } from "../module-context"; -import { MIPropertiesModel } from "../model/mi-properties"; +import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; +import { MIModel } from "../model/mi-model"; -interface MIPropertiesProviderProps extends PropsWithChildren, Pick {} +export interface MIPropertiesProviderProps extends PropsWithChildren { + daoAddress: SputnikDAO["address"]; +} export const MIPropertiesProvider = ({ children, daoAddress }: MIPropertiesProviderProps) => ( - + {children} - + ); diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index 2a8ebffa..cdb551e3 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,5 +1,5 @@ -import { Scrollable, Table, type TableProps, Tile, TileProps } from "../../../shared/ui/design"; -import { MIPropertiesModel } from "../model/mi-properties"; +import { Scrollable, Table, TableProps, Tile, TileProps } from "../../../shared/ui/design"; +import { MIModel } from "../model/mi-model"; import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; @@ -19,7 +19,7 @@ export const MITokenWhitelistTable = ({ onItemsSelected, subheader, }: MITokenWhitelistTableProps) => { - const { data, error, loading } = MIPropertiesModel.useContext(), + const { data, error, loading } = MIModel.useProperties(), items = (data?.tokensWhitelist ?? []).concat(itemsAdditional ?? []); return ( diff --git a/src/entities/near-token/model/near-balances.ts b/src/entities/near-token/model/near-balances.ts index 52c86f17..7e0030d2 100644 --- a/src/entities/near-token/model/near-balances.ts +++ b/src/entities/near-token/model/near-balances.ts @@ -4,14 +4,14 @@ import { Big, formatTokenAmount } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; import { ModuleContext, type NEARToken } from "../module-context"; -type NEARTokenDataFxResponse = { +type NEARTokenDataResponse = { data: { dao: string; multicall: string; total: string } | null; loading: boolean; }; -const nearTokenDataFx = async ( +const nearTokenData = async ( { dao, multicallInstance }: NEARToken.Inputs["adapters"], - callback: (result: NEARTokenDataFxResponse) => void + callback: (result: NEARTokenDataResponse) => void ) => { const [daoAccInfo, multicallAccInfo] = await Promise.all([ viewAccount(dao.address), @@ -38,9 +38,9 @@ const nearTokenDataFx = async ( }; const useNEARTokenData = (adapters: NEARToken.Inputs["adapters"]) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); + const [state, stateUpdate] = useState({ data: null, loading: true }); - useEffect(() => void nearTokenDataFx(adapters, stateUpdate), [adapters, stateUpdate]); + useEffect(() => void nearTokenData(adapters, stateUpdate), [adapters, stateUpdate]); return state; }; diff --git a/src/features/external-login/index.ts b/src/features/external-login/index.ts index 489a5080..136d5b9c 100644 --- a/src/features/external-login/index.ts +++ b/src/features/external-login/index.ts @@ -1,8 +1,8 @@ import { ModuleContext } from "./module-context"; -import { Dialogs } from "./ui/external-login-dialogs"; -import { Menu } from "./ui/external-login-menu"; +import { ELDialogs } from "./ui/el-dialogs"; +import { ELMenu } from "./ui/el-menu"; export class ExternalLogin extends ModuleContext { - static Dialogs = Dialogs; - static Menu = Menu; + static Dialogs = ELDialogs; + static Menu = ELMenu; } diff --git a/src/features/external-login/model/external-login-dialogs.ts b/src/features/external-login/model/el-model.ts similarity index 86% rename from src/features/external-login/model/external-login-dialogs.ts rename to src/features/external-login/model/el-model.ts index 2295d800..06df59fe 100644 --- a/src/features/external-login/model/external-login-dialogs.ts +++ b/src/features/external-login/model/el-model.ts @@ -9,7 +9,7 @@ import { ModuleContext } from "../module-context"; const _dialogOpenRequested = "dialogOpenRequested"; const dialogOpenRequested = { - dispatch: (dialogKey: keyof typeof ModuleContext.METHODS) => + dispatch: (dialogKey: keyof typeof ModuleContext.methods) => document.dispatchEvent(new CustomEvent(_dialogOpenRequested, { detail: { dialogKey } })), subscribe: (callback: EventListener) => { @@ -19,14 +19,14 @@ const dialogOpenRequested = { }, }; -export class ExternalLoginDialogsModel { +export class ELModel { static dialogOpenRequested = dialogOpenRequested.dispatch; - static useVisibilityState = () => { + static useDialogsState = () => { const [dialogsVisibility, dialogVisibilitySwitch] = useState< - Record | {} + Record | {} >( - Object.values(ModuleContext.METHODS).reduce( + Object.values(ModuleContext.methods).reduce( (visibilityState, { type }) => ({ ...visibilityState, [type]: false }), {} ) diff --git a/src/features/external-login/module-context.ts b/src/features/external-login/module-context.ts index 84e6232f..d47ea262 100644 --- a/src/features/external-login/module-context.ts +++ b/src/features/external-login/module-context.ts @@ -1,15 +1,15 @@ export class ModuleContext { - static KEYS = { + static keys = { all: "ed25519%3A9jeqkc8ybv7aYSA7uLNFUEn8cgKo759yue4771bBWsSr", public: "ed25519%3ADEaoD65LomNHAMzhNZva15LC85ntwBHdcTbCnZRXciZH", }; - static METHODS: Record<"dao" | "multicall", { title: string; type: keyof typeof ModuleContext.METHODS }> = { + static methods: Record<"dao" | "multicall", { title: string; type: keyof typeof ModuleContext.methods }> = { dao: { title: "Login in dApps as DAO", type: "dao" }, multicall: { title: "Login in dApps as Multicall", type: "multicall" }, }; - static STEP_BY_STEP_GUIDE = [ + static stepByStepGuide = [ { text: "Open the dApp in another browser tab", }, diff --git a/src/features/external-login/ui/external-login-dialog.scss b/src/features/external-login/ui/el-dialog.scss similarity index 96% rename from src/features/external-login/ui/external-login-dialog.scss rename to src/features/external-login/ui/el-dialog.scss index d2cf6c96..0910bb75 100644 --- a/src/features/external-login/ui/external-login-dialog.scss +++ b/src/features/external-login/ui/el-dialog.scss @@ -1,7 +1,7 @@ @use "sass/size"; @use "sass/mixin"; -.ExternalLoginDialog { +.ELDialog { &-stepByStepGuide { padding: 0 size.$gap; list-style-type: decimal; diff --git a/src/features/external-login/ui/external-login-dialogs.tsx b/src/features/external-login/ui/el-dialog.tsx similarity index 62% rename from src/features/external-login/ui/external-login-dialogs.tsx rename to src/features/external-login/ui/el-dialog.tsx index fef03357..677ce59a 100644 --- a/src/features/external-login/ui/external-login-dialogs.tsx +++ b/src/features/external-login/ui/el-dialog.tsx @@ -7,18 +7,16 @@ import { STORAGE } from "../../../shared/lib/persistent"; import { Validation } from "../../../shared/lib/validation"; import { Dialog, TextInput, Tooltip } from "../../../shared/ui/design"; import { ModuleContext } from "../module-context"; -import { ExternalLoginDialogsModel } from "../model/external-login-dialogs"; -import "./external-login-dialog.scss"; +import "./el-dialog.scss"; -interface ExternalLoginDialogProps - extends Pick, "className" | "onClose" | "open" | "title"> { +interface ELDialogProps extends Pick, "className" | "onClose" | "open" | "title"> { method: "dao" | "multicall"; } -const _ExternalLoginDialog = "ExternalLoginDialog"; +const _ELDialog = "ELDialog"; -const ExternalLoginDialog = ({ className, method, onClose, open, title }: ExternalLoginDialogProps) => { +export const ELDialog = ({ className, method, onClose, open, title }: ELDialogProps) => { const dAppURL = useMemo(() => new ArgsString(""), []); const URLInvalid = ArgsError.useInstance("Invalid URL", Validation.isUrl, true); @@ -30,8 +28,8 @@ const ExternalLoginDialog = ({ className, method, onClose, open, title }: Extern } else { const url = new URL(value); url.searchParams.set("account_id", STORAGE.addresses[method]); - url.searchParams.set("public_key", ModuleContext.KEYS.public); - url.searchParams.set("all_keys", ModuleContext.KEYS.all); + url.searchParams.set("public_key", ModuleContext.keys.public); + url.searchParams.set("all_keys", ModuleContext.keys.all); return url.toString(); } }, @@ -40,14 +38,14 @@ const ExternalLoginDialog = ({ className, method, onClose, open, title }: Extern return ( window.open(requestURL, "_blank")} {...{ onClose, open, title }} > -
          - {ModuleContext.STEP_BY_STEP_GUIDE.map((step) => ( +
            + {ModuleContext.stepByStepGuide.map((step) => (
          • {step.text} @@ -76,24 +74,3 @@ const ExternalLoginDialog = ({ className, method, onClose, open, title }: Extern
        ); }; - -export const Dialogs = () => { - const { dialogsVisibility, closeHandlerBinding } = ExternalLoginDialogsModel.useVisibilityState(); - - return ( - <> - {" "} - {Object.values(ModuleContext.METHODS).map((loginMethod) => ( - - ))} - - ); -}; - -Dialogs.displayName = `${_ExternalLoginDialog}s`; diff --git a/src/features/external-login/ui/el-dialogs.tsx b/src/features/external-login/ui/el-dialogs.tsx new file mode 100644 index 00000000..f8f4db43 --- /dev/null +++ b/src/features/external-login/ui/el-dialogs.tsx @@ -0,0 +1,22 @@ +import { ModuleContext } from "../module-context"; +import { ELModel } from "../model/el-model"; +import { ELDialog } from "./el-dialog"; + +export const ELDialogs = () => { + const { dialogsVisibility, closeHandlerBinding } = ELModel.useDialogsState(); + + return ( + <> + {" "} + {Object.values(ModuleContext.methods).map((loginMethod) => ( + + ))} + + ); +}; diff --git a/src/features/external-login/ui/el-menu.tsx b/src/features/external-login/ui/el-menu.tsx new file mode 100644 index 00000000..2963625d --- /dev/null +++ b/src/features/external-login/ui/el-menu.tsx @@ -0,0 +1,25 @@ +import { PreviewOutlined } from "@mui/icons-material"; +import { ComponentProps } from "react"; + +import { PopupMenu } from "../../../shared/ui/design"; +import { ModuleContext } from "../module-context"; +import { ELModel } from "../model/el-model"; + +interface ELMenuProps extends Pick, "triggerClassName"> { + FeatureFlags: { + ExternalLogin: Record; + }; +} + +export const ELMenu = ({ FeatureFlags, triggerClassName }: ELMenuProps) => ( + } + items={Object.values(ModuleContext.methods).map(({ title, type }) => ({ + disabled: !FeatureFlags.ExternalLogin[type], + key: type, + onClick: () => ELModel.dialogOpenRequested(type), + title, + }))} + {...{ triggerClassName }} + /> +); diff --git a/src/features/external-login/ui/external-login-menu.tsx b/src/features/external-login/ui/external-login-menu.tsx deleted file mode 100644 index 75fda15a..00000000 --- a/src/features/external-login/ui/external-login-menu.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { PreviewOutlined } from "@mui/icons-material"; -import { ComponentProps } from "react"; - -import { PopupMenu } from "../../../shared/ui/design"; -import { ModuleContext } from "../module-context"; -import { ExternalLoginDialogsModel } from "../model/external-login-dialogs"; - -const _ExternalLoginMenu = "ExternalLoginMenu"; - -interface MenuProps extends Pick, "triggerClassName"> { - FeatureFlags: { - ExternalLogin: Record; - }; -} - -export const Menu = ({ FeatureFlags, triggerClassName }: MenuProps) => ( - } - items={Object.values(ModuleContext.METHODS).map(({ title, type }) => ({ - disabled: !FeatureFlags.ExternalLogin[type], - key: type, - onClick: () => ExternalLoginDialogsModel.dialogOpenRequested(type), - title, - }))} - {...{ triggerClassName }} - /> -); - -Menu.displayName = _ExternalLoginMenu; diff --git a/src/features/index.ts b/src/features/index.ts index 1e40fac1..8dd7789b 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,3 +1,3 @@ export { ExternalLogin } from "./external-login"; -export { SchedulingSettingsChange, type SchedulingSettingsChangeFeature } from "./scheduling/settings-change"; +export { SchedulingSettingsChange } from "./scheduling/settings-change"; export { TokenWhitelistChange, type TokenWhitelistChangeFeature } from "./token/whitelist-change"; diff --git a/src/features/scheduling/settings-change/index.ts b/src/features/scheduling/settings-change/index.ts index 3aeeb3b4..be7292df 100644 --- a/src/features/scheduling/settings-change/index.ts +++ b/src/features/scheduling/settings-change/index.ts @@ -1,8 +1,6 @@ -import { ModuleContext, Feature as SchedulingSettingsChangeFeature } from "./module-context"; -import { Form } from "./ui/scheduling-settings-change"; - -export { type SchedulingSettingsChangeFeature }; +import { ModuleContext } from "./module-context"; +import { SchedulingSettingsChangeUI } from "./ui/scheduling-settings-change"; export class SchedulingSettingsChange extends ModuleContext { - public static readonly Form = Form; + public static readonly UI = SchedulingSettingsChangeUI; } diff --git a/src/features/scheduling/settings-change/module-context.ts b/src/features/scheduling/settings-change/module-context.ts index c2468a36..20349d64 100644 --- a/src/features/scheduling/settings-change/module-context.ts +++ b/src/features/scheduling/settings-change/module-context.ts @@ -1,22 +1,8 @@ -import { HTMLProps } from "react"; - -import { MI, MIEntity } from "../../../entities"; -import { MulticallSettingsDiff, Multicall } from "../../../shared/lib/contracts/multicall"; +import { MulticallInstance } from "../../../entities"; import { DesignContext } from "../../../shared/ui/design"; -export namespace Feature { - export type DiffKey = MIEntity.ParamKey; - - export type FormState = Pick; - - export interface Inputs extends Omit, "onChange"> { - onEdit: (payload: FormState) => void; - resetTrigger: { subscribe: (callback: EventListener) => () => void }; - } -} - export class ModuleContext { - public static readonly DiffKey = MI.ParamKey; + public static readonly DiffKey = MulticallInstance.ParamKey; public static readonly DiffMeta = { [ModuleContext.DiffKey.croncatManager]: { diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx index 3b9bee28..f0073045 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx +++ b/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx @@ -1,30 +1,38 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; import { IconButton, TextField, TextFieldProps } from "@mui/material"; -import { useCallback, useEffect, useMemo, useState } from "react"; +import { HTMLProps, useCallback, useEffect, useMemo, useState } from "react"; -import { MI } from "../../../../entities"; +import { MulticallInstance } from "../../../../entities"; import { ArgsString } from "../../../../shared/lib/args-old"; +import { MulticallSettingsChange, MulticallPropertyKey } from "../../../../shared/lib/contracts/multicall"; import { toNEAR, toYocto } from "../../../../shared/lib/converter"; import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../../shared/ui/design"; -import { ModuleContext, Feature } from "../module-context"; +import { ModuleContext } from "../module-context"; import "./scheduling-settings-change.scss"; const _SchedulingSettingsChange = "SchedulingSettingsChange"; -export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { - const { data: MIProperties } = MI.useProperties(); +type FormState = Pick; + +interface SchedulingSettingsChangeUIProps extends Omit, "onChange"> { + onEdit: (payload: FormState) => void; + resetTrigger: { subscribe: (callback: EventListener) => () => void }; +} + +export const SchedulingSettingsChangeUI = ({ disabled, onEdit, resetTrigger }: SchedulingSettingsChangeUIProps) => { + const { data: MIProperties } = MulticallInstance.useProperties(); const [editModeEnabled, editModeSwitch] = useState(false); - const formInitialState: Feature.FormState = { + const formInitialState: FormState = { [ModuleContext.DiffKey.croncatManager]: "", [ModuleContext.DiffKey.jobBond]: "", }; const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ - useState(formInitialState.croncatManager), - useState(formInitialState.jobBond), + useState(formInitialState.croncatManager), + useState(formInitialState.jobBond), ]; const formFields = { @@ -61,7 +69,6 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { }, [croncatManagerUpdate, editModeSwitch, formInitialState, jobBondUpdate]); useEffect(() => resetTrigger.subscribe(formReset), [formReset, resetTrigger]); - useEffect(() => void onEdit({ croncatManager, jobBond }), [croncatManager, jobBond, onEdit]); return ( @@ -104,8 +111,9 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { centeredTitle: true, idToHighlightColor: (id) => - ({ croncatManager, jobBond }[id] === formInitialState[id as Feature.DiffKey] || - { croncatManager, jobBond }[id] === MIProperties[id as Feature.DiffKey] + ({ croncatManager, jobBond }[id] === + formInitialState[id as keyof typeof ModuleContext["DiffKey"]] || + { croncatManager, jobBond }[id] === MIProperties[id as keyof typeof ModuleContext["DiffKey"]] ? null : "blue"), @@ -168,5 +176,3 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => {
        ); }; - -Form.displayName = _SchedulingSettingsChange; diff --git a/src/features/token/whitelist-change/index.ts b/src/features/token/whitelist-change/index.ts index 594f75ca..c24ed744 100644 --- a/src/features/token/whitelist-change/index.ts +++ b/src/features/token/whitelist-change/index.ts @@ -1,8 +1,8 @@ import { ModuleContext, Feature as TokenWhitelistChangeFeature } from "./module-context"; -import { Form } from "./ui/token-whitelist-change"; +import { TokenWhitelistChangeUI } from "./ui/token-whitelist-change"; export { type TokenWhitelistChangeFeature }; export class TokenWhitelistChange extends ModuleContext { - public static readonly Form = Form; + public static readonly UI = TokenWhitelistChangeUI; } diff --git a/src/features/token/whitelist-change/module-context.ts b/src/features/token/whitelist-change/module-context.ts index 271584fc..d98923ca 100644 --- a/src/features/token/whitelist-change/module-context.ts +++ b/src/features/token/whitelist-change/module-context.ts @@ -1,20 +1,20 @@ import { HTMLProps } from "react"; -import { MulticallTokenWhitelistDiffKey, MulticallSettingsDiff } from "../../../shared/lib/contracts/multicall"; +import { MulticallTokenWhitelistDiffKey, MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; import { DesignContext } from "../../../shared/ui/design"; export namespace Feature { export type DiffKey = MulticallTokenWhitelistDiffKey; export interface Inputs extends Omit, "onChange"> { - onEdit: (payload: Pick) => void; + onEdit: (payload: Pick) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } export interface FormStates extends Record< - keyof Pick, - Set][number]> + keyof Pick, + Set][number]> > {} } diff --git a/src/features/token/whitelist-change/ui/token-whitelist-change.tsx b/src/features/token/whitelist-change/ui/token-whitelist-change.tsx index 1b2a6175..96e593ff 100644 --- a/src/features/token/whitelist-change/ui/token-whitelist-change.tsx +++ b/src/features/token/whitelist-change/ui/token-whitelist-change.tsx @@ -4,14 +4,14 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { TextInput, Tooltip } from "../../../../shared/ui/design"; import { ArgsString } from "../../../../shared/lib/args-old"; -import { MI } from "../../../../entities"; +import { MulticallInstance } from "../../../../entities"; import { ModuleContext, Feature } from "../module-context"; import "./token-whitelist-change.scss"; const _TokenWhitelistChange = "TokenWhitelistChange"; -export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { +export const TokenWhitelistChangeUI = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { const [editModeEnabled, editModeSwitch] = useState(false); const [addTokens, markForAddition] = useState(new Set()), @@ -64,7 +64,7 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { ); return ( - (addTokens.has(id) && ModuleContext.DiffMeta.addTokens.color) || @@ -128,5 +128,3 @@ export const Form = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { /> ); }; - -Form.displayName = _TokenWhitelistChange; diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index 1e5fa046..a3ce37d7 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -3,7 +3,7 @@ import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component, ContextType } from "react"; -import { MI, Wallet } from "../../entities"; +import { MulticallInstance, Wallet } from "../../entities"; import { Form, Formik } from "formik"; import { args } from "../../shared/lib/args/args"; import { fields } from "../../shared/lib/args/args-types/args-object"; @@ -181,7 +181,7 @@ export class DaoPage extends Component { const multicallAddress = this.toMulticallAddress(formData.addr); - const depo = Big(this.fee).plus(MI.MIN_BALANCE); + const depo = Big(this.fee).plus(MulticallInstance.MIN_BALANCE); /** * Can user propose a FunctionCall to DAO? diff --git a/src/pages/dao/settings/settings.tsx b/src/pages/dao/settings/settings.tsx index 7b3c5040..7cd06af7 100644 --- a/src/pages/dao/settings/settings.tsx +++ b/src/pages/dao/settings/settings.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { MI } from "../../../entities"; +import { MulticallInstance } from "../../../entities"; import { SettingsEditor, SettingsEditorProps } from "../../../widgets"; import "./settings.scss"; @@ -11,14 +11,14 @@ const _DaoSettingsTab = "DaoSettingsTab"; interface DaoSettingsTabProps extends HTMLProps, SettingsEditorProps {} const Content = ({ className, adapters, ...props }: DaoSettingsTabProps) => ( - +
        -
        + ); Content.displayName = _DaoSettingsTab; diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 8bb4f782..c2c807a9 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -1,6 +1,6 @@ import { Big, toGas, dateToCron, toYocto } from "../converter"; import { AccountId, Base64String, U128String, U64String } from "../types"; -import { viewAccount, viewState, view } from "../wallet"; +import { viewAccount, viewState, view, Tx } from "../wallet"; import { FunctionCallAction as daoFunctionCallAction } from "./sputnik-dao"; @@ -58,7 +58,7 @@ type MulticallArgs = { calls: BatchCall[][]; }; -enum MulticallSettingsParamKey { +enum MulticallPropertyKey { croncatManager = "croncatManager", jobBond = "jobBond", } @@ -68,12 +68,12 @@ enum MulticallTokenWhitelistDiffKey { removeTokens = "removeTokens", } -type MulticallSettingsDiff = { +interface MulticallSettingsChange { [MulticallTokenWhitelistDiffKey.addTokens]: AccountId[]; - [MulticallSettingsParamKey.croncatManager]: AccountId; - [MulticallSettingsParamKey.jobBond]: U128String; + [MulticallPropertyKey.croncatManager]: AccountId; + [MulticallPropertyKey.jobBond]: U128String; [MulticallTokenWhitelistDiffKey.removeTokens]: AccountId[]; -}; +} class Multicall { static FACTORY_ADDRESS: AccountId = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; @@ -83,12 +83,12 @@ class Multicall { address: AccountId; admins: AccountId[] = []; - [MulticallSettingsParamKey.croncatManager]: AccountId = ""; + [MulticallPropertyKey.croncatManager]: AccountId = ""; // only whitelisted tokens can be attached to multicalls or job activations. tokensWhitelist: AccountId[] = []; // job bond amount must be attached as deposit when adding new jobs. // needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). - [MulticallSettingsParamKey.jobBond]: U128String = ""; + [MulticallPropertyKey.jobBond]: U128String = ""; // Multicall instance is ready when info (admins...) are fetched & assigned correctly. ready: boolean = false; @@ -166,7 +166,7 @@ class Multicall { addTokens = [], jobBond = "", croncatManager = "", - }: MulticallSettingsDiff): daoFunctionCallAction[] { + }: MulticallSettingsChange): daoFunctionCallAction[] { const actions: daoFunctionCallAction[] = []; // action: change croncat manager address @@ -292,5 +292,5 @@ class Multicall { } } -export { Multicall, MulticallSettingsParamKey, MulticallTokenWhitelistDiffKey }; -export type { JobData, MulticallArgs, MulticallSettingsDiff }; +export { Multicall, MulticallPropertyKey, MulticallTokenWhitelistDiffKey }; +export type { JobData, MulticallArgs, MulticallSettingsChange }; diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx index 27f82a9d..e9b30591 100644 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.tsx @@ -1,10 +1,10 @@ import clsx from "clsx"; import { useCallback, useMemo, useState, FormEventHandler, useEffect, useContext, HTMLProps } from "react"; -import { MI, Wallet } from "../../../entities"; +import { MulticallInstance, Wallet } from "../../../entities"; import { SchedulingSettingsChange, TokenWhitelistChange } from "../../../features"; import { ArgsString } from "../../../shared/lib/args-old"; -import { Multicall, MulticallSettingsDiff } from "../../../shared/lib/contracts/multicall"; +import { Multicall, MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { signAndSendTxs } from "../../../shared/lib/wallet"; import { ModuleContext } from "../module-context"; @@ -21,21 +21,21 @@ export interface SettingsEditorProps extends HTMLProps { export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => { const wallet = useContext(Wallet.SelectorContext), - { data: MIProperties, error: MIError } = MI.useProperties(); + { data: MIProperties, error: MIError } = MulticallInstance.useProperties(); const proposalCreationPermitted = !wallet?.accountId || adapters.dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); const [editMode, editModeSwitch] = useState(false); - const changesDiffInitialState: MulticallSettingsDiff = { + const changesDiffInitialState: MulticallSettingsChange = { [ModuleContext.DiffKey.removeTokens]: [], [ModuleContext.DiffKey.addTokens]: [], [ModuleContext.DiffKey.jobBond]: "", [ModuleContext.DiffKey.croncatManager]: "", }; - const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), + const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), formValues = { proposalDescription: useMemo(() => new ArgsString(""), []) }, [proposalDescription, proposalDescriptionUpdate] = useState(formValues.proposalDescription.value), _childFormsResetRequested = "childFormsResetRequested"; @@ -64,7 +64,7 @@ export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( - (update: Partial) => + (update: Partial) => void changesDiffUpdate((latestState) => ({ ...latestState, ...update })), [changesDiffUpdate] @@ -99,16 +99,16 @@ export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => error={MIError} /> - {false && } + {false && } - - { - changesDiff: MulticallSettingsDiff; + changesDiff: MulticallSettingsChange; description: Parameters[0]; formValues: { proposalDescription: ArgsString }; editMode: boolean; diff --git a/src/widgets/sidebar/sidebar.jsx b/src/widgets/sidebar/sidebar.jsx index c0c7c213..52f6b1cb 100644 --- a/src/widgets/sidebar/sidebar.jsx +++ b/src/widgets/sidebar/sidebar.jsx @@ -31,8 +31,8 @@ export class Sidebar extends Component { initialized: false, ExternalLogin: { - [ExternalLogin.METHODS.dao.type]: true, - [ExternalLogin.METHODS.multicall.type]: false, + [ExternalLogin.methods.dao.type]: true, + [ExternalLogin.methods.multicall.type]: false, }, }, @@ -58,7 +58,7 @@ export class Sidebar extends Component { ExternalLogin: { ...this.state.FeatureFlags.ExternalLogin, - [ExternalLogin.METHODS.multicall.type]: true, + [ExternalLogin.methods.multicall.type]: true, }, }, }) @@ -71,7 +71,7 @@ export class Sidebar extends Component { ExternalLogin: { ...this.state.FeatureFlags.ExternalLogin, - [ExternalLogin.METHODS.multicall.type]: false, + [ExternalLogin.methods.multicall.type]: false, }, }, }) From df6d641a5ccb598f6a96951135ca7d1355c1bca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 15 Dec 2022 20:27:17 +0400 Subject: [PATCH 451/537] wip: Remove type redundancy --- src/features/index.ts | 2 +- .../settings-change/module-context.ts | 6 ++--- src/features/token/whitelist-change/index.ts | 4 +-- .../token/whitelist-change/module-context.ts | 25 +++---------------- .../ui/token-whitelist-change.tsx | 20 +++++++++++---- src/pages/dao/funds/funds.tsx | 2 +- src/shared/ui/design/index.ts | 2 +- src/shared/ui/design/module-context.ts | 4 +-- src/shared/ui/design/table/row.tsx | 5 ++-- 9 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/features/index.ts b/src/features/index.ts index 8dd7789b..bb543528 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,3 +1,3 @@ export { ExternalLogin } from "./external-login"; export { SchedulingSettingsChange } from "./scheduling/settings-change"; -export { TokenWhitelistChange, type TokenWhitelistChangeFeature } from "./token/whitelist-change"; +export { TokenWhitelistChange } from "./token/whitelist-change"; diff --git a/src/features/scheduling/settings-change/module-context.ts b/src/features/scheduling/settings-change/module-context.ts index 20349d64..6457d26f 100644 --- a/src/features/scheduling/settings-change/module-context.ts +++ b/src/features/scheduling/settings-change/module-context.ts @@ -1,17 +1,17 @@ import { MulticallInstance } from "../../../entities"; -import { DesignContext } from "../../../shared/ui/design"; +import { Color } from "../../../shared/ui/design"; export class ModuleContext { public static readonly DiffKey = MulticallInstance.ParamKey; public static readonly DiffMeta = { [ModuleContext.DiffKey.croncatManager]: { - color: "blue" as DesignContext.Color, + color: "blue" as Color, description: "Croncat manager", }, [ModuleContext.DiffKey.jobBond]: { - color: "blue" as DesignContext.Color, + color: "blue" as Color, description: "Job bond", }, }; diff --git a/src/features/token/whitelist-change/index.ts b/src/features/token/whitelist-change/index.ts index c24ed744..fecb3ed9 100644 --- a/src/features/token/whitelist-change/index.ts +++ b/src/features/token/whitelist-change/index.ts @@ -1,8 +1,6 @@ -import { ModuleContext, Feature as TokenWhitelistChangeFeature } from "./module-context"; +import { ModuleContext } from "./module-context"; import { TokenWhitelistChangeUI } from "./ui/token-whitelist-change"; -export { type TokenWhitelistChangeFeature }; - export class TokenWhitelistChange extends ModuleContext { public static readonly UI = TokenWhitelistChangeUI; } diff --git a/src/features/token/whitelist-change/module-context.ts b/src/features/token/whitelist-change/module-context.ts index d98923ca..c9886fdb 100644 --- a/src/features/token/whitelist-change/module-context.ts +++ b/src/features/token/whitelist-change/module-context.ts @@ -1,34 +1,17 @@ -import { HTMLProps } from "react"; - -import { MulticallTokenWhitelistDiffKey, MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; -import { DesignContext } from "../../../shared/ui/design"; - -export namespace Feature { - export type DiffKey = MulticallTokenWhitelistDiffKey; - - export interface Inputs extends Omit, "onChange"> { - onEdit: (payload: Pick) => void; - resetTrigger: { subscribe: (callback: EventListener) => () => void }; - } - - export interface FormStates - extends Record< - keyof Pick, - Set][number]> - > {} -} +import { MulticallTokenWhitelistDiffKey } from "../../../shared/lib/contracts/multicall"; +import { Color } from "../../../shared/ui/design"; export class ModuleContext { public static readonly DiffKey = MulticallTokenWhitelistDiffKey; public static readonly DiffMeta = { [ModuleContext.DiffKey.addTokens]: { - color: "green" as DesignContext.Color, + color: "green" as Color, description: "Tokens to add to whitelist", }, [ModuleContext.DiffKey.removeTokens]: { - color: "red" as DesignContext.Color, + color: "red" as Color, description: "Tokens to remove from whitelist", }, }; diff --git a/src/features/token/whitelist-change/ui/token-whitelist-change.tsx b/src/features/token/whitelist-change/ui/token-whitelist-change.tsx index 96e593ff..8a87a957 100644 --- a/src/features/token/whitelist-change/ui/token-whitelist-change.tsx +++ b/src/features/token/whitelist-change/ui/token-whitelist-change.tsx @@ -1,21 +1,31 @@ import { CancelOutlined, DeleteOutlined, EditOutlined, SettingsBackupRestoreOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; -import { useCallback, useEffect, useMemo, useState } from "react"; +import { HTMLProps, useCallback, useEffect, useMemo, useState } from "react"; +import { MulticallSettingsChange, MulticallTokenWhitelistDiffKey } from "../../../../shared/lib/contracts/multicall"; import { TextInput, Tooltip } from "../../../../shared/ui/design"; import { ArgsString } from "../../../../shared/lib/args-old"; import { MulticallInstance } from "../../../../entities"; -import { ModuleContext, Feature } from "../module-context"; +import { ModuleContext } from "../module-context"; import "./token-whitelist-change.scss"; const _TokenWhitelistChange = "TokenWhitelistChange"; -export const TokenWhitelistChangeUI = ({ disabled, onEdit, resetTrigger }: Feature.Inputs) => { +type FormState = Pick; + +interface TokenWhitelistChangeUIProps extends Omit, "onChange"> { + onEdit: (payload: FormState) => void; + resetTrigger: { subscribe: (callback: EventListener) => () => void }; +} + +interface FormStates extends Record> {} + +export const TokenWhitelistChangeUI = ({ disabled, onEdit, resetTrigger }: TokenWhitelistChangeUIProps) => { const [editModeEnabled, editModeSwitch] = useState(false); - const [addTokens, markForAddition] = useState(new Set()), - [removeTokens, markForRemoval] = useState(new Set()); + const [addTokens, markForAddition] = useState(new Set()), + [removeTokens, markForRemoval] = useState(new Set()); const tokenToAddAddress = useMemo(() => new ArgsString(""), []); diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index 7cc93f0a..e0d1b6ac 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import { HTMLProps } from "react"; -import { TokenBalances, type TokenBalancesProps } from "../../../widgets"; +import { TokenBalances, TokenBalancesProps } from "../../../widgets"; import "./funds.scss"; diff --git a/src/shared/ui/design/index.ts b/src/shared/ui/design/index.ts index f36509a5..e445e73c 100644 --- a/src/shared/ui/design/index.ts +++ b/src/shared/ui/design/index.ts @@ -1,4 +1,4 @@ -export { type DesignContext } from "./module-context"; +export { type Color } from "./module-context"; /** Atoms */ export { Button } from "./button"; diff --git a/src/shared/ui/design/module-context.ts b/src/shared/ui/design/module-context.ts index 1acca136..8260461b 100644 --- a/src/shared/ui/design/module-context.ts +++ b/src/shared/ui/design/module-context.ts @@ -1,3 +1 @@ -export namespace DesignContext { - export type Color = "blue" | "green" | "red" | "yellow"; -} +export type Color = "blue" | "green" | "red" | "yellow"; diff --git a/src/shared/ui/design/table/row.tsx b/src/shared/ui/design/table/row.tsx index 67dea921..07a8aa8b 100644 --- a/src/shared/ui/design/table/row.tsx +++ b/src/shared/ui/design/table/row.tsx @@ -1,7 +1,8 @@ import { Checkbox, TableCell, TableRow as MuiTableRow } from "@mui/material"; import clsx from "clsx"; import { ChangeEvent, useCallback } from "react"; -import { DesignContext } from "../module-context"; + +import { Color } from "../module-context"; import "./row.scss"; @@ -19,7 +20,7 @@ export interface TableRowProps { withTitle?: boolean; header: TableHeader; id: string; - idToHighlightColor?: (id: TableRowProps["id"]) => DesignContext.Color | null; + idToHighlightColor?: (id: TableRowProps["id"]) => Color | null; noKeys?: boolean; onSelect?: (selectedRow: { id: TableRowProps["id"]; checked: boolean }) => void; selectable: boolean; From b4ef013fe26af6d5ff26cbe0d34087c76905f0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Thu, 15 Dec 2022 20:39:05 +0400 Subject: [PATCH 452/537] wip: Fix type error --- src/features/external-login/model/el-model.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/features/external-login/model/el-model.ts b/src/features/external-login/model/el-model.ts index 06df59fe..0c5b8dbf 100644 --- a/src/features/external-login/model/el-model.ts +++ b/src/features/external-login/model/el-model.ts @@ -8,6 +8,10 @@ import { ModuleContext } from "../module-context"; const _dialogOpenRequested = "dialogOpenRequested"; +type DialogOpenRequestedEvent = CustomEventInit<{ + dialogKey: "dao" | "multicall"; +}>; + const dialogOpenRequested = { dispatch: (dialogKey: keyof typeof ModuleContext.methods) => document.dispatchEvent(new CustomEvent(_dialogOpenRequested, { detail: { dialogKey } })), @@ -34,12 +38,12 @@ export class ELModel { useEffect( () => - dialogOpenRequested.subscribe(({ detail }) => + dialogOpenRequested.subscribe(({ detail }: DialogOpenRequestedEvent) => dialogVisibilitySwitch( Object.keys(dialogsVisibility).reduce( (visibilityState, someDialogKey) => ({ ...visibilityState, - [someDialogKey]: someDialogKey === detail.dialogKey ? true : false, + [someDialogKey]: someDialogKey === detail?.dialogKey ? true : false, }), dialogsVisibility From d3d33be36835d2f5d1fb303290ec3864a30acb5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 16 Dec 2022 03:06:33 +0400 Subject: [PATCH 453/537] wip: Apply code review and naming remarks --- src/entities/fungible-token/index.ts | 12 +- src/entities/fungible-token/model/ft-info.ts | 64 -------- src/entities/fungible-token/model/ft-model.ts | 82 +++++++++++ src/entities/fungible-token/module-context.ts | 12 -- .../fungible-token/ui/ft-balances.tsx | 16 +- .../fungible-token/ui/ft-providers.tsx | 13 ++ src/entities/index.ts | 4 +- src/entities/multicall-instance/index.ts | 6 +- .../multicall-instance/model/mi-model.ts | 13 +- .../multicall-instance/ui/mi-admins.tsx | 3 +- .../multicall-instance/ui/mi-providers.tsx | 13 +- .../ui/mi-token-whitelist.tsx | 9 +- src/entities/near-token/index.ts | 8 +- .../model/{near-balances.ts => nt-model.ts} | 0 src/entities/near-token/ui/nt-balances.tsx | 8 +- src/entities/wallet/ui/wallet.tsx | 15 +- src/features/index.ts | 5 +- .../manage-scheduling-settings/index.ts | 6 + .../module-context.ts | 4 +- .../manage-scheduling-settings/ui.scss | 3 + .../ui.tsx} | 57 +++---- .../manage-whitelisted-tokens/index.ts | 6 + .../module-context.ts | 4 +- .../manage-whitelisted-tokens/ui.scss | 3 + .../ui.tsx} | 20 +-- src/features/propose-settings/index.ts | 6 + .../propose-settings/module-context.ts | 1 + .../ui/propose-settings.scss} | 4 +- .../propose-settings/ui/propose-settings.tsx | 139 ++++++++++++++++++ .../scheduling/settings-change/index.ts | 6 - .../ui/scheduling-settings-change.scss | 3 - src/features/token/whitelist-change/index.ts | 6 - .../ui/token-whitelist-change.scss | 3 - src/pages/dao/dao.tsx | 105 ++++++------- src/pages/dao/funds/funds.scss | 4 +- src/pages/dao/funds/funds.tsx | 30 ++-- src/pages/dao/jobs/jobs.tsx | 23 ++- src/pages/dao/settings/settings.tsx | 26 ++-- src/shared/lib/contracts/multicall.ts | 53 +++++-- src/widgets/balances/index.ts | 1 + .../token-balances.scss => balances/ui.scss} | 4 +- src/widgets/balances/ui.tsx | 55 +++++++ src/widgets/dialogs-layer/index.ts | 2 +- .../{ui/dialogs-layer.tsx => ui.tsx} | 2 +- src/widgets/index.ts | 2 +- src/widgets/settings-editor/index.ts | 2 +- src/widgets/settings-editor/module-context.ts | 10 +- .../{ui/settings-editor.scss => ui.scss} | 4 +- src/widgets/settings-editor/ui.tsx | 94 ++++++++++++ .../settings-editor/ui/settings-editor.tsx | 125 ---------------- .../ui/settings-proposal-create.tsx | 120 --------------- src/widgets/token-balances/index.ts | 1 - .../token-balances/ui/token-balances.tsx | 36 ----- 53 files changed, 650 insertions(+), 603 deletions(-) delete mode 100644 src/entities/fungible-token/model/ft-info.ts create mode 100644 src/entities/fungible-token/model/ft-model.ts create mode 100644 src/entities/fungible-token/ui/ft-providers.tsx rename src/entities/near-token/model/{near-balances.ts => nt-model.ts} (100%) create mode 100644 src/features/manage-scheduling-settings/index.ts rename src/features/{scheduling/settings-change => manage-scheduling-settings}/module-context.ts (79%) create mode 100644 src/features/manage-scheduling-settings/ui.scss rename src/features/{scheduling/settings-change/ui/scheduling-settings-change.tsx => manage-scheduling-settings/ui.tsx} (73%) create mode 100644 src/features/manage-whitelisted-tokens/index.ts rename src/features/{token/whitelist-change => manage-whitelisted-tokens}/module-context.ts (76%) create mode 100644 src/features/manage-whitelisted-tokens/ui.scss rename src/features/{token/whitelist-change/ui/token-whitelist-change.tsx => manage-whitelisted-tokens/ui.tsx} (89%) create mode 100644 src/features/propose-settings/index.ts create mode 100644 src/features/propose-settings/module-context.ts rename src/{widgets/settings-editor/ui/settings-proposal-create.scss => features/propose-settings/ui/propose-settings.scss} (96%) create mode 100644 src/features/propose-settings/ui/propose-settings.tsx delete mode 100644 src/features/scheduling/settings-change/index.ts delete mode 100644 src/features/scheduling/settings-change/ui/scheduling-settings-change.scss delete mode 100644 src/features/token/whitelist-change/index.ts delete mode 100644 src/features/token/whitelist-change/ui/token-whitelist-change.scss create mode 100644 src/widgets/balances/index.ts rename src/widgets/{token-balances/ui/token-balances.scss => balances/ui.scss} (80%) create mode 100644 src/widgets/balances/ui.tsx rename src/widgets/dialogs-layer/{ui/dialogs-layer.tsx => ui.tsx} (57%) rename src/widgets/settings-editor/{ui/settings-editor.scss => ui.scss} (84%) create mode 100644 src/widgets/settings-editor/ui.tsx delete mode 100644 src/widgets/settings-editor/ui/settings-editor.tsx delete mode 100644 src/widgets/settings-editor/ui/settings-proposal-create.tsx delete mode 100644 src/widgets/token-balances/index.ts delete mode 100644 src/widgets/token-balances/ui/token-balances.tsx diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 766e8fcb..6bb14c59 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,8 +1,10 @@ -import { ModuleContext, FT as FTModule } from "./module-context"; -import { ftBalances } from "./ui/ft-balances"; - -export { type FTModule }; +import { ModuleContext } from "./module-context"; +import { FTBalancesProps, ftBalancesRender } from "./ui/ft-balances"; +import { FTBalancesProvider, FTBalancesProviderProps } from "./ui/ft-providers"; export class FT extends ModuleContext { - static balances = ftBalances; + static BalancesProvider = FTBalancesProvider; + static balancesRender = ftBalancesRender; } + +export type { FTBalancesProps, FTBalancesProviderProps }; diff --git a/src/entities/fungible-token/model/ft-info.ts b/src/entities/fungible-token/model/ft-info.ts deleted file mode 100644 index ca32d81d..00000000 --- a/src/entities/fungible-token/model/ft-info.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { useEffect, useState } from "react"; - -import { Big } from "../../../shared/lib/converter"; -import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; -import { FT } from "../module-context"; - -type FTInfo = { - data: { metadata: FungibleToken["metadata"]; dao: string; multicall: string; total: string }[] | null; - loading: boolean; -}; - -export class FTInfoModel { - private static readonly nonZeroBalancesFetch = async ( - { dao, multicallInstance }: FT.Inputs["adapters"], - callback: (result: FTInfo) => void - ) => { - /* Get LikelyTokens list on DAO and its Multicall instance */ - const [daoLikelyTokensList, multicallLikelyTokensList] = await Promise.all([ - FungibleToken.getLikelyTokenContracts(dao.address), - FungibleToken.getLikelyTokenContracts(multicallInstance.address), - ]); - - /* Merge and de-duplicate both token lists */ - const likelyTokensAddressesList = [...new Set([...daoLikelyTokensList, ...multicallLikelyTokensList])]; - - const likelyTokensList = await Promise.all( - likelyTokensAddressesList.map((address) => FungibleToken.init(address)) - ); - - const rawBalances = await Promise.all( - likelyTokensList - .filter((token) => token.ready === true) - .map(async (token) => { - const [daoRawBalance, multicallRawBalance] = await Promise.all([ - token.ftBalanceOf(dao.address), - token.ftBalanceOf(multicallInstance.address), - ]); - - return { - metadata: token.metadata, - dao: daoRawBalance, - multicall: multicallRawBalance, - total: Big(multicallRawBalance).add(daoRawBalance).toFixed(), - }; - }) - ); - - // remove tokens with 0 total balance - const nonZeroBalances = rawBalances.filter(({ total }) => Big(total).gt("0")); - - return callback({ - data: nonZeroBalances.map(({ dao, metadata, multicall, total }) => ({ metadata, dao, multicall, total })), - loading: false, - }); - }; - - public static readonly useNonZeroBalances = (adapters: FT.Inputs["adapters"]) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); - - useEffect(() => void FTInfoModel.nonZeroBalancesFetch(adapters, stateUpdate), [adapters, stateUpdate]); - - return state; - }; -} diff --git a/src/entities/fungible-token/model/ft-model.ts b/src/entities/fungible-token/model/ft-model.ts new file mode 100644 index 00000000..af4f321c --- /dev/null +++ b/src/entities/fungible-token/model/ft-model.ts @@ -0,0 +1,82 @@ +import { Account } from "@near-wallet-selector/core"; +import { createContext, useEffect, useState } from "react"; + +import { Multicall } from "../../../shared/lib/contracts/multicall"; +import { Big } from "../../../shared/lib/converter"; +import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; + +export interface FTModelInputs { + balances: Pick; +} + +export class FTModel { + public static readonly balances: { + data: (Pick & { account: string; multicall: string; total: string })[] | null; + error: Error | null; + loading: boolean; + } = { + data: null, + error: null, + loading: true, + }; + + public static readonly BalancesContext = createContext(FTModel.balances); + + private static readonly balancesFetch = async ( + { accountId }: FTModelInputs["balances"], + callback: (result: typeof FTModel.balances) => void + ) => { + const multicallInstanceAddress = Multicall.getInstanceAddress(accountId); + + /** + * Get LikelyTokens list on account and its Multicall Instance + */ + const [accountLikelyTokensList, multicallLikelyTokensList] = await Promise.all([ + FungibleToken.getLikelyTokenContracts(accountId), + FungibleToken.getLikelyTokenContracts(multicallInstanceAddress), + ]); + + /* Merge and de-duplicate both token lists */ + const likelyTokensAddressesList = [...new Set([...accountLikelyTokensList, ...multicallLikelyTokensList])]; + + const likelyTokensList = await Promise.all( + likelyTokensAddressesList.map((address) => FungibleToken.init(address)) + ); + + const rawBalances = await Promise.all( + likelyTokensList + .filter((token) => token.ready === true) + .map(async (token) => { + const [accountRawBalance, multicallRawBalance] = await Promise.all([ + token.ftBalanceOf(accountId), + token.ftBalanceOf(multicallInstanceAddress), + ]); + + return { + account: accountRawBalance, + metadata: token.metadata, + multicall: multicallRawBalance, + total: Big(multicallRawBalance).add(accountRawBalance).toFixed(), + }; + }) + ); + + return callback({ + data: rawBalances.filter( + /** Removes tokens with 0 total balance */ + ({ total }) => Big(total).gt("0") + ), + + error: null, + loading: false, + }); + }; + + public static readonly useBalancesState = (inputs: FTModelInputs["balances"]) => { + const [state, stateUpdate] = useState(FTModel.balances); + + useEffect(() => void FTModel.balancesFetch(inputs, stateUpdate), [inputs, stateUpdate]); + + return state; + }; +} diff --git a/src/entities/fungible-token/module-context.ts b/src/entities/fungible-token/module-context.ts index d9d07793..7202517a 100644 --- a/src/entities/fungible-token/module-context.ts +++ b/src/entities/fungible-token/module-context.ts @@ -1,15 +1,3 @@ -import { Multicall } from "../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; - -export namespace FT { - export interface Inputs { - adapters: { - dao: SputnikDAO; - multicallInstance: Multicall; - }; - } -} - export class ModuleContext { static FRACTIONAL_PART_LENGTH = 5; } diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/ft-balances.tsx index 07ecc526..1321a03e 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/ft-balances.tsx @@ -1,16 +1,18 @@ +import { useContext } from "react"; import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { FTFormat } from "../lib/ft-format"; -import { FTInfoModel } from "../model/ft-info"; -import { FT } from "../module-context"; +import { FTModel } from "../model/ft-model"; -interface FTBalancesProps extends FT.Inputs {} +export interface FTBalancesProps { + nonZeroOnly?: boolean; +} -export const ftBalances = ({ adapters }: FTBalancesProps) => { - const { data } = FTInfoModel.useNonZeroBalances(adapters); +export const ftBalancesRender = ({ nonZeroOnly = false }: FTBalancesProps) => { + const { data } = useContext(FTModel.BalancesContext); return !data ? null - : data.map(({ dao, metadata, multicall, total }) => ({ + : data.map(({ account, metadata, multicall, total }) => ({ content: [ } @@ -18,7 +20,7 @@ export const ftBalances = ({ adapters }: FTBalancesProps) => { />, FTFormat.amountToDisplayAmount(multicall, metadata.decimals), - FTFormat.amountToDisplayAmount(dao, metadata.decimals), + FTFormat.amountToDisplayAmount(account, metadata.decimals), FTFormat.amountToDisplayAmount(total, metadata.decimals), ], diff --git a/src/entities/fungible-token/ui/ft-providers.tsx b/src/entities/fungible-token/ui/ft-providers.tsx new file mode 100644 index 00000000..195405da --- /dev/null +++ b/src/entities/fungible-token/ui/ft-providers.tsx @@ -0,0 +1,13 @@ +import { PropsWithChildren } from "react"; + +import { FTModel, FTModelInputs } from "../model/ft-model"; + +export interface FTBalancesProviderProps + extends Pick, + Pick {} + +export const FTBalancesProvider = ({ children, ...modelInputs }: FTBalancesProviderProps) => ( + + {children} + +); diff --git a/src/entities/index.ts b/src/entities/index.ts index 74c4f051..aad7a63f 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ export { Task } from "./task"; export { Job, type JobEntity } from "./job"; -export { FT, type FTModule } from "./fungible-token"; +export { FT, type FTBalancesProps, type FTBalancesProviderProps } from "./fungible-token"; export { MulticallInstance } from "./multicall-instance"; -export { NEARToken, type NEARTokenModule } from "./near-token"; +export { NEARToken, type NEARTokenBalancesProps, type NEARTokenBalancesProviderProps } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 8b792c75..995a2ec7 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,12 +1,12 @@ import { ModuleContext } from "./module-context"; import { MIModel } from "./model/mi-model"; import { MIAdminsTable } from "./ui/mi-admins"; -import { MIPropertiesProvider } from "./ui/mi-providers"; +import { MIContextProvider } from "./ui/mi-providers"; import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; export class MulticallInstance extends ModuleContext { + static Context = MIModel.Context; + static ContextProvider = MIContextProvider; static AdminsTable = MIAdminsTable; static TokenWhitelistTable = MITokenWhitelistTable; - static PropertiesProvider = MIPropertiesProvider; - static useProperties = MIModel.useProperties; } diff --git a/src/entities/multicall-instance/model/mi-model.ts b/src/entities/multicall-instance/model/mi-model.ts index f930566a..ace56e83 100644 --- a/src/entities/multicall-instance/model/mi-model.ts +++ b/src/entities/multicall-instance/model/mi-model.ts @@ -1,4 +1,4 @@ -import { createContext, useContext, useEffect, useState } from "react"; +import { createContext, useEffect, useState } from "react"; import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; @@ -19,8 +19,7 @@ export class MIModel { loading: true, }; - public static readonly PropertiesContext = createContext(MIModel.properties); - public static readonly useProperties = () => useContext(MIModel.PropertiesContext); + public static readonly Context = createContext(MIModel.properties); /** * Calls the given callback with a result of multicall contract instantiation, @@ -30,7 +29,7 @@ export class MIModel { * @param callback Stateful data fetch callback */ private static readonly propertiesFetch = async ( - daoAddress: MIModelInputs["daoAddress"], + { daoAddress }: MIModelInputs, callback: (result: typeof MIModel.properties) => void ) => callback( @@ -43,10 +42,10 @@ export class MIModel { })) ); - public static readonly usePropertiesState = (daoAddress: MIModelInputs["daoAddress"]) => { - const [state, stateUpdate] = useState(MIModel.properties); + public static readonly usePropertiesState = (inputs: MIModelInputs) => { + const [state, stateUpdate] = useState(MIModel.properties); - useEffect(() => void MIModel.propertiesFetch(daoAddress, stateUpdate), [daoAddress, stateUpdate]); + useEffect(() => void MIModel.propertiesFetch(inputs, stateUpdate), [inputs, stateUpdate]); return state; }; diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/mi-admins.tsx index 30b78f9f..c2bb6b0c 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/mi-admins.tsx @@ -1,3 +1,4 @@ +import { useContext } from "react"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; import { MIModel } from "../model/mi-model"; @@ -9,7 +10,7 @@ interface MIAdminsTableProps { } export const MIAdminsTable = ({ className, itemsAdditional }: MIAdminsTableProps) => { - const { data, error, loading } = MIModel.useProperties(), + const { data, error, loading } = useContext(MIModel.Context), items = (data?.admins ?? []).concat(itemsAdditional ?? []); return ( diff --git a/src/entities/multicall-instance/ui/mi-providers.tsx b/src/entities/multicall-instance/ui/mi-providers.tsx index 5364e9b1..77798ffd 100644 --- a/src/entities/multicall-instance/ui/mi-providers.tsx +++ b/src/entities/multicall-instance/ui/mi-providers.tsx @@ -1,14 +1,9 @@ import { PropsWithChildren } from "react"; -import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; -import { MIModel } from "../model/mi-model"; +import { MIModel, MIModelInputs } from "../model/mi-model"; -export interface MIPropertiesProviderProps extends PropsWithChildren { - daoAddress: SputnikDAO["address"]; -} +export interface MIContextProviderProps extends Pick, MIModelInputs {} -export const MIPropertiesProvider = ({ children, daoAddress }: MIPropertiesProviderProps) => ( - - {children} - +export const MIContextProvider = ({ children, ...modelInputs }: MIContextProviderProps) => ( + {children} ); diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx index cdb551e3..339e724d 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/mi-token-whitelist.tsx @@ -1,3 +1,5 @@ +import { useContext } from "react"; + import { Scrollable, Table, TableProps, Tile, TileProps } from "../../../shared/ui/design"; import { MIModel } from "../model/mi-model"; @@ -19,15 +21,16 @@ export const MITokenWhitelistTable = ({ onItemsSelected, subheader, }: MITokenWhitelistTableProps) => { - const { data, error, loading } = MIModel.useProperties(), - items = (data?.tokensWhitelist ?? []).concat(itemsAdditional ?? []); + const multicallInstance = useContext(MIModel.Context), + items = (multicallInstance.data?.tokensWhitelist ?? []).concat(itemsAdditional ?? []), + tileProps = { ...multicallInstance, footer, headerSlots, subheader }; return (
    { +export const nearTokenBalancesRender = ({ adapters }: NEARTokenBalancesProps) => { const { data } = NEARTokenBalancesModel.useTokenFrom(adapters); return !data diff --git a/src/entities/wallet/ui/wallet.tsx b/src/entities/wallet/ui/wallet.tsx index 4d78bdf9..e379bf53 100644 --- a/src/entities/wallet/ui/wallet.tsx +++ b/src/entities/wallet/ui/wallet.tsx @@ -64,7 +64,7 @@ export class WalletComponent extends Component { }) .transform((_, addr) => ({ noAddress: addr, - noMulticall: this.toMulticallAddress(addr), + noMulticall: Multicall.getInstanceAddress(addr), })) .retain(), }) @@ -110,15 +110,6 @@ export class WalletComponent extends Component { } } - toMulticallAddress(addr: string): string { - return args - .string() - .ensure() - .intoBaseAddress() - .append("." + Multicall.FACTORY_ADDRESS) - .cast(addr); - } - signIn() { const { modal } = this.context!; modal.show(); @@ -137,7 +128,7 @@ export class WalletComponent extends Component { connectDao(dao: SputnikDAO["address"]) { const { accountId } = this.context!; - const multicallAddress = this.toMulticallAddress(dao); + const multicallAddress = Multicall.getInstanceAddress(dao); Promise.all([ SputnikDAO.init(dao).catch(() => { @@ -270,7 +261,7 @@ export class WalletComponent extends Component { onInputChange={(e, newValue) => { // set STORAGE.addresses to have no delay, thus no rubber banding STORAGE.addresses.dao = newValue; - STORAGE.addresses.multicall = this.toMulticallAddress(newValue); + STORAGE.addresses.multicall = Multicall.getInstanceAddress(newValue); this.daoSearchDebounced(newValue); }} /> diff --git a/src/features/index.ts b/src/features/index.ts index bb543528..fde1a217 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,3 +1,4 @@ export { ExternalLogin } from "./external-login"; -export { SchedulingSettingsChange } from "./scheduling/settings-change"; -export { TokenWhitelistChange } from "./token/whitelist-change"; +export { ManageScheduleSettings } from "./manage-scheduling-settings"; +export { ManageTokenWhitelist } from "./manage-whitelisted-tokens"; +export { ProposeSettings } from "./propose-settings"; diff --git a/src/features/manage-scheduling-settings/index.ts b/src/features/manage-scheduling-settings/index.ts new file mode 100644 index 00000000..e247c0c2 --- /dev/null +++ b/src/features/manage-scheduling-settings/index.ts @@ -0,0 +1,6 @@ +import { ModuleContext } from "./module-context"; +import { ManageScheduleSettingsUI } from "./ui"; + +export class ManageScheduleSettings extends ModuleContext { + public static readonly UI = ManageScheduleSettingsUI; +} diff --git a/src/features/scheduling/settings-change/module-context.ts b/src/features/manage-scheduling-settings/module-context.ts similarity index 79% rename from src/features/scheduling/settings-change/module-context.ts rename to src/features/manage-scheduling-settings/module-context.ts index 6457d26f..7c50da57 100644 --- a/src/features/scheduling/settings-change/module-context.ts +++ b/src/features/manage-scheduling-settings/module-context.ts @@ -1,5 +1,5 @@ -import { MulticallInstance } from "../../../entities"; -import { Color } from "../../../shared/ui/design"; +import { MulticallInstance } from "../../entities"; +import { Color } from "../../shared/ui/design"; export class ModuleContext { public static readonly DiffKey = MulticallInstance.ParamKey; diff --git a/src/features/manage-scheduling-settings/ui.scss b/src/features/manage-scheduling-settings/ui.scss new file mode 100644 index 00000000..3987b1aa --- /dev/null +++ b/src/features/manage-scheduling-settings/ui.scss @@ -0,0 +1,3 @@ +.ManageScheduleSettings { + grid-area: ManageScheduleSettings; +} diff --git a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx b/src/features/manage-scheduling-settings/ui.tsx similarity index 73% rename from src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx rename to src/features/manage-scheduling-settings/ui.tsx index f0073045..05388f7f 100644 --- a/src/features/scheduling/settings-change/ui/scheduling-settings-change.tsx +++ b/src/features/manage-scheduling-settings/ui.tsx @@ -1,27 +1,27 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; import { IconButton, TextField, TextFieldProps } from "@mui/material"; -import { HTMLProps, useCallback, useEffect, useMemo, useState } from "react"; +import { HTMLProps, useCallback, useContext, useEffect, useMemo, useState } from "react"; -import { MulticallInstance } from "../../../../entities"; -import { ArgsString } from "../../../../shared/lib/args-old"; -import { MulticallSettingsChange, MulticallPropertyKey } from "../../../../shared/lib/contracts/multicall"; -import { toNEAR, toYocto } from "../../../../shared/lib/converter"; -import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../../shared/ui/design"; -import { ModuleContext } from "../module-context"; +import { MulticallInstance } from "../../entities"; +import { ArgsString } from "../../shared/lib/args-old"; +import { MulticallSettingsChange, MulticallPropertyKey } from "../../shared/lib/contracts/multicall"; +import { toNEAR, toYocto } from "../../shared/lib/converter"; +import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../shared/ui/design"; +import { ModuleContext } from "./module-context"; -import "./scheduling-settings-change.scss"; +import "./ui.scss"; -const _SchedulingSettingsChange = "SchedulingSettingsChange"; +const _ManageScheduleSettings = "ManageScheduleSettings"; type FormState = Pick; -interface SchedulingSettingsChangeUIProps extends Omit, "onChange"> { +interface ManageScheduleSettingsUIProps extends Omit, "onChange"> { onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } -export const SchedulingSettingsChangeUI = ({ disabled, onEdit, resetTrigger }: SchedulingSettingsChangeUIProps) => { - const { data: MIProperties } = MulticallInstance.useProperties(); +export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: ManageScheduleSettingsUIProps) => { + const multicallInstance = useContext(MulticallInstance.Context); const [editModeEnabled, editModeSwitch] = useState(false); @@ -36,32 +36,36 @@ export const SchedulingSettingsChangeUI = ({ disabled, onEdit, resetTrigger }: S ]; const formFields = { - croncatManager: useMemo(() => new ArgsString(MIProperties.croncatManager), [MIProperties]), + croncatManager: useMemo(() => new ArgsString(multicallInstance.data.croncatManager), [multicallInstance.data]), jobBond: useMemo( - () => new ArgsString(MIProperties.jobBond !== "" ? toNEAR(MIProperties.jobBond) : ""), + () => new ArgsString(multicallInstance.data.jobBond !== "" ? toNEAR(multicallInstance.data.jobBond) : ""), - [MIProperties] + [multicallInstance.data] ), }; const onCroncatManagerChange = useCallback["onChange"]>( ({ target: { value } }) => - void croncatManagerUpdate(value !== MIProperties.croncatManager ? value : formInitialState.croncatManager), + void croncatManagerUpdate( + value !== multicallInstance.data.croncatManager ? value : formInitialState.croncatManager + ), [croncatManagerUpdate] ); const onJobBondChange = useCallback["onChange"]>( ({ target: { value } }) => - void jobBondUpdate(value !== toNEAR(MIProperties.jobBond) ? toYocto(value) : formInitialState.jobBond), + void jobBondUpdate( + value !== toNEAR(multicallInstance.data.jobBond) ? toYocto(value) : formInitialState.jobBond + ), [jobBondUpdate] ); const formReset = useCallback(() => { - formFields.croncatManager.value = MIProperties.croncatManager; - formFields.jobBond.value = toNEAR(MIProperties.jobBond); + formFields.croncatManager.value = multicallInstance.data.croncatManager; + formFields.jobBond.value = toNEAR(multicallInstance.data.jobBond); void croncatManagerUpdate(formInitialState.croncatManager); void jobBondUpdate(formInitialState.jobBond); @@ -73,7 +77,7 @@ export const SchedulingSettingsChangeUI = ({ disabled, onEdit, resetTrigger }: S return ( ({ croncatManager, jobBond }[id] === formInitialState[id as keyof typeof ModuleContext["DiffKey"]] || - { croncatManager, jobBond }[id] === MIProperties[id as keyof typeof ModuleContext["DiffKey"]] + { croncatManager, jobBond }[id] === + multicallInstance.data[id as keyof typeof ModuleContext["DiffKey"]] ? null : "blue"), @@ -134,10 +139,10 @@ export const SchedulingSettingsChangeUI = ({ disabled, onEdit, resetTrigger }: S ) : ( - + ), ], }, @@ -156,14 +161,14 @@ export const SchedulingSettingsChangeUI = ({ disabled, onEdit, resetTrigger }: S fullWidth onChange={onJobBondChange} type="number" - value={toNEAR(jobBond || MIProperties.jobBond)} + value={toNEAR(jobBond || multicallInstance.data.jobBond)} /> ) : ( ; -interface TokenWhitelistChangeUIProps extends Omit, "onChange"> { +interface ManageTokenWhitelistUIProps extends Omit, "onChange"> { onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } interface FormStates extends Record> {} -export const TokenWhitelistChangeUI = ({ disabled, onEdit, resetTrigger }: TokenWhitelistChangeUIProps) => { +export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: ManageTokenWhitelistUIProps) => { const [editModeEnabled, editModeSwitch] = useState(false); const [addTokens, markForAddition] = useState(new Set()), @@ -97,7 +97,7 @@ export const TokenWhitelistChangeUI = ({ disabled, onEdit, resetTrigger }: Token void null, }, }} - className={_TokenWhitelistChange} + className={_ManageTokenWhitelist} headerSlots={{ end: editModeEnabled ? ( diff --git a/src/features/propose-settings/index.ts b/src/features/propose-settings/index.ts new file mode 100644 index 00000000..34e0cbdf --- /dev/null +++ b/src/features/propose-settings/index.ts @@ -0,0 +1,6 @@ +import { ModuleContext } from "./module-context"; +import { ProposeSettingsUI } from "./ui/propose-settings"; + +export class ProposeSettings extends ModuleContext { + public static readonly UI = ProposeSettingsUI; +} diff --git a/src/features/propose-settings/module-context.ts b/src/features/propose-settings/module-context.ts new file mode 100644 index 00000000..0c13d485 --- /dev/null +++ b/src/features/propose-settings/module-context.ts @@ -0,0 +1 @@ +export class ModuleContext {} diff --git a/src/widgets/settings-editor/ui/settings-proposal-create.scss b/src/features/propose-settings/ui/propose-settings.scss similarity index 96% rename from src/widgets/settings-editor/ui/settings-proposal-create.scss rename to src/features/propose-settings/ui/propose-settings.scss index c7bd0f98..0ebb64f2 100644 --- a/src/widgets/settings-editor/ui/settings-proposal-create.scss +++ b/src/features/propose-settings/ui/propose-settings.scss @@ -2,8 +2,8 @@ @use "sass/mixin"; @use "sass/size"; -.SettingsProposalCreate { - grid-area: SettingsProposalCreate; +.ProposeSettings { + grid-area: ProposeSettings; gap: size.$gap * 0.4; &-hint { diff --git a/src/features/propose-settings/ui/propose-settings.tsx b/src/features/propose-settings/ui/propose-settings.tsx new file mode 100644 index 00000000..014447fe --- /dev/null +++ b/src/features/propose-settings/ui/propose-settings.tsx @@ -0,0 +1,139 @@ +import clsx from "clsx"; +import { FormEventHandler, HTMLProps, useCallback, useContext, useMemo, useState } from "react"; + +import { MulticallInstance } from "../../../entities"; +import { ArgsString } from "../../../shared/lib/args-old"; +import { Multicall, MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; +import { toNEAR } from "../../../shared/lib/converter"; +import { signAndSendTxs } from "../../../shared/lib/wallet"; +import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; + +import { ModuleContext } from "../../../widgets/settings-editor/module-context"; +import "./propose-settings.scss"; + +const _ProposeSettings = "ProposeSettings"; + +export interface ProposeSettingsUIProps extends HTMLProps { + dao: SputnikDAO; + diff: MulticallSettingsChange; + editMode: boolean; + onCancel: VoidFunction; +} + +export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, ...props }: ProposeSettingsUIProps) => { + const multicallInstance = useContext(MulticallInstance.Context); + + const formValues = { description: useMemo(() => new ArgsString(""), []) }, + [description, descriptionUpdate] = useState(formValues.description.value); + + const onCancel = useCallback(() => { + void props.onCancel(); + void descriptionUpdate(""); + + formValues.description.value = ""; + }, [props.onCancel, descriptionUpdate]); + + const onSubmit = useCallback( + (event) => { + void event.preventDefault(); + + void dao + .proposeFunctionCall( + description, + multicallInstance.data.address, + Multicall.configDiffToProposalActions(diff) + ) + .then((someTx) => signAndSendTxs([someTx])) + .catch(console.error); + }, + + [dao, diff, description] + ); + + return ( + +

    + {disabled + ? "Current account has no permission to propose changes" + : "Start editing to create config changes proposal template"} +

    + +
    + {Object.values(ModuleContext.DiffKey).map( + (DiffKey) => + diff[DiffKey].length > 0 && ( +
    +

    + {ModuleContext.DiffMeta[DiffKey].description + ":"} +

    + +
      + {(Array.isArray(diff[DiffKey]) ? Array.from(diff[DiffKey]) : [diff[DiffKey]]).map( + (data) => ( +
    • + {!Number.isNaN(data) && DiffKey === ModuleContext.DiffKey.jobBond + ? `${toNEAR(data as string)} ${NearIcon.NATIVE_TOKEN_CHARACTER}` + : (data as string)} +
    • + ) + )} +
    +
    + ) + )} +
    + + +
    + void descriptionUpdate(event.target.value)} + value={formValues.description} + /> +
    + + +
    + + )} + + {(!nearTokenBalances || !fungibleTokenBalances) &&
    } + + + + ); +}; diff --git a/src/widgets/dialogs-layer/index.ts b/src/widgets/dialogs-layer/index.ts index 62bc5a04..8b941b4b 100644 --- a/src/widgets/dialogs-layer/index.ts +++ b/src/widgets/dialogs-layer/index.ts @@ -1 +1 @@ -export { DialogsLayer } from "./ui/dialogs-layer"; +export { DialogsLayer } from "./ui"; diff --git a/src/widgets/dialogs-layer/ui/dialogs-layer.tsx b/src/widgets/dialogs-layer/ui.tsx similarity index 57% rename from src/widgets/dialogs-layer/ui/dialogs-layer.tsx rename to src/widgets/dialogs-layer/ui.tsx index e8494095..6628f7e9 100644 --- a/src/widgets/dialogs-layer/ui/dialogs-layer.tsx +++ b/src/widgets/dialogs-layer/ui.tsx @@ -1,4 +1,4 @@ -import { ExternalLogin } from "../../../features/external-login"; +import { ExternalLogin } from "../../features/external-login"; export const DialogsLayer = () => ( <> diff --git a/src/widgets/index.ts b/src/widgets/index.ts index ddc8c7bb..b07ce110 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -1,4 +1,5 @@ export { Column } from "./column/column.jsx"; +export { Balances, type BalancesProps } from "./balances"; export { DialogsLayer } from "./dialogs-layer"; export { Menu } from "./menu/menu.jsx"; export { Builder } from "./builder/builder.jsx"; @@ -6,4 +7,3 @@ export { Editor } from "./editor/editor.jsx"; export { Export } from "./export"; export { SettingsEditor, type SettingsEditorProps } from "./settings-editor"; export { Sidebar } from "./sidebar/sidebar.jsx"; -export { TokenBalances, type TokenBalancesProps } from "./token-balances"; diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts index 99796e30..17165fea 100644 --- a/src/widgets/settings-editor/index.ts +++ b/src/widgets/settings-editor/index.ts @@ -1 +1 @@ -export { SettingsEditor, type SettingsEditorProps } from "./ui/settings-editor"; +export { SettingsEditor, type SettingsEditorProps } from "./ui"; diff --git a/src/widgets/settings-editor/module-context.ts b/src/widgets/settings-editor/module-context.ts index b3ba6920..4bf98edb 100644 --- a/src/widgets/settings-editor/module-context.ts +++ b/src/widgets/settings-editor/module-context.ts @@ -1,13 +1,13 @@ -import { SchedulingSettingsChange, TokenWhitelistChange } from "../../features"; +import { ManageScheduleSettings, ManageTokenWhitelist } from "../../features"; export class ModuleContext { public static readonly DiffKey = { - ...SchedulingSettingsChange.DiffKey, - ...TokenWhitelistChange.DiffKey, + ...ManageScheduleSettings.DiffKey, + ...ManageTokenWhitelist.DiffKey, }; public static readonly DiffMeta = { - ...SchedulingSettingsChange.DiffMeta, - ...TokenWhitelistChange.DiffMeta, + ...ManageScheduleSettings.DiffMeta, + ...ManageTokenWhitelist.DiffMeta, }; } diff --git a/src/widgets/settings-editor/ui/settings-editor.scss b/src/widgets/settings-editor/ui.scss similarity index 84% rename from src/widgets/settings-editor/ui/settings-editor.scss rename to src/widgets/settings-editor/ui.scss index 3b83e786..caa3a96e 100644 --- a/src/widgets/settings-editor/ui/settings-editor.scss +++ b/src/widgets/settings-editor/ui.scss @@ -9,8 +9,8 @@ height: 100%; grid-template-areas: - "TokenWhitelistChange SchedulingSettingsChange" - "TokenWhitelistChange SettingsProposalCreate"; + "ManageTokenWhitelist ManageScheduleSettings" + "ManageTokenWhitelist ProposeSettings"; &-error { grid-area: SettingsEditorError; diff --git a/src/widgets/settings-editor/ui.tsx b/src/widgets/settings-editor/ui.tsx new file mode 100644 index 00000000..1640d5c5 --- /dev/null +++ b/src/widgets/settings-editor/ui.tsx @@ -0,0 +1,94 @@ +import clsx from "clsx"; +import { useCallback, useState, useEffect, useContext, HTMLProps } from "react"; + +import { MulticallInstance, Wallet } from "../../entities"; +import { ManageScheduleSettings, ManageTokenWhitelist, ProposeSettings } from "../../features"; +import { MulticallSettingsChange } from "../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; +import { ModuleContext } from "./module-context"; +import { Tile } from "../../shared/ui/design"; + +import "./ui.scss"; + +const _SettingsEditor = "SettingsEditor"; + +export interface SettingsEditorProps extends HTMLProps { + dao: SputnikDAO; +} + +export const SettingsEditor = ({ className, dao }: SettingsEditorProps) => { + const wallet = useContext(Wallet.SelectorContext), + multicallInstance = useContext(MulticallInstance.Context); + + const canCreateProposals = + !wallet?.accountId || dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); + + const initialDiff: MulticallSettingsChange = { + [ModuleContext.DiffKey.removeTokens]: [], + [ModuleContext.DiffKey.addTokens]: [], + [ModuleContext.DiffKey.jobBond]: "", + [ModuleContext.DiffKey.croncatManager]: "", + }; + + const [editMode, editModeSwitch] = useState(false), + [diff, diffUpdate] = useState(initialDiff), + _childFormsResetRequested = "childFormsResetRequested"; + + const resetTrigger = { + dispatch: () => document.dispatchEvent(new CustomEvent(_childFormsResetRequested)), + + subscribe: (callback: EventListener) => { + void document.addEventListener(_childFormsResetRequested, callback); + + return () => void document.removeEventListener(_childFormsResetRequested, callback); + }, + }; + + const formReset = useCallback(() => { + void resetTrigger.dispatch(); + void diffUpdate(initialDiff); + }, [diffUpdate, initialDiff]); + + const onCancel = useCallback(() => { + void formReset(); + void editModeSwitch(false); + }, [editMode, editModeSwitch, formReset]); + + const onEdit = useCallback( + (update: Partial) => void diffUpdate((latestState) => ({ ...latestState, ...update })), + + [diffUpdate] + ); + + useEffect( + () => void editModeSwitch(Object.values(diff).filter(({ length }) => length > 0).length > 0), + [diff, editModeSwitch] + ); + + return ( +
    + + + {false && } + + + + + + +
    + ); +}; diff --git a/src/widgets/settings-editor/ui/settings-editor.tsx b/src/widgets/settings-editor/ui/settings-editor.tsx deleted file mode 100644 index e9b30591..00000000 --- a/src/widgets/settings-editor/ui/settings-editor.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import clsx from "clsx"; -import { useCallback, useMemo, useState, FormEventHandler, useEffect, useContext, HTMLProps } from "react"; - -import { MulticallInstance, Wallet } from "../../../entities"; -import { SchedulingSettingsChange, TokenWhitelistChange } from "../../../features"; -import { ArgsString } from "../../../shared/lib/args-old"; -import { Multicall, MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; -import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { ModuleContext } from "../module-context"; -import { Tile } from "../../../shared/ui/design"; - -import { SettingsProposalCreate } from "./settings-proposal-create"; -import "./settings-editor.scss"; - -const _SettingsEditor = "SettingsEditor"; - -export interface SettingsEditorProps extends HTMLProps { - adapters: { dao: SputnikDAO }; -} - -export const SettingsEditor = ({ className, adapters }: SettingsEditorProps) => { - const wallet = useContext(Wallet.SelectorContext), - { data: MIProperties, error: MIError } = MulticallInstance.useProperties(); - - const proposalCreationPermitted = - !wallet?.accountId || adapters.dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); - - const [editMode, editModeSwitch] = useState(false); - - const changesDiffInitialState: MulticallSettingsChange = { - [ModuleContext.DiffKey.removeTokens]: [], - [ModuleContext.DiffKey.addTokens]: [], - [ModuleContext.DiffKey.jobBond]: "", - [ModuleContext.DiffKey.croncatManager]: "", - }; - - const [changesDiff, changesDiffUpdate] = useState(changesDiffInitialState), - formValues = { proposalDescription: useMemo(() => new ArgsString(""), []) }, - [proposalDescription, proposalDescriptionUpdate] = useState(formValues.proposalDescription.value), - _childFormsResetRequested = "childFormsResetRequested"; - - const childFormsResetRequested = { - dispatch: () => document.dispatchEvent(new CustomEvent(_childFormsResetRequested)), - - subscribe: (callback: EventListener) => { - void document.addEventListener(_childFormsResetRequested, callback); - - return () => void document.removeEventListener(_childFormsResetRequested, callback); - }, - }; - - const formReset = useCallback(() => { - void childFormsResetRequested.dispatch(); - void proposalDescriptionUpdate(""); - void changesDiffUpdate(changesDiffInitialState); - - formValues.proposalDescription.value = ""; - }, [changesDiffUpdate, changesDiffInitialState]); - - const onCancel = useCallback(() => { - void formReset(); - void editModeSwitch(false); - }, [editMode, editModeSwitch, formReset]); - - const onEdit = useCallback( - (update: Partial) => - void changesDiffUpdate((latestState) => ({ ...latestState, ...update })), - - [changesDiffUpdate] - ); - - const onSubmit = useCallback( - (event) => { - void event.preventDefault(); - - void adapters.dao - .proposeFunctionCall( - proposalDescription, - MIProperties.address, - Multicall.configDiffToProposalActions(changesDiff) - ) - .then((someTx) => signAndSendTxs([someTx])) - .catch(console.error); - }, - - [changesDiff, adapters, proposalDescription] - ); - - useEffect( - () => void editModeSwitch(Object.values(changesDiff).filter(({ length }) => length > 0).length > 0), - [changesDiff, editModeSwitch] - ); - - return ( -
    - - - {false && } - - - - - - -
    - ); -}; diff --git a/src/widgets/settings-editor/ui/settings-proposal-create.tsx b/src/widgets/settings-editor/ui/settings-proposal-create.tsx deleted file mode 100644 index 48a36c77..00000000 --- a/src/widgets/settings-editor/ui/settings-proposal-create.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import clsx from "clsx"; -import { FormEventHandler, HTMLProps } from "react"; - -import { ArgsString } from "../../../shared/lib/args-old"; -import { MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; -import { toNEAR } from "../../../shared/lib/converter"; -import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; -import { ModuleContext } from "../module-context"; - -import "./settings-proposal-create.scss"; - -const _SettingsProposalCreate = "SettingsProposalCreate"; - -export interface SettingsProposalCreateProps extends HTMLProps { - changesDiff: MulticallSettingsChange; - description: Parameters[0]; - formValues: { proposalDescription: ArgsString }; - editMode: boolean; - onCancel: FormEventHandler; - onDescriptionUpdate: (value: string) => void; - onSubmit: FormEventHandler; -} - -export const SettingsProposalCreate = ({ - changesDiff, - className, - description, - disabled, - formValues, - editMode, - onCancel, - onDescriptionUpdate, - onSubmit, -}: SettingsProposalCreateProps) => ( - -

    - {disabled - ? "Current account has no permission to propose changes" - : "Start editing to create config changes proposal template"} -

    - -
    - {Object.values(ModuleContext.DiffKey).map( - (DiffKey) => - changesDiff[DiffKey].length > 0 && ( -
    -

    - {ModuleContext.DiffMeta[DiffKey].description + ":"} -

    - -
      - {(Array.isArray(changesDiff[DiffKey]) - ? Array.from(changesDiff[DiffKey]) - : [changesDiff[DiffKey]] - ).map((data) => ( -
    • - {!Number.isNaN(data) && DiffKey === ModuleContext.DiffKey.jobBond - ? `${toNEAR(data as string)} ${NearIcon.NATIVE_TOKEN_CHARACTER}` - : (data as string)} -
    • - ))} -
    -
    - ) - )} -
    - -
    -
    - void onDescriptionUpdate(event.target.value)} - value={formValues.proposalDescription} - /> -
    - - -
    - - )} - - {(!nearTokenBalances || !fungibleTokenBalances) &&
    } - - ); -}; From fd6b3a7787853d6f5d0dd44adbd00ad366f9118a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 16 Dec 2022 11:24:10 +0400 Subject: [PATCH 454/537] wip: Move UI segment to the upper level --- src/features/propose-settings/index.ts | 2 +- .../{ui/propose-settings.scss => ui.scss} | 0 .../{ui/propose-settings.tsx => ui.tsx} | 20 +++++++++---------- 3 files changed, 11 insertions(+), 11 deletions(-) rename src/features/propose-settings/{ui/propose-settings.scss => ui.scss} (100%) rename src/features/propose-settings/{ui/propose-settings.tsx => ui.tsx} (90%) diff --git a/src/features/propose-settings/index.ts b/src/features/propose-settings/index.ts index 34e0cbdf..1ec8430f 100644 --- a/src/features/propose-settings/index.ts +++ b/src/features/propose-settings/index.ts @@ -1,5 +1,5 @@ import { ModuleContext } from "./module-context"; -import { ProposeSettingsUI } from "./ui/propose-settings"; +import { ProposeSettingsUI } from "./ui"; export class ProposeSettings extends ModuleContext { public static readonly UI = ProposeSettingsUI; diff --git a/src/features/propose-settings/ui/propose-settings.scss b/src/features/propose-settings/ui.scss similarity index 100% rename from src/features/propose-settings/ui/propose-settings.scss rename to src/features/propose-settings/ui.scss diff --git a/src/features/propose-settings/ui/propose-settings.tsx b/src/features/propose-settings/ui.tsx similarity index 90% rename from src/features/propose-settings/ui/propose-settings.tsx rename to src/features/propose-settings/ui.tsx index 014447fe..43d362a9 100644 --- a/src/features/propose-settings/ui/propose-settings.tsx +++ b/src/features/propose-settings/ui.tsx @@ -1,16 +1,16 @@ import clsx from "clsx"; import { FormEventHandler, HTMLProps, useCallback, useContext, useMemo, useState } from "react"; -import { MulticallInstance } from "../../../entities"; -import { ArgsString } from "../../../shared/lib/args-old"; -import { Multicall, MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; -import { toNEAR } from "../../../shared/lib/converter"; -import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; - -import { ModuleContext } from "../../../widgets/settings-editor/module-context"; -import "./propose-settings.scss"; +import { MulticallInstance } from "../../entities"; +import { ArgsString } from "../../shared/lib/args-old"; +import { Multicall, MulticallSettingsChange } from "../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; +import { toNEAR } from "../../shared/lib/converter"; +import { signAndSendTxs } from "../../shared/lib/wallet"; +import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../shared/ui/design"; + +import { ModuleContext } from "../../widgets/settings-editor/module-context"; +import "./ui.scss"; const _ProposeSettings = "ProposeSettings"; From 52cca6af61759a5aeb7a3738ab4ae3beeaff53d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 16 Dec 2022 16:34:17 +0400 Subject: [PATCH 455/537] wip: Apply code review and naming remarks --- src/features/external-login/index.ts | 4 ++-- .../{el-model.ts => external-login.model.ts} | 2 +- ...dialog.scss => external-login.dialog.scss} | 0 ...l-dialog.tsx => external-login.dialog.tsx} | 2 +- ...dialogs.tsx => external-login.dialogs.tsx} | 6 +++--- .../{el-menu.tsx => external-login.menu.tsx} | 2 +- .../manage-scheduling-settings/index.ts | 2 +- .../manage-scheduling-settings.ui.scss} | 0 .../manage-scheduling-settings.ui.tsx} | 16 +++++++-------- .../manage-whitelisted-tokens/index.ts | 2 +- .../manage-whitelisted-tokens.ui.scss} | 0 .../manage-whitelisted-tokens.ui.tsx} | 12 +++++------ src/features/propose-settings/index.ts | 2 +- .../{ui.scss => ui/propose-settings.ui.scss} | 0 .../{ui.tsx => ui/propose-settings.ui.tsx} | 20 +++++++++---------- 15 files changed, 35 insertions(+), 35 deletions(-) rename src/features/external-login/model/{el-model.ts => external-login.model.ts} (96%) rename src/features/external-login/ui/{el-dialog.scss => external-login.dialog.scss} (100%) rename src/features/external-login/ui/{el-dialog.tsx => external-login.dialog.tsx} (98%) rename src/features/external-login/ui/{el-dialogs.tsx => external-login.dialogs.tsx} (84%) rename src/features/external-login/ui/{el-menu.tsx => external-login.menu.tsx} (93%) rename src/features/manage-scheduling-settings/{ui.scss => ui/manage-scheduling-settings.ui.scss} (100%) rename src/features/manage-scheduling-settings/{ui.tsx => ui/manage-scheduling-settings.ui.tsx} (95%) rename src/features/manage-whitelisted-tokens/{ui.scss => ui/manage-whitelisted-tokens.ui.scss} (100%) rename src/features/manage-whitelisted-tokens/{ui.tsx => ui/manage-whitelisted-tokens.ui.tsx} (94%) rename src/features/propose-settings/{ui.scss => ui/propose-settings.ui.scss} (100%) rename src/features/propose-settings/{ui.tsx => ui/propose-settings.ui.tsx} (90%) diff --git a/src/features/external-login/index.ts b/src/features/external-login/index.ts index 136d5b9c..6b8e23b7 100644 --- a/src/features/external-login/index.ts +++ b/src/features/external-login/index.ts @@ -1,6 +1,6 @@ import { ModuleContext } from "./module-context"; -import { ELDialogs } from "./ui/el-dialogs"; -import { ELMenu } from "./ui/el-menu"; +import { ELDialogs } from "./ui/external-login.dialogs"; +import { ELMenu } from "./ui/external-login.menu"; export class ExternalLogin extends ModuleContext { static Dialogs = ELDialogs; diff --git a/src/features/external-login/model/el-model.ts b/src/features/external-login/model/external-login.model.ts similarity index 96% rename from src/features/external-login/model/el-model.ts rename to src/features/external-login/model/external-login.model.ts index 0c5b8dbf..7bed06b1 100644 --- a/src/features/external-login/model/el-model.ts +++ b/src/features/external-login/model/external-login.model.ts @@ -28,7 +28,7 @@ export class ELModel { static useDialogsState = () => { const [dialogsVisibility, dialogVisibilitySwitch] = useState< - Record | {} + Record >( Object.values(ModuleContext.methods).reduce( (visibilityState, { type }) => ({ ...visibilityState, [type]: false }), diff --git a/src/features/external-login/ui/el-dialog.scss b/src/features/external-login/ui/external-login.dialog.scss similarity index 100% rename from src/features/external-login/ui/el-dialog.scss rename to src/features/external-login/ui/external-login.dialog.scss diff --git a/src/features/external-login/ui/el-dialog.tsx b/src/features/external-login/ui/external-login.dialog.tsx similarity index 98% rename from src/features/external-login/ui/el-dialog.tsx rename to src/features/external-login/ui/external-login.dialog.tsx index 677ce59a..0ff69d05 100644 --- a/src/features/external-login/ui/el-dialog.tsx +++ b/src/features/external-login/ui/external-login.dialog.tsx @@ -8,7 +8,7 @@ import { Validation } from "../../../shared/lib/validation"; import { Dialog, TextInput, Tooltip } from "../../../shared/ui/design"; import { ModuleContext } from "../module-context"; -import "./el-dialog.scss"; +import "./external-login.dialog.scss"; interface ELDialogProps extends Pick, "className" | "onClose" | "open" | "title"> { method: "dao" | "multicall"; diff --git a/src/features/external-login/ui/el-dialogs.tsx b/src/features/external-login/ui/external-login.dialogs.tsx similarity index 84% rename from src/features/external-login/ui/el-dialogs.tsx rename to src/features/external-login/ui/external-login.dialogs.tsx index f8f4db43..74aba66b 100644 --- a/src/features/external-login/ui/el-dialogs.tsx +++ b/src/features/external-login/ui/external-login.dialogs.tsx @@ -1,13 +1,13 @@ import { ModuleContext } from "../module-context"; -import { ELModel } from "../model/el-model"; -import { ELDialog } from "./el-dialog"; +import { ELModel } from "../model/external-login.model"; + +import { ELDialog } from "./external-login.dialog"; export const ELDialogs = () => { const { dialogsVisibility, closeHandlerBinding } = ELModel.useDialogsState(); return ( <> - {" "} {Object.values(ModuleContext.methods).map((loginMethod) => ( , "triggerClassName"> { FeatureFlags: { diff --git a/src/features/manage-scheduling-settings/index.ts b/src/features/manage-scheduling-settings/index.ts index e247c0c2..fab3e4ed 100644 --- a/src/features/manage-scheduling-settings/index.ts +++ b/src/features/manage-scheduling-settings/index.ts @@ -1,5 +1,5 @@ import { ModuleContext } from "./module-context"; -import { ManageScheduleSettingsUI } from "./ui"; +import { ManageScheduleSettingsUI } from "./ui/manage-scheduling-settings.ui"; export class ManageScheduleSettings extends ModuleContext { public static readonly UI = ManageScheduleSettingsUI; diff --git a/src/features/manage-scheduling-settings/ui.scss b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.scss similarity index 100% rename from src/features/manage-scheduling-settings/ui.scss rename to src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.scss diff --git a/src/features/manage-scheduling-settings/ui.tsx b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx similarity index 95% rename from src/features/manage-scheduling-settings/ui.tsx rename to src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx index 05388f7f..155669e7 100644 --- a/src/features/manage-scheduling-settings/ui.tsx +++ b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx @@ -2,14 +2,14 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-mat import { IconButton, TextField, TextFieldProps } from "@mui/material"; import { HTMLProps, useCallback, useContext, useEffect, useMemo, useState } from "react"; -import { MulticallInstance } from "../../entities"; -import { ArgsString } from "../../shared/lib/args-old"; -import { MulticallSettingsChange, MulticallPropertyKey } from "../../shared/lib/contracts/multicall"; -import { toNEAR, toYocto } from "../../shared/lib/converter"; -import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../shared/ui/design"; -import { ModuleContext } from "./module-context"; - -import "./ui.scss"; +import { MulticallInstance } from "../../../entities"; +import { ArgsString } from "../../../shared/lib/args-old"; +import { MulticallSettingsChange, MulticallPropertyKey } from "../../../shared/lib/contracts/multicall"; +import { toNEAR, toYocto } from "../../../shared/lib/converter"; +import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../shared/ui/design"; +import { ModuleContext } from "../module-context"; + +import "./manage-scheduling-settings.ui.scss"; const _ManageScheduleSettings = "ManageScheduleSettings"; diff --git a/src/features/manage-whitelisted-tokens/index.ts b/src/features/manage-whitelisted-tokens/index.ts index 9f451e10..64ee13e4 100644 --- a/src/features/manage-whitelisted-tokens/index.ts +++ b/src/features/manage-whitelisted-tokens/index.ts @@ -1,5 +1,5 @@ import { ModuleContext } from "./module-context"; -import { ManageTokenWhitelistUI } from "./ui"; +import { ManageTokenWhitelistUI } from "./ui/manage-whitelisted-tokens.ui"; export class ManageTokenWhitelist extends ModuleContext { public static readonly UI = ManageTokenWhitelistUI; diff --git a/src/features/manage-whitelisted-tokens/ui.scss b/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.scss similarity index 100% rename from src/features/manage-whitelisted-tokens/ui.scss rename to src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.scss diff --git a/src/features/manage-whitelisted-tokens/ui.tsx b/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.tsx similarity index 94% rename from src/features/manage-whitelisted-tokens/ui.tsx rename to src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.tsx index 20c5d271..56b0a88c 100644 --- a/src/features/manage-whitelisted-tokens/ui.tsx +++ b/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.tsx @@ -2,13 +2,13 @@ import { CancelOutlined, DeleteOutlined, EditOutlined, SettingsBackupRestoreOutl import { IconButton } from "@mui/material"; import { HTMLProps, useCallback, useEffect, useMemo, useState } from "react"; -import { MulticallSettingsChange, MulticallTokenWhitelistDiffKey } from "../../shared/lib/contracts/multicall"; -import { TextInput, Tooltip } from "../../shared/ui/design"; -import { ArgsString } from "../../shared/lib/args-old"; -import { MulticallInstance } from "../../entities"; -import { ModuleContext } from "./module-context"; +import { MulticallSettingsChange, MulticallTokenWhitelistDiffKey } from "../../../shared/lib/contracts/multicall"; +import { TextInput, Tooltip } from "../../../shared/ui/design"; +import { ArgsString } from "../../../shared/lib/args-old"; +import { MulticallInstance } from "../../../entities"; +import { ModuleContext } from "../module-context"; -import "./ui.scss"; +import "./manage-whitelisted-tokens.ui.scss"; const _ManageTokenWhitelist = "ManageTokenWhitelist"; diff --git a/src/features/propose-settings/index.ts b/src/features/propose-settings/index.ts index 1ec8430f..f7e72aa7 100644 --- a/src/features/propose-settings/index.ts +++ b/src/features/propose-settings/index.ts @@ -1,5 +1,5 @@ import { ModuleContext } from "./module-context"; -import { ProposeSettingsUI } from "./ui"; +import { ProposeSettingsUI } from "./ui/propose-settings.ui"; export class ProposeSettings extends ModuleContext { public static readonly UI = ProposeSettingsUI; diff --git a/src/features/propose-settings/ui.scss b/src/features/propose-settings/ui/propose-settings.ui.scss similarity index 100% rename from src/features/propose-settings/ui.scss rename to src/features/propose-settings/ui/propose-settings.ui.scss diff --git a/src/features/propose-settings/ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx similarity index 90% rename from src/features/propose-settings/ui.tsx rename to src/features/propose-settings/ui/propose-settings.ui.tsx index 43d362a9..34367dcf 100644 --- a/src/features/propose-settings/ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -1,16 +1,16 @@ import clsx from "clsx"; import { FormEventHandler, HTMLProps, useCallback, useContext, useMemo, useState } from "react"; -import { MulticallInstance } from "../../entities"; -import { ArgsString } from "../../shared/lib/args-old"; -import { Multicall, MulticallSettingsChange } from "../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -import { toNEAR } from "../../shared/lib/converter"; -import { signAndSendTxs } from "../../shared/lib/wallet"; -import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../shared/ui/design"; - -import { ModuleContext } from "../../widgets/settings-editor/module-context"; -import "./ui.scss"; +import { MulticallInstance } from "../../../entities"; +import { ArgsString } from "../../../shared/lib/args-old"; +import { Multicall, MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; +import { toNEAR } from "../../../shared/lib/converter"; +import { signAndSendTxs } from "../../../shared/lib/wallet"; +import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; + +import { ModuleContext } from "../../../widgets/settings-editor/module-context"; +import "./propose-settings.ui.scss"; const _ProposeSettings = "ProposeSettings"; From 87f4f43d684518a7a5f6a73c211b50ab5825656b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 16 Dec 2022 16:57:09 +0400 Subject: [PATCH 456/537] wip: Apply code review and naming remarks --- src/entities/fungible-token/index.ts | 4 ++-- .../lib/{ft-format.ts => fungible-token.format.ts} | 0 .../model/{ft-model.ts => fungible-token.model.ts} | 0 .../ui/{ft-balances.tsx => fungible-token.balances.tsx} | 4 ++-- .../ui/{ft-providers.tsx => fungible-token.providers.tsx} | 2 +- src/entities/multicall-instance/index.ts | 8 ++++---- .../model/{mi-model.ts => multicall-instance.model.ts} | 0 .../ui/{mi-admin.tsx => multicall-instance.admin.tsx} | 0 .../ui/{mi-admins.tsx => multicall-instance.admins.tsx} | 4 ++-- ...{mi-providers.tsx => multicall-instance.providers.tsx} | 2 +- ...itelist.tsx => multicall-instance.token-whitelist.tsx} | 4 ++-- ...token.tsx => multicall-instance.whitelisted-token.tsx} | 0 src/entities/near-token/index.ts | 2 +- .../near-token/model/{nt-model.ts => near-token.model.ts} | 0 .../ui/{nt-balances.tsx => near-token.balances.tsx} | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) rename src/entities/fungible-token/lib/{ft-format.ts => fungible-token.format.ts} (100%) rename src/entities/fungible-token/model/{ft-model.ts => fungible-token.model.ts} (100%) rename src/entities/fungible-token/ui/{ft-balances.tsx => fungible-token.balances.tsx} (88%) rename src/entities/fungible-token/ui/{ft-providers.tsx => fungible-token.providers.tsx} (85%) rename src/entities/multicall-instance/model/{mi-model.ts => multicall-instance.model.ts} (100%) rename src/entities/multicall-instance/ui/{mi-admin.tsx => multicall-instance.admin.tsx} (100%) rename src/entities/multicall-instance/ui/{mi-admins.tsx => multicall-instance.admins.tsx} (87%) rename src/entities/multicall-instance/ui/{mi-providers.tsx => multicall-instance.providers.tsx} (82%) rename src/entities/multicall-instance/ui/{mi-token-whitelist.tsx => multicall-instance.token-whitelist.tsx} (93%) rename src/entities/multicall-instance/ui/{mi-whitelisted-token.tsx => multicall-instance.whitelisted-token.tsx} (100%) rename src/entities/near-token/model/{nt-model.ts => near-token.model.ts} (100%) rename src/entities/near-token/ui/{nt-balances.tsx => near-token.balances.tsx} (91%) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 6bb14c59..0e3ffda0 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,6 +1,6 @@ import { ModuleContext } from "./module-context"; -import { FTBalancesProps, ftBalancesRender } from "./ui/ft-balances"; -import { FTBalancesProvider, FTBalancesProviderProps } from "./ui/ft-providers"; +import { FTBalancesProps, ftBalancesRender } from "./ui/fungible-token.balances"; +import { FTBalancesProvider, FTBalancesProviderProps } from "./ui/fungible-token.providers"; export class FT extends ModuleContext { static BalancesProvider = FTBalancesProvider; diff --git a/src/entities/fungible-token/lib/ft-format.ts b/src/entities/fungible-token/lib/fungible-token.format.ts similarity index 100% rename from src/entities/fungible-token/lib/ft-format.ts rename to src/entities/fungible-token/lib/fungible-token.format.ts diff --git a/src/entities/fungible-token/model/ft-model.ts b/src/entities/fungible-token/model/fungible-token.model.ts similarity index 100% rename from src/entities/fungible-token/model/ft-model.ts rename to src/entities/fungible-token/model/fungible-token.model.ts diff --git a/src/entities/fungible-token/ui/ft-balances.tsx b/src/entities/fungible-token/ui/fungible-token.balances.tsx similarity index 88% rename from src/entities/fungible-token/ui/ft-balances.tsx rename to src/entities/fungible-token/ui/fungible-token.balances.tsx index 1321a03e..f0582009 100644 --- a/src/entities/fungible-token/ui/ft-balances.tsx +++ b/src/entities/fungible-token/ui/fungible-token.balances.tsx @@ -1,7 +1,7 @@ import { useContext } from "react"; import { IconLabel, NearIcon } from "../../../shared/ui/design"; -import { FTFormat } from "../lib/ft-format"; -import { FTModel } from "../model/ft-model"; +import { FTFormat } from "../lib/fungible-token.format"; +import { FTModel } from "../model/fungible-token.model"; export interface FTBalancesProps { nonZeroOnly?: boolean; diff --git a/src/entities/fungible-token/ui/ft-providers.tsx b/src/entities/fungible-token/ui/fungible-token.providers.tsx similarity index 85% rename from src/entities/fungible-token/ui/ft-providers.tsx rename to src/entities/fungible-token/ui/fungible-token.providers.tsx index 195405da..f1fbf17f 100644 --- a/src/entities/fungible-token/ui/ft-providers.tsx +++ b/src/entities/fungible-token/ui/fungible-token.providers.tsx @@ -1,6 +1,6 @@ import { PropsWithChildren } from "react"; -import { FTModel, FTModelInputs } from "../model/ft-model"; +import { FTModel, FTModelInputs } from "../model/fungible-token.model"; export interface FTBalancesProviderProps extends Pick, diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts index 995a2ec7..221e6096 100644 --- a/src/entities/multicall-instance/index.ts +++ b/src/entities/multicall-instance/index.ts @@ -1,8 +1,8 @@ import { ModuleContext } from "./module-context"; -import { MIModel } from "./model/mi-model"; -import { MIAdminsTable } from "./ui/mi-admins"; -import { MIContextProvider } from "./ui/mi-providers"; -import { MITokenWhitelistTable } from "./ui/mi-token-whitelist"; +import { MIModel } from "./model/multicall-instance.model"; +import { MIAdminsTable } from "./ui/multicall-instance.admins"; +import { MIContextProvider } from "./ui/multicall-instance.providers"; +import { MITokenWhitelistTable } from "./ui/multicall-instance.token-whitelist"; export class MulticallInstance extends ModuleContext { static Context = MIModel.Context; diff --git a/src/entities/multicall-instance/model/mi-model.ts b/src/entities/multicall-instance/model/multicall-instance.model.ts similarity index 100% rename from src/entities/multicall-instance/model/mi-model.ts rename to src/entities/multicall-instance/model/multicall-instance.model.ts diff --git a/src/entities/multicall-instance/ui/mi-admin.tsx b/src/entities/multicall-instance/ui/multicall-instance.admin.tsx similarity index 100% rename from src/entities/multicall-instance/ui/mi-admin.tsx rename to src/entities/multicall-instance/ui/multicall-instance.admin.tsx diff --git a/src/entities/multicall-instance/ui/mi-admins.tsx b/src/entities/multicall-instance/ui/multicall-instance.admins.tsx similarity index 87% rename from src/entities/multicall-instance/ui/mi-admins.tsx rename to src/entities/multicall-instance/ui/multicall-instance.admins.tsx index c2bb6b0c..3a5606a7 100644 --- a/src/entities/multicall-instance/ui/mi-admins.tsx +++ b/src/entities/multicall-instance/ui/multicall-instance.admins.tsx @@ -1,8 +1,8 @@ import { useContext } from "react"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { MIModel } from "../model/mi-model"; +import { MIModel } from "../model/multicall-instance.model"; -import { miAdminAsTableRow, MIAdminProps } from "./mi-admin"; +import { miAdminAsTableRow, MIAdminProps } from "./multicall-instance.admin"; interface MIAdminsTableProps { className?: string; diff --git a/src/entities/multicall-instance/ui/mi-providers.tsx b/src/entities/multicall-instance/ui/multicall-instance.providers.tsx similarity index 82% rename from src/entities/multicall-instance/ui/mi-providers.tsx rename to src/entities/multicall-instance/ui/multicall-instance.providers.tsx index 77798ffd..59a025e3 100644 --- a/src/entities/multicall-instance/ui/mi-providers.tsx +++ b/src/entities/multicall-instance/ui/multicall-instance.providers.tsx @@ -1,6 +1,6 @@ import { PropsWithChildren } from "react"; -import { MIModel, MIModelInputs } from "../model/mi-model"; +import { MIModel, MIModelInputs } from "../model/multicall-instance.model"; export interface MIContextProviderProps extends Pick, MIModelInputs {} diff --git a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx b/src/entities/multicall-instance/ui/multicall-instance.token-whitelist.tsx similarity index 93% rename from src/entities/multicall-instance/ui/mi-token-whitelist.tsx rename to src/entities/multicall-instance/ui/multicall-instance.token-whitelist.tsx index 339e724d..1d36b46a 100644 --- a/src/entities/multicall-instance/ui/mi-token-whitelist.tsx +++ b/src/entities/multicall-instance/ui/multicall-instance.token-whitelist.tsx @@ -1,9 +1,9 @@ import { useContext } from "react"; import { Scrollable, Table, TableProps, Tile, TileProps } from "../../../shared/ui/design"; -import { MIModel } from "../model/mi-model"; +import { MIModel } from "../model/multicall-instance.model"; -import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./mi-whitelisted-token"; +import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./multicall-instance.whitelisted-token"; interface MITokenWhitelistTableProps extends Pick { ItemProps?: TableProps["RowProps"]; diff --git a/src/entities/multicall-instance/ui/mi-whitelisted-token.tsx b/src/entities/multicall-instance/ui/multicall-instance.whitelisted-token.tsx similarity index 100% rename from src/entities/multicall-instance/ui/mi-whitelisted-token.tsx rename to src/entities/multicall-instance/ui/multicall-instance.whitelisted-token.tsx diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts index f76ba10a..0eddfc70 100644 --- a/src/entities/near-token/index.ts +++ b/src/entities/near-token/index.ts @@ -1,5 +1,5 @@ import { ModuleContext, type NEARToken as NEARTokenModule } from "./module-context"; -import { nearTokenBalancesRender, type NEARTokenBalancesProps } from "./ui/nt-balances"; +import { nearTokenBalancesRender, type NEARTokenBalancesProps } from "./ui/near-token.balances"; export class NEARToken extends ModuleContext { static balancesRender = nearTokenBalancesRender; diff --git a/src/entities/near-token/model/nt-model.ts b/src/entities/near-token/model/near-token.model.ts similarity index 100% rename from src/entities/near-token/model/nt-model.ts rename to src/entities/near-token/model/near-token.model.ts diff --git a/src/entities/near-token/ui/nt-balances.tsx b/src/entities/near-token/ui/near-token.balances.tsx similarity index 91% rename from src/entities/near-token/ui/nt-balances.tsx rename to src/entities/near-token/ui/near-token.balances.tsx index 9752544d..a4211709 100644 --- a/src/entities/near-token/ui/nt-balances.tsx +++ b/src/entities/near-token/ui/near-token.balances.tsx @@ -1,6 +1,6 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; -import { NEARTokenBalancesModel } from "../model/nt-model"; +import { NEARTokenBalancesModel } from "../model/near-token.model"; import { NEARToken } from "../module-context"; export interface NEARTokenBalancesProps extends NEARToken.Inputs {} From c05423b6a2819766db928f0f0f48b453a6c89300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 16 Dec 2022 17:00:26 +0400 Subject: [PATCH 457/537] wip: Apply code review and naming remarks --- src/widgets/balances/index.ts | 2 +- .../balances/{ui.scss => ui/balances.ui.scss} | 0 .../balances/{ui.tsx => ui/balances.ui.tsx} | 6 +++--- src/widgets/dialogs-layer/index.ts | 2 +- .../{ui.tsx => ui/dialogs-layer.ui.tsx} | 2 +- src/widgets/settings-editor/index.ts | 2 +- .../{ui.scss => ui/settings-editor.ui.scss} | 0 .../{ui.tsx => ui/settings-editor.ui.tsx} | 16 ++++++++-------- 8 files changed, 15 insertions(+), 15 deletions(-) rename src/widgets/balances/{ui.scss => ui/balances.ui.scss} (100%) rename src/widgets/balances/{ui.tsx => ui/balances.ui.tsx} (93%) rename src/widgets/dialogs-layer/{ui.tsx => ui/dialogs-layer.ui.tsx} (57%) rename src/widgets/settings-editor/{ui.scss => ui/settings-editor.ui.scss} (100%) rename src/widgets/settings-editor/{ui.tsx => ui/settings-editor.ui.tsx} (88%) diff --git a/src/widgets/balances/index.ts b/src/widgets/balances/index.ts index 7f1d6bd3..79cee002 100644 --- a/src/widgets/balances/index.ts +++ b/src/widgets/balances/index.ts @@ -1 +1 @@ -export { Balances, type BalancesProps } from "./ui"; +export { Balances, type BalancesProps } from "./ui/balances.ui"; diff --git a/src/widgets/balances/ui.scss b/src/widgets/balances/ui/balances.ui.scss similarity index 100% rename from src/widgets/balances/ui.scss rename to src/widgets/balances/ui/balances.ui.scss diff --git a/src/widgets/balances/ui.tsx b/src/widgets/balances/ui/balances.ui.tsx similarity index 93% rename from src/widgets/balances/ui.tsx rename to src/widgets/balances/ui/balances.ui.tsx index 78d92562..85977179 100644 --- a/src/widgets/balances/ui.tsx +++ b/src/widgets/balances/ui/balances.ui.tsx @@ -1,6 +1,6 @@ import clsx from "clsx"; -import { Tile, Scrollable, Table } from "../../shared/ui/design"; +import { Tile, Scrollable, Table } from "../../../shared/ui/design"; import { FT, FTBalancesProps, @@ -8,9 +8,9 @@ import { NEARToken, NEARTokenBalancesProps, NEARTokenBalancesProviderProps, -} from "../../entities"; +} from "../../../entities"; -import "./ui.scss"; +import "./balances.ui.scss"; const _Balances = "Balances"; diff --git a/src/widgets/dialogs-layer/index.ts b/src/widgets/dialogs-layer/index.ts index 8b941b4b..27b26f56 100644 --- a/src/widgets/dialogs-layer/index.ts +++ b/src/widgets/dialogs-layer/index.ts @@ -1 +1 @@ -export { DialogsLayer } from "./ui"; +export { DialogsLayer } from "./ui/dialogs-layer.ui"; diff --git a/src/widgets/dialogs-layer/ui.tsx b/src/widgets/dialogs-layer/ui/dialogs-layer.ui.tsx similarity index 57% rename from src/widgets/dialogs-layer/ui.tsx rename to src/widgets/dialogs-layer/ui/dialogs-layer.ui.tsx index 6628f7e9..e8494095 100644 --- a/src/widgets/dialogs-layer/ui.tsx +++ b/src/widgets/dialogs-layer/ui/dialogs-layer.ui.tsx @@ -1,4 +1,4 @@ -import { ExternalLogin } from "../../features/external-login"; +import { ExternalLogin } from "../../../features/external-login"; export const DialogsLayer = () => ( <> diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts index 17165fea..3bc10977 100644 --- a/src/widgets/settings-editor/index.ts +++ b/src/widgets/settings-editor/index.ts @@ -1 +1 @@ -export { SettingsEditor, type SettingsEditorProps } from "./ui"; +export { SettingsEditor, type SettingsEditorProps } from "./ui/settings-editor.ui"; diff --git a/src/widgets/settings-editor/ui.scss b/src/widgets/settings-editor/ui/settings-editor.ui.scss similarity index 100% rename from src/widgets/settings-editor/ui.scss rename to src/widgets/settings-editor/ui/settings-editor.ui.scss diff --git a/src/widgets/settings-editor/ui.tsx b/src/widgets/settings-editor/ui/settings-editor.ui.tsx similarity index 88% rename from src/widgets/settings-editor/ui.tsx rename to src/widgets/settings-editor/ui/settings-editor.ui.tsx index 1640d5c5..7ee75307 100644 --- a/src/widgets/settings-editor/ui.tsx +++ b/src/widgets/settings-editor/ui/settings-editor.ui.tsx @@ -1,14 +1,14 @@ import clsx from "clsx"; import { useCallback, useState, useEffect, useContext, HTMLProps } from "react"; -import { MulticallInstance, Wallet } from "../../entities"; -import { ManageScheduleSettings, ManageTokenWhitelist, ProposeSettings } from "../../features"; -import { MulticallSettingsChange } from "../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -import { ModuleContext } from "./module-context"; -import { Tile } from "../../shared/ui/design"; - -import "./ui.scss"; +import { MulticallInstance, Wallet } from "../../../entities"; +import { ManageScheduleSettings, ManageTokenWhitelist, ProposeSettings } from "../../../features"; +import { MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; +import { ModuleContext } from "../module-context"; +import { Tile } from "../../../shared/ui/design"; + +import "./settings-editor.ui.scss"; const _SettingsEditor = "SettingsEditor"; From 29c4ad82b5fab2e5045ed47dd28d2983275b5b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 17 Dec 2022 03:42:19 +0400 Subject: [PATCH 458/537] wip: Apply code review and naming remarks --- src/entities/fungible-token/index.ts | 4 +- .../ui/fungible-token.providers.tsx | 2 +- src/entities/index.ts | 6 +- src/entities/job/index.ts | 11 ++- .../lib/{job-normalized.ts => job.format.ts} | 25 +++---- src/entities/job/model/job-info.ts | 51 ------------- src/entities/job/model/job.model.ts | 71 +++++++++++++++++++ src/entities/job/module-context.ts | 34 --------- .../ui/{jobs-table.scss => job.entries.scss} | 4 +- .../ui/{jobs-table.tsx => job.entries.tsx} | 22 +++--- .../job/ui/{job.scss => job.entry.scss} | 1 + .../job/ui/{job.tsx => job.entry.tsx} | 24 ++++--- src/pages/dao/dao.tsx | 4 +- src/pages/dao/jobs/jobs.scss | 4 +- src/pages/dao/jobs/jobs.tsx | 27 +++---- src/widgets/balances/ui/balances.ui.tsx | 14 ++-- 16 files changed, 147 insertions(+), 157 deletions(-) rename src/entities/job/lib/{job-normalized.ts => job.format.ts} (68%) delete mode 100644 src/entities/job/model/job-info.ts create mode 100644 src/entities/job/model/job.model.ts delete mode 100644 src/entities/job/module-context.ts rename src/entities/job/ui/{jobs-table.scss => job.entries.scss} (92%) rename src/entities/job/ui/{jobs-table.tsx => job.entries.tsx} (53%) rename src/entities/job/ui/{job.scss => job.entry.scss} (99%) rename src/entities/job/ui/{job.tsx => job.entry.tsx} (68%) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 0e3ffda0..c2c1f697 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,10 +1,10 @@ import { ModuleContext } from "./module-context"; import { FTBalancesProps, ftBalancesRender } from "./ui/fungible-token.balances"; -import { FTBalancesProvider, FTBalancesProviderProps } from "./ui/fungible-token.providers"; +import { FTBalancesProvider } from "./ui/fungible-token.providers"; export class FT extends ModuleContext { static BalancesProvider = FTBalancesProvider; static balancesRender = ftBalancesRender; } -export type { FTBalancesProps, FTBalancesProviderProps }; +export type { FTBalancesProps }; diff --git a/src/entities/fungible-token/ui/fungible-token.providers.tsx b/src/entities/fungible-token/ui/fungible-token.providers.tsx index f1fbf17f..40edf26a 100644 --- a/src/entities/fungible-token/ui/fungible-token.providers.tsx +++ b/src/entities/fungible-token/ui/fungible-token.providers.tsx @@ -2,7 +2,7 @@ import { PropsWithChildren } from "react"; import { FTModel, FTModelInputs } from "../model/fungible-token.model"; -export interface FTBalancesProviderProps +interface FTBalancesProviderProps extends Pick, Pick {} diff --git a/src/entities/index.ts b/src/entities/index.ts index aad7a63f..196c4128 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ export { Task } from "./task"; -export { Job, type JobEntity } from "./job"; -export { FT, type FTBalancesProps, type FTBalancesProviderProps } from "./fungible-token"; +export { Job } from "./job"; +export { FT, type FTBalancesProps } from "./fungible-token"; export { MulticallInstance } from "./multicall-instance"; -export { NEARToken, type NEARTokenBalancesProps, type NEARTokenBalancesProviderProps } from "./near-token"; +export { NEARToken, type NEARTokenBalancesProps } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index 1e53de43..91a34b80 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,8 +1,7 @@ -import { ModuleContext, Entity as JobEntity } from "./module-context"; -import { JobsTable } from "./ui/jobs-table"; +import { JobEntriesTable, JobEntriesTableProps } from "./ui/job.entries"; -export { type JobEntity }; - -export class Job extends ModuleContext { - static EntriesTable = JobsTable; +export class Job { + static EntriesTable = JobEntriesTable; } + +export type { JobEntriesTableProps }; diff --git a/src/entities/job/lib/job-normalized.ts b/src/entities/job/lib/job.format.ts similarity index 68% rename from src/entities/job/lib/job-normalized.ts rename to src/entities/job/lib/job.format.ts index db0cf3c5..a1ce8530 100644 --- a/src/entities/job/lib/job-normalized.ts +++ b/src/entities/job/lib/job.format.ts @@ -1,7 +1,8 @@ import { Base64 } from "js-base64"; +import { JobData } from "../../../shared/lib/contracts/multicall"; import { Big } from "../../../shared/lib/converter"; -import { ModuleContext, Entity } from "../module-context"; +import { JobDataWithStatus, JobStatus } from "../model/job.model"; /** * Job status is: @@ -10,16 +11,16 @@ import { ModuleContext, Entity } from "../module-context"; * - Expired: job not active, and execution moment is in the past. * - Inactive: job not active, but execution moment in the future. */ -const jobToStatus = ({ job }: Entity.Data): Entity.Status => { +const jobToStatus = ({ job }: JobData): JobStatus => { if (job.is_active) { - if (job.run_count > -1) return ModuleContext.Status.Running; - else return ModuleContext.Status.Active; + if (job.run_count > -1) return JobStatus.Running; + else return JobStatus.Active; } else { // Date.now() returns timestamp in milliseconds, we use nanoseconds const currentTime = Big(Date.now()).times("1000000"); const jobTime = job.start_at; - if (currentTime.gt(jobTime)) return ModuleContext.Status.Expired; - else return ModuleContext.Status.Inactive; + if (currentTime.gt(jobTime)) return JobStatus.Expired; + else return JobStatus.Inactive; } }; @@ -29,7 +30,7 @@ const jobToStatus = ({ job }: Entity.Data): Entity.Status => { * * @returns Updated job data structure. */ -const jobToJobWithMulticallsDataDecoded = ({ id, job }: Entity.Data): Entity.Data => ({ +const withMulticallsDataDecoded = ({ id, job }: JobData): JobData => ({ id, job: { @@ -61,12 +62,12 @@ const jobToJobWithMulticallsDataDecoded = ({ id, job }: Entity.Data): Entity.Dat * * @returns Extended job data structure. */ -const jobToJobWithStatus = (job: Entity.Data): Entity.DataWithStatus => ({ +const withStatus = (job: JobData): JobDataWithStatus => ({ ...job, - job: { ...job.job, status: ModuleContext.Status[jobToStatus(job)] }, + job: { ...job.job, status: JobStatus[jobToStatus(job)] }, }); -export const JobNormalized = { - withMulticallsDataDecoded: jobToJobWithMulticallsDataDecoded, - withStatus: jobToJobWithStatus, +export const JobFormat = { + withMulticallsDataDecoded, + withStatus, }; diff --git a/src/entities/job/model/job-info.ts b/src/entities/job/model/job-info.ts deleted file mode 100644 index ec8a2ccd..00000000 --- a/src/entities/job/model/job-info.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { useEffect, useState } from "react"; - -import { Entity } from "../module-context"; -import { JobNormalized } from "../lib/job-normalized"; - -type Jobs = { - /** Jobs indexed by ID for easy access to each particular job */ - data: Record | null; - error?: Error | null; - loading: boolean; -}; - -export class JobInfoModel { - static allEntriesFetch = async ( - { multicallInstance }: Entity.Inputs["adapters"], - callback: (result: Jobs) => void - ) => - callback( - await multicallInstance - .getJobs() - .then((data) => ({ - data: data.reduce( - (jobsIndexedById, job) => ({ - ...jobsIndexedById, - [job.id]: JobNormalized.withMulticallsDataDecoded(JobNormalized.withStatus(job)), - }), - {} - ), - - error: null, - loading: false, - })) - .catch((error) => ({ - data: null, - error: new Error(error), - loading: false, - })) - ); - - static useAllEntries = (adapters: Entity.Inputs["adapters"]) => { - const [state, stateUpdate] = useState({ data: null, error: null, loading: true }); - - useEffect(() => void JobInfoModel.allEntriesFetch(adapters, stateUpdate), [adapters, stateUpdate]); - - useEffect(() => { - state.error instanceof Error && void console.error(state.error); - }, [state]); - - return state; - }; -} diff --git a/src/entities/job/model/job.model.ts b/src/entities/job/model/job.model.ts new file mode 100644 index 00000000..81bf2682 --- /dev/null +++ b/src/entities/job/model/job.model.ts @@ -0,0 +1,71 @@ +import { useEffect, useState } from "react"; + +import { JobData, Multicall } from "../../../shared/lib/contracts/multicall"; +import { JobFormat } from "../lib/job.format"; + +export interface JobModelInputs { + multicallInstance: Multicall; +} + +export enum JobStatus { + Inactive = "Inactive", + Expired = "Expired", + Active = "Active", + Running = "Running", + Unknown = "Unknown", +} + +export type JobDataWithStatus = Omit & { + job: JobData["job"] & { status: JobStatus }; +}; + +export class JobModel { + public static readonly allEntries: { + /** Jobs indexed by ID for easy access to each particular job */ + data: Record | null; + error?: Error | null; + loading: boolean; + } = { + data: null, + error: null, + loading: true, + }; + + private static readonly allEntriesFetch = async ( + { multicallInstance }: JobModelInputs, + callback: (result: typeof JobModel.allEntries) => void + ) => + callback( + await multicallInstance + .getJobs() + .then((data) => ({ + data: data.reduce( + (jobsIndexedById, job) => ({ + ...jobsIndexedById, + [job.id]: JobFormat.withMulticallsDataDecoded(JobFormat.withStatus(job)), + }), + {} + ), + + error: null, + loading: false, + })) + .catch((error) => ({ + data: null, + error: new Error(error), + loading: false, + })) + ); + + public static readonly useAllEntriesState = (inputs: JobModelInputs) => { + const [state, stateUpdate] = useState(JobModel.allEntries); + + useEffect(() => void JobModel.allEntriesFetch(inputs, stateUpdate), [inputs, stateUpdate]); + + useEffect(() => { + state.error instanceof Error && void console.error(state.error); + }, [state]); + + return state; + }; +} diff --git a/src/entities/job/module-context.ts b/src/entities/job/module-context.ts deleted file mode 100644 index e6fb6f76..00000000 --- a/src/entities/job/module-context.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { JobData, Multicall } from "../../shared/lib/contracts/multicall"; - -export namespace Entity { - export interface Inputs { - className?: string; - adapters: { multicallInstance: Multicall }; - } - - export type Data = JobData; - - export enum Status { - Inactive = "Inactive", - Expired = "Expired", - Active = "Active", - Running = "Running", - Unknown = "Unknown", - } - - export type DataWithStatus = Omit & { - job: Data["job"] & { status: Status }; - }; -} - -export class ModuleContext { - static readonly Status = Entity.Status; - - static StatusIcons = { - [Entity.Status.Inactive]: "🟡", - [Entity.Status.Expired]: "🔴", - [Entity.Status.Active]: "🟢", - [Entity.Status.Running]: "🟣", - [Entity.Status.Unknown]: "❔", - }; -} diff --git a/src/entities/job/ui/jobs-table.scss b/src/entities/job/ui/job.entries.scss similarity index 92% rename from src/entities/job/ui/jobs-table.scss rename to src/entities/job/ui/job.entries.scss index 053287b1..0ba1b84d 100644 --- a/src/entities/job/ui/jobs-table.scss +++ b/src/entities/job/ui/job.entries.scss @@ -2,8 +2,8 @@ @use "sass/font"; @use "sass/size"; -.JobsTable { - grid-area: JobsTable; +.JobEntriesTable { + grid-area: JobEntriesTable; &-body { .TableRow-content--compact { diff --git a/src/entities/job/ui/jobs-table.tsx b/src/entities/job/ui/job.entries.tsx similarity index 53% rename from src/entities/job/ui/jobs-table.tsx rename to src/entities/job/ui/job.entries.tsx index 75bb1161..06496a9e 100644 --- a/src/entities/job/ui/jobs-table.tsx +++ b/src/entities/job/ui/job.entries.tsx @@ -1,23 +1,25 @@ import clsx from "clsx"; import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { JobInfoModel } from "../model/job-info"; -import { Entity } from "../module-context"; +import { JobModel, JobModelInputs } from "../model/job.model"; -import { jobAsTableRow } from "./job"; -import "./jobs-table.scss"; +import { jobAsTableRow } from "./job.entry"; +import "./job.entries.scss"; +import { Context } from "react"; -interface JobsTableProps extends Entity.Inputs {} +const _JobEntriesTable = "JobEntriesTable"; -const _JobsTable = "JobsTable"; +export interface JobEntriesTableProps extends JobModelInputs { + className?: string; +} -export const JobsTable = ({ className, adapters }: JobsTableProps) => { - const { data, error, loading } = JobInfoModel.useAllEntries(adapters), +export const JobEntriesTable = ({ className, ...modelInputs }: JobEntriesTableProps) => { + const { data, error, loading } = JobModel.useAllEntriesState(modelInputs), items = Object.values(data ?? {}); return ( {
    ) => { +const JobStatusIcons = { + [JobStatus.Inactive]: "🟡", + [JobStatus.Expired]: "🔴", + [JobStatus.Active]: "🟢", + [JobStatus.Running]: "🟣", + [JobStatus.Unknown]: "❔", +}; + +const JobDisplayStatus = ({ job }: Pick) => { const statusTextByStatus = { - ...ModuleContext.Status, - [ModuleContext.Status.Running]: `${ModuleContext.Status.Running}: ${job.run_count + 1}/${ - job.multicalls.length - }`, + ...JobStatus, + [JobStatus.Running]: `${JobStatus.Running}: ${job.run_count + 1}/${job.multicalls.length}`, }; return ( ); }; -export const jobAsTableRow = ({ id, job }: Entity.DataWithStatus) => ({ +export const jobAsTableRow = ({ id, job }: JobDataWithStatus) => ({ content: [ , id, diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index c29f9e65..cba41f03 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -513,9 +513,9 @@ export class DaoPage extends Component { contentSpace: `${_DaoPage}-tabs-contentSpace`, }} items={[ - DaoSettingsTab.render({ className: `${_DaoPage}-content`, adapters: { dao } }), + DaoSettingsTab.render({ className: `${_DaoPage}-content`, dao }), DaoFundsTab.render({ accountId: dao.address, className: `${_DaoPage}-content` }), - DaoJobsTab.render({ className: `${_DaoPage}-content`, adapters: { multicallInstance } }), + DaoJobsTab.render({ className: `${_DaoPage}-content` }), ]} /> diff --git a/src/pages/dao/jobs/jobs.scss b/src/pages/dao/jobs/jobs.scss index 5292825e..30f6df14 100644 --- a/src/pages/dao/jobs/jobs.scss +++ b/src/pages/dao/jobs/jobs.scss @@ -4,6 +4,6 @@ grid-template-rows: 1fr 1fr; grid-template-areas: - "JobsTable JobsTable" - "JobsTable JobsTable"; + "JobEntriesTable JobEntriesTable" + "JobEntriesTable JobEntriesTable"; } diff --git a/src/pages/dao/jobs/jobs.tsx b/src/pages/dao/jobs/jobs.tsx index 8a4e958e..7c219031 100644 --- a/src/pages/dao/jobs/jobs.tsx +++ b/src/pages/dao/jobs/jobs.tsx @@ -1,25 +1,26 @@ import clsx from "clsx"; -import { ComponentProps, HTMLProps } from "react"; +import { HTMLProps, useContext } from "react"; -import { Job } from "../../../entities"; +import { Job, MulticallInstance } from "../../../entities"; import "./jobs.scss"; const _DaoJobsTab = "DaoJobsTab"; -interface DaoJobsTabProps extends HTMLProps, ComponentProps {} +interface DaoJobsTabProps extends HTMLProps {} -export const DaoJobsTab = { - render: ({ className, adapters, ...props }: DaoJobsTabProps) => ({ - content: ( -
    - -
    - ), +const DAOJobsTabContent = ({ className, ...props }: DaoJobsTabProps) => ( +
    + +
    +); +export const DaoJobsTab = { + render: (props: DaoJobsTabProps) => ({ + content: , lazy: true, name: "Jobs", }), diff --git a/src/widgets/balances/ui/balances.ui.tsx b/src/widgets/balances/ui/balances.ui.tsx index 85977179..d33b8f08 100644 --- a/src/widgets/balances/ui/balances.ui.tsx +++ b/src/widgets/balances/ui/balances.ui.tsx @@ -1,14 +1,8 @@ import clsx from "clsx"; +import { ComponentProps } from "react"; import { Tile, Scrollable, Table } from "../../../shared/ui/design"; -import { - FT, - FTBalancesProps, - FTBalancesProviderProps, - NEARToken, - NEARTokenBalancesProps, - NEARTokenBalancesProviderProps, -} from "../../../entities"; +import { FT, FTBalancesProps, NEARToken, NEARTokenBalancesProps } from "../../../entities"; import "./balances.ui.scss"; @@ -16,9 +10,9 @@ const _Balances = "Balances"; export interface BalancesProps extends FTBalancesProps, - FTBalancesProviderProps, + ComponentProps, NEARTokenBalancesProps, - NEARTokenBalancesProviderProps { + ComponentProps { accountName: string; className?: string; } From d9f7f415f9d54f6a5e6514463277910dd1cc1b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 17 Dec 2022 03:45:32 +0400 Subject: [PATCH 459/537] wip: Format --- src/entities/job/ui/job.entries.tsx | 1 - src/pages/dao/dao.tsx | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/entities/job/ui/job.entries.tsx b/src/entities/job/ui/job.entries.tsx index 06496a9e..de2a4a2c 100644 --- a/src/entities/job/ui/job.entries.tsx +++ b/src/entities/job/ui/job.entries.tsx @@ -5,7 +5,6 @@ import { JobModel, JobModelInputs } from "../model/job.model"; import { jobAsTableRow } from "./job.entry"; import "./job.entries.scss"; -import { Context } from "react"; const _JobEntriesTable = "JobEntriesTable"; diff --git a/src/pages/dao/dao.tsx b/src/pages/dao/dao.tsx index cba41f03..6e8e0bf7 100644 --- a/src/pages/dao/dao.tsx +++ b/src/pages/dao/dao.tsx @@ -1,10 +1,10 @@ import clsx from "clsx"; +import { Form, Formik } from "formik"; import { Base64 } from "js-base64"; import debounce from "lodash.debounce"; import { Component, ContextType } from "react"; import { MulticallInstance, Wallet } from "../../entities"; -import { Form, Formik } from "formik"; import { args } from "../../shared/lib/args/args"; import { fields } from "../../shared/lib/args/args-types/args-object"; import { Multicall } from "../../shared/lib/contracts/multicall"; @@ -153,6 +153,7 @@ export class DaoPage extends Component { this.setState({ multicallInstance: new Multicall(Multicall.getInstanceAddress(e.detail.dao)), }); + this.formikSetValues?.({ addr: e.detail.dao }); } } From 512e5b9f1c08426c87acf4901f92158a13a38cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 18 Dec 2022 19:51:08 +0400 Subject: [PATCH 460/537] fix: Don't wrap error additionally --- src/entities/job/model/job.model.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/entities/job/model/job.model.ts b/src/entities/job/model/job.model.ts index 81bf2682..5bdeeaba 100644 --- a/src/entities/job/model/job.model.ts +++ b/src/entities/job/model/job.model.ts @@ -50,11 +50,7 @@ export class JobModel { error: null, loading: false, })) - .catch((error) => ({ - data: null, - error: new Error(error), - loading: false, - })) + .catch((error) => ({ data: null, error, loading: false })) ); public static readonly useAllEntriesState = (inputs: JobModelInputs) => { From 147f03cffcd2aca7dc915d6faff70c0a7f5eac8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 18 Dec 2022 22:13:27 +0400 Subject: [PATCH 461/537] wip: Apply code review and naming remarks --- src/entities/fungible-token/index.ts | 4 + .../lib/fungible-token.format.ts | 1 - .../model/fungible-token.model.ts | 54 +++++----- .../ui/fungible-token.balances.tsx | 33 +++--- src/entities/near-token/index.ts | 10 +- .../near-token/lib/near-token.format.ts | 15 +++ .../near-token/model/near-token.model.ts | 102 ++++++++++-------- src/entities/near-token/module-context.ts | 12 --- .../near-token/ui/near-token.balances.tsx | 20 ++-- .../near-token/ui/near-token.providers.tsx | 13 +++ src/widgets/balances/ui/balances.ui.tsx | 2 +- 11 files changed, 153 insertions(+), 113 deletions(-) create mode 100644 src/entities/near-token/lib/near-token.format.ts create mode 100644 src/entities/near-token/ui/near-token.providers.tsx diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index c2c1f697..2daa9927 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,10 +1,14 @@ import { ModuleContext } from "./module-context"; +import { FTFormat } from "./lib/fungible-token.format"; +import { FTModel } from "./model/fungible-token.model"; import { FTBalancesProps, ftBalancesRender } from "./ui/fungible-token.balances"; import { FTBalancesProvider } from "./ui/fungible-token.providers"; export class FT extends ModuleContext { + static BalancesContext = FTModel.BalancesContext; static BalancesProvider = FTBalancesProvider; static balancesRender = ftBalancesRender; + static format = FTFormat; } export type { FTBalancesProps }; diff --git a/src/entities/fungible-token/lib/fungible-token.format.ts b/src/entities/fungible-token/lib/fungible-token.format.ts index b11e8e64..94e2af2b 100644 --- a/src/entities/fungible-token/lib/fungible-token.format.ts +++ b/src/entities/fungible-token/lib/fungible-token.format.ts @@ -1,5 +1,4 @@ import { Big, formatTokenAmount } from "../../../shared/lib/converter"; - import { ModuleContext } from "../module-context"; const amountToDisplayAmount = (amount: string, decimals: number): string => { diff --git a/src/entities/fungible-token/model/fungible-token.model.ts b/src/entities/fungible-token/model/fungible-token.model.ts index af4f321c..e42a938e 100644 --- a/src/entities/fungible-token/model/fungible-token.model.ts +++ b/src/entities/fungible-token/model/fungible-token.model.ts @@ -11,7 +11,14 @@ export interface FTModelInputs { export class FTModel { public static readonly balances: { - data: (Pick & { account: string; multicall: string; total: string })[] | null; + data: + | null + | (Pick & { + account: string; + multicallInstance: string; + total: string; + })[]; + error: Error | null; loading: boolean; } = { @@ -26,45 +33,40 @@ export class FTModel { { accountId }: FTModelInputs["balances"], callback: (result: typeof FTModel.balances) => void ) => { - const multicallInstanceAddress = Multicall.getInstanceAddress(accountId); + const miAddress = Multicall.getInstanceAddress(accountId); /** * Get LikelyTokens list on account and its Multicall Instance */ - const [accountLikelyTokensList, multicallLikelyTokensList] = await Promise.all([ + const [accountLikelyTokensList, miLikelyTokensList] = await Promise.all([ FungibleToken.getLikelyTokenContracts(accountId), - FungibleToken.getLikelyTokenContracts(multicallInstanceAddress), + FungibleToken.getLikelyTokenContracts(miAddress), ]); /* Merge and de-duplicate both token lists */ - const likelyTokensAddressesList = [...new Set([...accountLikelyTokensList, ...multicallLikelyTokensList])]; + const likelyTokensAddressesList = [...new Set([...accountLikelyTokensList, ...miLikelyTokensList])]; const likelyTokensList = await Promise.all( likelyTokensAddressesList.map((address) => FungibleToken.init(address)) ); - const rawBalances = await Promise.all( - likelyTokensList - .filter((token) => token.ready === true) - .map(async (token) => { - const [accountRawBalance, multicallRawBalance] = await Promise.all([ - token.ftBalanceOf(accountId), - token.ftBalanceOf(multicallInstanceAddress), - ]); - - return { - account: accountRawBalance, - metadata: token.metadata, - multicall: multicallRawBalance, - total: Big(multicallRawBalance).add(accountRawBalance).toFixed(), - }; - }) - ); - return callback({ - data: rawBalances.filter( - /** Removes tokens with 0 total balance */ - ({ total }) => Big(total).gt("0") + data: await Promise.all( + likelyTokensList + .filter((token) => token.ready === true) + .map(async (token) => { + const [account, multicallInstance] = await Promise.all([ + token.ftBalanceOf(accountId), + token.ftBalanceOf(miAddress), + ]); + + return { + account, + metadata: token.metadata, + multicallInstance, + total: Big(multicallInstance).add(account).toFixed(), + }; + }) ), error: null, diff --git a/src/entities/fungible-token/ui/fungible-token.balances.tsx b/src/entities/fungible-token/ui/fungible-token.balances.tsx index f0582009..8297d3d6 100644 --- a/src/entities/fungible-token/ui/fungible-token.balances.tsx +++ b/src/entities/fungible-token/ui/fungible-token.balances.tsx @@ -1,4 +1,6 @@ +import Big from "big.js"; import { useContext } from "react"; + import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { FTFormat } from "../lib/fungible-token.format"; import { FTModel } from "../model/fungible-token.model"; @@ -8,22 +10,23 @@ export interface FTBalancesProps { } export const ftBalancesRender = ({ nonZeroOnly = false }: FTBalancesProps) => { - const { data } = useContext(FTModel.BalancesContext); + const { data } = useContext(FTModel.BalancesContext), + items = nonZeroOnly ? data?.filter(({ total }) => Big(total).gt("0")) : data; - return !data - ? null - : data.map(({ account, metadata, multicall, total }) => ({ - content: [ - } - label={metadata.symbol} - />, + return ( + items?.map(({ account, metadata, multicallInstance, total }) => ({ + content: [ + } + label={metadata.symbol} + />, - FTFormat.amountToDisplayAmount(multicall, metadata.decimals), - FTFormat.amountToDisplayAmount(account, metadata.decimals), - FTFormat.amountToDisplayAmount(total, metadata.decimals), - ], + FTFormat.amountToDisplayAmount(multicallInstance, metadata.decimals), + FTFormat.amountToDisplayAmount(account, metadata.decimals), + FTFormat.amountToDisplayAmount(total, metadata.decimals), + ], - id: metadata.symbol, - })); + id: metadata.symbol, + })) ?? null + ); }; diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts index 0eddfc70..174863b2 100644 --- a/src/entities/near-token/index.ts +++ b/src/entities/near-token/index.ts @@ -1,8 +1,14 @@ -import { ModuleContext, type NEARToken as NEARTokenModule } from "./module-context"; +import { ModuleContext } from "./module-context"; +import { NEARTokenFormat } from "./lib/near-token.format"; +import { NEARTokenModel } from "./model/near-token.model"; import { nearTokenBalancesRender, type NEARTokenBalancesProps } from "./ui/near-token.balances"; +import { NEARTokenBalancesProvider } from "./ui/near-token.providers"; export class NEARToken extends ModuleContext { + static BalancesContext = NEARTokenModel.BalancesContext; + static BalancesProvider = NEARTokenBalancesProvider; static balancesRender = nearTokenBalancesRender; + static format = NEARTokenFormat; } -export type { NEARTokenModule, NEARTokenBalancesProps }; +export type { NEARTokenBalancesProps }; diff --git a/src/entities/near-token/lib/near-token.format.ts b/src/entities/near-token/lib/near-token.format.ts new file mode 100644 index 00000000..90c39b7e --- /dev/null +++ b/src/entities/near-token/lib/near-token.format.ts @@ -0,0 +1,15 @@ +import { Big, formatTokenAmount } from "../../../shared/lib/converter"; +import { ModuleContext } from "../module-context"; + +const amountToDisplayAmount = (amount: string, decimals: number): string => { + const formattedAmount = formatTokenAmount(amount, decimals), + minimalDisplayAmount = Big("10").pow(-ModuleContext.FRACTIONAL_PART_LENGTH).toFixed(); + + return Big(formattedAmount).gt("0") && Big(formattedAmount).lt(minimalDisplayAmount) + ? "< " + minimalDisplayAmount + : formatTokenAmount(amount, decimals, ModuleContext.FRACTIONAL_PART_LENGTH); +}; + +export const NEARTokenFormat = { + amountToDisplayAmount, +}; diff --git a/src/entities/near-token/model/near-token.model.ts b/src/entities/near-token/model/near-token.model.ts index 7e0030d2..a68f9868 100644 --- a/src/entities/near-token/model/near-token.model.ts +++ b/src/entities/near-token/model/near-token.model.ts @@ -1,50 +1,58 @@ -import { useEffect, useState } from "react"; +import { Account } from "@near-wallet-selector/core"; +import { createContext, useEffect, useState } from "react"; -import { Big, formatTokenAmount } from "../../../shared/lib/converter"; +import { Big } from "../../../shared/lib/converter"; import { viewAccount } from "../../../shared/lib/wallet"; -import { ModuleContext, type NEARToken } from "../module-context"; - -type NEARTokenDataResponse = { - data: { dao: string; multicall: string; total: string } | null; - loading: boolean; -}; - -const nearTokenData = async ( - { dao, multicallInstance }: NEARToken.Inputs["adapters"], - callback: (result: NEARTokenDataResponse) => void -) => { - const [daoAccInfo, multicallAccInfo] = await Promise.all([ - viewAccount(dao.address), - viewAccount(multicallInstance.address), - ]); - - const daoRawBalance = daoAccInfo.amount, - multicallRawBalance = multicallAccInfo.amount; - - return callback({ - data: { - dao: formatTokenAmount(daoRawBalance, 24, ModuleContext.FRACTIONAL_PART_LENGTH), - multicall: formatTokenAmount(multicallRawBalance, 24, ModuleContext.FRACTIONAL_PART_LENGTH), - - total: formatTokenAmount( - Big(daoRawBalance).add(multicallRawBalance).toFixed(), - 24, - ModuleContext.FRACTIONAL_PART_LENGTH - ), - }, - - loading: false, - }); -}; - -const useNEARTokenData = (adapters: NEARToken.Inputs["adapters"]) => { - const [state, stateUpdate] = useState({ data: null, loading: true }); - - useEffect(() => void nearTokenData(adapters, stateUpdate), [adapters, stateUpdate]); - - return state; -}; - -export class NEARTokenBalancesModel { - static useTokenFrom = useNEARTokenData; +import { Multicall } from "../../../shared/lib/contracts/multicall"; + +export interface NEARTokenModelInputs { + balances: Pick; +} + +export class NEARTokenModel { + public static readonly balances: { + data: null | { + account: string; + multicallInstance: string; + total: string; + }; + + error: Error | null; + loading: boolean; + } = { + data: null, + error: null, + loading: true, + }; + + public static readonly BalancesContext = createContext(NEARTokenModel.balances); + + private static readonly balancesFetch = async ( + { accountId }: NEARTokenModelInputs["balances"], + callback: (result: typeof NEARTokenModel.balances) => void + ) => { + const [{ amount: account }, { amount: multicallInstance }] = await Promise.all([ + viewAccount(accountId), + viewAccount(Multicall.getInstanceAddress(accountId)), + ]); + + return callback({ + data: { + account, + multicallInstance, + total: Big(account).add(multicallInstance).toFixed(), + }, + + error: null, + loading: false, + }); + }; + + public static readonly useBalancesState = (inputs: NEARTokenModelInputs["balances"]) => { + const [state, stateUpdate] = useState(NEARTokenModel.balances); + + useEffect(() => void NEARTokenModel.balancesFetch(inputs, stateUpdate), [inputs, stateUpdate]); + + return state; + }; } diff --git a/src/entities/near-token/module-context.ts b/src/entities/near-token/module-context.ts index 0b6ba9ed..7202517a 100644 --- a/src/entities/near-token/module-context.ts +++ b/src/entities/near-token/module-context.ts @@ -1,15 +1,3 @@ -import { Multicall } from "../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; - -export namespace NEARToken { - export interface Inputs { - adapters: { - dao: SputnikDAO; - multicallInstance: Multicall; - }; - } -} - export class ModuleContext { static FRACTIONAL_PART_LENGTH = 5; } diff --git a/src/entities/near-token/ui/near-token.balances.tsx b/src/entities/near-token/ui/near-token.balances.tsx index a4211709..2c88b889 100644 --- a/src/entities/near-token/ui/near-token.balances.tsx +++ b/src/entities/near-token/ui/near-token.balances.tsx @@ -1,12 +1,14 @@ -import { IconLabel, NearIcon } from "../../../shared/ui/design"; +import { useContext } from "react"; -import { NEARTokenBalancesModel } from "../model/near-token.model"; -import { NEARToken } from "../module-context"; +import { formatTokenAmount } from "../../../shared/lib/converter"; +import { IconLabel, NearIcon } from "../../../shared/ui/design"; +import { NEARTokenModel } from "../model/near-token.model"; +import { ModuleContext } from "../module-context"; -export interface NEARTokenBalancesProps extends NEARToken.Inputs {} +export interface NEARTokenBalancesProps {} -export const nearTokenBalancesRender = ({ adapters }: NEARTokenBalancesProps) => { - const { data } = NEARTokenBalancesModel.useTokenFrom(adapters); +export const nearTokenBalancesRender = () => { + const { data } = useContext(NEARTokenModel.BalancesContext); return !data ? null @@ -17,9 +19,9 @@ export const nearTokenBalancesRender = ({ adapters }: NEARTokenBalancesProps) => label="NEAR" />, - data.multicall, - data.dao, - data.total, + formatTokenAmount(data.multicallInstance, 24, ModuleContext.FRACTIONAL_PART_LENGTH), + formatTokenAmount(data.account, 24, ModuleContext.FRACTIONAL_PART_LENGTH), + formatTokenAmount(data.total, 24, ModuleContext.FRACTIONAL_PART_LENGTH), ], id: "NEAR", diff --git a/src/entities/near-token/ui/near-token.providers.tsx b/src/entities/near-token/ui/near-token.providers.tsx new file mode 100644 index 00000000..2a100932 --- /dev/null +++ b/src/entities/near-token/ui/near-token.providers.tsx @@ -0,0 +1,13 @@ +import { PropsWithChildren } from "react"; + +import { NEARTokenModel, NEARTokenModelInputs } from "../model/near-token.model"; + +interface NEARTokenBalancesProviderProps + extends Pick, + Pick {} + +export const NEARTokenBalancesProvider = ({ children, ...modelInputs }: NEARTokenBalancesProviderProps) => ( + + {children} + +); diff --git a/src/widgets/balances/ui/balances.ui.tsx b/src/widgets/balances/ui/balances.ui.tsx index d33b8f08..254be239 100644 --- a/src/widgets/balances/ui/balances.ui.tsx +++ b/src/widgets/balances/ui/balances.ui.tsx @@ -18,7 +18,7 @@ export interface BalancesProps } export const Balances = ({ className, accountId, accountName, nonZeroOnly = true }: BalancesProps) => { - const nearTokenBalances = NEARToken.balancesRender({ nonZeroOnly }), + const nearTokenBalances = NEARToken.balancesRender(), fungibleTokenBalances = FT.balancesRender({ nonZeroOnly }); return ( From 037f4852c005a0d87de02cd97f118f1cc1bf5abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 18 Dec 2022 22:17:42 +0400 Subject: [PATCH 462/537] wip: Remove redundant code --- src/entities/fungible-token/index.ts | 4 +--- .../fungible-token/ui/fungible-token.balances.tsx | 2 +- src/entities/index.ts | 4 ++-- src/entities/near-token/index.ts | 4 +--- src/entities/near-token/ui/near-token.balances.tsx | 2 -- src/widgets/balances/ui/balances.ui.tsx | 10 ++++------ 6 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 2daa9927..95e3960e 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -1,7 +1,7 @@ import { ModuleContext } from "./module-context"; import { FTFormat } from "./lib/fungible-token.format"; import { FTModel } from "./model/fungible-token.model"; -import { FTBalancesProps, ftBalancesRender } from "./ui/fungible-token.balances"; +import { ftBalancesRender } from "./ui/fungible-token.balances"; import { FTBalancesProvider } from "./ui/fungible-token.providers"; export class FT extends ModuleContext { @@ -10,5 +10,3 @@ export class FT extends ModuleContext { static balancesRender = ftBalancesRender; static format = FTFormat; } - -export type { FTBalancesProps }; diff --git a/src/entities/fungible-token/ui/fungible-token.balances.tsx b/src/entities/fungible-token/ui/fungible-token.balances.tsx index 8297d3d6..73640ae9 100644 --- a/src/entities/fungible-token/ui/fungible-token.balances.tsx +++ b/src/entities/fungible-token/ui/fungible-token.balances.tsx @@ -5,7 +5,7 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { FTFormat } from "../lib/fungible-token.format"; import { FTModel } from "../model/fungible-token.model"; -export interface FTBalancesProps { +interface FTBalancesProps { nonZeroOnly?: boolean; } diff --git a/src/entities/index.ts b/src/entities/index.ts index 196c4128..119606c7 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ export { Task } from "./task"; export { Job } from "./job"; -export { FT, type FTBalancesProps } from "./fungible-token"; +export { FT } from "./fungible-token"; export { MulticallInstance } from "./multicall-instance"; -export { NEARToken, type NEARTokenBalancesProps } from "./near-token"; +export { NEARToken } from "./near-token"; export { Wallet } from "./wallet"; diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts index 174863b2..6e4dc975 100644 --- a/src/entities/near-token/index.ts +++ b/src/entities/near-token/index.ts @@ -1,7 +1,7 @@ import { ModuleContext } from "./module-context"; import { NEARTokenFormat } from "./lib/near-token.format"; import { NEARTokenModel } from "./model/near-token.model"; -import { nearTokenBalancesRender, type NEARTokenBalancesProps } from "./ui/near-token.balances"; +import { nearTokenBalancesRender } from "./ui/near-token.balances"; import { NEARTokenBalancesProvider } from "./ui/near-token.providers"; export class NEARToken extends ModuleContext { @@ -10,5 +10,3 @@ export class NEARToken extends ModuleContext { static balancesRender = nearTokenBalancesRender; static format = NEARTokenFormat; } - -export type { NEARTokenBalancesProps }; diff --git a/src/entities/near-token/ui/near-token.balances.tsx b/src/entities/near-token/ui/near-token.balances.tsx index 2c88b889..6f8be33a 100644 --- a/src/entities/near-token/ui/near-token.balances.tsx +++ b/src/entities/near-token/ui/near-token.balances.tsx @@ -5,8 +5,6 @@ import { IconLabel, NearIcon } from "../../../shared/ui/design"; import { NEARTokenModel } from "../model/near-token.model"; import { ModuleContext } from "../module-context"; -export interface NEARTokenBalancesProps {} - export const nearTokenBalancesRender = () => { const { data } = useContext(NEARTokenModel.BalancesContext); diff --git a/src/widgets/balances/ui/balances.ui.tsx b/src/widgets/balances/ui/balances.ui.tsx index 254be239..9c1f348a 100644 --- a/src/widgets/balances/ui/balances.ui.tsx +++ b/src/widgets/balances/ui/balances.ui.tsx @@ -2,24 +2,22 @@ import clsx from "clsx"; import { ComponentProps } from "react"; import { Tile, Scrollable, Table } from "../../../shared/ui/design"; -import { FT, FTBalancesProps, NEARToken, NEARTokenBalancesProps } from "../../../entities"; +import { FT, NEARToken } from "../../../entities"; import "./balances.ui.scss"; const _Balances = "Balances"; export interface BalancesProps - extends FTBalancesProps, - ComponentProps, - NEARTokenBalancesProps, + extends ComponentProps, ComponentProps { accountName: string; className?: string; } -export const Balances = ({ className, accountId, accountName, nonZeroOnly = true }: BalancesProps) => { +export const Balances = ({ className, accountId, accountName }: BalancesProps) => { const nearTokenBalances = NEARToken.balancesRender(), - fungibleTokenBalances = FT.balancesRender({ nonZeroOnly }); + fungibleTokenBalances = FT.balancesRender({ nonZeroOnly: true }); return ( From b7a01a52b40908e39708ac99c21bc9203f160fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 19 Dec 2022 02:13:52 +0400 Subject: [PATCH 463/537] wip: Extract NEAR token display amount formatter --- src/entities/near-token/lib/near-token.format.ts | 12 +++--------- src/entities/near-token/module-context.ts | 3 ++- src/entities/near-token/ui/near-token.balances.tsx | 9 ++++----- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/entities/near-token/lib/near-token.format.ts b/src/entities/near-token/lib/near-token.format.ts index 90c39b7e..50429d67 100644 --- a/src/entities/near-token/lib/near-token.format.ts +++ b/src/entities/near-token/lib/near-token.format.ts @@ -1,14 +1,8 @@ -import { Big, formatTokenAmount } from "../../../shared/lib/converter"; +import { formatTokenAmount } from "../../../shared/lib/converter"; import { ModuleContext } from "../module-context"; -const amountToDisplayAmount = (amount: string, decimals: number): string => { - const formattedAmount = formatTokenAmount(amount, decimals), - minimalDisplayAmount = Big("10").pow(-ModuleContext.FRACTIONAL_PART_LENGTH).toFixed(); - - return Big(formattedAmount).gt("0") && Big(formattedAmount).lt(minimalDisplayAmount) - ? "< " + minimalDisplayAmount - : formatTokenAmount(amount, decimals, ModuleContext.FRACTIONAL_PART_LENGTH); -}; +const amountToDisplayAmount = (amount: string): string => + formatTokenAmount(amount, ModuleContext.DECIMALS, ModuleContext.FRACTIONAL_PART_LENGTH); export const NEARTokenFormat = { amountToDisplayAmount, diff --git a/src/entities/near-token/module-context.ts b/src/entities/near-token/module-context.ts index 7202517a..ee43bc90 100644 --- a/src/entities/near-token/module-context.ts +++ b/src/entities/near-token/module-context.ts @@ -1,3 +1,4 @@ export class ModuleContext { - static FRACTIONAL_PART_LENGTH = 5; + public static readonly DECIMALS = 24; + public static readonly FRACTIONAL_PART_LENGTH = 5; } diff --git a/src/entities/near-token/ui/near-token.balances.tsx b/src/entities/near-token/ui/near-token.balances.tsx index 6f8be33a..e79c10c0 100644 --- a/src/entities/near-token/ui/near-token.balances.tsx +++ b/src/entities/near-token/ui/near-token.balances.tsx @@ -1,9 +1,8 @@ import { useContext } from "react"; -import { formatTokenAmount } from "../../../shared/lib/converter"; import { IconLabel, NearIcon } from "../../../shared/ui/design"; +import { NEARTokenFormat } from "../lib/near-token.format"; import { NEARTokenModel } from "../model/near-token.model"; -import { ModuleContext } from "../module-context"; export const nearTokenBalancesRender = () => { const { data } = useContext(NEARTokenModel.BalancesContext); @@ -17,9 +16,9 @@ export const nearTokenBalancesRender = () => { label="NEAR" />, - formatTokenAmount(data.multicallInstance, 24, ModuleContext.FRACTIONAL_PART_LENGTH), - formatTokenAmount(data.account, 24, ModuleContext.FRACTIONAL_PART_LENGTH), - formatTokenAmount(data.total, 24, ModuleContext.FRACTIONAL_PART_LENGTH), + NEARTokenFormat.amountToDisplayAmount(data.multicallInstance), + NEARTokenFormat.amountToDisplayAmount(data.account), + NEARTokenFormat.amountToDisplayAmount(data.total), ], id: "NEAR", From 86ddad835915381303563cea06b3e320cfb6d0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 19 Dec 2022 02:48:31 +0400 Subject: [PATCH 464/537] wip: Remove redundant code & Use proper error handling --- .../ui/manage-scheduling-settings.ui.tsx | 6 ++ src/pages/dao/dao.tsx | 90 ++++++------------- 2 files changed, 34 insertions(+), 62 deletions(-) diff --git a/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx index 155669e7..9ca4e8b1 100644 --- a/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx +++ b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx @@ -23,6 +23,11 @@ interface ManageScheduleSettingsUIProps extends Omit, export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: ManageScheduleSettingsUIProps) => { const multicallInstance = useContext(MulticallInstance.Context); + const error = + multicallInstance.data.ready && multicallInstance.data.jobBond === "" + ? new Error("Error while getting Multicall Instance job bond") + : null; + const [editModeEnabled, editModeSwitch] = useState(false); const formInitialState: FormState = { @@ -109,6 +114,7 @@ export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: Man ), }} + {...{ error }} >
    { const addr = STORAGE.addresses.dao; this.state = { - formData: { - addr, - }, - + formData: { addr }, dao: new SputnikDAO(addr), - multicallInstance: new Multicall(Multicall.getInstanceAddress(addr)), loading: false, proposed: -1, proposedInfo: null, @@ -150,10 +145,6 @@ export class DaoPage extends Component { onAddressesUpdated(e: CustomEvent<{ dao: string }>) { if (e.detail.dao !== this.state.formData.addr) { - this.setState({ - multicallInstance: new Multicall(Multicall.getInstanceAddress(e.detail.dao)), - }); - this.formikSetValues?.({ addr: e.detail.dao }); } } @@ -171,8 +162,6 @@ export class DaoPage extends Component { return null; } - const multicallAddress = Multicall.getInstanceAddress(formData.addr); - const depo = Big(this.fee).plus(MulticallInstance.MIN_BALANCE); /** @@ -187,7 +176,7 @@ export class DaoPage extends Component { const args = { proposal: { - description: `create multicall instance for this DAO at ${multicallAddress}`, + description: `create multicall instance for this DAO at ${Multicall.getInstanceAddress(formData.addr)}`, kind: { FunctionCall: { receiver_id: Multicall.FACTORY_ADDRESS, @@ -359,29 +348,22 @@ export class DaoPage extends Component { confidentlyLoadOnlyDaoInfo() { const { addr } = this.state.formData; - const multicallAddress = Multicall.getInstanceAddress(addr); - this.setState({ loading: true }); // initialize DAO object SputnikDAO.init(addr) .catch((e) => new SputnikDAO(addr)) - .then((newDao) => { + .then((dao) => { // some error happened during DAO object init. - if (!newDao.ready) { - this.setState({ - dao: newDao, - multicallInstance: new Multicall(multicallAddress), - loading: false, - }); + if (!dao.ready) { + this.setState({ dao, loading: false }); return; } else { - this.proposalAlreadyExists(newDao) + this.proposalAlreadyExists(dao) .catch((e) => {}) .then((proposalData) => this.setState({ - dao: newDao, - multicallInstance: new Multicall(multicallAddress), + dao, loading: false, proposed: proposalData?.proposal_id ?? -1, proposedInfo: (proposalData?.proposal_info as ProposalOutput) ?? null, @@ -394,35 +376,27 @@ export class DaoPage extends Component { confidentlyLoadInfo() { const { addr: daoAddress } = this.state.formData; - const multicallAddress = Multicall.getInstanceAddress(daoAddress); - this.setState({ loading: true }); - Promise.all([ - SputnikDAO.init(daoAddress).catch((e) => new SputnikDAO(daoAddress)), - Multicall.init(multicallAddress).catch((e) => new Multicall(multicallAddress)), - ]).then(([newDao, multicallInstance]) => { - // some error happened during DAO object init. - if (!newDao.ready || !multicallInstance.ready) { - this.setState({ - dao: newDao, - multicallInstance, - loading: false, - }); - } else { - this.proposalAlreadyExists(newDao) - .catch((e) => {}) - .then((proposalData) => - this.setState({ - dao: newDao, - multicallInstance, - loading: false, - proposed: proposalData?.proposal_id ?? -1, - proposedInfo: (proposalData?.proposal_info as ProposalOutput) ?? null, - }) - ); - } - }); + SputnikDAO.init(daoAddress) + .catch((e) => new SputnikDAO(daoAddress)) + .then((dao) => { + // some error happened during DAO object init. + if (!dao.ready) { + this.setState({ dao, loading: false }); + } else { + this.proposalAlreadyExists(dao) + .catch((e) => {}) + .then((proposalData) => + this.setState({ + dao, + loading: false, + proposed: proposalData?.proposal_id ?? -1, + proposedInfo: (proposalData?.proposal_info as ProposalOutput) ?? null, + }) + ); + } + }); } componentDidMount(): void { @@ -432,7 +406,6 @@ export class DaoPage extends Component { render() { const { selector: walletSelector } = this.context!; - const { dao, multicallInstance } = this.state; // if user not logged in, remind them to sign in. // TODO: only require signIn when DAO has no multicall instance (to know if user can propose or vote on existing proposal to create multicall) @@ -468,13 +441,6 @@ export class DaoPage extends Component { ); - /* - * Everything should be loaded - */ - if (!multicallInstance.admins || !multicallInstance.tokensWhitelist || !multicallInstance.jobBond) { - console.error("Unexpected error! Multicall might be outdated."); - } - return (
    @@ -514,8 +480,8 @@ export class DaoPage extends Component { contentSpace: `${_DaoPage}-tabs-contentSpace`, }} items={[ - DaoSettingsTab.render({ className: `${_DaoPage}-content`, dao }), - DaoFundsTab.render({ accountId: dao.address, className: `${_DaoPage}-content` }), + DaoSettingsTab.render({ className: `${_DaoPage}-content`, dao: this.state.dao }), + DaoFundsTab.render({ accountId: this.state.dao.address, className: `${_DaoPage}-content` }), DaoJobsTab.render({ className: `${_DaoPage}-content` }), ]} /> From 75a55f4908ef06f4a8d969084a2517f16ca4219f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 19 Dec 2022 02:55:51 +0400 Subject: [PATCH 465/537] wip: Construct MI address using adapter's method --- .../multicall-instance/model/multicall-instance.model.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/entities/multicall-instance/model/multicall-instance.model.ts b/src/entities/multicall-instance/model/multicall-instance.model.ts index ace56e83..01a3db19 100644 --- a/src/entities/multicall-instance/model/multicall-instance.model.ts +++ b/src/entities/multicall-instance/model/multicall-instance.model.ts @@ -1,6 +1,5 @@ import { createContext, useEffect, useState } from "react"; -import { ArgsAccount } from "../../../shared/lib/args-old"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; @@ -33,9 +32,7 @@ export class MIModel { callback: (result: typeof MIModel.properties) => void ) => callback( - await Multicall.init( - `${ArgsAccount.deconstructAddress(daoAddress).name}.${Multicall.FACTORY_ADDRESS}` - ).then((multicallInstance) => ({ + await Multicall.init(Multicall.getInstanceAddress(daoAddress)).then((multicallInstance) => ({ data: multicallInstance, error: multicallInstance.ready ? null : new Error("Unable to connect to Multicall Instance"), loading: false, From c7512464a1083cd936203b23641fae570f3f7204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 19 Dec 2022 03:20:13 +0400 Subject: [PATCH 466/537] wip: Apply code review remarks --- .../multicall-instance/module-context.ts | 28 ++++++++++++++++--- .../manage-scheduling-settings/index.ts | 3 +- .../module-context.ts | 18 ------------ .../ui/manage-scheduling-settings.ui.tsx | 23 +++++++-------- .../manage-whitelisted-tokens/index.ts | 3 +- .../module-context.ts | 18 ------------ .../ui/manage-whitelisted-tokens.ui.tsx | 5 ++-- src/features/propose-settings/index.ts | 3 +- .../propose-settings/module-context.ts | 1 - .../ui/propose-settings.ui.tsx | 24 +++++++++------- src/widgets/settings-editor/module-context.ts | 13 --------- .../settings-editor/ui/settings-editor.ui.tsx | 19 +++++++------ 12 files changed, 64 insertions(+), 94 deletions(-) delete mode 100644 src/features/manage-scheduling-settings/module-context.ts delete mode 100644 src/features/manage-whitelisted-tokens/module-context.ts delete mode 100644 src/features/propose-settings/module-context.ts delete mode 100644 src/widgets/settings-editor/module-context.ts diff --git a/src/entities/multicall-instance/module-context.ts b/src/entities/multicall-instance/module-context.ts index 5d62ff5e..730e168e 100644 --- a/src/entities/multicall-instance/module-context.ts +++ b/src/entities/multicall-instance/module-context.ts @@ -1,9 +1,7 @@ -import { MulticallPropertyKey } from "../../shared/lib/contracts/multicall"; +import { MulticallPropertyKey, MulticallTokenWhitelistDiffKey } from "../../shared/lib/contracts/multicall"; import { toYocto } from "../../shared/lib/converter"; +import { Color } from "../../shared/ui/design"; -/** - * Multicall Instance entity context. - */ export class ModuleContext { public static readonly ParamKey = MulticallPropertyKey; @@ -11,4 +9,26 @@ export class ModuleContext { * Minimum balance needed for storage + state. */ public static readonly MIN_BALANCE = toYocto(1); + + public static readonly SettingsDiffMeta = { + [MulticallPropertyKey.croncatManager]: { + color: "blue" as Color, + description: "Croncat manager", + }, + + [MulticallPropertyKey.jobBond]: { + color: "blue" as Color, + description: "Job bond", + }, + + [MulticallTokenWhitelistDiffKey.addTokens]: { + color: "green" as Color, + description: "Tokens to add to whitelist", + }, + + [MulticallTokenWhitelistDiffKey.removeTokens]: { + color: "red" as Color, + description: "Tokens to remove from whitelist", + }, + }; } diff --git a/src/features/manage-scheduling-settings/index.ts b/src/features/manage-scheduling-settings/index.ts index fab3e4ed..7918bc46 100644 --- a/src/features/manage-scheduling-settings/index.ts +++ b/src/features/manage-scheduling-settings/index.ts @@ -1,6 +1,5 @@ -import { ModuleContext } from "./module-context"; import { ManageScheduleSettingsUI } from "./ui/manage-scheduling-settings.ui"; -export class ManageScheduleSettings extends ModuleContext { +export class ManageScheduleSettings { public static readonly UI = ManageScheduleSettingsUI; } diff --git a/src/features/manage-scheduling-settings/module-context.ts b/src/features/manage-scheduling-settings/module-context.ts deleted file mode 100644 index 7c50da57..00000000 --- a/src/features/manage-scheduling-settings/module-context.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { MulticallInstance } from "../../entities"; -import { Color } from "../../shared/ui/design"; - -export class ModuleContext { - public static readonly DiffKey = MulticallInstance.ParamKey; - - public static readonly DiffMeta = { - [ModuleContext.DiffKey.croncatManager]: { - color: "blue" as Color, - description: "Croncat manager", - }, - - [ModuleContext.DiffKey.jobBond]: { - color: "blue" as Color, - description: "Job bond", - }, - }; -} diff --git a/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx index 9ca4e8b1..28ee81b3 100644 --- a/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx +++ b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx @@ -2,12 +2,11 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-mat import { IconButton, TextField, TextFieldProps } from "@mui/material"; import { HTMLProps, useCallback, useContext, useEffect, useMemo, useState } from "react"; -import { MulticallInstance } from "../../../entities"; -import { ArgsString } from "../../../shared/lib/args-old"; import { MulticallSettingsChange, MulticallPropertyKey } from "../../../shared/lib/contracts/multicall"; +import { ArgsString } from "../../../shared/lib/args-old"; import { toNEAR, toYocto } from "../../../shared/lib/converter"; import { IconLabel, NearIcon, NearLink, Table, Tile, Tooltip } from "../../../shared/ui/design"; -import { ModuleContext } from "../module-context"; +import { MulticallInstance } from "../../../entities"; import "./manage-scheduling-settings.ui.scss"; @@ -31,8 +30,8 @@ export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: Man const [editModeEnabled, editModeSwitch] = useState(false); const formInitialState: FormState = { - [ModuleContext.DiffKey.croncatManager]: "", - [ModuleContext.DiffKey.jobBond]: "", + [MulticallPropertyKey.croncatManager]: "", + [MulticallPropertyKey.jobBond]: "", }; const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ @@ -121,10 +120,8 @@ export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: Man centeredTitle: true, idToHighlightColor: (id) => - ({ croncatManager, jobBond }[id] === - formInitialState[id as keyof typeof ModuleContext["DiffKey"]] || - { croncatManager, jobBond }[id] === - multicallInstance.data[id as keyof typeof ModuleContext["DiffKey"]] + ({ croncatManager, jobBond }[id] === formInitialState[id as MulticallPropertyKey] || + { croncatManager, jobBond }[id] === multicallInstance.data[id as MulticallPropertyKey] ? null : "blue"), @@ -136,10 +133,10 @@ export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: Man header={["Option", "Value"]} rows={[ { - id: ModuleContext.DiffKey.croncatManager, + id: MulticallPropertyKey.croncatManager, content: [ - ModuleContext.DiffMeta[ModuleContext.DiffKey.croncatManager].description, + MulticallInstance.SettingsDiffMeta[MulticallPropertyKey.croncatManager].description, editModeEnabled ? ( - (addTokens.has(id) && ModuleContext.DiffMeta.addTokens.color) || - (removeTokens.has(id) && ModuleContext.DiffMeta.removeTokens.color) || + (addTokens.has(id) && MulticallInstance.SettingsDiffMeta.addTokens.color) || + (removeTokens.has(id) && MulticallInstance.SettingsDiffMeta.removeTokens.color) || null, slots: { diff --git a/src/features/propose-settings/index.ts b/src/features/propose-settings/index.ts index f7e72aa7..85f03d09 100644 --- a/src/features/propose-settings/index.ts +++ b/src/features/propose-settings/index.ts @@ -1,6 +1,5 @@ -import { ModuleContext } from "./module-context"; import { ProposeSettingsUI } from "./ui/propose-settings.ui"; -export class ProposeSettings extends ModuleContext { +export class ProposeSettings { public static readonly UI = ProposeSettingsUI; } diff --git a/src/features/propose-settings/module-context.ts b/src/features/propose-settings/module-context.ts deleted file mode 100644 index 0c13d485..00000000 --- a/src/features/propose-settings/module-context.ts +++ /dev/null @@ -1 +0,0 @@ -export class ModuleContext {} diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index 34367dcf..03a4a6dd 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -3,13 +3,17 @@ import { FormEventHandler, HTMLProps, useCallback, useContext, useMemo, useState import { MulticallInstance } from "../../../entities"; import { ArgsString } from "../../../shared/lib/args-old"; -import { Multicall, MulticallSettingsChange } from "../../../shared/lib/contracts/multicall"; +import { + Multicall, + MulticallPropertyKey, + MulticallSettingsChange, + MulticallTokenWhitelistDiffKey, +} from "../../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { toNEAR } from "../../../shared/lib/converter"; import { signAndSendTxs } from "../../../shared/lib/wallet"; import { Button, ButtonGroup, NearIcon, TextInput, Tile } from "../../../shared/ui/design"; -import { ModuleContext } from "../../../widgets/settings-editor/module-context"; import "./propose-settings.ui.scss"; const _ProposeSettings = "ProposeSettings"; @@ -65,19 +69,19 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, ..

    - {Object.values(ModuleContext.DiffKey).map( - (DiffKey) => - diff[DiffKey].length > 0 && ( + {Object.values({ ...MulticallPropertyKey, ...MulticallTokenWhitelistDiffKey }).map( + (diffKey) => + diff[diffKey].length > 0 && (

    - {ModuleContext.DiffMeta[DiffKey].description + ":"} + {MulticallInstance.SettingsDiffMeta[diffKey].description + ":"}

    - - )} + + {(nearTokenBalances ?? fungibleTokenBalances) && ( + +
    + + )} - {(!nearTokenBalances || !fungibleTokenBalances) &&
    } - - - + {(!nearTokenBalances || !fungibleTokenBalances) &&
    } + ); }; From ccc2c24f52ce06872a4e0a7f3302240d67a458fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 19 Dec 2022 23:28:35 +0400 Subject: [PATCH 471/537] wip: Encapsulate providers into Balances widget --- src/pages/dao/funds/funds.tsx | 30 +++++++++---------------- src/widgets/balances/index.ts | 1 - src/widgets/balances/index.tsx | 17 ++++++++++++++ src/widgets/balances/ui/balances.ui.tsx | 5 ++--- 4 files changed, 30 insertions(+), 23 deletions(-) delete mode 100644 src/widgets/balances/index.ts create mode 100644 src/widgets/balances/index.tsx diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index f5a7d83e..12deae91 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -1,36 +1,28 @@ import clsx from "clsx"; -import { ComponentProps, HTMLProps } from "react"; +import { HTMLProps } from "react"; -import { FT, NEARToken } from "../../../entities"; -import { Balances } from "../../../widgets"; +import { Balances, BalancesProps } from "../../../widgets"; import "./funds.scss"; const _DAOFundsTab = "DAOFundsTab"; -interface DAOFundsTabProps - extends HTMLProps, - ComponentProps, - ComponentProps { - className?: string; -} +interface DAOFundsTabProps extends HTMLProps, BalancesProps {} -const DAOFundsTabContent = ({ className, accountId, ...props }: DAOFundsTabProps) => ( - - +export const DAOFundsTab = { + render: ({ className, accountId, ...props }: DAOFundsTabProps) => ({ + content: (
    - +
    -
    -
    -); + ), -export const DAOFundsTab = { - render: (props: DAOFundsTabProps) => ({ - content: , lazy: true, name: "Funds", }), diff --git a/src/widgets/balances/index.ts b/src/widgets/balances/index.ts deleted file mode 100644 index 79cee002..00000000 --- a/src/widgets/balances/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { Balances, type BalancesProps } from "./ui/balances.ui"; diff --git a/src/widgets/balances/index.tsx b/src/widgets/balances/index.tsx new file mode 100644 index 00000000..13b10e1c --- /dev/null +++ b/src/widgets/balances/index.tsx @@ -0,0 +1,17 @@ +import { ComponentProps } from "react"; + +import { FT, NEARToken } from "../../entities"; +import { BalancesUI, BalancesUIProps } from "./ui/balances.ui"; + +export interface BalancesProps + extends ComponentProps, + ComponentProps, + BalancesUIProps {} + +export const Balances = ({ accountId, ...props }: BalancesProps) => ( + + + + + +); diff --git a/src/widgets/balances/ui/balances.ui.tsx b/src/widgets/balances/ui/balances.ui.tsx index b5a95816..aa2dad6e 100644 --- a/src/widgets/balances/ui/balances.ui.tsx +++ b/src/widgets/balances/ui/balances.ui.tsx @@ -1,5 +1,4 @@ import clsx from "clsx"; -import { ComponentProps } from "react"; import { Tile, Scrollable, Table } from "../../../shared/ui/design"; import { FT, NEARToken } from "../../../entities"; @@ -8,12 +7,12 @@ import "./balances.ui.scss"; const _Balances = "Balances"; -export interface BalancesProps { +export interface BalancesUIProps { accountName: string; className?: string; } -export const Balances = ({ className, accountName }: BalancesProps) => { +export const BalancesUI = ({ className, accountName }: BalancesUIProps) => { const nearTokenBalances = NEARToken.balancesRender(), fungibleTokenBalances = FT.balancesRender({ nonZeroOnly: true }); From 18785dadad867cdc0a40edb5ed389ab8f55d5748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 19 Dec 2022 23:29:13 +0400 Subject: [PATCH 472/537] chore: Format --- src/widgets/balances/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/balances/index.tsx b/src/widgets/balances/index.tsx index 13b10e1c..85c87e9f 100644 --- a/src/widgets/balances/index.tsx +++ b/src/widgets/balances/index.tsx @@ -1,6 +1,7 @@ import { ComponentProps } from "react"; import { FT, NEARToken } from "../../entities"; + import { BalancesUI, BalancesUIProps } from "./ui/balances.ui"; export interface BalancesProps From 127121bdbf774eeeed158ba5317a986ca85d4a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 19 Dec 2022 23:49:55 +0400 Subject: [PATCH 473/537] wip: Fix error on job bond editing --- .../ui/manage-scheduling-settings.ui.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx index 1c28af75..43c32603 100644 --- a/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx +++ b/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx @@ -55,7 +55,7 @@ export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: Man value !== multicallInstance.data.croncatManager ? value : formInitialState.croncatManager ), - [croncatManagerUpdate] + [croncatManagerUpdate, multicallInstance.data] ); const onJobBondChange = useCallback["onChange"]>( @@ -64,7 +64,7 @@ export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: Man value !== toNEAR(multicallInstance.data.jobBond) ? toYocto(value) : formInitialState.jobBond ), - [jobBondUpdate] + [jobBondUpdate, multicallInstance.data] ); const formReset = useCallback(() => { From cccdceb18b19c35f7888faadeb60a119319cd368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 21 Dec 2022 22:40:16 +0400 Subject: [PATCH 474/537] chore: Fix TS error --- src/pages/dao/funds/funds.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/dao/funds/funds.tsx b/src/pages/dao/funds/funds.tsx index 12deae91..b0c77716 100644 --- a/src/pages/dao/funds/funds.tsx +++ b/src/pages/dao/funds/funds.tsx @@ -7,7 +7,7 @@ import "./funds.scss"; const _DAOFundsTab = "DAOFundsTab"; -interface DAOFundsTabProps extends HTMLProps, BalancesProps {} +interface DAOFundsTabProps extends HTMLProps, Omit {} export const DAOFundsTab = { render: ({ className, accountId, ...props }: DAOFundsTabProps) => ({ From fdd17578e96018381b23ba2a3bab17a90574232a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 25 Dec 2022 22:03:12 +0400 Subject: [PATCH 475/537] chore: Move typings to dev dependencies --- package.json | 6 +++--- yarn.lock | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 7961759f..426c5c4f 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,8 @@ "@parcel/transformer-sass": "^2.4.1", "@types/big.js": "^6.1.5", "@types/lodash.debounce": "^4.0.7", + "@types/luxon": "^3.0.1", + "@types/react": "^18.0.0", "@types/react-dom": "^18.0.6", "@typescript-eslint/parser": "^5.36.1", "babel-jest": "^28.0.2", @@ -72,12 +74,10 @@ "@near-wallet-selector/my-near-wallet": "^5.0.0", "@near-wallet-selector/near-wallet": "^5.0.0", "@near-wallet-selector/sender": "^5.0.0", - "@types/luxon": "^3.0.1", - "@types/react": "^18.0.0", "big.js": "^6.2.1", "clsx": "^1.2.1", - "formik": "^2.2.9", "cron-parser": "^4.6.0", + "formik": "^2.2.9", "js-base64": "^3.7.2", "lodash.debounce": "^4.0.8", "luxon": "^3.0.4", diff --git a/yarn.lock b/yarn.lock index 7d8e97aa..1c6609de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8865,4 +8865,3 @@ yup@^0.32.11: nanoclone "^0.2.1" property-expr "^2.0.4" toposort "^2.0.2" - \ No newline at end of file From de0424ca6f27be783c718f991c257b755a050214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 26 Dec 2022 22:23:16 +0400 Subject: [PATCH 476/537] feat: Implement validation for settings proposal --- .../ui/propose-settings.ui.tsx | 115 ++++++++++-------- 1 file changed, 63 insertions(+), 52 deletions(-) diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index 6f56debe..305e9167 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -1,8 +1,9 @@ import clsx from "clsx"; -import { FormEventHandler, HTMLProps, useCallback, useContext, useMemo, useState } from "react"; +import { Form, Formik, FormikHelpers } from "formik"; +import { HTMLProps, useCallback, useContext } from "react"; +import { InferType } from "yup"; -import { MulticallInstance } from "../../../entities"; -import { ArgsString } from "../../../shared/lib/args-old"; +import { args } from "../../../shared/lib/args/args"; import { Multicall, MulticallPropertyKey, @@ -12,7 +13,9 @@ import { import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { toNEAR } from "../../../shared/lib/converter"; import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { Button, ButtonGroup, NEARIcon, TextInput, Tile } from "../../../shared/ui/design"; +import { Button, ButtonGroup, NEARIcon, Tile } from "../../../shared/ui/design"; +import { TextField } from "../../../shared/ui/form"; +import { MulticallInstance } from "../../../entities"; import "./propose-settings.ui.scss"; @@ -25,23 +28,32 @@ export interface ProposeSettingsUIProps extends HTMLProps { onCancel: VoidFunction; } -export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, ...props }: ProposeSettingsUIProps) => { +export const ProposeSettingsUI = ({ + className, + dao, + diff, + disabled, + editMode, + onCancel, + ...props +}: ProposeSettingsUIProps) => { const multicallInstance = useContext(MulticallInstance.Context); - const formValues = { description: useMemo(() => new ArgsString(""), []) }, - [description, descriptionUpdate] = useState(formValues.description.value); - - const onCancel = useCallback(() => { - void props.onCancel(); - void descriptionUpdate(""); + const schema = args.object().shape({ + description: args.string().default("").required("Proposal description is required"), + }); - formValues.description.value = ""; - }, [props.onCancel, descriptionUpdate]); + const onReset = useCallback( + (_values: InferType, { setValues }: FormikHelpers>) => { + void setValues(schema.getDefault()); + void onCancel(); + }, - const onSubmit = useCallback( - (event) => { - void event.preventDefault(); + [onCancel] + ); + const onSubmit = useCallback( + ({ description }: InferType) => void dao .proposeFunctionCall( description, @@ -49,10 +61,9 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, .. Multicall.configDiffToProposalActions(diff) ) .then((someTx) => signAndSendTxs([someTx])) - .catch(console.error); - }, + .catch(console.error), - [dao, diff, description] + [dao, diff] ); return ( @@ -105,39 +116,39 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, .. )}
    -
    -
    - void descriptionUpdate(event.target.value)} - value={formValues.description} - /> -
    - - -
    - - )} - - {(!nearTokenBalances || !fungibleTokenBalances) &&
    } - - ); -}; diff --git a/src/widgets/balances/index.tsx b/src/widgets/funds-overview/index.tsx similarity index 58% rename from src/widgets/balances/index.tsx rename to src/widgets/funds-overview/index.tsx index 85c87e9f..565ee8b6 100644 --- a/src/widgets/balances/index.tsx +++ b/src/widgets/funds-overview/index.tsx @@ -2,17 +2,17 @@ import { ComponentProps } from "react"; import { FT, NEARToken } from "../../entities"; -import { BalancesUI, BalancesUIProps } from "./ui/balances.ui"; +import { FundsOverviewUI, FundsOverviewUIProps } from "./ui/funds-overview.ui"; -export interface BalancesProps +export interface FundsOverviewProps extends ComponentProps, ComponentProps, - BalancesUIProps {} + FundsOverviewUIProps {} -export const Balances = ({ accountId, ...props }: BalancesProps) => ( +export const FundsOverview = ({ accountId, ...props }: FundsOverviewProps) => ( - + ); diff --git a/src/widgets/funds-overview/ui/funds-overview.ui.scss b/src/widgets/funds-overview/ui/funds-overview.ui.scss new file mode 100644 index 00000000..765c399e --- /dev/null +++ b/src/widgets/funds-overview/ui/funds-overview.ui.scss @@ -0,0 +1,20 @@ +@use "sass/font"; + +.FundsOverview { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr; + grid-template-areas: "FundsOverview"; + + &-content { + grid-area: FundsOverview; + + .TableRow-content--compact { + &:not(&:first-of-type) { + span:last-of-type { + font-family: font.$code; + } + } + } + } +} diff --git a/src/widgets/funds-overview/ui/funds-overview.ui.tsx b/src/widgets/funds-overview/ui/funds-overview.ui.tsx new file mode 100644 index 00000000..89200994 --- /dev/null +++ b/src/widgets/funds-overview/ui/funds-overview.ui.tsx @@ -0,0 +1,39 @@ +import clsx from "clsx"; + +import { Tile, Scrollable, Table } from "../../../shared/ui/design"; +import { FT, NEARToken } from "../../../entities"; + +import "./funds-overview.ui.scss"; + +const _FundsOverview = "FundsOverview"; + +export interface FundsOverviewUIProps { + accountName: string; + className?: string; +} + +export const FundsOverviewUI = ({ className, accountName }: FundsOverviewUIProps) => { + const nearTokenBalances = NEARToken.balancesRender(), + fungibleTokenBalances = FT.balancesRender({ nonZeroOnly: true }); + + return ( +
    + + {(nearTokenBalances ?? fungibleTokenBalances) && ( + +
    + + )} + + {(!nearTokenBalances || !fungibleTokenBalances) &&
    } + +
    + ); +}; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index b07ce110..89831baf 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -1,9 +1,10 @@ +export { Builder } from "./builder/builder.jsx"; export { Column } from "./column/column.jsx"; -export { Balances, type BalancesProps } from "./balances"; export { DialogsLayer } from "./dialogs-layer"; -export { Menu } from "./menu/menu.jsx"; -export { Builder } from "./builder/builder.jsx"; export { Editor } from "./editor/editor.jsx"; export { Export } from "./export"; -export { SettingsEditor, type SettingsEditorProps } from "./settings-editor"; +export { FundsOverview, type FundsOverviewProps } from "./funds-overview"; +export { Menu } from "./menu/menu.jsx"; +export { MulticallScheduleOverview, type MulticallScheduleOverviewProps } from "./multicall-schedule-overview"; +export { MulticallSettingsManager, type MulticallSettingsManagerProps } from "./multicall-settings-manager"; export { Sidebar } from "./sidebar/sidebar.jsx"; diff --git a/src/widgets/menu/menu.jsx b/src/widgets/menu/menu.jsx index df64dafa..2e2311cc 100644 --- a/src/widgets/menu/menu.jsx +++ b/src/widgets/menu/menu.jsx @@ -47,7 +47,7 @@ export class Menu extends Component { items={[ { name: "Build", - content: ( + ui: ( , + ui: , }, { name: "Export", - content: , + ui: , }, ]} /> diff --git a/src/widgets/multicall-schedule-overview/index.tsx b/src/widgets/multicall-schedule-overview/index.tsx new file mode 100644 index 00000000..349f4299 --- /dev/null +++ b/src/widgets/multicall-schedule-overview/index.tsx @@ -0,0 +1,15 @@ +import { ComponentProps } from "react"; + +import { MulticallInstance } from "../../entities"; + +import { MulticallScheduleOverviewUI, MulticallScheduleOverviewUIProps } from "./ui/multicall-schedule-overview.ui"; + +export interface MulticallScheduleOverviewProps extends MulticallScheduleOverviewUIProps { + accountId: ComponentProps["daoAddress"]; +} + +export const MulticallScheduleOverview = ({ accountId, ...props }: MulticallScheduleOverviewProps) => ( + + + +); diff --git a/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.scss b/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.scss new file mode 100644 index 00000000..a488993a --- /dev/null +++ b/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.scss @@ -0,0 +1,6 @@ +.MulticallScheduleOverview { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr; + grid-template-areas: "JobEntriesTable"; +} diff --git a/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.tsx b/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.tsx new file mode 100644 index 00000000..516ac870 --- /dev/null +++ b/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.tsx @@ -0,0 +1,23 @@ +import clsx from "clsx"; +import { HTMLProps, useContext } from "react"; + +import { Job, MulticallInstance } from "../../../entities"; + +import "./multicall-schedule-overview.ui.scss"; + +const _MulticallScheduleOverview = "MulticallScheduleOverview"; + +export interface MulticallScheduleOverviewUIProps extends HTMLProps {} + +export const MulticallScheduleOverviewUI = ({ className, ...props }: MulticallScheduleOverviewUIProps) => { + const multicallInstance = useContext(MulticallInstance.Context); + + return ( +
    + +
    + ); +}; diff --git a/src/widgets/multicall-settings-manager/index.tsx b/src/widgets/multicall-settings-manager/index.tsx new file mode 100644 index 00000000..ea3f3895 --- /dev/null +++ b/src/widgets/multicall-settings-manager/index.tsx @@ -0,0 +1,15 @@ +import { ComponentProps } from "react"; + +import { MulticallInstance } from "../../entities"; + +import { MulticallSettingsManagerUI, type MulticallSettingsManagerUIProps } from "./ui/multicall-settings-manager.ui"; + +export interface MulticallSettingsManagerProps extends MulticallSettingsManagerUIProps { + accountId: ComponentProps["daoAddress"]; +} + +export const MulticallSettingsManager = ({ accountId, ...props }: MulticallSettingsManagerProps) => ( + + + +); diff --git a/src/widgets/settings-editor/ui/settings-editor.ui.scss b/src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.scss similarity index 61% rename from src/widgets/settings-editor/ui/settings-editor.ui.scss rename to src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.scss index caa3a96e..4f0a7730 100644 --- a/src/widgets/settings-editor/ui/settings-editor.ui.scss +++ b/src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.scss @@ -1,25 +1,31 @@ +@use "sass/mixin"; @use "sass/size"; -.SettingsEditor { - grid-area: SettingsEditor; +.MulticallSettingsManager { + grid-area: MulticallSettingsManager; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: size.$gap; + margin: size.$gap !important; + border-radius: size.$task-radius; + padding: 0 !important; + overflow-y: scroll; height: 100%; + @include mixin.no-scrollbar; grid-template-areas: "ManageTokenWhitelist ManageScheduleSettings" "ManageTokenWhitelist ProposeSettings"; &-error { - grid-area: SettingsEditorError; + grid-area: MulticallSettingsError; } &.is-displayingError { grid-template-columns: 1fr; grid-template-rows: 1fr; - grid-template-areas: "SettingsEditorError"; + grid-template-areas: "MulticallSettingsError"; } &.is-displayingError > *:not(&-error) { diff --git a/src/widgets/settings-editor/ui/settings-editor.ui.tsx b/src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.tsx similarity index 80% rename from src/widgets/settings-editor/ui/settings-editor.ui.tsx rename to src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.tsx index 700b5201..7eaa074f 100644 --- a/src/widgets/settings-editor/ui/settings-editor.ui.tsx +++ b/src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.tsx @@ -11,15 +11,15 @@ import { Tile } from "../../../shared/ui/design"; import { MulticallInstance, Wallet } from "../../../entities"; import { ManageScheduleSettings, ManageTokenWhitelist, ProposeSettings } from "../../../features"; -import "./settings-editor.ui.scss"; +import "./multicall-settings-manager.ui.scss"; -const _SettingsEditor = "SettingsEditor"; +const _MulticallSettingsManager = "MulticallSettingsManager"; -export interface SettingsEditorProps extends HTMLProps { +export interface MulticallSettingsManagerUIProps extends HTMLProps { dao: SputnikDAO; } -export const SettingsEditor = ({ className, dao }: SettingsEditorProps) => { +export const MulticallSettingsManagerUI = ({ className, dao }: MulticallSettingsManagerUIProps) => { const wallet = useContext(Wallet.SelectorContext), multicallInstance = useContext(MulticallInstance.Context); @@ -69,16 +69,22 @@ export const SettingsEditor = ({ className, dao }: SettingsEditorProps) => { ); return ( -
    +
    - {false && } + {false && } diff --git a/src/widgets/settings-editor/index.ts b/src/widgets/settings-editor/index.ts deleted file mode 100644 index 3bc10977..00000000 --- a/src/widgets/settings-editor/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { SettingsEditor, type SettingsEditorProps } from "./ui/settings-editor.ui"; From 179abc5c40384352d66a18766be280a0432014af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 27 Dec 2022 02:42:11 +0400 Subject: [PATCH 480/537] chore: Remove unused setting example --- .vscode/settings.json.example | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json.example b/.vscode/settings.json.example index ab361244..9d8e0e8f 100644 --- a/.vscode/settings.json.example +++ b/.vscode/settings.json.example @@ -20,6 +20,5 @@ "[scss]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true - }, - "cSpell.words": ["mcce"] + } } From 2bfbe4aa16d8f9290161931f4fbc3a58770dfe21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Wed, 4 Jan 2023 19:36:39 +0400 Subject: [PATCH 481/537] wip: Fix textfield styles --- .../ui/propose-settings.ui.tsx | 1 + src/shared/ui/form/fields/text-field.scss | 50 +++++++++++++++++++ src/shared/ui/form/fields/text-field.tsx | 13 +++-- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index 4186a660..a49efcec 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -118,6 +118,7 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on
    span { font-size: 0.75em; visibility: hidden; } } + &:hover fieldset { border-color: color.$white; } + &.Mui-focused fieldset { border-color: color.$white; } + &.Mui-error fieldset { border-color: color.$red !important; } + &.MuiOutlinedInput-root.MuiInputBase-hiddenLabel legend { padding: 0; margin-top: 1px; } } + .MuiInput-underline { &:hover::before, &::before { border-bottom-color: color.$lightish; } + &:hover::after, &::after { border-bottom-color: color.$white; } + input { text-align: center; font-family: font.$text; font-weight: 500; + &:active, &:focus { text-align: left; } } } + *:not(.MuiOutlinedInput-input) { color: color.$light-text; font-size: 1em; } + font-size: size.$text; } } + + &--invertedColors &-input { + &.MuiTextField-root { + fieldset { + border-color: color.$darkish; + box-shadow: inset 0px 0px 30px 0px rgba(color.$black, 0.1); + + legend { + background-color: color.$white; + } + } + + label { + color: color.$black; + + .MuiFormLabel-asterisk { + color: color.$black; + } + } + + .MuiOutlinedInput-root { + .MuiOutlinedInput-input { + color: color.$black; + } + } + } + } + &.roundtop fieldset { border-top-left-radius: 0.75 * size.$task-radius !important; border-top-right-radius: 0.75 * size.$task-radius !important; } + &.roundbottom fieldset { border-bottom-left-radius: 0.75 * size.$task-radius !important; border-bottom-right-radius: 0.75 * size.$task-radius !important; diff --git a/src/shared/ui/form/fields/text-field.tsx b/src/shared/ui/form/fields/text-field.tsx index 4da1365e..5dbe346c 100644 --- a/src/shared/ui/form/fields/text-field.tsx +++ b/src/shared/ui/form/fields/text-field.tsx @@ -1,6 +1,7 @@ import { Autocomplete, TextField as MuiTextField, TextFieldProps as MuiTextFieldProps } from "@mui/material"; import clsx from "clsx"; import { useField } from "formik"; + import "./text-field.scss"; const _TextField = "TextField"; @@ -8,6 +9,7 @@ const _TextField = "TextField"; export type TextFieldProps = Partial & { name: string; autocomplete?: string[]; + invertedColors?: boolean; roundtop?: boolean; roundbottom?: boolean; className?: string; @@ -16,6 +18,7 @@ export type TextFieldProps = Partial & { export const TextField = ({ name, autocomplete, + invertedColors = false, roundtop, roundbottom, className, @@ -23,14 +26,12 @@ export const TextField = ({ ...props }: TextFieldProps) => { const [field, meta, helper] = useField(name); + return (
    @@ -40,9 +41,7 @@ export const TextField = ({ freeSolo fullWidth inputValue={field.value} - onInputChange={(e, value) => { - helper.setValue(value); - }} + onInputChange={(_event, value) => void helper.setValue(value)} renderInput={(params) => ( Date: Fri, 6 Jan 2023 02:49:17 +0400 Subject: [PATCH 482/537] feat: Add simple validation for token whitelisting --- .../lib/fungible-token.validation.ts | 2 + src/features/index.ts | 2 +- .../index.ts | 2 +- .../ui/manage-token-whitelist.ui.scss | 9 ++ .../ui/manage-token-whitelist.ui.tsx | 147 ++++++++++++++++++ .../ui/manage-whitelisted-tokens.ui.scss | 3 - .../ui/manage-whitelisted-tokens.ui.tsx | 139 ----------------- src/shared/ui/form/fields/text-field.scss | 10 +- 8 files changed, 166 insertions(+), 148 deletions(-) create mode 100644 src/entities/fungible-token/lib/fungible-token.validation.ts rename src/features/{manage-whitelisted-tokens => manage-token-whitelist}/index.ts (55%) create mode 100644 src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss create mode 100644 src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx delete mode 100644 src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.scss delete mode 100644 src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.tsx diff --git a/src/entities/fungible-token/lib/fungible-token.validation.ts b/src/entities/fungible-token/lib/fungible-token.validation.ts new file mode 100644 index 00000000..919e151f --- /dev/null +++ b/src/entities/fungible-token/lib/fungible-token.validation.ts @@ -0,0 +1,2 @@ +// silence TS +export {}; diff --git a/src/features/index.ts b/src/features/index.ts index fde1a217..301b9474 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,4 +1,4 @@ export { ExternalLogin } from "./external-login"; export { ManageScheduleSettings } from "./manage-scheduling-settings"; -export { ManageTokenWhitelist } from "./manage-whitelisted-tokens"; +export { ManageTokenWhitelist } from "./manage-token-whitelist"; export { ProposeSettings } from "./propose-settings"; diff --git a/src/features/manage-whitelisted-tokens/index.ts b/src/features/manage-token-whitelist/index.ts similarity index 55% rename from src/features/manage-whitelisted-tokens/index.ts rename to src/features/manage-token-whitelist/index.ts index 660031db..c47bdada 100644 --- a/src/features/manage-whitelisted-tokens/index.ts +++ b/src/features/manage-token-whitelist/index.ts @@ -1,4 +1,4 @@ -import { ManageTokenWhitelistUI } from "./ui/manage-whitelisted-tokens.ui"; +import { ManageTokenWhitelistUI } from "./ui/manage-token-whitelist.ui"; export class ManageTokenWhitelist { public static readonly UI = ManageTokenWhitelistUI; diff --git a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss new file mode 100644 index 00000000..974b021a --- /dev/null +++ b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss @@ -0,0 +1,9 @@ +.ManageTokenWhitelist { + grid-area: ManageTokenWhitelist; + display: flex; + flex-flow: column; + + &-table { + flex: auto; + } +} diff --git a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx new file mode 100644 index 00000000..e3bcadb1 --- /dev/null +++ b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx @@ -0,0 +1,147 @@ +import { CancelOutlined, DeleteOutlined, EditOutlined, SettingsBackupRestoreOutlined } from "@mui/icons-material"; +import { IconButton } from "@mui/material"; +import { Form, Formik, FormikHelpers } from "formik"; +import { HTMLProps, useCallback, useEffect, useState } from "react"; +import { InferType } from "yup"; + +import { args } from "../../../shared/lib/args/args"; +import { MulticallSettingsChange, MulticallTokenWhitelistDiffKey } from "../../../shared/lib/contracts/multicall"; +import { Tooltip } from "../../../shared/ui/design"; +import { TextField } from "../../../shared/ui/form"; +import { MulticallInstance } from "../../../entities"; + +import "./manage-token-whitelist.ui.scss"; +import { Props } from "../../../shared/lib/props"; + +const _ManageTokenWhitelist = "ManageTokenWhitelist"; + +type FormState = Pick; + +interface ManageTokenWhitelistUIProps extends Omit, "onChange"> { + onEdit: (payload: FormState) => void; + resetTrigger: { subscribe: (callback: EventListener) => () => void }; +} + +interface FormStates extends Record> {} + +export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: ManageTokenWhitelistUIProps) => { + const [editModeEnabled, editModeSwitch] = useState(false); + + const fungibleTokenSchema = args.object().shape({ + address: args.string().lowercase().address().default(""), + }); + + type FungibleTokenSchema = InferType; + + const [included, include] = useState(new Set()), + [discarded, discard] = useState(new Set()); + + const onSubmit = useCallback( + ({ address }: FungibleTokenSchema, { setTouched, setValues }: FormikHelpers) => { + if (discarded.has(address)) { + discard((addresses) => (addresses.delete(address) ? new Set(addresses) : addresses)); + } else { + include((addresses) => (address.length > 0 ? new Set(addresses.add(address)) : addresses)); + } + + setValues(fungibleTokenSchema.getDefault()); + setTouched({}); + }, + + [discard, discarded, include] + ); + + const onDiscard = useCallback( + ({ address }: FungibleTokenSchema) => { + if (included.has(address)) { + include((addresses) => (addresses.delete(address) ? new Set(addresses) : addresses)); + } else { + discard((addresses) => + addresses.delete(address) ? new Set(addresses) : new Set(addresses.add(address)) + ); + } + }, + + [discard, include, included] + ); + + const onReset = useCallback(() => { + include(new Set()); + discard(new Set()); + editModeSwitch(false); + }, [editModeSwitch, include, discard]); + + useEffect(() => resetTrigger.subscribe(onReset), [onReset, resetTrigger]); + + useEffect( + () => onEdit({ addTokens: Array.from(included), removeTokens: Array.from(discarded) }), + [discarded, included, onEdit] + ); + + return ( + + + + (included.has(id) && MulticallInstance.SettingsDiffMeta.addTokens.color) || + (discarded.has(id) && MulticallInstance.SettingsDiffMeta.removeTokens.color) || + null, + + slots: { + End: editModeEnabled + ? ({ rowId: address }) => ( + onDiscard({ address } as FungibleTokenSchema)}> + {discarded.has(address) ? ( + + ) : ( + + )} + + ) + : void null, + }, + }} + className={`${_ManageTokenWhitelist}-table`} + headerSlots={{ + end: editModeEnabled ? ( + + + + + + ) : ( + + + editModeSwitch(true)} + {...{ disabled }} + > + + + + + ), + }} + itemsAdditional={Array.from(included)} + subheader={ + editModeEnabled ? ( + + ) : ( + void null + ) + } + /> + + + ); +}; diff --git a/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.scss b/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.scss deleted file mode 100644 index ca70a36c..00000000 --- a/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.scss +++ /dev/null @@ -1,3 +0,0 @@ -.ManageTokenWhitelist { - grid-area: ManageTokenWhitelist; -} diff --git a/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.tsx b/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.tsx deleted file mode 100644 index 331a81cb..00000000 --- a/src/features/manage-whitelisted-tokens/ui/manage-whitelisted-tokens.ui.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { CancelOutlined, DeleteOutlined, EditOutlined, SettingsBackupRestoreOutlined } from "@mui/icons-material"; -import { IconButton } from "@mui/material"; -import { HTMLProps, useCallback, useEffect, useMemo, useState } from "react"; - -import { MulticallSettingsChange, MulticallTokenWhitelistDiffKey } from "../../../shared/lib/contracts/multicall"; -import { TextInput, Tooltip } from "../../../shared/ui/design"; -import { ArgsString } from "../../../shared/lib/args-old"; -import { MulticallInstance } from "../../../entities"; - -import "./manage-whitelisted-tokens.ui.scss"; - -const _ManageTokenWhitelist = "ManageTokenWhitelist"; - -type FormState = Pick; - -interface ManageTokenWhitelistUIProps extends Omit, "onChange"> { - onEdit: (payload: FormState) => void; - resetTrigger: { subscribe: (callback: EventListener) => () => void }; -} - -interface FormStates extends Record> {} - -export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: ManageTokenWhitelistUIProps) => { - const [editModeEnabled, editModeSwitch] = useState(false); - - const [addTokens, markForAddition] = useState(new Set()), - [removeTokens, markForRemoval] = useState(new Set()); - - const tokenToAddAddress = useMemo(() => new ArgsString(""), []); - - const onAdditionRequest = useCallback( - (input: string) => { - if (removeTokens.has(input)) { - void markForRemoval( - (markedForRemoval) => new Set(Array.from(markedForRemoval).filter((address) => address !== input)) - ); - } else { - void markForAddition((markedForAddition) => - input.length > 0 ? new Set(markedForAddition.add(input)) : markedForAddition - ); - } - - tokenToAddAddress.value = ""; - }, - - [markForAddition, markForRemoval, removeTokens] - ); - - const onRemovalRequest = useCallback( - (input: string) => { - if (addTokens.has(input)) { - void markForAddition( - (markedForAddition) => new Set(Array.from(markedForAddition).filter((address) => address !== input)) - ); - } else { - void markForRemoval((markedForRemoval) => new Set(markedForRemoval.add(input))); - } - }, - [addTokens, editModeSwitch, markForAddition, markForRemoval] - ); - - const formReset = useCallback(() => { - void markForAddition(new Set()); - void markForRemoval(new Set()); - void editModeSwitch(false); - }, [editModeSwitch, markForAddition, markForRemoval]); - - useEffect(() => resetTrigger.subscribe(formReset), [formReset, resetTrigger]); - - useEffect( - () => void onEdit({ addTokens: Array.from(addTokens), removeTokens: Array.from(removeTokens) }), - [addTokens, removeTokens, onEdit] - ); - - return ( - - (addTokens.has(id) && MulticallInstance.SettingsDiffMeta.addTokens.color) || - (removeTokens.has(id) && MulticallInstance.SettingsDiffMeta.removeTokens.color) || - null, - - slots: { - End: - (editModeEnabled && - (({ rowId }) => - removeTokens.has(rowId) ? ( - void onAdditionRequest(rowId)}> - - - ) : ( - void onRemovalRequest(rowId)}> - - - ))) || - void null, - }, - }} - className={_ManageTokenWhitelist} - headerSlots={{ - end: editModeEnabled ? ( - - - - - - ) : ( - - - void editModeSwitch(true)} - {...{ disabled }} - > - - - - - ), - }} - itemsAdditional={Array.from(addTokens)} - subheader={ - editModeEnabled ? ( - - void (key === "Enter" && Object.hasOwn(target, "value") - ? onAdditionRequest((target as HTMLInputElement).value) - : null) - } - value={tokenToAddAddress} - /> - ) : ( - void null - ) - } - /> - ); -}; diff --git a/src/shared/ui/form/fields/text-field.scss b/src/shared/ui/form/fields/text-field.scss index d297a3a9..89dc3ec3 100644 --- a/src/shared/ui/form/fields/text-field.scss +++ b/src/shared/ui/form/fields/text-field.scss @@ -72,14 +72,11 @@ } } + &.Mui-focused fieldset, &:hover fieldset { border-color: color.$white; } - &.Mui-focused fieldset { - border-color: color.$white; - } - &.Mui-error fieldset { border-color: color.$red !important; } @@ -145,6 +142,11 @@ .MuiOutlinedInput-input { color: color.$black; } + + &.Mui-focused fieldset, + &:hover fieldset { + border-color: color.$black; + } } } } From 6d166c8f5ff2c3e6df1f0b879f31c6fb1ba937a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 6 Jan 2023 03:03:56 +0400 Subject: [PATCH 483/537] chore: Use shorter names --- src/features/configure-scheduling/index.ts | 5 ++++ .../ui/configure-scheduling.ui.scss | 3 +++ .../ui/configure-scheduling.ui.tsx} | 10 +++---- src/features/index.ts | 2 +- .../manage-scheduling-settings/index.ts | 5 ---- .../ui/manage-scheduling-settings.ui.scss | 3 --- src/pages/dao/dao-page.ui.tsx | 6 ++--- src/widgets/index.ts | 4 +-- .../multicall-schedule-overview/index.tsx | 15 ----------- .../ui/multicall-schedule-overview.ui.tsx | 23 ---------------- .../multicall-settings-manager/index.tsx | 15 ----------- src/widgets/schedule-overview/index.tsx | 15 +++++++++++ .../ui/schedule-overview.ui.scss} | 2 +- .../ui/schedule-overview.ui.tsx | 23 ++++++++++++++++ src/widgets/settings-manager/index.tsx | 15 +++++++++++ .../ui/settings-manager.ui.scss} | 6 ++--- .../ui/settings-manager.ui.tsx} | 26 +++++++------------ 17 files changed, 86 insertions(+), 92 deletions(-) create mode 100644 src/features/configure-scheduling/index.ts create mode 100644 src/features/configure-scheduling/ui/configure-scheduling.ui.scss rename src/features/{manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx => configure-scheduling/ui/configure-scheduling.ui.tsx} (95%) delete mode 100644 src/features/manage-scheduling-settings/index.ts delete mode 100644 src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.scss delete mode 100644 src/widgets/multicall-schedule-overview/index.tsx delete mode 100644 src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.tsx delete mode 100644 src/widgets/multicall-settings-manager/index.tsx create mode 100644 src/widgets/schedule-overview/index.tsx rename src/widgets/{multicall-schedule-overview/ui/multicall-schedule-overview.ui.scss => schedule-overview/ui/schedule-overview.ui.scss} (81%) create mode 100644 src/widgets/schedule-overview/ui/schedule-overview.ui.tsx create mode 100644 src/widgets/settings-manager/index.tsx rename src/widgets/{multicall-settings-manager/ui/multicall-settings-manager.ui.scss => settings-manager/ui/settings-manager.ui.scss} (86%) rename src/widgets/{multicall-settings-manager/ui/multicall-settings-manager.ui.tsx => settings-manager/ui/settings-manager.ui.tsx} (77%) diff --git a/src/features/configure-scheduling/index.ts b/src/features/configure-scheduling/index.ts new file mode 100644 index 00000000..d7687473 --- /dev/null +++ b/src/features/configure-scheduling/index.ts @@ -0,0 +1,5 @@ +import { ConfigureSchedulingUI } from "./ui/configure-scheduling.ui"; + +export class ConfigureScheduling { + public static readonly UI = ConfigureSchedulingUI; +} diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.scss b/src/features/configure-scheduling/ui/configure-scheduling.ui.scss new file mode 100644 index 00000000..2070bbfe --- /dev/null +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.scss @@ -0,0 +1,3 @@ +.ConfigureScheduling { + grid-area: ConfigureScheduling; +} diff --git a/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx similarity index 95% rename from src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx rename to src/features/configure-scheduling/ui/configure-scheduling.ui.tsx index 43c32603..dca84585 100644 --- a/src/features/manage-scheduling-settings/ui/manage-scheduling-settings.ui.tsx +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx @@ -8,18 +8,18 @@ import { toNEAR, toYocto } from "../../../shared/lib/converter"; import { IconLabel, NEARIcon, NEARLink, Table, Tile, Tooltip } from "../../../shared/ui/design"; import { MulticallInstance } from "../../../entities"; -import "./manage-scheduling-settings.ui.scss"; +import "./configure-scheduling.ui.scss"; -const _ManageScheduleSettings = "ManageScheduleSettings"; +const _ConfigureScheduling = "ConfigureScheduling"; type FormState = Pick; -interface ManageScheduleSettingsUIProps extends Omit, "onChange"> { +interface ConfigureSchedulingUIProps extends Omit, "onChange"> { onEdit: (payload: FormState) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } -export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: ManageScheduleSettingsUIProps) => { +export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: ConfigureSchedulingUIProps) => { const multicallInstance = useContext(MulticallInstance.Context); const error = @@ -81,7 +81,7 @@ export const ManageScheduleSettingsUI = ({ disabled, onEdit, resetTrigger }: Man return ( { { name: "Settings", ui: ( - { lazy: true, name: "Jobs", ui: ( - diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 89831baf..f43a7de6 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -5,6 +5,6 @@ export { Editor } from "./editor/editor.jsx"; export { Export } from "./export"; export { FundsOverview, type FundsOverviewProps } from "./funds-overview"; export { Menu } from "./menu/menu.jsx"; -export { MulticallScheduleOverview, type MulticallScheduleOverviewProps } from "./multicall-schedule-overview"; -export { MulticallSettingsManager, type MulticallSettingsManagerProps } from "./multicall-settings-manager"; +export { ScheduleOverview, type ScheduleOverviewProps } from "./schedule-overview"; +export { SettingsManager, type SettingsManagerProps } from "./settings-manager"; export { Sidebar } from "./sidebar/sidebar.jsx"; diff --git a/src/widgets/multicall-schedule-overview/index.tsx b/src/widgets/multicall-schedule-overview/index.tsx deleted file mode 100644 index 349f4299..00000000 --- a/src/widgets/multicall-schedule-overview/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { ComponentProps } from "react"; - -import { MulticallInstance } from "../../entities"; - -import { MulticallScheduleOverviewUI, MulticallScheduleOverviewUIProps } from "./ui/multicall-schedule-overview.ui"; - -export interface MulticallScheduleOverviewProps extends MulticallScheduleOverviewUIProps { - accountId: ComponentProps["daoAddress"]; -} - -export const MulticallScheduleOverview = ({ accountId, ...props }: MulticallScheduleOverviewProps) => ( - - - -); diff --git a/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.tsx b/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.tsx deleted file mode 100644 index 516ac870..00000000 --- a/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import clsx from "clsx"; -import { HTMLProps, useContext } from "react"; - -import { Job, MulticallInstance } from "../../../entities"; - -import "./multicall-schedule-overview.ui.scss"; - -const _MulticallScheduleOverview = "MulticallScheduleOverview"; - -export interface MulticallScheduleOverviewUIProps extends HTMLProps {} - -export const MulticallScheduleOverviewUI = ({ className, ...props }: MulticallScheduleOverviewUIProps) => { - const multicallInstance = useContext(MulticallInstance.Context); - - return ( -
    - -
    - ); -}; diff --git a/src/widgets/multicall-settings-manager/index.tsx b/src/widgets/multicall-settings-manager/index.tsx deleted file mode 100644 index ea3f3895..00000000 --- a/src/widgets/multicall-settings-manager/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { ComponentProps } from "react"; - -import { MulticallInstance } from "../../entities"; - -import { MulticallSettingsManagerUI, type MulticallSettingsManagerUIProps } from "./ui/multicall-settings-manager.ui"; - -export interface MulticallSettingsManagerProps extends MulticallSettingsManagerUIProps { - accountId: ComponentProps["daoAddress"]; -} - -export const MulticallSettingsManager = ({ accountId, ...props }: MulticallSettingsManagerProps) => ( - - - -); diff --git a/src/widgets/schedule-overview/index.tsx b/src/widgets/schedule-overview/index.tsx new file mode 100644 index 00000000..5a4efffa --- /dev/null +++ b/src/widgets/schedule-overview/index.tsx @@ -0,0 +1,15 @@ +import { ComponentProps } from "react"; + +import { MulticallInstance } from "../../entities"; + +import { ScheduleOverviewUI, ScheduleOverviewUIProps } from "./ui/schedule-overview.ui"; + +export interface ScheduleOverviewProps extends ScheduleOverviewUIProps { + accountId: ComponentProps["daoAddress"]; +} + +export const ScheduleOverview = ({ accountId, ...props }: ScheduleOverviewProps) => ( + + + +); diff --git a/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.scss b/src/widgets/schedule-overview/ui/schedule-overview.ui.scss similarity index 81% rename from src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.scss rename to src/widgets/schedule-overview/ui/schedule-overview.ui.scss index a488993a..ff6aa099 100644 --- a/src/widgets/multicall-schedule-overview/ui/multicall-schedule-overview.ui.scss +++ b/src/widgets/schedule-overview/ui/schedule-overview.ui.scss @@ -1,4 +1,4 @@ -.MulticallScheduleOverview { +.ScheduleOverview { display: grid; grid-template-columns: 1fr; grid-template-rows: 1fr; diff --git a/src/widgets/schedule-overview/ui/schedule-overview.ui.tsx b/src/widgets/schedule-overview/ui/schedule-overview.ui.tsx new file mode 100644 index 00000000..e68326df --- /dev/null +++ b/src/widgets/schedule-overview/ui/schedule-overview.ui.tsx @@ -0,0 +1,23 @@ +import clsx from "clsx"; +import { HTMLProps, useContext } from "react"; + +import { Job, MulticallInstance } from "../../../entities"; + +import "./schedule-overview.ui.scss"; + +const _ScheduleOverview = "ScheduleOverview"; + +export interface ScheduleOverviewUIProps extends HTMLProps {} + +export const ScheduleOverviewUI = ({ className, ...props }: ScheduleOverviewUIProps) => { + const multicallInstance = useContext(MulticallInstance.Context); + + return ( +
    + +
    + ); +}; diff --git a/src/widgets/settings-manager/index.tsx b/src/widgets/settings-manager/index.tsx new file mode 100644 index 00000000..353cbed6 --- /dev/null +++ b/src/widgets/settings-manager/index.tsx @@ -0,0 +1,15 @@ +import { ComponentProps } from "react"; + +import { MulticallInstance } from "../../entities"; + +import { SettingsManagerUI, type SettingsManagerUIProps } from "./ui/settings-manager.ui"; + +export interface SettingsManagerProps extends SettingsManagerUIProps { + accountId: ComponentProps["daoAddress"]; +} + +export const SettingsManager = ({ accountId, ...props }: SettingsManagerProps) => ( + + + +); diff --git a/src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.scss b/src/widgets/settings-manager/ui/settings-manager.ui.scss similarity index 86% rename from src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.scss rename to src/widgets/settings-manager/ui/settings-manager.ui.scss index 4f0a7730..e7ecee6a 100644 --- a/src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.scss +++ b/src/widgets/settings-manager/ui/settings-manager.ui.scss @@ -1,8 +1,8 @@ @use "sass/mixin"; @use "sass/size"; -.MulticallSettingsManager { - grid-area: MulticallSettingsManager; +.SettingsManager { + grid-area: SettingsManager; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; @@ -15,7 +15,7 @@ @include mixin.no-scrollbar; grid-template-areas: - "ManageTokenWhitelist ManageScheduleSettings" + "ManageTokenWhitelist ConfigureScheduling" "ManageTokenWhitelist ProposeSettings"; &-error { diff --git a/src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.tsx b/src/widgets/settings-manager/ui/settings-manager.ui.tsx similarity index 77% rename from src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.tsx rename to src/widgets/settings-manager/ui/settings-manager.ui.tsx index 7eaa074f..999847c2 100644 --- a/src/widgets/multicall-settings-manager/ui/multicall-settings-manager.ui.tsx +++ b/src/widgets/settings-manager/ui/settings-manager.ui.tsx @@ -9,17 +9,17 @@ import { import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { Tile } from "../../../shared/ui/design"; import { MulticallInstance, Wallet } from "../../../entities"; -import { ManageScheduleSettings, ManageTokenWhitelist, ProposeSettings } from "../../../features"; +import { ConfigureScheduling, ManageTokenWhitelist, ProposeSettings } from "../../../features"; -import "./multicall-settings-manager.ui.scss"; +import "./settings-manager.ui.scss"; -const _MulticallSettingsManager = "MulticallSettingsManager"; +const _SettingsManager = "SettingsManager"; -export interface MulticallSettingsManagerUIProps extends HTMLProps { +export interface SettingsManagerUIProps extends HTMLProps { dao: SputnikDAO; } -export const MulticallSettingsManagerUI = ({ className, dao }: MulticallSettingsManagerUIProps) => { +export const SettingsManagerUI = ({ className, dao }: SettingsManagerUIProps) => { const wallet = useContext(Wallet.SelectorContext), multicallInstance = useContext(MulticallInstance.Context); @@ -69,27 +69,21 @@ export const MulticallSettingsManagerUI = ({ className, dao }: MulticallSettings ); return ( -
    +
    - {false && } + {false && } - From e5ed7323b933badc45900170c1fcf464044510d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 6 Jan 2023 03:05:23 +0400 Subject: [PATCH 484/537] fix: Capitalize exposed namespace --- src/entities/fungible-token/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts index 95e3960e..56cf7623 100644 --- a/src/entities/fungible-token/index.ts +++ b/src/entities/fungible-token/index.ts @@ -7,6 +7,6 @@ import { FTBalancesProvider } from "./ui/fungible-token.providers"; export class FT extends ModuleContext { static BalancesContext = FTModel.BalancesContext; static BalancesProvider = FTBalancesProvider; + static Format = FTFormat; static balancesRender = ftBalancesRender; - static format = FTFormat; } From b7142a7f579303b4ee3682f4b8cebb0203afecc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 6 Jan 2023 03:06:17 +0400 Subject: [PATCH 485/537] fix: Capitalize exposed namespace --- src/entities/near-token/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts index 6e4dc975..d6fd366c 100644 --- a/src/entities/near-token/index.ts +++ b/src/entities/near-token/index.ts @@ -7,6 +7,6 @@ import { NEARTokenBalancesProvider } from "./ui/near-token.providers"; export class NEARToken extends ModuleContext { static BalancesContext = NEARTokenModel.BalancesContext; static BalancesProvider = NEARTokenBalancesProvider; + static Format = NEARTokenFormat; static balancesRender = nearTokenBalancesRender; - static format = NEARTokenFormat; } From 659777169099779bd831cd85ab0135feb1e734be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 6 Jan 2023 03:08:21 +0400 Subject: [PATCH 486/537] chore: Remove unused import --- .../manage-token-whitelist/ui/manage-token-whitelist.ui.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx index e3bcadb1..9bb15d94 100644 --- a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx +++ b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx @@ -11,7 +11,6 @@ import { TextField } from "../../../shared/ui/form"; import { MulticallInstance } from "../../../entities"; import "./manage-token-whitelist.ui.scss"; -import { Props } from "../../../shared/lib/props"; const _ManageTokenWhitelist = "ManageTokenWhitelist"; From 5fea694fa4043c1b9501f3c403f942ec700e7cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 6 Jan 2023 03:28:51 +0400 Subject: [PATCH 487/537] fix: Don't try to load jobs if MI isn't ready --- src/entities/job/model/job.model.ts | 33 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/entities/job/model/job.model.ts b/src/entities/job/model/job.model.ts index a0a92f90..38198922 100644 --- a/src/entities/job/model/job.model.ts +++ b/src/entities/job/model/job.model.ts @@ -35,22 +35,25 @@ export class JobModel { { multicallInstance }: JobModelInputs, callback: (result: typeof JobModel.allEntries) => void ) => - callback( - await multicallInstance - .getJobs() - .then((data) => ({ - data: data.reduce( - (jobsIndexedById, job) => ({ - ...jobsIndexedById, - [job.id]: JobFormat.withMulticallsDataDecoded(JobFormat.withStatus(job)), - }), - {} - ), + void ( + multicallInstance.ready && + callback( + await multicallInstance + .getJobs() + .then((data) => ({ + data: data.reduce( + (jobsIndexedById, job) => ({ + ...jobsIndexedById, + [job.id]: JobFormat.withMulticallsDataDecoded(JobFormat.withStatus(job)), + }), + {} + ), - error: null, - loading: false, - })) - .catch((error) => ({ data: null, error, loading: false })) + error: null, + loading: false, + })) + .catch((error) => ({ data: null, error, loading: false })) + ) ); public static readonly useAllEntriesState = (inputs: JobModelInputs) => { From 98368432d2709d839a643edba1b8e89e0692de75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 6 Jan 2023 17:34:50 +0400 Subject: [PATCH 488/537] feat: Enable async validation for token whitelisting --- .../lib/fungible-token.validation.ts | 2 -- .../ui/manage-token-whitelist.ui.tsx | 18 +++++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) delete mode 100644 src/entities/fungible-token/lib/fungible-token.validation.ts diff --git a/src/entities/fungible-token/lib/fungible-token.validation.ts b/src/entities/fungible-token/lib/fungible-token.validation.ts deleted file mode 100644 index 919e151f..00000000 --- a/src/entities/fungible-token/lib/fungible-token.validation.ts +++ /dev/null @@ -1,2 +0,0 @@ -// silence TS -export {}; diff --git a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx index 9bb15d94..6e4e9c4f 100644 --- a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx +++ b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx @@ -26,24 +26,24 @@ interface FormStates extends Record { const [editModeEnabled, editModeSwitch] = useState(false); - const fungibleTokenSchema = args.object().shape({ - address: args.string().lowercase().address().default(""), + const schema = args.object().shape({ + address: args.string().ft().default(""), }); - type FungibleTokenSchema = InferType; + type Schema = InferType; const [included, include] = useState(new Set()), [discarded, discard] = useState(new Set()); const onSubmit = useCallback( - ({ address }: FungibleTokenSchema, { setTouched, setValues }: FormikHelpers) => { + ({ address }: Schema, { setTouched, setValues }: FormikHelpers) => { if (discarded.has(address)) { discard((addresses) => (addresses.delete(address) ? new Set(addresses) : addresses)); } else { include((addresses) => (address.length > 0 ? new Set(addresses.add(address)) : addresses)); } - setValues(fungibleTokenSchema.getDefault()); + setValues(schema.getDefault()); setTouched({}); }, @@ -51,7 +51,7 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag ); const onDiscard = useCallback( - ({ address }: FungibleTokenSchema) => { + ({ address }: Schema) => { if (included.has(address)) { include((addresses) => (addresses.delete(address) ? new Set(addresses) : addresses)); } else { @@ -79,8 +79,8 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag return (
    @@ -94,7 +94,7 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag slots: { End: editModeEnabled ? ({ rowId: address }) => ( - onDiscard({ address } as FungibleTokenSchema)}> + onDiscard({ address } as Schema)}> {discarded.has(address) ? ( ) : ( From 1ebe0cd1e2375f238c3cc3a623b04fbd4e489654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 8 Jan 2023 04:46:18 +0400 Subject: [PATCH 489/537] wip: Reorganize & actualize types --- .../multicall-instance/module-context.ts | 18 ++--- .../ui/configure-scheduling.ui.tsx | 61 ++++------------- .../ui/manage-token-whitelist.ui.tsx | 15 +++-- .../ui/propose-settings.ui.tsx | 13 ++-- src/shared/global.d.ts | 36 ++++++++++ src/shared/lib/contracts/multicall.ts | 67 ++++++------------- src/shared/lib/contracts/sputnik-dao.ts | 1 - src/shared/lib/types.d.ts | 7 -- src/types/images.d.ts | 4 -- .../ui/settings-manager.ui.tsx | 22 +++--- tsconfig.json | 4 +- 11 files changed, 98 insertions(+), 150 deletions(-) create mode 100644 src/shared/global.d.ts delete mode 100644 src/shared/lib/types.d.ts delete mode 100644 src/types/images.d.ts diff --git a/src/entities/multicall-instance/module-context.ts b/src/entities/multicall-instance/module-context.ts index 730e168e..f094847e 100644 --- a/src/entities/multicall-instance/module-context.ts +++ b/src/entities/multicall-instance/module-context.ts @@ -1,32 +1,24 @@ -import { MulticallPropertyKey, MulticallTokenWhitelistDiffKey } from "../../shared/lib/contracts/multicall"; import { toYocto } from "../../shared/lib/converter"; import { Color } from "../../shared/ui/design"; export class ModuleContext { - public static readonly ParamKey = MulticallPropertyKey; - /** * Minimum balance needed for storage + state. */ public static readonly MIN_BALANCE = toYocto(1); public static readonly SettingsDiffMeta = { - [MulticallPropertyKey.croncatManager]: { - color: "blue" as Color, - description: "Croncat manager", + addTokens: { + color: "green" as Color, + description: "Tokens to add to whitelist", }, - [MulticallPropertyKey.jobBond]: { + jobBond: { color: "blue" as Color, description: "Job bond", }, - [MulticallTokenWhitelistDiffKey.addTokens]: { - color: "green" as Color, - description: "Tokens to add to whitelist", - }, - - [MulticallTokenWhitelistDiffKey.removeTokens]: { + removeTokens: { color: "red" as Color, description: "Tokens to remove from whitelist", }, diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx index dca84585..8cb47430 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx @@ -2,20 +2,20 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-mat import { IconButton, TextField, TextFieldProps } from "@mui/material"; import { HTMLProps, useCallback, useContext, useEffect, useMemo, useState } from "react"; -import { MulticallSettingsChange, MulticallPropertyKey } from "../../../shared/lib/contracts/multicall"; import { ArgsString } from "../../../shared/lib/args-old"; +import { Multicall } from "../../../shared/lib/contracts/multicall"; import { toNEAR, toYocto } from "../../../shared/lib/converter"; -import { IconLabel, NEARIcon, NEARLink, Table, Tile, Tooltip } from "../../../shared/ui/design"; +import { IconLabel, NEARIcon, Table, Tile, Tooltip } from "../../../shared/ui/design"; import { MulticallInstance } from "../../../entities"; import "./configure-scheduling.ui.scss"; const _ConfigureScheduling = "ConfigureScheduling"; -type FormState = Pick; +type MISchedulingSettingsDiff = Pick; interface ConfigureSchedulingUIProps extends Omit, "onChange"> { - onEdit: (payload: FormState) => void; + onEdit: (diff: MISchedulingSettingsDiff) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } @@ -29,19 +29,13 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config const [editModeEnabled, editModeSwitch] = useState(false); - const formInitialState: FormState = { - [MulticallPropertyKey.croncatManager]: "", - [MulticallPropertyKey.jobBond]: "", + const formInitialState: MISchedulingSettingsDiff = { + jobBond: "", }; - const [[croncatManager, croncatManagerUpdate], [jobBond, jobBondUpdate]] = [ - useState(formInitialState.croncatManager), - useState(formInitialState.jobBond), - ]; + const [jobBond, jobBondUpdate] = useState(formInitialState.jobBond); const formFields = { - croncatManager: useMemo(() => new ArgsString(multicallInstance.data.croncatManager), [multicallInstance.data]), - jobBond: useMemo( () => new ArgsString(multicallInstance.data.jobBond !== "" ? toNEAR(multicallInstance.data.jobBond) : ""), @@ -49,15 +43,6 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config ), }; - const onCroncatManagerChange = useCallback["onChange"]>( - ({ target: { value } }) => - void croncatManagerUpdate( - value !== multicallInstance.data.croncatManager ? value : formInitialState.croncatManager - ), - - [croncatManagerUpdate, multicallInstance.data] - ); - const onJobBondChange = useCallback["onChange"]>( ({ target: { value } }) => void jobBondUpdate( @@ -68,16 +53,14 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config ); const formReset = useCallback(() => { - formFields.croncatManager.value = multicallInstance.data.croncatManager; formFields.jobBond.value = toNEAR(multicallInstance.data.jobBond); - void croncatManagerUpdate(formInitialState.croncatManager); void jobBondUpdate(formInitialState.jobBond); void editModeSwitch(false); - }, [croncatManagerUpdate, editModeSwitch, formInitialState, jobBondUpdate]); + }, [editModeSwitch, formInitialState, jobBondUpdate]); useEffect(() => resetTrigger.subscribe(formReset), [formReset, resetTrigger]); - useEffect(() => void onEdit({ croncatManager, jobBond }), [croncatManager, jobBond, onEdit]); + useEffect(() => void onEdit({ jobBond }), [jobBond, onEdit]); return ( - {(croncatManager.length > 0 || jobBond.length > 0) && ( + {jobBond.length > 0 && ( void editModeSwitch(false)}> @@ -120,8 +103,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config centeredTitle: true, idToHighlightColor: (id) => - ({ croncatManager, jobBond }[id] === formInitialState[id as MulticallPropertyKey] || - { croncatManager, jobBond }[id] === multicallInstance.data[id as MulticallPropertyKey] + ({ jobBond }[id] === formInitialState[id] || { jobBond }[id] === multicallInstance.data[id] ? null : "blue"), @@ -133,27 +115,10 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config header={["Option", "Value"]} rows={[ { - id: MulticallPropertyKey.croncatManager, - - content: [ - MulticallInstance.SettingsDiffMeta[MulticallPropertyKey.croncatManager].description, - - editModeEnabled ? ( - - ) : ( - - ), - ], - }, - { - id: MulticallPropertyKey.jobBond, + id: "jobBond", content: [ - MulticallInstance.SettingsDiffMeta[MulticallPropertyKey.jobBond].description, + MulticallInstance.SettingsDiffMeta.jobBond.description, editModeEnabled ? ( ; +type MITokenWhitelistDiff = Pick< + Arguments[0], + "addTokens" | "removeTokens" +>; interface ManageTokenWhitelistUIProps extends Omit, "onChange"> { - onEdit: (payload: FormState) => void; + onEdit: (diff: MITokenWhitelistDiff) => void; resetTrigger: { subscribe: (callback: EventListener) => () => void }; } -interface FormStates extends Record> {} - export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: ManageTokenWhitelistUIProps) => { const [editModeEnabled, editModeSwitch] = useState(false); @@ -32,8 +33,8 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag type Schema = InferType; - const [included, include] = useState(new Set()), - [discarded, discard] = useState(new Set()); + const [included, include] = useState>(new Set()), + [discarded, discard] = useState>(new Set()); const onSubmit = useCallback( ({ address }: Schema, { setTouched, setValues }: FormikHelpers) => { diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index a49efcec..574b4620 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -4,12 +4,7 @@ import { HTMLProps, useCallback, useContext } from "react"; import { InferType } from "yup"; import { args } from "../../../shared/lib/args/args"; -import { - Multicall, - MulticallPropertyKey, - MulticallSettingsChange, - MulticallTokenWhitelistDiffKey, -} from "../../../shared/lib/contracts/multicall"; +import { Multicall } from "../../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { toNEAR } from "../../../shared/lib/converter"; import { signAndSendTxs } from "../../../shared/lib/wallet"; @@ -23,7 +18,7 @@ const _ProposeSettings = "ProposeSettings"; export interface ProposeSettingsUIProps extends HTMLProps { dao: SputnikDAO; - diff: MulticallSettingsChange; + diff: Arguments[0]; editMode: boolean; onCancel: VoidFunction; } @@ -74,7 +69,7 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on

    - {Object.values({ ...MulticallPropertyKey, ...MulticallTokenWhitelistDiffKey }).map( + {Object.keys(MulticallInstance.SettingsDiffMeta).map( (diffKey) => diff[diffKey].length > 0 && (
    - {!Number.isNaN(data) && diffKey === MulticallPropertyKey.jobBond + {!Number.isNaN(data) && diffKey === "jobBond" ? `${toNEAR(data as string)} ${NEARIcon.NATIVE_TOKEN_CHARACTER}` : (data as string)} diff --git a/src/shared/global.d.ts b/src/shared/global.d.ts new file mode 100644 index 00000000..6666b2ef --- /dev/null +++ b/src/shared/global.d.ts @@ -0,0 +1,36 @@ +import { Account } from "@near-wallet-selector/core"; + +declare global { + /* Temporary workaround fixing typechecking with assets import */ + declare module "*.png"; + declare module "*.svg"; + declare module "*.jpeg"; + declare module "*.jpg"; + + /** + * Function arguments inference + */ + declare type Arguments = F extends (...args: infer A) => any ? A : never; + + /** + * String encoded number (u128) + */ + declare type U128String = string; + + /** + * String encoded number (u64) + */ + declare type U64String = string; + + declare type JsonString = string; + + /** + * Base64 encoded JSON + */ + declare type Base64String = string; + + /** + * NEAR Protocol account ID + */ + declare type AccountId = Account["accountId"]; +} diff --git a/src/shared/lib/contracts/multicall.ts b/src/shared/lib/contracts/multicall.ts index 6eb3a6a0..445cc6eb 100644 --- a/src/shared/lib/contracts/multicall.ts +++ b/src/shared/lib/contracts/multicall.ts @@ -1,6 +1,5 @@ import { args } from "../args/args"; import { Big, toGas, dateToCron, toYocto } from "../converter"; -import { AccountId, Base64String, U128String, U64String } from "../types"; import { viewAccount, viewState, view, Tx } from "../wallet"; import { FunctionCallAction as daoFunctionCallAction, SputnikDAO } from "./sputnik-dao"; @@ -32,11 +31,11 @@ type JobData = { job: { croncat_hash: string; creator: AccountId; - bond: U128String; // string encoded number (u128) + bond: U128String; cadence: string; - trigger_gas: U64String; // string encoded number (u64) - croncat_budget: U128String; // string encoded number (u128) - start_at: U64String; // string encoded number (u64) + trigger_gas: U64String; + croncat_budget: U128String; + start_at: U64String; run_count: number; is_active: boolean; multicalls: MulticallArgs[]; @@ -45,9 +44,9 @@ type JobData = { type FunctionCall = { func: string; - args: Base64String; // base64 encoded JSON args - gas: U64String; // string encoded number (u64) - depo: U128String; // string encoded number (u128) + args: Base64String; + gas: U64String; + depo: U128String; }; type BatchCall = { @@ -59,28 +58,6 @@ type MulticallArgs = { calls: BatchCall[][]; }; -enum MulticallPropertyKey { - croncatManager = "croncatManager", - - /** - * Job bond amount must be attached as deposit when adding new jobs. - * Needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). - */ - jobBond = "jobBond", -} - -enum MulticallTokenWhitelistDiffKey { - addTokens = "addTokens", - removeTokens = "removeTokens", -} - -interface MulticallSettingsChange { - [MulticallTokenWhitelistDiffKey.addTokens]: AccountId[]; - [MulticallPropertyKey.croncatManager]: AccountId; - [MulticallPropertyKey.jobBond]: U128String; - [MulticallTokenWhitelistDiffKey.removeTokens]: AccountId[]; -} - class Multicall { static FACTORY_ADDRESS: AccountId = FACTORY_ADDRESS_SELECTOR[window.NEAR_ENV]; static CONTRACT_CODE_HASHES: AccountId[] = CONTRACT_CODE_HASHES_SELECTOR[window.NEAR_ENV]; @@ -93,14 +70,18 @@ class Multicall { address: AccountId; admins: AccountId[] = []; - [MulticallPropertyKey.croncatManager]: AccountId = ""; + croncatManager: AccountId = ""; /** * Only whitelisted tokens can be attached to multicalls or job activations. */ tokensWhitelist: AccountId[] = []; - [MulticallPropertyKey.jobBond]: U128String = ""; + /** + * Job bond amount must be attached as deposit when adding new jobs. + * Needs initialization, but start with "" because it's distinguishable from a real value (string encoded numbers). + */ + jobBond: U128String = ""; /** * Multicall instance is ready when info (admins...) are fetched & assigned correctly. @@ -177,22 +158,16 @@ class Multicall { * @returns actions that can be passed to JSON for DAO "add_proposal". */ static configDiffToProposalActions({ - removeTokens = [], addTokens = [], jobBond = "", - croncatManager = "", - }: MulticallSettingsChange): daoFunctionCallAction[] { + removeTokens = [], + }: { + addTokens: Multicall["tokensWhitelist"]; + jobBond: Multicall["jobBond"]; + removeTokens: Multicall["tokensWhitelist"]; + }): daoFunctionCallAction[] { const actions: daoFunctionCallAction[] = []; - // action: change croncat manager address - if (croncatManager !== "") { - actions.push({ - method_name: "set_croncat_manager", - args: { address: croncatManager }, - deposit: "1", // 1 yocto - gas: toGas("10"), // 10 Tgas - }); - } // action: change amount of job bond if (jobBond !== "") { actions.push({ @@ -323,5 +298,5 @@ class Multicall { } } -export { Multicall, MulticallPropertyKey, MulticallTokenWhitelistDiffKey }; -export type { JobData, MulticallArgs, MulticallSettingsChange }; +export { Multicall }; +export type { JobData, MulticallArgs }; diff --git a/src/shared/lib/contracts/sputnik-dao.ts b/src/shared/lib/contracts/sputnik-dao.ts index a74cd3b4..54274262 100644 --- a/src/shared/lib/contracts/sputnik-dao.ts +++ b/src/shared/lib/contracts/sputnik-dao.ts @@ -6,7 +6,6 @@ import { args } from "../args/args"; import { toGas, Big } from "../converter"; import { STORAGE } from "../persistent"; import { FungibleToken } from "../standards/fungibleToken"; -import { AccountId } from "../types"; import { Tx, view, viewAccount } from "../wallet"; import { MulticallArgs } from "./multicall"; diff --git a/src/shared/lib/types.d.ts b/src/shared/lib/types.d.ts deleted file mode 100644 index d01d69db..00000000 --- a/src/shared/lib/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export declare type AccountId = string; - -export declare type U128String = string; -export declare type U64String = string; - -export declare type JsonString = string; -export declare type Base64String = string; diff --git a/src/types/images.d.ts b/src/types/images.d.ts deleted file mode 100644 index 0357e4f1..00000000 --- a/src/types/images.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module "*.png"; -declare module "*.svg"; -declare module "*.jpeg"; -declare module "*.jpg"; diff --git a/src/widgets/settings-manager/ui/settings-manager.ui.tsx b/src/widgets/settings-manager/ui/settings-manager.ui.tsx index 999847c2..1cdf8177 100644 --- a/src/widgets/settings-manager/ui/settings-manager.ui.tsx +++ b/src/widgets/settings-manager/ui/settings-manager.ui.tsx @@ -1,11 +1,6 @@ import clsx from "clsx"; -import { useCallback, useState, useEffect, useContext, HTMLProps } from "react"; +import { useCallback, useState, useEffect, useContext, HTMLProps, ComponentProps } from "react"; -import { - MulticallPropertyKey, - MulticallSettingsChange, - MulticallTokenWhitelistDiffKey, -} from "../../../shared/lib/contracts/multicall"; import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { Tile } from "../../../shared/ui/design"; import { MulticallInstance, Wallet } from "../../../entities"; @@ -15,6 +10,8 @@ import "./settings-manager.ui.scss"; const _SettingsManager = "SettingsManager"; +type MISettingsDiff = ComponentProps["diff"]; + export interface SettingsManagerUIProps extends HTMLProps { dao: SputnikDAO; } @@ -26,15 +23,14 @@ export const SettingsManagerUI = ({ className, dao }: SettingsManagerUIProps) => const canCreateProposals = !wallet?.accountId || dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); - const initialDiff: MulticallSettingsChange = { - [MulticallTokenWhitelistDiffKey.removeTokens]: [], - [MulticallTokenWhitelistDiffKey.addTokens]: [], - [MulticallPropertyKey.jobBond]: "", - [MulticallPropertyKey.croncatManager]: "", + const initialDiff: MISettingsDiff = { + addTokens: [], + jobBond: "", + removeTokens: [], }; const [editMode, editModeSwitch] = useState(false), - [diff, diffUpdate] = useState(initialDiff), + [diff, diffUpdate] = useState(initialDiff), _childFormsResetRequested = "childFormsResetRequested"; const resetTrigger = { @@ -58,7 +54,7 @@ export const SettingsManagerUI = ({ className, dao }: SettingsManagerUIProps) => }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( - (update: Partial) => void diffUpdate((latestState) => ({ ...latestState, ...update })), + (update: Partial) => void diffUpdate((latestState) => ({ ...latestState, ...update })), [diffUpdate] ); diff --git a/tsconfig.json b/tsconfig.json index 8ab31f45..ce5042ea 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "typeRoots": ["node_modules/@types", "src/types"], + "typeRoots": ["node_modules/@types"], "target": "es6", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, @@ -20,5 +20,5 @@ "noImplicitThis": true, "strictNullChecks": true }, - "include": ["src", "near-config.ts"] + "include": ["src"] } From beec2371a4a8ce7a23ff61c3ed550ea65aec115f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 8 Jan 2023 04:48:57 +0400 Subject: [PATCH 490/537] wip: GIve more space to settings proposal tile --- src/widgets/settings-manager/ui/settings-manager.ui.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/settings-manager/ui/settings-manager.ui.scss b/src/widgets/settings-manager/ui/settings-manager.ui.scss index e7ecee6a..812aeeb0 100644 --- a/src/widgets/settings-manager/ui/settings-manager.ui.scss +++ b/src/widgets/settings-manager/ui/settings-manager.ui.scss @@ -5,7 +5,7 @@ grid-area: SettingsManager; display: grid; grid-template-columns: 1fr 1fr; - grid-template-rows: 1fr 1fr; + grid-template-rows: 1fr 2fr; gap: size.$gap; margin: size.$gap !important; border-radius: size.$task-radius; From 201d25b96003edb5ea82f4f029aeb09879591dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 8 Jan 2023 04:54:41 +0400 Subject: [PATCH 491/537] fix: Add TS workaround --- .../configure-scheduling/ui/configure-scheduling.ui.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx index 8cb47430..378544f4 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx @@ -103,7 +103,8 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config centeredTitle: true, idToHighlightColor: (id) => - ({ jobBond }[id] === formInitialState[id] || { jobBond }[id] === multicallInstance.data[id] + ({ jobBond }[id] === formInitialState[id as keyof MISchedulingSettingsDiff] || + { jobBond }[id] === multicallInstance.data[id as keyof MISchedulingSettingsDiff] ? null : "blue"), From 2e2753a49938ca818662b722d4685bd86c15b43e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 8 Jan 2023 05:10:34 +0400 Subject: [PATCH 492/537] fix: Add more TS workarounds --- .../ui/propose-settings.ui.tsx | 50 +++++++++---------- .../ui/settings-manager.ui.tsx | 7 +-- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index 574b4620..8c68679e 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -16,9 +16,11 @@ import "./propose-settings.ui.scss"; const _ProposeSettings = "ProposeSettings"; +type MISettingsDiff = Arguments[0]; + export interface ProposeSettingsUIProps extends HTMLProps { dao: SputnikDAO; - diff: Arguments[0]; + diff: MISettingsDiff; editMode: boolean; onCancel: VoidFunction; } @@ -69,36 +71,32 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on

    - {Object.keys(MulticallInstance.SettingsDiffMeta).map( - (diffKey) => - diff[diffKey].length > 0 && ( + {Object.entries(MulticallInstance.SettingsDiffMeta).map( + ([key, { color, description }]) => + diff[key as keyof MISettingsDiff].length > 0 && (
    -

    - {MulticallInstance.SettingsDiffMeta[diffKey].description + ":"} -

    +

    {description + ":"}

      - {(Array.isArray(diff[diffKey]) ? Array.from(diff[diffKey]) : [diff[diffKey]]).map( - (data) => ( -
    • - {!Number.isNaN(data) && diffKey === "jobBond" - ? `${toNEAR(data as string)} ${NEARIcon.NATIVE_TOKEN_CHARACTER}` - : (data as string)} -
    • - ) - )} + {(Array.isArray(diff[key as keyof MISettingsDiff]) + ? Array.from(diff[key as keyof MISettingsDiff]) + : [diff[key as keyof MISettingsDiff]] + ).map((data) => ( +
    • + {!Number.isNaN(data) && key === "jobBond" + ? `${toNEAR(data as string)} ${NEARIcon.NATIVE_TOKEN_CHARACTER}` + : (data as string)} +
    • + ))}
    ) diff --git a/src/widgets/settings-manager/ui/settings-manager.ui.tsx b/src/widgets/settings-manager/ui/settings-manager.ui.tsx index 1cdf8177..a83936dd 100644 --- a/src/widgets/settings-manager/ui/settings-manager.ui.tsx +++ b/src/widgets/settings-manager/ui/settings-manager.ui.tsx @@ -10,8 +10,6 @@ import "./settings-manager.ui.scss"; const _SettingsManager = "SettingsManager"; -type MISettingsDiff = ComponentProps["diff"]; - export interface SettingsManagerUIProps extends HTMLProps { dao: SputnikDAO; } @@ -23,7 +21,7 @@ export const SettingsManagerUI = ({ className, dao }: SettingsManagerUIProps) => const canCreateProposals = !wallet?.accountId || dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); - const initialDiff: MISettingsDiff = { + const initialDiff: ComponentProps["diff"] = { addTokens: [], jobBond: "", removeTokens: [], @@ -54,8 +52,7 @@ export const SettingsManagerUI = ({ className, dao }: SettingsManagerUIProps) => }, [editMode, editModeSwitch, formReset]); const onEdit = useCallback( - (update: Partial) => void diffUpdate((latestState) => ({ ...latestState, ...update })), - + (update: Partial) => void diffUpdate((latestState) => ({ ...latestState, ...update })), [diffUpdate] ); From faffae0c123be70cab75fd2005267bd5bbdd3032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 8 Jan 2023 05:12:27 +0400 Subject: [PATCH 493/537] chore: Remove redundant statements --- src/features/propose-settings/ui/propose-settings.ui.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index 8c68679e..4edf6c5e 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -36,8 +36,8 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on const onReset = useCallback( (_values: Schema, { setValues }: FormikHelpers) => { - void setValues(schema.getDefault()); - void onCancel(); + setValues(schema.getDefault()); + onCancel(); }, [onCancel] From 6a670a0a5fbecce2356cf690c2d0283269519f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 13 Jan 2023 13:09:09 +0400 Subject: [PATCH 494/537] wip: Update Table API & Amend naming --- .../ui/manage-token-whitelist.ui.scss | 2 +- .../manage-token-whitelist/ui/manage-token-whitelist.ui.tsx | 4 ++-- src/features/propose-settings/ui/propose-settings.ui.tsx | 2 +- src/shared/ui/design/icons/near/near.tsx | 2 +- src/shared/ui/design/table/row.tsx | 6 +++--- src/shared/ui/design/table/table.tsx | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss index 974b021a..72ec71f1 100644 --- a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss +++ b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss @@ -3,7 +3,7 @@ display: flex; flex-flow: column; - &-table { + &-controls { flex: auto; } } diff --git a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx index 2a95fddd..ed0cca6e 100644 --- a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx +++ b/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx @@ -87,7 +87,7 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag + idToHighlight: (id) => (included.has(id) && MulticallInstance.SettingsDiffMeta.addTokens.color) || (discarded.has(id) && MulticallInstance.SettingsDiffMeta.removeTokens.color) || null, @@ -106,7 +106,7 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag : void null, }, }} - className={`${_ManageTokenWhitelist}-table`} + className={`${_ManageTokenWhitelist}-controls`} headerSlots={{ end: editModeEnabled ? ( diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index 4edf6c5e..d477b270 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -93,7 +93,7 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on key={data as string} > {!Number.isNaN(data) && key === "jobBond" - ? `${toNEAR(data as string)} ${NEARIcon.NATIVE_TOKEN_CHARACTER}` + ? `${toNEAR(data as string)} ${NEARIcon.NativeTokenCharacter}` : (data as string)} ))} diff --git a/src/shared/ui/design/icons/near/near.tsx b/src/shared/ui/design/icons/near/near.tsx index 51e7ddee..2f3854f6 100644 --- a/src/shared/ui/design/icons/near/near.tsx +++ b/src/shared/ui/design/icons/near/near.tsx @@ -45,5 +45,5 @@ const GenericTokenIconFilled = ({ className }: GenericTokenIconProps) => ( export const NEARIcon = { GenericTokenFilled: GenericTokenIconFilled, NativeTokenFilled: NativeTokenIconFilled, - NATIVE_TOKEN_CHARACTER: NEAR_NATIVE_TOKEN_CHARACTER, + NativeTokenCharacter: NEAR_NATIVE_TOKEN_CHARACTER, }; diff --git a/src/shared/ui/design/table/row.tsx b/src/shared/ui/design/table/row.tsx index 07a8aa8b..143752ba 100644 --- a/src/shared/ui/design/table/row.tsx +++ b/src/shared/ui/design/table/row.tsx @@ -20,7 +20,7 @@ export interface TableRowProps { withTitle?: boolean; header: TableHeader; id: string; - idToHighlightColor?: (id: TableRowProps["id"]) => Color | null; + idToHighlight?: (id: TableRowProps["id"]) => Color | null; noKeys?: boolean; onSelect?: (selectedRow: { id: TableRowProps["id"]; checked: boolean }) => void; selectable: boolean; @@ -47,7 +47,7 @@ export const TableRowCompact = ({ withTitle, header, id, - idToHighlightColor, + idToHighlight, noKeys, onSelect, selectable, @@ -62,7 +62,7 @@ export const TableRowCompact = ({
    {header.map((headerCell, headerCellIndex) => ( diff --git a/src/shared/ui/design/table/table.tsx b/src/shared/ui/design/table/table.tsx index 35510262..d954e645 100644 --- a/src/shared/ui/design/table/table.tsx +++ b/src/shared/ui/design/table/table.tsx @@ -37,7 +37,7 @@ export interface TableProps extends HTMLAttributes, Pick Date: Fri, 13 Jan 2023 13:11:27 +0400 Subject: [PATCH 495/537] wip: Use new APIs for scheduling configuration --- .../ui/configure-scheduling.ui.tsx | 232 +++++++++--------- 1 file changed, 112 insertions(+), 120 deletions(-) diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx index 378544f4..d7b30cd5 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx @@ -1,10 +1,14 @@ -import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-material"; -import { IconButton, TextField, TextFieldProps } from "@mui/material"; -import { HTMLProps, useCallback, useContext, useEffect, useMemo, useState } from "react"; +import { CancelOutlined, EditOutlined } from "@mui/icons-material"; +import { IconButton } from "@mui/material"; +import { Form, Formik } from "formik"; +import { HTMLProps, useCallback, useContext, useEffect, useState } from "react"; +import { InferType } from "yup"; -import { ArgsString } from "../../../shared/lib/args-old"; +import { args } from "../../../shared/lib/args/args"; import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { toNEAR, toYocto } from "../../../shared/lib/converter"; +import { Big, toNEAR, toYocto } from "../../../shared/lib/converter"; +import { Props } from "../../../shared/lib/props"; +import { TextField } from "../../../shared/ui/form"; import { IconLabel, NEARIcon, Table, Tile, Tooltip } from "../../../shared/ui/design"; import { MulticallInstance } from "../../../entities"; @@ -20,133 +24,121 @@ interface ConfigureSchedulingUIProps extends Omit, "on } export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: ConfigureSchedulingUIProps) => { - const multicallInstance = useContext(MulticallInstance.Context); + const [editModeEnabled, editModeSwitch] = useState(false), + mi = useContext(MulticallInstance.Context); const error = - multicallInstance.data.ready && multicallInstance.data.jobBond === "" + mi.data.ready && mi.data.jobBond === "" ? new Error("Error while getting Multicall Instance job bond") - : null; + : mi.error; - const [editModeEnabled, editModeSwitch] = useState(false); + const schema = args.object().shape({ + jobBond: args + .big() + .token() + .default(Big(toNEAR(mi.data.jobBond))), + }); - const formInitialState: MISchedulingSettingsDiff = { - jobBond: "", - }; + type Schema = InferType; - const [jobBond, jobBondUpdate] = useState(formInitialState.jobBond); - - const formFields = { - jobBond: useMemo( - () => new ArgsString(multicallInstance.data.jobBond !== "" ? toNEAR(multicallInstance.data.jobBond) : ""), - - [multicallInstance.data] - ), - }; - - const onJobBondChange = useCallback["onChange"]>( - ({ target: { value } }) => - void jobBondUpdate( - value !== toNEAR(multicallInstance.data.jobBond) ? toYocto(value) : formInitialState.jobBond - ), - - [jobBondUpdate, multicallInstance.data] + const onReset = useCallback(() => { + void editModeSwitch(false); + }, [editModeSwitch]); + + const onSubmit = useCallback( + (values: Schema) => { + onEdit( + Props.evolve( + { jobBond: (amount) => (amount !== toNEAR(mi.data.jobBond) ? toYocto(amount) : "") }, + values + ) + ); + + editModeSwitch(false); + }, + [editModeSwitch, onEdit] ); - const formReset = useCallback(() => { - formFields.jobBond.value = toNEAR(multicallInstance.data.jobBond); + useEffect(() => resetTrigger.subscribe(onReset), [onReset, resetTrigger]); - void jobBondUpdate(formInitialState.jobBond); - void editModeSwitch(false); - }, [editModeSwitch, formInitialState, jobBondUpdate]); - - useEffect(() => resetTrigger.subscribe(formReset), [formReset, resetTrigger]); - useEffect(() => void onEdit({ jobBond }), [jobBond, onEdit]); + const jobBond = false; // TODO: get jobBond from the form return ( - - - - - - - - {jobBond.length > 0 && ( - - void editModeSwitch(false)}> - + + + + + - )} - - ) : ( - - - void editModeSwitch(true)} - {...{ disabled }} - > - - - - - ), - }} - {...{ error }} - > -
    - ({ jobBond }[id] === formInitialState[id as keyof MISchedulingSettingsDiff] || - { jobBond }[id] === multicallInstance.data[id as keyof MISchedulingSettingsDiff] - ? null - : "blue"), - - withTitle: true, - noKeys: true, - }} - displayMode="compact" - dense - header={["Option", "Value"]} - rows={[ - { - id: "jobBond", - - content: [ - MulticallInstance.SettingsDiffMeta.jobBond.description, - - editModeEnabled ? ( - - ) : ( - - ), - ], - }, - ]} - /> - + ) : ( + + + void editModeSwitch(true)} + {...{ disabled }} + > + + + + + ), + }} + {...{ error }} + > +
    (id === "jobBond" ? null : "blue"), + withTitle: true, + noKeys: true, + }} + displayMode="compact" + dense + header={["Option", "Value"]} + rows={[ + { + id: "jobBond", + + content: [ + MulticallInstance.SettingsDiffMeta.jobBond.description, + + editModeEnabled ? ( + + ) : ( + + ), + ], + }, + ]} + /> + + + ); }; From 018db4732a88b06bf47bbd7866807d26b17cc9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 13 Jan 2023 13:24:43 +0400 Subject: [PATCH 496/537] wip: Don't convert initial job bond until bugs are fixed --- .../configure-scheduling/ui/configure-scheduling.ui.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx index d7b30cd5..b91f4753 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx @@ -13,6 +13,7 @@ import { IconLabel, NEARIcon, Table, Tile, Tooltip } from "../../../shared/ui/de import { MulticallInstance } from "../../../entities"; import "./configure-scheduling.ui.scss"; +import { Maybe } from "yup/lib/types"; const _ConfigureScheduling = "ConfigureScheduling"; @@ -36,7 +37,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config jobBond: args .big() .token() - .default(Big(toNEAR(mi.data.jobBond))), + .default(mi.data.jobBond as unknown as Maybe), }); type Schema = InferType; From f02b0fa900c0af4e5f3ffaa70a155a58069fbcfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 13 Jan 2023 21:24:43 +0400 Subject: [PATCH 497/537] wip: Update styles --- .../ui/configure-scheduling.ui.scss | 6 + .../ui/configure-scheduling.ui.tsx | 2 +- .../ui/propose-settings.ui.tsx | 104 +++++++++--------- .../ui/settings-manager.ui.scss | 2 +- 4 files changed, 60 insertions(+), 54 deletions(-) diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.scss b/src/features/configure-scheduling/ui/configure-scheduling.ui.scss index 2070bbfe..de1fd26b 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.scss +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.scss @@ -1,3 +1,9 @@ .ConfigureScheduling { grid-area: ConfigureScheduling; + display: flex; + flex-flow: column; + + &-controls { + flex: auto; + } } diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx index b91f4753..a94ecbc3 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx @@ -3,6 +3,7 @@ import { IconButton } from "@mui/material"; import { Form, Formik } from "formik"; import { HTMLProps, useCallback, useContext, useEffect, useState } from "react"; import { InferType } from "yup"; +import { Maybe } from "yup/lib/types"; import { args } from "../../../shared/lib/args/args"; import { Multicall } from "../../../shared/lib/contracts/multicall"; @@ -13,7 +14,6 @@ import { IconLabel, NEARIcon, Table, Tile, Tooltip } from "../../../shared/ui/de import { MulticallInstance } from "../../../entities"; import "./configure-scheduling.ui.scss"; -import { Maybe } from "yup/lib/types"; const _ConfigureScheduling = "ConfigureScheduling"; diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index d477b270..82b72412 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -39,7 +39,6 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on setValues(schema.getDefault()); onCancel(); }, - [onCancel] ); @@ -53,61 +52,62 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on ) .then((someTx) => signAndSendTxs([someTx])) .catch(console.error), - [dao, diff] ); return ( - -

    - {disabled - ? "Current account has no permission to propose changes" - : "Start editing to create config changes proposal template"} -

    - -
    - {Object.entries(MulticallInstance.SettingsDiffMeta).map( - ([key, { color, description }]) => - diff[key as keyof MISettingsDiff].length > 0 && ( -
    -

    {description + ":"}

    - -
      - {(Array.isArray(diff[key as keyof MISettingsDiff]) - ? Array.from(diff[key as keyof MISettingsDiff]) - : [diff[key as keyof MISettingsDiff]] - ).map((data) => ( -
    • - {!Number.isNaN(data) && key === "jobBond" - ? `${toNEAR(data as string)} ${NEARIcon.NativeTokenCharacter}` - : (data as string)} -
    • - ))} -
    -
    - ) - )} -
    - - +

    + {disabled + ? "Current account has no permission to propose changes" + : "Start editing to create config changes proposal template"} +

    + +
    + {Object.entries(MulticallInstance.SettingsDiffMeta).map( + ([key, { color, description }]) => + diff[key as keyof MISettingsDiff].length > 0 && ( +
    +

    + {description + ":"} +

    + +
      + {(Array.isArray(diff[key as keyof MISettingsDiff]) + ? Array.from(diff[key as keyof MISettingsDiff]) + : [diff[key as keyof MISettingsDiff]] + ).map((data) => ( +
    • + {!Number.isNaN(data) && key === "jobBond" + ? `${toNEAR(data as string)} ${NEARIcon.NativeTokenCharacter}` + : (data as string)} +
    • + ))} +
    +
    + ) + )} +
    +
    - - + + ); }; diff --git a/src/widgets/settings-manager/ui/settings-manager.ui.scss b/src/widgets/settings-manager/ui/settings-manager.ui.scss index 812aeeb0..82d49713 100644 --- a/src/widgets/settings-manager/ui/settings-manager.ui.scss +++ b/src/widgets/settings-manager/ui/settings-manager.ui.scss @@ -5,7 +5,7 @@ grid-area: SettingsManager; display: grid; grid-template-columns: 1fr 1fr; - grid-template-rows: 1fr 2fr; + grid-template-rows: 1fr 4fr; gap: size.$gap; margin: size.$gap !important; border-radius: size.$task-radius; From 98d79d77a348ed8dc449fc9e00ee348990ea3221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 13 Jan 2023 22:57:08 +0400 Subject: [PATCH 498/537] wip: Update compact table styles --- src/shared/ui/design/table/row.scss | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/shared/ui/design/table/row.scss b/src/shared/ui/design/table/row.scss index c87ce99a..caf8de61 100644 --- a/src/shared/ui/design/table/row.scss +++ b/src/shared/ui/design/table/row.scss @@ -168,16 +168,6 @@ font-size: size.$text; } - &--dense.TableRow-content--compact--withTitle { - &:not(:first-of-type) { - padding: 0; - - & > span { - padding: size.$gap * 0.4; - } - } - } - &--noKeys { & > span { &:first-of-type { From 3ef49a5668c070f50d1f3e9f051aee52ddc6401e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 13 Jan 2023 23:00:13 +0400 Subject: [PATCH 499/537] wip: Update compact table styles --- src/shared/ui/design/table/row.scss | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/shared/ui/design/table/row.scss b/src/shared/ui/design/table/row.scss index c87ce99a..caf8de61 100644 --- a/src/shared/ui/design/table/row.scss +++ b/src/shared/ui/design/table/row.scss @@ -168,16 +168,6 @@ font-size: size.$text; } - &--dense.TableRow-content--compact--withTitle { - &:not(:first-of-type) { - padding: 0; - - & > span { - padding: size.$gap * 0.4; - } - } - } - &--noKeys { & > span { &:first-of-type { From 0e14ab21984b36fb9e19c888fec08657b7ee1658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 13 Jan 2023 23:00:26 +0400 Subject: [PATCH 500/537] wip: Use more minimalistic layout --- .../ui/configure-scheduling.ui.tsx | 58 +++++++------------ 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx index a94ecbc3..046d3e8c 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx @@ -3,14 +3,13 @@ import { IconButton } from "@mui/material"; import { Form, Formik } from "formik"; import { HTMLProps, useCallback, useContext, useEffect, useState } from "react"; import { InferType } from "yup"; -import { Maybe } from "yup/lib/types"; import { args } from "../../../shared/lib/args/args"; import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { Big, toNEAR, toYocto } from "../../../shared/lib/converter"; +import { toNEAR, toYocto } from "../../../shared/lib/converter"; import { Props } from "../../../shared/lib/props"; import { TextField } from "../../../shared/ui/form"; -import { IconLabel, NEARIcon, Table, Tile, Tooltip } from "../../../shared/ui/design"; +import { NEARIcon, Table, Tile, Tooltip } from "../../../shared/ui/design"; import { MulticallInstance } from "../../../entities"; import "./configure-scheduling.ui.scss"; @@ -33,11 +32,13 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config ? new Error("Error while getting Multicall Instance job bond") : mi.error; + console.log({ jobBond: mi.data.jobBond }); + const schema = args.object().shape({ jobBond: args - .big() - .token() - .default(mi.data.jobBond as unknown as Maybe), + .string() + .transform(toNEAR) + .default(mi.data.ready ? toNEAR(mi.data.jobBond) : "0.001"), }); type Schema = InferType; @@ -62,8 +63,6 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config useEffect(() => resetTrigger.subscribe(onReset), [onReset, resetTrigger]); - const jobBond = false; // TODO: get jobBond from the form - return (
    (id === "jobBond" ? null : "blue"), - withTitle: true, - noKeys: true, - }} + RowProps={{ idToHighlight: (id) => (id === "jobBond" ? null : "blue") }} displayMode="compact" dense - header={["Option", "Value"]} + header={[MulticallInstance.SettingsDiffMeta.jobBond.description]} rows={[ { id: "jobBond", content: [ - MulticallInstance.SettingsDiffMeta.jobBond.description, - - editModeEnabled ? ( - - ) : ( - - ), + , ], }, ]} From 454cb6f9f2a13e5185c4567a96f7d96445d16157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 13 Jan 2023 23:12:46 +0400 Subject: [PATCH 501/537] fix: Remove ugly styling --- src/shared/ui/form/fields/text-field.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/ui/form/fields/text-field.scss b/src/shared/ui/form/fields/text-field.scss index 89dc3ec3..a9ef2ee5 100644 --- a/src/shared/ui/form/fields/text-field.scss +++ b/src/shared/ui/form/fields/text-field.scss @@ -59,11 +59,9 @@ border-radius: 0.25 * size.$task-radius; legend { - background-color: color.$black; - margin-left: -2px; - padding: 2px; - border-radius: 20px; visibility: visible; + border-radius: 20px; + background-color: color.$black; } legend > span { @@ -139,6 +137,8 @@ } .MuiOutlinedInput-root { + color: color.$black; + .MuiOutlinedInput-input { color: color.$black; } From af8b79c8bcd4c80d2d1fa9ebbd96a01481db83c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 13 Jan 2023 23:49:24 +0400 Subject: [PATCH 502/537] wip: Amend settings proposal hints --- src/features/propose-settings/ui/propose-settings.ui.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/ui/propose-settings.ui.tsx index 82b72412..f82dcd47 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/ui/propose-settings.ui.tsx @@ -69,8 +69,8 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on >

    {disabled - ? "Current account has no permission to propose changes" - : "Start editing to create config changes proposal template"} + ? "Your account has no permission to create proposals" + : "Start editing to draft changes proposal"}

    From 71eda76fbeea3d04b85302d9c9af666945a5cf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 14 Jan 2023 00:11:23 +0400 Subject: [PATCH 503/537] wip: Fix form submission --- .../ui/configure-scheduling.ui.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx index 046d3e8c..c7a9e002 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx @@ -32,13 +32,8 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config ? new Error("Error while getting Multicall Instance job bond") : mi.error; - console.log({ jobBond: mi.data.jobBond }); - const schema = args.object().shape({ - jobBond: args - .string() - .transform(toNEAR) - .default(mi.data.ready ? toNEAR(mi.data.jobBond) : "0.001"), + jobBond: args.string().default(mi.data.ready ? toNEAR(mi.data.jobBond) : "0.001"), }); type Schema = InferType; @@ -58,11 +53,13 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config editModeSwitch(false); }, - [editModeSwitch, onEdit] + [editModeSwitch, mi.data, onEdit] ); useEffect(() => resetTrigger.subscribe(onReset), [onReset, resetTrigger]); + console.log({ jobBond: mi.data.jobBond }); + return ( Date: Thu, 19 Jan 2023 22:41:37 +0400 Subject: [PATCH 504/537] fix: Resolve circular dependencies & Flatten FS structure --- package-lock.json | 2 +- src/{shared => app}/global.d.ts | 12 +- src/{ => app}/global.scss | 0 src/{ => app}/index.tsx | 18 ++- src/entities/ft/ft.lib.ts | 14 +++ src/entities/ft/ft.model.ts | 23 ++++ .../module-context.ts => ft/ft.params.ts} | 2 +- .../ft.service.ts} | 41 ++----- src/entities/ft/ft.ui.tsx | 41 +++++++ src/entities/ft/index.ts | 9 ++ src/entities/fungible-token/index.ts | 12 -- .../lib/fungible-token.format.ts | 15 --- .../ui/fungible-token.balances.tsx | 32 ----- .../ui/fungible-token.providers.tsx | 13 -- src/entities/index.ts | 8 +- src/entities/job/index.ts | 2 +- src/entities/job/job.lib.ts | 71 +++++++++++ src/entities/job/job.model.ts | 20 +++ src/entities/job/job.service.ts | 49 ++++++++ .../job/{ui/job.entries.scss => job.ui.scss} | 27 +++++ src/entities/job/job.ui.tsx | 111 +++++++++++++++++ src/entities/job/lib/job.format.ts | 73 ----------- src/entities/job/model/job.model.ts | 70 ----------- src/entities/job/ui/job.entries.tsx | 37 ------ src/entities/job/ui/job.entry.scss | 29 ----- src/entities/job/ui/job.entry.tsx | 82 ------------- src/entities/mi/index.ts | 10 ++ src/entities/mi/mi.model.ts | 11 ++ .../module-context.ts => mi/mi.params.ts} | 2 +- .../mi.service.ts} | 32 ++--- src/entities/mi/mi.ui.tsx | 112 +++++++++++++++++ src/entities/multicall-instance/index.ts | 12 -- .../ui/multicall-instance.admin.tsx | 14 --- .../ui/multicall-instance.admins.tsx | 34 ------ .../ui/multicall-instance.providers.tsx | 9 -- .../ui/multicall-instance.token-whitelist.tsx | 47 -------- .../multicall-instance.whitelisted-token.tsx | 17 --- src/entities/near-token/index.ts | 12 -- .../near-token/lib/near-token.format.ts | 9 -- .../near-token/model/near-token.model.ts | 65 ---------- .../near-token/ui/near-token.balances.tsx | 26 ---- .../near-token/ui/near-token.providers.tsx | 13 -- src/entities/near/index.ts | 9 ++ src/entities/near/near.lib.ts | 8 ++ src/entities/near/near.model.ts | 21 ++++ .../module-context.ts => near/near.params.ts} | 2 +- src/entities/near/near.service.ts | 47 ++++++++ src/entities/near/near.ui.tsx | 35 ++++++ src/entities/task/config/keywords.ts | 43 ------- src/entities/task/index.ts | 35 +++++- src/entities/task/task.params.ts | 45 +++++++ .../task/ui/{task.jsx => task.card.jsx} | 9 +- .../task/ui/{task.scss => task.card.scss} | 2 +- .../task/ui/task.cards-list.jsx} | 28 +++-- .../task/ui/task.cards-list.scss} | 4 +- .../task/ui/task.sequence.jsx} | 8 +- .../task/ui/task.sequence.scss} | 0 src/entities/wallet/index.ts | 24 +++- .../{providers.tsx => wallet.providers.tsx} | 45 ++----- .../ui/{wallet.scss => wallet.selector.scss} | 0 .../ui/{wallet.tsx => wallet.selector.tsx} | 16 ++- src/entities/wallet/wallet.model.ts | 9 ++ src/entities/wallet/wallet.service.ts | 13 ++ src/families/meta-pool/meta-pool.scss | 2 +- src/families/meta-pool/nslp-add-liquidity.tsx | 2 +- .../meta-pool/nslp-remove-liquidity.tsx | 2 +- src/families/mintbase/add-minter.tsx | 2 +- src/families/mintbase/buy-nft.tsx | 2 +- src/families/mintbase/create-store.tsx | 2 +- src/families/mintbase/mintbase.scss | 2 +- src/families/mintbase/remove-minter.tsx | 2 +- .../mintbase/transfer-store-ownership.tsx | 2 +- src/families/paras/buy-nft.tsx | 2 +- src/families/token-farm/create-token.tsx | 2 +- src/families/token-farm/token-farm.scss | 2 +- .../{ui => }/configure-scheduling.ui.scss | 0 .../{ui => }/configure-scheduling.ui.tsx | 14 +-- src/features/configure-scheduling/index.ts | 2 +- .../edit-task/edit-task.ui.jsx} | 7 +- .../edit-task/edit-task.ui.scss} | 0 src/features/edit-task/index.ts | 11 ++ .../ext-auth.params.ts} | 4 +- .../ext-auth.service.ts} | 11 +- .../ext-auth.ui.scss} | 2 +- src/features/external-auth/ext-auth.ui.tsx | 114 ++++++++++++++++++ src/features/external-auth/index.ts | 7 ++ src/features/external-login/index.ts | 8 -- .../ui/external-login.dialog.tsx | 76 ------------ .../ui/external-login.dialogs.tsx | 22 ---- .../external-login/ui/external-login.menu.tsx | 25 ---- src/features/index.ts | 4 +- src/features/manage-token-whitelist/index.ts | 2 +- .../{ui => }/manage-token-whitelist.ui.scss | 0 .../{ui => }/manage-token-whitelist.ui.tsx | 16 +-- src/features/propose-settings/index.ts | 2 +- .../{ui => }/propose-settings.ui.scss | 0 .../{ui => }/propose-settings.ui.tsx | 20 +-- src/features/workflow-export/index.ts | 5 + .../workflow-export/workflow-export.ui.scss} | 2 +- .../workflow-export/workflow-export.ui.tsx} | 28 +++-- src/index.html | 8 +- src/pages/app/{app.jsx => app-page.ui.jsx} | 22 ++-- src/pages/app/{app.scss => app-page.ui.scss} | 8 +- src/pages/app/global.d.ts | 7 ++ src/pages/app/index.ts | 5 +- src/pages/dao/dao-page.ui.tsx | 16 ++- src/pages/dao/index.ts | 4 +- src/shared/lib/persistent.ts | 5 +- src/shared/lib/wallet.ts | 9 +- src/shared/lib/window.ts | 46 ------- .../near-protocol.params.ts} | 12 +- .../params/workflow-editor.params.ts} | 2 +- src/{app => shared}/static/discord.svg | 0 src/{app => shared}/static/favicon.ico | Bin src/{app => shared}/static/github.svg | 0 src/{app => shared}/static/logo-black.svg | 0 src/{app => shared}/static/logo-white.svg | 0 .../static/meta-pool/MetaPool_logo.png | Bin .../static/meta-pool/MetaPool_logo.svg | 0 .../static/meta-pool/MetaPool_symbol.svg | 0 .../static/mintbase/Mintbase_logo.svg | 0 .../static/mintbase/Mintbase_symbol.svg | 0 .../outline_dynamic_feed_black_24dp.png | Bin src/{app => shared}/static/parallel.svg | 0 .../static/paras/Paras_logo.svg | 0 src/{app => shared}/static/sequence.svg | 0 src/{app => shared}/static/telegram.svg | 0 .../static/token-farm/TokenFarm_symbol.png | Bin src/{app => shared}/static/twitter.svg | 0 ...ector-node.tsx => data-inspector.node.tsx} | 0 ...le-context.ts => data-inspector.params.ts} | 0 .../design/data-inspector/data-inspector.tsx | 4 +- src/shared/ui/design/index.ts | 2 +- .../design/{module-context.ts => params.ts} | 0 src/shared/ui/design/table/row.tsx | 2 +- src/widgets/builder/index.ts | 1 - src/widgets/column/index.ts | 1 - .../dialogs-layer/dialogs-layer.ui.tsx | 7 ++ src/widgets/dialogs-layer/index.ts | 2 +- .../dialogs-layer/ui/dialogs-layer.ui.tsx | 7 -- src/widgets/editor/index.ts | 1 - src/widgets/export/index.ts | 1 - .../{ui => }/funds-overview.ui.scss | 0 .../{ui => }/funds-overview.ui.tsx | 12 +- src/widgets/funds-overview/index.tsx | 14 +-- src/widgets/index.ts | 14 +-- src/widgets/menu/index.ts | 1 - src/widgets/schedule-overview/index.tsx | 14 +-- .../{ui => }/schedule-overview.ui.scss | 0 .../{ui => }/schedule-overview.ui.tsx | 4 +- src/widgets/settings-manager/index.tsx | 14 +-- .../{ui => }/settings-manager.ui.scss | 0 .../{ui => }/settings-manager.ui.tsx | 14 +-- src/widgets/sidebar/index.ts | 10 +- .../sidebar/{sidebar.jsx => sidebar.ui.jsx} | 34 +++--- .../sidebar/{sidebar.scss => sidebar.ui.scss} | 0 src/widgets/workflow-editor/index.ts | 9 ++ .../workflow-editor.ui.jsx} | 26 ++-- .../workflow-editor.ui.scss} | 2 +- 159 files changed, 1203 insertions(+), 1184 deletions(-) rename src/{shared => app}/global.d.ts (68%) rename src/{ => app}/global.scss (100%) rename src/{ => app}/index.tsx (82%) create mode 100644 src/entities/ft/ft.lib.ts create mode 100644 src/entities/ft/ft.model.ts rename src/entities/{fungible-token/module-context.ts => ft/ft.params.ts} (58%) rename src/entities/{fungible-token/model/fungible-token.model.ts => ft/ft.service.ts} (62%) create mode 100644 src/entities/ft/ft.ui.tsx create mode 100644 src/entities/ft/index.ts delete mode 100644 src/entities/fungible-token/index.ts delete mode 100644 src/entities/fungible-token/lib/fungible-token.format.ts delete mode 100644 src/entities/fungible-token/ui/fungible-token.balances.tsx delete mode 100644 src/entities/fungible-token/ui/fungible-token.providers.tsx create mode 100644 src/entities/job/job.lib.ts create mode 100644 src/entities/job/job.model.ts create mode 100644 src/entities/job/job.service.ts rename src/entities/job/{ui/job.entries.scss => job.ui.scss} (52%) create mode 100644 src/entities/job/job.ui.tsx delete mode 100644 src/entities/job/lib/job.format.ts delete mode 100644 src/entities/job/model/job.model.ts delete mode 100644 src/entities/job/ui/job.entries.tsx delete mode 100644 src/entities/job/ui/job.entry.scss delete mode 100644 src/entities/job/ui/job.entry.tsx create mode 100644 src/entities/mi/index.ts create mode 100644 src/entities/mi/mi.model.ts rename src/entities/{multicall-instance/module-context.ts => mi/mi.params.ts} (95%) rename src/entities/{multicall-instance/model/multicall-instance.model.ts => mi/mi.service.ts} (53%) create mode 100644 src/entities/mi/mi.ui.tsx delete mode 100644 src/entities/multicall-instance/index.ts delete mode 100644 src/entities/multicall-instance/ui/multicall-instance.admin.tsx delete mode 100644 src/entities/multicall-instance/ui/multicall-instance.admins.tsx delete mode 100644 src/entities/multicall-instance/ui/multicall-instance.providers.tsx delete mode 100644 src/entities/multicall-instance/ui/multicall-instance.token-whitelist.tsx delete mode 100644 src/entities/multicall-instance/ui/multicall-instance.whitelisted-token.tsx delete mode 100644 src/entities/near-token/index.ts delete mode 100644 src/entities/near-token/lib/near-token.format.ts delete mode 100644 src/entities/near-token/model/near-token.model.ts delete mode 100644 src/entities/near-token/ui/near-token.balances.tsx delete mode 100644 src/entities/near-token/ui/near-token.providers.tsx create mode 100644 src/entities/near/index.ts create mode 100644 src/entities/near/near.lib.ts create mode 100644 src/entities/near/near.model.ts rename src/entities/{near-token/module-context.ts => near/near.params.ts} (77%) create mode 100644 src/entities/near/near.service.ts create mode 100644 src/entities/near/near.ui.tsx delete mode 100644 src/entities/task/config/keywords.ts create mode 100644 src/entities/task/task.params.ts rename src/entities/task/ui/{task.jsx => task.card.jsx} (98%) rename src/entities/task/ui/{task.scss => task.card.scss} (92%) rename src/{widgets/builder/builder.jsx => entities/task/ui/task.cards-list.jsx} (81%) rename src/{widgets/builder/builder.scss => entities/task/ui/task.cards-list.scss} (95%) rename src/{widgets/column/column.jsx => entities/task/ui/task.sequence.jsx} (94%) rename src/{widgets/column/column.scss => entities/task/ui/task.sequence.scss} (100%) rename src/entities/wallet/ui/{providers.tsx => wallet.providers.tsx} (69%) rename src/entities/wallet/ui/{wallet.scss => wallet.selector.scss} (100%) rename src/entities/wallet/ui/{wallet.tsx => wallet.selector.tsx} (95%) create mode 100644 src/entities/wallet/wallet.model.ts create mode 100644 src/entities/wallet/wallet.service.ts rename src/features/configure-scheduling/{ui => }/configure-scheduling.ui.scss (100%) rename src/features/configure-scheduling/{ui => }/configure-scheduling.ui.tsx (93%) rename src/{widgets/editor/editor.jsx => features/edit-task/edit-task.ui.jsx} (93%) rename src/{widgets/editor/editor.scss => features/edit-task/edit-task.ui.scss} (100%) create mode 100644 src/features/edit-task/index.ts rename src/features/{external-login/module-context.ts => external-auth/ext-auth.params.ts} (92%) rename src/features/{external-login/model/external-login.model.ts => external-auth/ext-auth.service.ts} (83%) rename src/features/{external-login/ui/external-login.dialog.scss => external-auth/ext-auth.ui.scss} (97%) create mode 100644 src/features/external-auth/ext-auth.ui.tsx create mode 100644 src/features/external-auth/index.ts delete mode 100644 src/features/external-login/index.ts delete mode 100644 src/features/external-login/ui/external-login.dialog.tsx delete mode 100644 src/features/external-login/ui/external-login.dialogs.tsx delete mode 100644 src/features/external-login/ui/external-login.menu.tsx rename src/features/manage-token-whitelist/{ui => }/manage-token-whitelist.ui.scss (100%) rename src/features/manage-token-whitelist/{ui => }/manage-token-whitelist.ui.tsx (90%) rename src/features/propose-settings/{ui => }/propose-settings.ui.scss (100%) rename src/features/propose-settings/{ui => }/propose-settings.ui.tsx (88%) create mode 100644 src/features/workflow-export/index.ts rename src/{widgets/export/export.scss => features/workflow-export/workflow-export.ui.scss} (99%) rename src/{widgets/export/export.tsx => features/workflow-export/workflow-export.ui.tsx} (96%) rename src/pages/app/{app.jsx => app-page.ui.jsx} (95%) rename src/pages/app/{app.scss => app-page.ui.scss} (86%) create mode 100644 src/pages/app/global.d.ts delete mode 100644 src/shared/lib/window.ts rename src/shared/{config/near-protocol.ts => params/near-protocol.params.ts} (97%) rename src/{entities/task/config/initial-data.ts => shared/params/workflow-editor.params.ts} (98%) rename src/{app => shared}/static/discord.svg (100%) rename src/{app => shared}/static/favicon.ico (100%) rename src/{app => shared}/static/github.svg (100%) rename src/{app => shared}/static/logo-black.svg (100%) rename src/{app => shared}/static/logo-white.svg (100%) rename src/{app => shared}/static/meta-pool/MetaPool_logo.png (100%) rename src/{app => shared}/static/meta-pool/MetaPool_logo.svg (100%) rename src/{app => shared}/static/meta-pool/MetaPool_symbol.svg (100%) rename src/{app => shared}/static/mintbase/Mintbase_logo.svg (100%) rename src/{app => shared}/static/mintbase/Mintbase_symbol.svg (100%) rename src/{app => shared}/static/outline_dynamic_feed_black_24dp.png (100%) rename src/{app => shared}/static/parallel.svg (100%) rename src/{app => shared}/static/paras/Paras_logo.svg (100%) rename src/{app => shared}/static/sequence.svg (100%) rename src/{app => shared}/static/telegram.svg (100%) rename src/{app => shared}/static/token-farm/TokenFarm_symbol.png (100%) rename src/{app => shared}/static/twitter.svg (100%) rename src/shared/ui/design/data-inspector/{data-inspector-node.tsx => data-inspector.node.tsx} (100%) rename src/shared/ui/design/data-inspector/{module-context.ts => data-inspector.params.ts} (100%) rename src/shared/ui/design/{module-context.ts => params.ts} (100%) delete mode 100644 src/widgets/builder/index.ts delete mode 100644 src/widgets/column/index.ts create mode 100644 src/widgets/dialogs-layer/dialogs-layer.ui.tsx delete mode 100644 src/widgets/dialogs-layer/ui/dialogs-layer.ui.tsx delete mode 100644 src/widgets/editor/index.ts delete mode 100644 src/widgets/export/index.ts rename src/widgets/funds-overview/{ui => }/funds-overview.ui.scss (100%) rename src/widgets/funds-overview/{ui => }/funds-overview.ui.tsx (66%) delete mode 100644 src/widgets/menu/index.ts rename src/widgets/schedule-overview/{ui => }/schedule-overview.ui.scss (100%) rename src/widgets/schedule-overview/{ui => }/schedule-overview.ui.tsx (80%) rename src/widgets/settings-manager/{ui => }/settings-manager.ui.scss (100%) rename src/widgets/settings-manager/{ui => }/settings-manager.ui.tsx (86%) rename src/widgets/sidebar/{sidebar.jsx => sidebar.ui.jsx} (92%) rename src/widgets/sidebar/{sidebar.scss => sidebar.ui.scss} (100%) create mode 100644 src/widgets/workflow-editor/index.ts rename src/widgets/{menu/menu.jsx => workflow-editor/workflow-editor.ui.jsx} (74%) rename src/widgets/{menu/menu.scss => workflow-editor/workflow-editor.ui.scss} (99%) diff --git a/package-lock.json b/package-lock.json index 1a40d35f..bac7015e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6593,7 +6593,7 @@ "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuEAuthMwkRMVH1EpIkX5bTZGRB3eCA==", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", diff --git a/src/shared/global.d.ts b/src/app/global.d.ts similarity index 68% rename from src/shared/global.d.ts rename to src/app/global.d.ts index 6666b2ef..0d5f097a 100644 --- a/src/shared/global.d.ts +++ b/src/app/global.d.ts @@ -1,4 +1,10 @@ -import { Account } from "@near-wallet-selector/core"; +import { Account, NetworkId } from "@near-wallet-selector/core"; +import { Component } from "react"; + +import { Task, TaskCardCopy, TaskCardInfo, Wallet } from "../entities"; +import { EditTask } from "../features"; +import { AppPage } from "../pages/app"; +import { Sidebar } from "../widgets"; declare global { /* Temporary workaround fixing typechecking with assets import */ @@ -33,4 +39,8 @@ declare global { * NEAR Protocol account ID */ declare type AccountId = Account["accountId"]; + + interface Window { + EXPORT: Component; + } } diff --git a/src/global.scss b/src/app/global.scss similarity index 100% rename from src/global.scss rename to src/app/global.scss diff --git a/src/index.tsx b/src/app/index.tsx similarity index 82% rename from src/index.tsx rename to src/app/index.tsx index 102c60c0..cca8fdb4 100644 --- a/src/index.tsx +++ b/src/app/index.tsx @@ -1,22 +1,20 @@ import "@near-wallet-selector/modal-ui/styles.css"; -import { lazy, Suspense } from "react"; +import { Suspense } from "react"; import { createRoot } from "react-dom/client"; import { HashRouter, Routes, Route, Navigate } from "react-router-dom"; -import { Wallet } from "./entities"; -import { DialogsLayer, Sidebar } from "./widgets"; - -import "./shared/lib/persistent"; - -const AppPage = lazy(() => import("./pages/app")); -const DAOPage = lazy(() => import("./pages/dao")); +import { Wallet } from "../entities"; +import { AppPage } from "../pages/app"; +import { DAOPage } from "../pages/dao"; +import { DialogsLayer, Sidebar } from "../widgets"; +import "../shared/lib/persistent"; const appMountPoint = document.querySelector("#root") ?? document.createElement("div"); appMountPoint.setAttribute("id", "root"); createRoot(appMountPoint).render( - + - + ); diff --git a/src/entities/ft/ft.lib.ts b/src/entities/ft/ft.lib.ts new file mode 100644 index 00000000..dc675cdf --- /dev/null +++ b/src/entities/ft/ft.lib.ts @@ -0,0 +1,14 @@ +import { Big, formatTokenAmount } from "../../shared/lib/converter"; + +import { FTParams } from "./ft.params"; + +export class FTLib { + public static readonly amountToDisplayAmount = (amount: string, decimals: number): string => { + const formattedAmount = formatTokenAmount(amount, decimals), + minimalDisplayAmount = Big("10").pow(-FTParams.FRACTIONAL_PART_LENGTH).toFixed(); + + return Big(formattedAmount).gt("0") && Big(formattedAmount).lt(minimalDisplayAmount) + ? "< " + minimalDisplayAmount + : formatTokenAmount(amount, decimals, FTParams.FRACTIONAL_PART_LENGTH); + }; +} diff --git a/src/entities/ft/ft.model.ts b/src/entities/ft/ft.model.ts new file mode 100644 index 00000000..54d11a5a --- /dev/null +++ b/src/entities/ft/ft.model.ts @@ -0,0 +1,23 @@ +import { FungibleToken } from "../../shared/lib/standards/fungibleToken"; + +export type FTModel = { + balances: Pick & { + account: string; + multicallInstance: string; + total: string; + }; +}; + +export const FTSchema: { + balances: { + data: null | FTModel["balances"][]; + error: Error | null; + loading: boolean; + }; +} = { + balances: { + data: null, + error: null, + loading: true, + }, +}; diff --git a/src/entities/fungible-token/module-context.ts b/src/entities/ft/ft.params.ts similarity index 58% rename from src/entities/fungible-token/module-context.ts rename to src/entities/ft/ft.params.ts index 7202517a..ac2be53e 100644 --- a/src/entities/fungible-token/module-context.ts +++ b/src/entities/ft/ft.params.ts @@ -1,3 +1,3 @@ -export class ModuleContext { +export class FTParams { static FRACTIONAL_PART_LENGTH = 5; } diff --git a/src/entities/fungible-token/model/fungible-token.model.ts b/src/entities/ft/ft.service.ts similarity index 62% rename from src/entities/fungible-token/model/fungible-token.model.ts rename to src/entities/ft/ft.service.ts index 5e2a64aa..b6c6adbe 100644 --- a/src/entities/fungible-token/model/fungible-token.model.ts +++ b/src/entities/ft/ft.service.ts @@ -1,37 +1,20 @@ import { Account } from "@near-wallet-selector/core"; import { createContext, useEffect, useMemo, useState } from "react"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { Big } from "../../../shared/lib/converter"; -import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; +import { Multicall } from "../../shared/lib/contracts/multicall"; +import { Big } from "../../shared/lib/converter"; +import { FungibleToken } from "../../shared/lib/standards/fungibleToken"; -export interface FTModelInputs { - balances: Pick; -} - -export class FTModel { - public static readonly balances: { - data: - | null - | (Pick & { - account: string; - multicallInstance: string; - total: string; - })[]; +import { FTSchema } from "./ft.model"; - error: Error | null; - loading: boolean; - } = { - data: null, - error: null, - loading: true, - }; +export interface IFTService extends Pick {} - public static readonly BalancesContext = createContext(FTModel.balances); +export class FTService { + public static readonly BalancesContext = createContext(FTSchema.balances); private static readonly balancesFetch = async ( - { accountId }: FTModelInputs["balances"], - callback: (result: typeof FTModel.balances) => void + { accountId }: IFTService, + callback: (result: typeof FTSchema.balances) => void ) => { const miAddress = Multicall.getInstanceAddress(accountId); @@ -74,10 +57,10 @@ export class FTModel { }); }; - public static readonly useBalancesState = (inputs: FTModelInputs["balances"]) => { - const [state, stateUpdate] = useState(FTModel.balances); + public static readonly useBalancesState = (inputs: IFTService) => { + const [state, stateUpdate] = useState(FTSchema.balances); - useEffect(() => void FTModel.balancesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); + useEffect(() => void FTService.balancesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/ft/ft.ui.tsx b/src/entities/ft/ft.ui.tsx new file mode 100644 index 00000000..4b5724e3 --- /dev/null +++ b/src/entities/ft/ft.ui.tsx @@ -0,0 +1,41 @@ +import Big from "big.js"; +import { PropsWithChildren, useContext } from "react"; + +import { IconLabel, NEARIcon } from "../../shared/ui/design"; + +import { FTLib } from "./ft.lib"; +import { FTService, IFTService } from "./ft.service"; + +interface FTBalancesProviderProps extends Pick, IFTService {} + +export const FTBalancesProvider = ({ children, ...modelInputs }: FTBalancesProviderProps) => ( + + {children} + +); + +interface FTBalancesProps { + nonZeroOnly?: boolean; +} + +export const ftBalancesRender = ({ nonZeroOnly = false }: FTBalancesProps) => { + const { data } = useContext(FTService.BalancesContext), + items = nonZeroOnly ? data?.filter(({ total }) => Big(total).gt("0")) : data; + + return ( + items?.map(({ account, metadata, multicallInstance, total }) => ({ + content: [ + } + label={metadata.symbol} + />, + + FTLib.amountToDisplayAmount(multicallInstance, metadata.decimals), + FTLib.amountToDisplayAmount(account, metadata.decimals), + FTLib.amountToDisplayAmount(total, metadata.decimals), + ], + + id: metadata.symbol, + })) ?? null + ); +}; diff --git a/src/entities/ft/index.ts b/src/entities/ft/index.ts new file mode 100644 index 00000000..152cfd28 --- /dev/null +++ b/src/entities/ft/index.ts @@ -0,0 +1,9 @@ +import { FTService } from "./ft.service"; +import { FTParams } from "./ft.params"; +import { FTBalancesProvider, ftBalancesRender } from "./ft.ui"; + +export class FT extends FTParams { + static BalancesContext = FTService.BalancesContext; + static BalancesProvider = FTBalancesProvider; + static balancesRender = ftBalancesRender; +} diff --git a/src/entities/fungible-token/index.ts b/src/entities/fungible-token/index.ts deleted file mode 100644 index 56cf7623..00000000 --- a/src/entities/fungible-token/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ModuleContext } from "./module-context"; -import { FTFormat } from "./lib/fungible-token.format"; -import { FTModel } from "./model/fungible-token.model"; -import { ftBalancesRender } from "./ui/fungible-token.balances"; -import { FTBalancesProvider } from "./ui/fungible-token.providers"; - -export class FT extends ModuleContext { - static BalancesContext = FTModel.BalancesContext; - static BalancesProvider = FTBalancesProvider; - static Format = FTFormat; - static balancesRender = ftBalancesRender; -} diff --git a/src/entities/fungible-token/lib/fungible-token.format.ts b/src/entities/fungible-token/lib/fungible-token.format.ts deleted file mode 100644 index 94e2af2b..00000000 --- a/src/entities/fungible-token/lib/fungible-token.format.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Big, formatTokenAmount } from "../../../shared/lib/converter"; -import { ModuleContext } from "../module-context"; - -const amountToDisplayAmount = (amount: string, decimals: number): string => { - const formattedAmount = formatTokenAmount(amount, decimals), - minimalDisplayAmount = Big("10").pow(-ModuleContext.FRACTIONAL_PART_LENGTH).toFixed(); - - return Big(formattedAmount).gt("0") && Big(formattedAmount).lt(minimalDisplayAmount) - ? "< " + minimalDisplayAmount - : formatTokenAmount(amount, decimals, ModuleContext.FRACTIONAL_PART_LENGTH); -}; - -export const FTFormat = { - amountToDisplayAmount, -}; diff --git a/src/entities/fungible-token/ui/fungible-token.balances.tsx b/src/entities/fungible-token/ui/fungible-token.balances.tsx deleted file mode 100644 index 075e081d..00000000 --- a/src/entities/fungible-token/ui/fungible-token.balances.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import Big from "big.js"; -import { useContext } from "react"; - -import { IconLabel, NEARIcon } from "../../../shared/ui/design"; -import { FTFormat } from "../lib/fungible-token.format"; -import { FTModel } from "../model/fungible-token.model"; - -interface FTBalancesProps { - nonZeroOnly?: boolean; -} - -export const ftBalancesRender = ({ nonZeroOnly = false }: FTBalancesProps) => { - const { data } = useContext(FTModel.BalancesContext), - items = nonZeroOnly ? data?.filter(({ total }) => Big(total).gt("0")) : data; - - return ( - items?.map(({ account, metadata, multicallInstance, total }) => ({ - content: [ - } - label={metadata.symbol} - />, - - FTFormat.amountToDisplayAmount(multicallInstance, metadata.decimals), - FTFormat.amountToDisplayAmount(account, metadata.decimals), - FTFormat.amountToDisplayAmount(total, metadata.decimals), - ], - - id: metadata.symbol, - })) ?? null - ); -}; diff --git a/src/entities/fungible-token/ui/fungible-token.providers.tsx b/src/entities/fungible-token/ui/fungible-token.providers.tsx deleted file mode 100644 index 40edf26a..00000000 --- a/src/entities/fungible-token/ui/fungible-token.providers.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { PropsWithChildren } from "react"; - -import { FTModel, FTModelInputs } from "../model/fungible-token.model"; - -interface FTBalancesProviderProps - extends Pick, - Pick {} - -export const FTBalancesProvider = ({ children, ...modelInputs }: FTBalancesProviderProps) => ( - - {children} - -); diff --git a/src/entities/index.ts b/src/entities/index.ts index 119606c7..3c90bdee 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -1,6 +1,6 @@ -export { Task } from "./task"; +export { FT } from "./ft"; export { Job } from "./job"; -export { FT } from "./fungible-token"; -export { MulticallInstance } from "./multicall-instance"; -export { NEARToken } from "./near-token"; +export { MI } from "./mi"; +export { NEAR } from "./near"; +export { Task } from "./task"; export { Wallet } from "./wallet"; diff --git a/src/entities/job/index.ts b/src/entities/job/index.ts index 91a34b80..f4f7260c 100644 --- a/src/entities/job/index.ts +++ b/src/entities/job/index.ts @@ -1,4 +1,4 @@ -import { JobEntriesTable, JobEntriesTableProps } from "./ui/job.entries"; +import { JobEntriesTable, JobEntriesTableProps } from "./job.ui"; export class Job { static EntriesTable = JobEntriesTable; diff --git a/src/entities/job/job.lib.ts b/src/entities/job/job.lib.ts new file mode 100644 index 00000000..5aa59b1e --- /dev/null +++ b/src/entities/job/job.lib.ts @@ -0,0 +1,71 @@ +import { Base64 } from "js-base64"; + +import { JobData } from "../../shared/lib/contracts/multicall"; +import { Big } from "../../shared/lib/converter"; + +import { JobModel } from "./job.model"; + +export class JobLib { + /** + * Job status is: + * - running: job is active, and was triggered at least once. + * - active: job is active, but not triggered yet. + * - Expired: job not active, and execution moment is in the past. + * - Inactive: job not active, but execution moment in the future. + */ + public static readonly toStatus = ({ job }: JobData): JobModel["job"]["status"] => { + if (job.is_active) { + return job.run_count > -1 ? "running" : "active"; + } else { + /** + * Date.now() returns timestamp in milliseconds, we use nanoseconds + */ + const currentTime = Big(Date.now()).times("1000000"); + + return currentTime.gt(job.start_at) ? "expired" : "inactive"; + } + }; + + /** + * Decodes base64-encoded arguments of for every multicall's FunctionCall + * and returns a new data structure with encoded version replaced with decoded one. + * + * @returns Updated job data structure. + */ + public static readonly toDecoded = ({ id, job }: JobData): JobData => ({ + id, + + job: { + ...job, + + multicalls: job.multicalls.map((multicall) => ({ + ...multicall, + + calls: multicall.calls.map((batchCalls) => + batchCalls.map((batchCall) => ({ + ...batchCall, + + actions: batchCall.actions.map((action) => ({ + ...action, + + args: JSON.parse(Base64.decode(action.args)), + })), + })) + ), + })), + }, + }); + + /** + * Calculates the actual job status from the given data + * and adds it as an additional property to the new data structure. + * + * If a calculation error has ocurred, the `"Unknown"` status is being presented. + * + * @returns Extended job data structure. + */ + public static readonly toNormalized = (job: JobData): JobModel => ({ + ...job, + job: { ...job.job, status: JobLib.toStatus(job) }, + }); +} diff --git a/src/entities/job/job.model.ts b/src/entities/job/job.model.ts new file mode 100644 index 00000000..386fc318 --- /dev/null +++ b/src/entities/job/job.model.ts @@ -0,0 +1,20 @@ +import { JobData } from "../../shared/lib/contracts/multicall"; + +export type JobModel = Omit & { + job: JobData["job"] & { + status: "inactive" | "expired" | "active" | "running" | "unknown"; + }; +}; + +export const JobsSchema: { + /** + * Jobs indexed by ID for easy access to each particular job + */ + data: Record | null; + error?: Error | null; + loading: boolean; +} = { + data: null, + error: null, + loading: true, +}; diff --git a/src/entities/job/job.service.ts b/src/entities/job/job.service.ts new file mode 100644 index 00000000..56ac4572 --- /dev/null +++ b/src/entities/job/job.service.ts @@ -0,0 +1,49 @@ +import { useEffect, useMemo, useState } from "react"; + +import { Multicall } from "../../shared/lib/contracts/multicall"; + +import { JobLib } from "./job.lib"; +import { JobsSchema } from "./job.model"; + +export interface IJobService { + multicallInstance: Multicall; +} + +export class JobService { + private static readonly allEntriesFetch = async ( + { multicallInstance }: IJobService, + callback: (result: typeof JobsSchema) => void + ) => + void ( + multicallInstance.ready && + callback( + await multicallInstance + .getJobs() + .then((data) => ({ + data: data.reduce( + (jobsIndexedById, job) => ({ + ...jobsIndexedById, + [job.id]: JobLib.toDecoded(JobLib.toNormalized(job)), + }), + {} + ), + + error: null, + loading: false, + })) + .catch((error) => ({ data: null, error, loading: false })) + ) + ); + + public static readonly useAllEntriesState = (inputs: IJobService) => { + const [state, stateUpdate] = useState(JobsSchema); + + useEffect(() => void JobService.allEntriesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); + + useEffect(() => { + state.error instanceof Error && void console.error(state.error); + }, [state.error]); + + return useMemo(() => state, [...Object.values(inputs), state]); + }; +} diff --git a/src/entities/job/ui/job.entries.scss b/src/entities/job/job.ui.scss similarity index 52% rename from src/entities/job/ui/job.entries.scss rename to src/entities/job/job.ui.scss index 0ba1b84d..d4785576 100644 --- a/src/entities/job/ui/job.entries.scss +++ b/src/entities/job/job.ui.scss @@ -1,7 +1,34 @@ @use "sass/color"; @use "sass/font"; +@use "sass/mixin"; @use "sass/size"; +.Job { + &-dataInspector { + &-label { + width: fit-content; + margin-left: auto; + } + } + + &-action { + margin-top: 0.5 * size.$gap; + margin-left: 0.5 * size.$gap; + padding: 0 1em; + border-radius: size.$task-radius; + border: 2px solid color.$blue; + font-size: size.$text; + font-weight: 800; + color: darken(color.$blue, 30%) !important; + background-color: rgba(color.$blue, 0.2); + float: right; + + &:hover { + background-color: color.$blue; + } + } +} + .JobEntriesTable { grid-area: JobEntriesTable; diff --git a/src/entities/job/job.ui.tsx b/src/entities/job/job.ui.tsx new file mode 100644 index 00000000..2410cbdc --- /dev/null +++ b/src/entities/job/job.ui.tsx @@ -0,0 +1,111 @@ +import clsx from "clsx"; +import { NavLink } from "react-router-dom"; + +import { Big, toTGas } from "../../shared/lib/converter"; +import { DataInspector, IconLabel, Scrollable, Table, Tile } from "../../shared/ui/design"; + +import { JobModel } from "./job.model"; +import { IJobService, JobService } from "./job.service"; +import "./job.ui.scss"; + +const _Job = "Job"; + +const JobStatusIcons: Record = { + inactive: "🟡", + expired: "🔴", + active: "🟢", + running: "🟣", + unknown: "❔", +}; + +const JobDisplayStatus = ({ job }: Pick) => { + const statusToLabel = (status: JobModel["job"]["status"]): JobModel["job"]["status"] | string => + status === "running" ? `Running: ${job.run_count + 1}/${job.multicalls.length}` : status; + + return ( + + ); +}; + +export const jobAsTableRow = ({ id, job }: JobModel) => ({ + content: [ + , + id, + /** Multicall returns timestamp in nanoseconds, JS Date uses milliseconds */ + new Date(parseInt(Big(job.start_at).div("1000000").toFixed())).toLocaleString(), + job.croncat_hash.length === 0 ? none : job.croncat_hash, + job.creator, + `${toTGas(job.trigger_gas)} Tgas`, + + <> + + + {job.multicalls.length === 1 && ( + setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0)} + > + Open in Editor + + )} + + + , + ], + + id: id.toString(), +}); + +const _JobEntriesTable = "JobEntriesTable"; + +export interface JobEntriesTableProps extends IJobService { + className?: string; +} + +export const JobEntriesTable = ({ className, ...modelInputs }: JobEntriesTableProps) => { + const { data, error, loading } = JobService.useAllEntriesState(modelInputs), + items = Object.values(data ?? {}); + + return ( + + +
    + + + ); +}; diff --git a/src/entities/job/lib/job.format.ts b/src/entities/job/lib/job.format.ts deleted file mode 100644 index a1ce8530..00000000 --- a/src/entities/job/lib/job.format.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Base64 } from "js-base64"; - -import { JobData } from "../../../shared/lib/contracts/multicall"; -import { Big } from "../../../shared/lib/converter"; -import { JobDataWithStatus, JobStatus } from "../model/job.model"; - -/** - * Job status is: - * - running: job is active, and was triggered at least once. - * - active: job is active, but not triggered yet. - * - Expired: job not active, and execution moment is in the past. - * - Inactive: job not active, but execution moment in the future. - */ -const jobToStatus = ({ job }: JobData): JobStatus => { - if (job.is_active) { - if (job.run_count > -1) return JobStatus.Running; - else return JobStatus.Active; - } else { - // Date.now() returns timestamp in milliseconds, we use nanoseconds - const currentTime = Big(Date.now()).times("1000000"); - const jobTime = job.start_at; - if (currentTime.gt(jobTime)) return JobStatus.Expired; - else return JobStatus.Inactive; - } -}; - -/** - * Decodes base64-encoded arguments of for every multicall's FunctionCall - * and returns a new data structure with encoded version replaced with decoded one. - * - * @returns Updated job data structure. - */ -const withMulticallsDataDecoded = ({ id, job }: JobData): JobData => ({ - id, - - job: { - ...job, - - multicalls: job.multicalls.map((multicall) => ({ - ...multicall, - - calls: multicall.calls.map((batchCalls) => - batchCalls.map((batchCall) => ({ - ...batchCall, - - actions: batchCall.actions.map((action) => ({ - ...action, - - args: JSON.parse(Base64.decode(action.args)), - })), - })) - ), - })), - }, -}); - -/** - * Calculates the actual job status from the given data - * and adds it as an additional property to the new data structure. - * - * If a calculation error has ocurred, the `"Unknown"` status is being presented. - * - * @returns Extended job data structure. - */ -const withStatus = (job: JobData): JobDataWithStatus => ({ - ...job, - job: { ...job.job, status: JobStatus[jobToStatus(job)] }, -}); - -export const JobFormat = { - withMulticallsDataDecoded, - withStatus, -}; diff --git a/src/entities/job/model/job.model.ts b/src/entities/job/model/job.model.ts deleted file mode 100644 index 38198922..00000000 --- a/src/entities/job/model/job.model.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { useEffect, useMemo, useState } from "react"; - -import { JobData, Multicall } from "../../../shared/lib/contracts/multicall"; -import { JobFormat } from "../lib/job.format"; - -export interface JobModelInputs { - multicallInstance: Multicall; -} - -export enum JobStatus { - Inactive = "Inactive", - Expired = "Expired", - Active = "Active", - Running = "Running", - Unknown = "Unknown", -} - -export type JobDataWithStatus = Omit & { - job: JobData["job"] & { status: JobStatus }; -}; - -export class JobModel { - public static readonly allEntries: { - /** Jobs indexed by ID for easy access to each particular job */ - data: Record | null; - error?: Error | null; - loading: boolean; - } = { - data: null, - error: null, - loading: true, - }; - - private static readonly allEntriesFetch = async ( - { multicallInstance }: JobModelInputs, - callback: (result: typeof JobModel.allEntries) => void - ) => - void ( - multicallInstance.ready && - callback( - await multicallInstance - .getJobs() - .then((data) => ({ - data: data.reduce( - (jobsIndexedById, job) => ({ - ...jobsIndexedById, - [job.id]: JobFormat.withMulticallsDataDecoded(JobFormat.withStatus(job)), - }), - {} - ), - - error: null, - loading: false, - })) - .catch((error) => ({ data: null, error, loading: false })) - ) - ); - - public static readonly useAllEntriesState = (inputs: JobModelInputs) => { - const [state, stateUpdate] = useState(JobModel.allEntries); - - useEffect(() => void JobModel.allEntriesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); - - useEffect(() => { - state.error instanceof Error && void console.error(state.error); - }, [state.error]); - - return useMemo(() => state, [...Object.values(inputs), state]); - }; -} diff --git a/src/entities/job/ui/job.entries.tsx b/src/entities/job/ui/job.entries.tsx deleted file mode 100644 index de2a4a2c..00000000 --- a/src/entities/job/ui/job.entries.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import clsx from "clsx"; - -import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { JobModel, JobModelInputs } from "../model/job.model"; - -import { jobAsTableRow } from "./job.entry"; -import "./job.entries.scss"; - -const _JobEntriesTable = "JobEntriesTable"; - -export interface JobEntriesTableProps extends JobModelInputs { - className?: string; -} - -export const JobEntriesTable = ({ className, ...modelInputs }: JobEntriesTableProps) => { - const { data, error, loading } = JobModel.useAllEntriesState(modelInputs), - items = Object.values(data ?? {}); - - return ( - - -
    - - - ); -}; diff --git a/src/entities/job/ui/job.entry.scss b/src/entities/job/ui/job.entry.scss deleted file mode 100644 index e2c06f97..00000000 --- a/src/entities/job/ui/job.entry.scss +++ /dev/null @@ -1,29 +0,0 @@ -@use "sass/color"; -@use "sass/size"; -@use "sass/mixin"; - -.Job { - &-dataInspector { - &-label { - width: fit-content; - margin-left: auto; - } - } - - &-action { - margin-top: 0.5 * size.$gap; - margin-left: 0.5 * size.$gap; - padding: 0 1em; - border-radius: size.$task-radius; - border: 2px solid color.$blue; - font-size: size.$text; - font-weight: 800; - color: darken(color.$blue, 30%) !important; - background-color: rgba(color.$blue, 0.2); - float: right; - - &:hover { - background-color: color.$blue; - } - } -} diff --git a/src/entities/job/ui/job.entry.tsx b/src/entities/job/ui/job.entry.tsx deleted file mode 100644 index e3bd125d..00000000 --- a/src/entities/job/ui/job.entry.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { Icon } from "@mui/material"; -import { NavLink } from "react-router-dom"; - -import { Big, toTGas } from "../../../shared/lib/converter"; -import { DataInspector, IconLabel } from "../../../shared/ui/design"; -import { JobDataWithStatus, JobStatus } from "../model/job.model"; - -import "./job.entry.scss"; - -const _Job = "Job"; - -const JobStatusIcons = { - [JobStatus.Inactive]: "🟡", - [JobStatus.Expired]: "🔴", - [JobStatus.Active]: "🟢", - [JobStatus.Running]: "🟣", - [JobStatus.Unknown]: "❔", -}; - -const JobDisplayStatus = ({ job }: Pick) => { - const statusTextByStatus = { - ...JobStatus, - [JobStatus.Running]: `${JobStatus.Running}: ${job.run_count + 1}/${job.multicalls.length}`, - }; - - return ( - - ); -}; - -export const jobAsTableRow = ({ id, job }: JobDataWithStatus) => ({ - content: [ - , - id, - /** Multicall returns timestamp in nanoseconds, JS Date uses milliseconds */ - new Date(parseInt(Big(job.start_at).div("1000000").toFixed())).toLocaleString(), - job.croncat_hash.length === 0 ? none : job.croncat_hash, - job.creator, - `${toTGas(job.trigger_gas)} Tgas`, - - <> - - - {job.multicalls.length === 1 && ( - setTimeout(() => window.LAYOUT.fromJSON(job.multicalls[0].calls), 0)} - > - Open in Editor - - )} - - - , - ], - - id: id.toString(), -}); diff --git a/src/entities/mi/index.ts b/src/entities/mi/index.ts new file mode 100644 index 00000000..55936569 --- /dev/null +++ b/src/entities/mi/index.ts @@ -0,0 +1,10 @@ +import { MIParams } from "./mi.params"; +import { MIService } from "./mi.service"; +import { MIAdminsTable, MIContextProvider, MITokenWhitelistTable } from "./mi.ui"; + +export class MI extends MIParams { + static Context = MIService.Context; + static ContextProvider = MIContextProvider; + static AdminsTable = MIAdminsTable; + static TokenWhitelistTable = MITokenWhitelistTable; +} diff --git a/src/entities/mi/mi.model.ts b/src/entities/mi/mi.model.ts new file mode 100644 index 00000000..107a497d --- /dev/null +++ b/src/entities/mi/mi.model.ts @@ -0,0 +1,11 @@ +import { Multicall } from "../../shared/lib/contracts/multicall"; + +export const MISchema: { + data: Multicall; + error: Error | null; + loading: boolean; +} = { + data: new Multicall(""), + error: null, + loading: true, +}; diff --git a/src/entities/multicall-instance/module-context.ts b/src/entities/mi/mi.params.ts similarity index 95% rename from src/entities/multicall-instance/module-context.ts rename to src/entities/mi/mi.params.ts index f094847e..ea64c82d 100644 --- a/src/entities/multicall-instance/module-context.ts +++ b/src/entities/mi/mi.params.ts @@ -1,7 +1,7 @@ import { toYocto } from "../../shared/lib/converter"; import { Color } from "../../shared/ui/design"; -export class ModuleContext { +export class MIParams { /** * Minimum balance needed for storage + state. */ diff --git a/src/entities/multicall-instance/model/multicall-instance.model.ts b/src/entities/mi/mi.service.ts similarity index 53% rename from src/entities/multicall-instance/model/multicall-instance.model.ts rename to src/entities/mi/mi.service.ts index cc89f10e..9fea5061 100644 --- a/src/entities/multicall-instance/model/multicall-instance.model.ts +++ b/src/entities/mi/mi.service.ts @@ -1,24 +1,16 @@ import { createContext, useEffect, useMemo, useState } from "react"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; +import { Multicall } from "../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; -export interface MIModelInputs { +import { MISchema } from "./mi.model"; + +export interface IMIService { daoAddress: SputnikDAO["address"]; } -export class MIModel { - public static readonly properties: { - data: Multicall; - error: Error | null; - loading: boolean; - } = { - data: new Multicall(""), - error: null, - loading: true, - }; - - public static readonly Context = createContext(MIModel.properties); +export class MIService { + public static readonly Context = createContext(MISchema); /** * Calls the given callback with a result of multicall contract instantiation, @@ -28,8 +20,8 @@ export class MIModel { * @param callback Stateful data fetch callback */ private static readonly propertiesFetch = async ( - { daoAddress }: MIModelInputs, - callback: (result: typeof MIModel.properties) => void + { daoAddress }: IMIService, + callback: (result: typeof MISchema) => void ) => callback( await Multicall.init(Multicall.getInstanceAddress(daoAddress)).then((multicallInstance) => ({ @@ -39,10 +31,10 @@ export class MIModel { })) ); - public static readonly usePropertiesState = (inputs: MIModelInputs) => { - const [state, stateUpdate] = useState(MIModel.properties); + public static readonly usePropertiesState = (inputs: IMIService) => { + const [state, stateUpdate] = useState(MISchema); - useEffect(() => void MIModel.propertiesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); + useEffect(() => void MIService.propertiesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/mi/mi.ui.tsx b/src/entities/mi/mi.ui.tsx new file mode 100644 index 00000000..8389052b --- /dev/null +++ b/src/entities/mi/mi.ui.tsx @@ -0,0 +1,112 @@ +import { PropsWithChildren, useContext } from "react"; + +import { FungibleToken } from "../../shared/lib/standards/fungibleToken"; +import { NEARLink, NEARLinkProps, Scrollable, Table, TableProps, Tile, TileProps } from "../../shared/ui/design"; + +import { MIService, IMIService } from "./mi.service"; + +export interface MIContextProviderProps extends Pick, IMIService {} + +export const MIContextProvider = ({ children, ...modelInputs }: MIContextProviderProps) => ( + + {children} + +); + +export interface MIAdminProps extends NEARLinkProps {} + +const MIAdmin = ({ address }: MIAdminProps) => ( + + + +); + +export const miAdminAsTableRow = (item: MIAdminProps["address"]) => ({ + content: [], + id: item, +}); + +interface MIAdminsTableProps { + className?: string; + itemsAdditional?: MIAdminProps["address"][]; +} + +export const MIAdminsTable = ({ className, itemsAdditional }: MIAdminsTableProps) => { + const { data, error, loading } = useContext(MIService.Context), + items = (data?.admins ?? []).concat(itemsAdditional ?? []); + + return ( + + +
    + + + ); +}; + +export interface MIWhitelistedTokenProps { + address: FungibleToken["address"]; +} + +const MIWhitelistedToken = ({ address }: MIWhitelistedTokenProps) => ( + + + +); + +export const miWhitelistedTokenAsTableRow = (item: MIWhitelistedTokenProps["address"]) => ({ + content: [], + id: item, +}); + +interface MITokenWhitelistTableProps extends Pick { + ItemProps?: TableProps["RowProps"]; + className?: string; + itemsAdditional?: MIWhitelistedTokenProps["address"][]; + onItemsSelected?: TableProps["onRowsSelected"]; +} + +export const MITokenWhitelistTable = ({ + ItemProps, + className, + footer, + headerSlots, + itemsAdditional, + onItemsSelected, + subheader, +}: MITokenWhitelistTableProps) => { + const multicallInstance = useContext(MIService.Context), + items = (multicallInstance.data?.tokensWhitelist ?? []).concat(itemsAdditional ?? []), + tileProps = { ...multicallInstance, footer, headerSlots, subheader }; + + return ( + + +
    + + + ); +}; diff --git a/src/entities/multicall-instance/index.ts b/src/entities/multicall-instance/index.ts deleted file mode 100644 index 221e6096..00000000 --- a/src/entities/multicall-instance/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ModuleContext } from "./module-context"; -import { MIModel } from "./model/multicall-instance.model"; -import { MIAdminsTable } from "./ui/multicall-instance.admins"; -import { MIContextProvider } from "./ui/multicall-instance.providers"; -import { MITokenWhitelistTable } from "./ui/multicall-instance.token-whitelist"; - -export class MulticallInstance extends ModuleContext { - static Context = MIModel.Context; - static ContextProvider = MIContextProvider; - static AdminsTable = MIAdminsTable; - static TokenWhitelistTable = MITokenWhitelistTable; -} diff --git a/src/entities/multicall-instance/ui/multicall-instance.admin.tsx b/src/entities/multicall-instance/ui/multicall-instance.admin.tsx deleted file mode 100644 index bc6d692c..00000000 --- a/src/entities/multicall-instance/ui/multicall-instance.admin.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { NEARLink, NEARLinkProps } from "../../../shared/ui/design"; - -export interface MIAdminProps extends NEARLinkProps {} - -const MIAdmin = ({ address }: MIAdminProps) => ( - - - -); - -export const miAdminAsTableRow = (item: MIAdminProps["address"]) => ({ - content: [], - id: item, -}); diff --git a/src/entities/multicall-instance/ui/multicall-instance.admins.tsx b/src/entities/multicall-instance/ui/multicall-instance.admins.tsx deleted file mode 100644 index 3a5606a7..00000000 --- a/src/entities/multicall-instance/ui/multicall-instance.admins.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { useContext } from "react"; -import { Scrollable, Table, Tile } from "../../../shared/ui/design"; -import { MIModel } from "../model/multicall-instance.model"; - -import { miAdminAsTableRow, MIAdminProps } from "./multicall-instance.admin"; - -interface MIAdminsTableProps { - className?: string; - itemsAdditional?: MIAdminProps["address"][]; -} - -export const MIAdminsTable = ({ className, itemsAdditional }: MIAdminsTableProps) => { - const { data, error, loading } = useContext(MIModel.Context), - items = (data?.admins ?? []).concat(itemsAdditional ?? []); - - return ( - - -
    - - - ); -}; diff --git a/src/entities/multicall-instance/ui/multicall-instance.providers.tsx b/src/entities/multicall-instance/ui/multicall-instance.providers.tsx deleted file mode 100644 index 59a025e3..00000000 --- a/src/entities/multicall-instance/ui/multicall-instance.providers.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { PropsWithChildren } from "react"; - -import { MIModel, MIModelInputs } from "../model/multicall-instance.model"; - -export interface MIContextProviderProps extends Pick, MIModelInputs {} - -export const MIContextProvider = ({ children, ...modelInputs }: MIContextProviderProps) => ( - {children} -); diff --git a/src/entities/multicall-instance/ui/multicall-instance.token-whitelist.tsx b/src/entities/multicall-instance/ui/multicall-instance.token-whitelist.tsx deleted file mode 100644 index 1d36b46a..00000000 --- a/src/entities/multicall-instance/ui/multicall-instance.token-whitelist.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { useContext } from "react"; - -import { Scrollable, Table, TableProps, Tile, TileProps } from "../../../shared/ui/design"; -import { MIModel } from "../model/multicall-instance.model"; - -import { MIWhitelistedTokenProps, miWhitelistedTokenAsTableRow } from "./multicall-instance.whitelisted-token"; - -interface MITokenWhitelistTableProps extends Pick { - ItemProps?: TableProps["RowProps"]; - className?: string; - itemsAdditional?: MIWhitelistedTokenProps["address"][]; - onItemsSelected?: TableProps["onRowsSelected"]; -} - -export const MITokenWhitelistTable = ({ - ItemProps, - className, - footer, - headerSlots, - itemsAdditional, - onItemsSelected, - subheader, -}: MITokenWhitelistTableProps) => { - const multicallInstance = useContext(MIModel.Context), - items = (multicallInstance.data?.tokensWhitelist ?? []).concat(itemsAdditional ?? []), - tileProps = { ...multicallInstance, footer, headerSlots, subheader }; - - return ( - - -
    - - - ); -}; diff --git a/src/entities/multicall-instance/ui/multicall-instance.whitelisted-token.tsx b/src/entities/multicall-instance/ui/multicall-instance.whitelisted-token.tsx deleted file mode 100644 index ddc7554d..00000000 --- a/src/entities/multicall-instance/ui/multicall-instance.whitelisted-token.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { FungibleToken } from "../../../shared/lib/standards/fungibleToken"; -import { NEARLink } from "../../../shared/ui/design"; - -export interface MIWhitelistedTokenProps { - address: FungibleToken["address"]; -} - -const MIWhitelistedToken = ({ address }: MIWhitelistedTokenProps) => ( - - - -); - -export const miWhitelistedTokenAsTableRow = (item: MIWhitelistedTokenProps["address"]) => ({ - content: [], - id: item, -}); diff --git a/src/entities/near-token/index.ts b/src/entities/near-token/index.ts deleted file mode 100644 index d6fd366c..00000000 --- a/src/entities/near-token/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ModuleContext } from "./module-context"; -import { NEARTokenFormat } from "./lib/near-token.format"; -import { NEARTokenModel } from "./model/near-token.model"; -import { nearTokenBalancesRender } from "./ui/near-token.balances"; -import { NEARTokenBalancesProvider } from "./ui/near-token.providers"; - -export class NEARToken extends ModuleContext { - static BalancesContext = NEARTokenModel.BalancesContext; - static BalancesProvider = NEARTokenBalancesProvider; - static Format = NEARTokenFormat; - static balancesRender = nearTokenBalancesRender; -} diff --git a/src/entities/near-token/lib/near-token.format.ts b/src/entities/near-token/lib/near-token.format.ts deleted file mode 100644 index 50429d67..00000000 --- a/src/entities/near-token/lib/near-token.format.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { formatTokenAmount } from "../../../shared/lib/converter"; -import { ModuleContext } from "../module-context"; - -const amountToDisplayAmount = (amount: string): string => - formatTokenAmount(amount, ModuleContext.DECIMALS, ModuleContext.FRACTIONAL_PART_LENGTH); - -export const NEARTokenFormat = { - amountToDisplayAmount, -}; diff --git a/src/entities/near-token/model/near-token.model.ts b/src/entities/near-token/model/near-token.model.ts deleted file mode 100644 index 2188a3ae..00000000 --- a/src/entities/near-token/model/near-token.model.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Account } from "@near-wallet-selector/core"; -import { createContext, useEffect, useMemo, useState } from "react"; - -import { Big } from "../../../shared/lib/converter"; -import { viewAccount } from "../../../shared/lib/wallet"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; - -export interface NEARTokenModelInputs { - balances: Pick; -} - -export class NEARTokenModel { - public static readonly balances: { - data: null | { - account: string; - multicallInstance: string; - total: string; - }; - - error: Error | null; - loading: boolean; - } = { - data: null, - error: null, - loading: true, - }; - - public static readonly BalancesContext = createContext(NEARTokenModel.balances); - - private static readonly balancesFetch = async ( - { accountId }: NEARTokenModelInputs["balances"], - callback: (result: typeof NEARTokenModel.balances) => void - ) => { - const [{ amount: account }, { amount: multicallInstance }] = await Promise.all([ - viewAccount(accountId), - viewAccount(Multicall.getInstanceAddress(accountId)), - ]); - - return callback({ - data: { - account, - multicallInstance, - total: Big(account).add(multicallInstance).toFixed(), - }, - - error: null, - loading: false, - }); - }; - - public static readonly useBalancesState = (inputs: NEARTokenModelInputs["balances"]) => { - const [state, stateUpdate] = useState(NEARTokenModel.balances); - - useEffect( - () => void NEARTokenModel.balancesFetch(inputs, stateUpdate), - [...Object.values(inputs), stateUpdate] - ); - - useEffect(() => { - state.error instanceof Error && void console.error(state.error); - }, [state.error]); - - return useMemo(() => state, [...Object.values(inputs), ...Object.values(state)]); - }; -} diff --git a/src/entities/near-token/ui/near-token.balances.tsx b/src/entities/near-token/ui/near-token.balances.tsx deleted file mode 100644 index 67b8e17c..00000000 --- a/src/entities/near-token/ui/near-token.balances.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { useContext } from "react"; - -import { IconLabel, NEARIcon } from "../../../shared/ui/design"; -import { NEARTokenFormat } from "../lib/near-token.format"; -import { NEARTokenModel } from "../model/near-token.model"; - -export const nearTokenBalancesRender = () => { - const { data } = useContext(NEARTokenModel.BalancesContext); - - return data === null - ? data - : { - content: [ - } - label="NEAR" - />, - - NEARTokenFormat.amountToDisplayAmount(data.multicallInstance), - NEARTokenFormat.amountToDisplayAmount(data.account), - NEARTokenFormat.amountToDisplayAmount(data.total), - ], - - id: "NEAR", - }; -}; diff --git a/src/entities/near-token/ui/near-token.providers.tsx b/src/entities/near-token/ui/near-token.providers.tsx deleted file mode 100644 index 2a100932..00000000 --- a/src/entities/near-token/ui/near-token.providers.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { PropsWithChildren } from "react"; - -import { NEARTokenModel, NEARTokenModelInputs } from "../model/near-token.model"; - -interface NEARTokenBalancesProviderProps - extends Pick, - Pick {} - -export const NEARTokenBalancesProvider = ({ children, ...modelInputs }: NEARTokenBalancesProviderProps) => ( - - {children} - -); diff --git a/src/entities/near/index.ts b/src/entities/near/index.ts new file mode 100644 index 00000000..d12b59a8 --- /dev/null +++ b/src/entities/near/index.ts @@ -0,0 +1,9 @@ +import { NEARParams } from "./near.params"; +import { NEARService } from "./near.service"; +import { NEARBalancesProvider, nearBalancesRender } from "./near.ui"; + +export class NEAR extends NEARParams { + static BalancesContext = NEARService.BalancesContext; + static BalancesProvider = NEARBalancesProvider; + static balancesRender = nearBalancesRender; +} diff --git a/src/entities/near/near.lib.ts b/src/entities/near/near.lib.ts new file mode 100644 index 00000000..7393a136 --- /dev/null +++ b/src/entities/near/near.lib.ts @@ -0,0 +1,8 @@ +import { formatTokenAmount } from "../../shared/lib/converter"; + +import { NEARParams } from "./near.params"; + +export class NEARLib { + public static readonly amountToDisplayAmount = (amount: string): string => + formatTokenAmount(amount, NEARParams.DECIMALS, NEARParams.FRACTIONAL_PART_LENGTH); +} diff --git a/src/entities/near/near.model.ts b/src/entities/near/near.model.ts new file mode 100644 index 00000000..edfc024a --- /dev/null +++ b/src/entities/near/near.model.ts @@ -0,0 +1,21 @@ +export type NEARModel = { + balances: { + account: string; + multicallInstance: string; + total: string; + }; +}; + +export const NEARSchema: { + balances: { + data: null | NEARModel["balances"]; + error: Error | null; + loading: boolean; + }; +} = { + balances: { + data: null, + error: null, + loading: true, + }, +}; diff --git a/src/entities/near-token/module-context.ts b/src/entities/near/near.params.ts similarity index 77% rename from src/entities/near-token/module-context.ts rename to src/entities/near/near.params.ts index ee43bc90..e864b9ec 100644 --- a/src/entities/near-token/module-context.ts +++ b/src/entities/near/near.params.ts @@ -1,4 +1,4 @@ -export class ModuleContext { +export class NEARParams { public static readonly DECIMALS = 24; public static readonly FRACTIONAL_PART_LENGTH = 5; } diff --git a/src/entities/near/near.service.ts b/src/entities/near/near.service.ts new file mode 100644 index 00000000..723231e6 --- /dev/null +++ b/src/entities/near/near.service.ts @@ -0,0 +1,47 @@ +import { Account } from "@near-wallet-selector/core"; +import { createContext, useEffect, useMemo, useState } from "react"; + +import { Big } from "../../shared/lib/converter"; +import { viewAccount } from "../../shared/lib/wallet"; +import { Multicall } from "../../shared/lib/contracts/multicall"; + +import { NEARSchema } from "./near.model"; + +export interface INEARService extends Pick {} + +export class NEARService { + public static readonly BalancesContext = createContext(NEARSchema.balances); + + private static readonly balancesFetch = async ( + { accountId }: INEARService, + callback: (result: typeof NEARSchema.balances) => void + ) => { + const [{ amount: account }, { amount: multicallInstance }] = await Promise.all([ + viewAccount(accountId), + viewAccount(Multicall.getInstanceAddress(accountId)), + ]); + + return callback({ + data: { + account, + multicallInstance, + total: Big(account).add(multicallInstance).toFixed(), + }, + + error: null, + loading: false, + }); + }; + + public static readonly useBalancesState = (inputs: INEARService) => { + const [state, stateUpdate] = useState(NEARSchema.balances); + + useEffect(() => void NEARService.balancesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); + + useEffect(() => { + state.error instanceof Error && void console.error(state.error); + }, [state.error]); + + return useMemo(() => state, [...Object.values(inputs), ...Object.values(state)]); + }; +} diff --git a/src/entities/near/near.ui.tsx b/src/entities/near/near.ui.tsx new file mode 100644 index 00000000..5881335d --- /dev/null +++ b/src/entities/near/near.ui.tsx @@ -0,0 +1,35 @@ +import { PropsWithChildren, useContext } from "react"; + +import { IconLabel, NEARIcon } from "../../shared/ui/design"; + +import { NEARLib } from "./near.lib"; +import { NEARService, INEARService } from "./near.service"; + +interface NEARBalancesProviderProps extends Pick, INEARService {} + +export const NEARBalancesProvider = ({ children, ...modelInputs }: NEARBalancesProviderProps) => ( + + {children} + +); + +export const nearBalancesRender = () => { + const { data } = useContext(NEARService.BalancesContext); + + return data === null + ? data + : { + content: [ + } + label="NEAR" + />, + + NEARLib.amountToDisplayAmount(data.multicallInstance), + NEARLib.amountToDisplayAmount(data.account), + NEARLib.amountToDisplayAmount(data.total), + ], + + id: "NEAR", + }; +}; diff --git a/src/entities/task/config/keywords.ts b/src/entities/task/config/keywords.ts deleted file mode 100644 index f2f4c356..00000000 --- a/src/entities/task/config/keywords.ts +++ /dev/null @@ -1,43 +0,0 @@ -export const keywords = { - "": { - "": ["custom"], - }, - near: { - ft_transfer: ["pay", "fungible", "token"], - ft_transfer_call: ["pay", "fungible", "token"], - nft_transfer: ["token", "non fungible"], - nft_transfer_call: ["token", "non fungible"], - nft_approve: ["token", "non fungible"], - nft_revoke: ["revoke_all", "token", "non fungible"], - mft_transfer: ["LP", "token"], - mft_transfer_call: ["LP", "token"], - deposit_and_stake: ["validator"], - unstake: ["validator", "unstake_all"], - withdraw: ["validator"], - storage_withdraw: [], - storage_unregister: [], - storage_deposit: [], - near_deposit: ["wnear", "wrapped", "wrap", "fungible", "token"], - near_withdraw: ["wnear", "wrapped", "unwrap", "fungible", "token"], - }, - multicall: { - near_transfer: ["pay"], - }, - mintbase: { - create_store: ["create store"], - grant_minter: ["add minter"], - revoke_minter: ["remove minter"], - transfer_store_ownership: ["transfer store ownership"], - buy: ["nft", "marketplace"], - }, - paras: { - buy: ["nft", "marketplace"], - }, - token_farm: { - create_token: ["TokenFarm", "treasury"], - }, - "meta-pool": { - nslp_add_liquidity: ["add liquidity", "lp"], - nslp_remove_liquidity: ["remove liquidity", "lp"], - }, -}; diff --git a/src/entities/task/index.ts b/src/entities/task/index.ts index 87b7ede5..26c28401 100644 --- a/src/entities/task/index.ts +++ b/src/entities/task/index.ts @@ -1 +1,34 @@ -export { Task } from "./ui/task"; +import { TaskParams } from "./task.params"; +import { TaskCard } from "./ui/task.card"; +import { TaskCardsList } from "./ui/task.cards-list"; +import { TaskSequenceColumn } from "./ui/task.sequence"; + +export class Task extends TaskParams { + public static readonly Card = TaskCard; + public static readonly CardsList = TaskCardsList; + public static readonly SequenceColumn = TaskSequenceColumn; +} + +type TaskCardInfo = { + formData: object; + showArgs: boolean; + isEdited: boolean; + options: object; +}; + +type TaskCardCopy = { + from: string; + to: string; + payload?: Omit; +}; + +declare global { + interface Window { + // Temporary storage for moving and cloning cards + TEMP: TaskCardInfo | null; + COPY: TaskCardCopy | null; + + // List of all mounted tasks + TASKS: Array; + } +} diff --git a/src/entities/task/task.params.ts b/src/entities/task/task.params.ts new file mode 100644 index 00000000..cbdb8053 --- /dev/null +++ b/src/entities/task/task.params.ts @@ -0,0 +1,45 @@ +export class TaskParams { + public static readonly keywords = { + "": { + "": ["custom"], + }, + near: { + ft_transfer: ["pay", "fungible", "token"], + ft_transfer_call: ["pay", "fungible", "token"], + nft_transfer: ["token", "non fungible"], + nft_transfer_call: ["token", "non fungible"], + nft_approve: ["token", "non fungible"], + nft_revoke: ["revoke_all", "token", "non fungible"], + mft_transfer: ["LP", "token"], + mft_transfer_call: ["LP", "token"], + deposit_and_stake: ["validator"], + unstake: ["validator", "unstake_all"], + withdraw: ["validator"], + storage_withdraw: [], + storage_unregister: [], + storage_deposit: [], + near_deposit: ["wnear", "wrapped", "wrap", "fungible", "token"], + near_withdraw: ["wnear", "wrapped", "unwrap", "fungible", "token"], + }, + multicall: { + near_transfer: ["pay"], + }, + mintbase: { + create_store: ["create store"], + grant_minter: ["add minter"], + revoke_minter: ["remove minter"], + transfer_store_ownership: ["transfer store ownership"], + buy: ["nft", "marketplace"], + }, + paras: { + buy: ["nft", "marketplace"], + }, + token_farm: { + create_token: ["TokenFarm", "treasury"], + }, + "meta-pool": { + nslp_add_liquidity: ["add liquidity", "lp"], + nslp_remove_liquidity: ["remove liquidity", "lp"], + }, + }; +} diff --git a/src/entities/task/ui/task.jsx b/src/entities/task/ui/task.card.jsx similarity index 98% rename from src/entities/task/ui/task.jsx rename to src/entities/task/ui/task.card.jsx index 15d8ef31..ea31f19a 100644 --- a/src/entities/task/ui/task.jsx +++ b/src/entities/task/ui/task.card.jsx @@ -2,10 +2,11 @@ import React, { Component } from "react"; import { Draggable } from "react-beautiful-dnd"; import { Family } from "../../../families"; -import "./task.scss"; -/* TODO: Decompose model and view */ -export class Task extends Component { +import "./task.card.scss"; + +/* TODO: Separate model and service from view */ +export class TaskCard extends Component { id; constructor(props) { @@ -337,7 +338,7 @@ export class Task extends Component { > {(provided, snapshot) => (
    str.replace("_", " ").replace("-", " ").toLowerCase(); -const _Builder = "Builder"; -export class Builder extends Component { +const _TaskCardsList = "TaskCardsList"; + +export class TaskCardsList extends Component { resolveDebounced = debounce((resolve) => resolve(), 400); constructor(props) { @@ -37,7 +39,7 @@ export class Builder extends Component { return tasks.filter((task) => { return ( searchTerm === "" || - (keywords[task.family]?.[task.func] ?? []) + (TaskParams.keywords[task.family]?.[task.func] ?? []) .concat(task.family, task.func) .some((kw) => normalize(kw).includes(normalize(searchTerm))) ); @@ -45,12 +47,12 @@ export class Builder extends Component { } render() { - const LAYOUT = this.props.layout; // ususally global parameter + const LAYOUT = this.props.layout; // usually global parameter const menuColumn = LAYOUT.getColumns()["menu"]; return ( -
    +
    { @@ -65,7 +67,7 @@ export class Builder extends Component { }} onSubmit={() => {}} > -
    + {(provided) => (
    -
    - + LAYOUT.getTasks()[taskId])} diff --git a/src/widgets/builder/builder.scss b/src/entities/task/ui/task.cards-list.scss similarity index 95% rename from src/widgets/builder/builder.scss rename to src/entities/task/ui/task.cards-list.scss index a5ae7cd8..7169154f 100644 --- a/src/widgets/builder/builder.scss +++ b/src/entities/task/ui/task.cards-list.scss @@ -3,7 +3,7 @@ @use "sass/color"; @use "sass/base"; -.Builder { +.TaskCardsList { @include mixin.center-items(flex-start); gap: size.$gap; @@ -33,7 +33,7 @@ .tasks-wrapper { flex: 1 1 0; box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); - .task-wrapper:last-of-type { + .TaskCard:last-of-type { margin-bottom: 0 !important; } .icon { diff --git a/src/widgets/column/column.jsx b/src/entities/task/ui/task.sequence.jsx similarity index 94% rename from src/widgets/column/column.jsx rename to src/entities/task/ui/task.sequence.jsx index b639880f..3ca51974 100644 --- a/src/widgets/column/column.jsx +++ b/src/entities/task/ui/task.sequence.jsx @@ -3,10 +3,10 @@ import hash from "object-hash"; import { Component } from "react"; import { Draggable, Droppable } from "react-beautiful-dnd"; -import { Task } from "../../entities"; -import "./column.scss"; +import { TaskCard } from "./task.card.jsx"; +import "./task.sequence.scss"; -export class Column extends Component { +export class TaskSequenceColumn extends Component { render() { const menuColumn = this.props.column.id === "menu"; @@ -57,7 +57,7 @@ export class Column extends Component { {this.props.tasks.map( (task, index) => (!menuColumn || this.props.show.includes(task.id)) && ( - ; - accountId: string | null; -} - -export const WalletSelectorContext = React.createContext(null); - -export const WalletSelectorContextProvider: React.FC = ({ children }) => { +export const WalletContextProvider: FC = ({ children }) => { const [selector, setSelector] = useState(null); const [modal, setModal] = useState(null); const [accounts, setAccounts] = useState>([]); @@ -94,7 +77,7 @@ export const WalletSelectorContextProvider: React.FC = ({ children }) => { const accountId = accounts.find((account) => account.active)?.accountId || null; return ( - = ({ children }) => { }} > {children} - + ); }; - -export const tryWalletSelectorContext = () => { - if (!WalletSelectorContext) { - throw new Error("tryWalletSelectorContext must be used within a WalletSelectorContextProvider"); - } - - return WalletSelectorContext; -}; diff --git a/src/entities/wallet/ui/wallet.scss b/src/entities/wallet/ui/wallet.selector.scss similarity index 100% rename from src/entities/wallet/ui/wallet.scss rename to src/entities/wallet/ui/wallet.selector.scss diff --git a/src/entities/wallet/ui/wallet.tsx b/src/entities/wallet/ui/wallet.selector.tsx similarity index 95% rename from src/entities/wallet/ui/wallet.tsx rename to src/entities/wallet/ui/wallet.selector.tsx index 073d028d..e325f565 100644 --- a/src/entities/wallet/ui/wallet.tsx +++ b/src/entities/wallet/ui/wallet.selector.tsx @@ -1,8 +1,6 @@ // TODO: use Multicall helper class to fetch & store infos, like admins, tokens etc... -import { Icon } from "@mui/material"; -import Autocomplete from "@mui/material/Autocomplete"; -import TextField from "@mui/material/TextField"; +import { Autocomplete, Icon, TextField } from "@mui/material"; import debounce from "lodash.debounce"; import { Component, ContextType } from "react"; @@ -11,9 +9,9 @@ import { fields } from "../../../shared/lib/args/args-types/args-object"; import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { STORAGE } from "../../../shared/lib/persistent"; +import { WalletContext, tryWalletContext } from "../wallet.service"; -import { tryWalletSelectorContext } from "./providers"; -import "./wallet.scss"; +import "./wallet.selector.scss"; enum Color { WHITE, @@ -35,9 +33,9 @@ interface State { } /* TODO: Decompose code */ -export class WalletComponent extends Component { - static contextType = tryWalletSelectorContext(); - declare context: ContextType; +export class WalletSelector extends Component { + static contextType = tryWalletContext(); + declare context: ContextType; schema = args .object() @@ -81,7 +79,7 @@ export class WalletComponent extends Component { 400 ); - constructor(props: Props, context: ContextType) { + constructor(props: Props, context: ContextType) { super(props); const { accountId } = context!; diff --git a/src/entities/wallet/wallet.model.ts b/src/entities/wallet/wallet.model.ts new file mode 100644 index 00000000..422b4e78 --- /dev/null +++ b/src/entities/wallet/wallet.model.ts @@ -0,0 +1,9 @@ +import { AccountState, WalletSelector } from "@near-wallet-selector/core"; +import { WalletSelectorModal } from "@near-wallet-selector/modal-ui"; + +export type WalletModel = { + selector: WalletSelector; + modal: WalletSelectorModal; + accounts: Array; + accountId: string | null; +}; diff --git a/src/entities/wallet/wallet.service.ts b/src/entities/wallet/wallet.service.ts new file mode 100644 index 00000000..2b7710a7 --- /dev/null +++ b/src/entities/wallet/wallet.service.ts @@ -0,0 +1,13 @@ +import { createContext } from "react"; + +import { WalletModel } from "./wallet.model"; + +export const WalletContext = createContext(null); + +export const tryWalletContext = () => { + if (!WalletContext) { + throw new Error("tryWalletContext must be used within a WalletContextProvider"); + } + + return WalletContext; +}; diff --git a/src/families/meta-pool/meta-pool.scss b/src/families/meta-pool/meta-pool.scss index 868dca3b..ce09516c 100644 --- a/src/families/meta-pool/meta-pool.scss +++ b/src/families/meta-pool/meta-pool.scss @@ -8,7 +8,7 @@ $meta-pool-purple: #735de9; .meta-pool-nslp-add-liquidity-task, .meta-pool-nslp-remove-liquidity-task { background-color: $meta-pool-purple; - background-image: url("../../app/static/meta-pool/MetaPool_symbol.svg"); + background-image: url("../../shared/static/meta-pool/MetaPool_symbol.svg"); background-position-x: 0rem; background-position-y: -2rem; background-repeat: no-repeat; diff --git a/src/families/meta-pool/nslp-add-liquidity.tsx b/src/families/meta-pool/nslp-add-liquidity.tsx index e4bff274..05199702 100644 --- a/src/families/meta-pool/nslp-add-liquidity.tsx +++ b/src/families/meta-pool/nslp-add-liquidity.tsx @@ -5,7 +5,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { GetAccountInfoResult, MetaPool } from "../../shared/lib/contracts/meta-pool"; import { InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "../base"; -import * as MetaPoolLogo from "../../app/static/meta-pool/MetaPool_logo.png"; +import * as MetaPoolLogo from "../../shared/static/meta-pool/MetaPool_logo.png"; import "./meta-pool.scss"; import { STORAGE } from "../../shared/lib/persistent"; diff --git a/src/families/meta-pool/nslp-remove-liquidity.tsx b/src/families/meta-pool/nslp-remove-liquidity.tsx index c950a136..7b00ab0a 100644 --- a/src/families/meta-pool/nslp-remove-liquidity.tsx +++ b/src/families/meta-pool/nslp-remove-liquidity.tsx @@ -5,7 +5,7 @@ import { Call, CallError } from "../../shared/lib/call"; import { GetAccountInfoResult, MetaPool } from "../../shared/lib/contracts/meta-pool"; import { CheckboxField, InfoField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState, DefaultFormData } from "../base"; -import * as MetaPoolLogo from "../../app/static/meta-pool/MetaPool_logo.png"; +import * as MetaPoolLogo from "../../shared/static/meta-pool/MetaPool_logo.png"; import "./meta-pool.scss"; import { STORAGE } from "../../shared/lib/persistent"; import { Big, unit } from "../../shared/lib/converter"; diff --git a/src/families/mintbase/add-minter.tsx b/src/families/mintbase/add-minter.tsx index 6d095013..c6db9539 100644 --- a/src/families/mintbase/add-minter.tsx +++ b/src/families/mintbase/add-minter.tsx @@ -1,6 +1,6 @@ import { Form, FormikErrors, useFormikContext } from "formik"; import { useEffect } from "react"; -import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; +import MintbaseLogo from "../../shared/static/mintbase/Mintbase_logo.svg"; import { args as arx } from "../../shared/lib/args/args"; import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; diff --git a/src/families/mintbase/buy-nft.tsx b/src/families/mintbase/buy-nft.tsx index f74865b4..06edae40 100644 --- a/src/families/mintbase/buy-nft.tsx +++ b/src/families/mintbase/buy-nft.tsx @@ -1,6 +1,6 @@ import { Form, FormikErrors, useFormikContext } from "formik"; import { useEffect } from "react"; -import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; +import MintbaseLogo from "../../shared/static/mintbase/Mintbase_logo.svg"; import { args as arx } from "../../shared/lib/args/args"; import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; diff --git a/src/families/mintbase/create-store.tsx b/src/families/mintbase/create-store.tsx index b8f6e6ab..a3ccab1d 100644 --- a/src/families/mintbase/create-store.tsx +++ b/src/families/mintbase/create-store.tsx @@ -1,6 +1,6 @@ import { Form, useFormikContext } from "formik"; import { useEffect } from "react"; -import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; +import MintbaseLogo from "../../shared/static/mintbase/Mintbase_logo.svg"; import { args as arx } from "../../shared/lib/args/args"; import { Call, CallError } from "../../shared/lib/call"; import { BASE_URI_ARWEAVE, MintbaseStore } from "../../shared/lib/contracts/mintbase"; diff --git a/src/families/mintbase/mintbase.scss b/src/families/mintbase/mintbase.scss index 0a2e768c..68059461 100644 --- a/src/families/mintbase/mintbase.scss +++ b/src/families/mintbase/mintbase.scss @@ -12,7 +12,7 @@ $mintbase-red: #ff2424; .mintbase-remove-minter-task, .mintbase-buy-nft-task { background-color: $mintbase-blue; - background-image: url("../../app/static/mintbase/Mintbase_symbol.svg"); + background-image: url("../../shared/static/mintbase/Mintbase_symbol.svg"); background-position-x: 42rem; background-position-y: 239rem; background-size: 77rem; diff --git a/src/families/mintbase/remove-minter.tsx b/src/families/mintbase/remove-minter.tsx index aefe1d76..6b836b08 100644 --- a/src/families/mintbase/remove-minter.tsx +++ b/src/families/mintbase/remove-minter.tsx @@ -1,6 +1,6 @@ import { Form, FormikErrors, useFormikContext } from "formik"; import { useEffect } from "react"; -import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; +import MintbaseLogo from "../../shared/static/mintbase/Mintbase_logo.svg"; import { args as arx } from "../../shared/lib/args/args"; import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; diff --git a/src/families/mintbase/transfer-store-ownership.tsx b/src/families/mintbase/transfer-store-ownership.tsx index d7de90fb..04695d5c 100644 --- a/src/families/mintbase/transfer-store-ownership.tsx +++ b/src/families/mintbase/transfer-store-ownership.tsx @@ -9,7 +9,7 @@ import { toGas } from "../../shared/lib/converter"; import { MintbaseStore } from "../../shared/lib/contracts/mintbase"; import { CheckboxField, TextField, UnitField } from "../../shared/ui/form"; import { BaseTask, BaseTaskProps, BaseTaskState } from "../base"; -import MintbaseLogo from "../../app/static/mintbase/Mintbase_logo.svg"; +import MintbaseLogo from "../../shared/static/mintbase/Mintbase_logo.svg"; import "./mintbase.scss"; import { STORAGE } from "../../shared/lib/persistent"; diff --git a/src/families/paras/buy-nft.tsx b/src/families/paras/buy-nft.tsx index 6a05ea7d..f2ffc873 100644 --- a/src/families/paras/buy-nft.tsx +++ b/src/families/paras/buy-nft.tsx @@ -1,6 +1,6 @@ import { Form, FormikErrors, useFormikContext } from "formik"; import { useEffect } from "react"; -import ParasLogo from "../../app/static/paras/Paras_logo.svg"; +import ParasLogo from "../../shared/static/paras/Paras_logo.svg"; import { args as arx } from "../../shared/lib/args/args"; import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; diff --git a/src/families/token-farm/create-token.tsx b/src/families/token-farm/create-token.tsx index 3e4b04e7..de305356 100644 --- a/src/families/token-farm/create-token.tsx +++ b/src/families/token-farm/create-token.tsx @@ -1,7 +1,7 @@ import { InputAdornment } from "@mui/material"; import { Form, FormikErrors, useFormikContext } from "formik"; import { useEffect } from "react"; -import * as TokenFarmSymbol from "../../app/static/token-farm/TokenFarm_symbol.png"; +import * as TokenFarmSymbol from "../../shared/static/token-farm/TokenFarm_symbol.png"; import { args as arx } from "../../shared/lib/args/args"; import { fields } from "../../shared/lib/args/args-types/args-object"; import { Call, CallError } from "../../shared/lib/call"; diff --git a/src/families/token-farm/token-farm.scss b/src/families/token-farm/token-farm.scss index bb6bff26..8294d711 100644 --- a/src/families/token-farm/token-farm.scss +++ b/src/families/token-farm/token-farm.scss @@ -3,7 +3,7 @@ .token-farm-create-token-task { background-color: color.$yellow; - background-image: url("../../app/static/token-farm/TokenFarm_symbol.png"); + background-image: url("../../shared/static/token-farm/TokenFarm_symbol.png"); background-size: 60rem; // background-blend-mode: luminosity; @include base.task-theme(color.$text); diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.scss b/src/features/configure-scheduling/configure-scheduling.ui.scss similarity index 100% rename from src/features/configure-scheduling/ui/configure-scheduling.ui.scss rename to src/features/configure-scheduling/configure-scheduling.ui.scss diff --git a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx similarity index 93% rename from src/features/configure-scheduling/ui/configure-scheduling.ui.tsx rename to src/features/configure-scheduling/configure-scheduling.ui.tsx index 378544f4..e695fe57 100644 --- a/src/features/configure-scheduling/ui/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -2,11 +2,11 @@ import { CancelOutlined, EditOutlined, VisibilityOutlined } from "@mui/icons-mat import { IconButton, TextField, TextFieldProps } from "@mui/material"; import { HTMLProps, useCallback, useContext, useEffect, useMemo, useState } from "react"; -import { ArgsString } from "../../../shared/lib/args-old"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { toNEAR, toYocto } from "../../../shared/lib/converter"; -import { IconLabel, NEARIcon, Table, Tile, Tooltip } from "../../../shared/ui/design"; -import { MulticallInstance } from "../../../entities"; +import { ArgsString } from "../../shared/lib/args-old"; +import { Multicall } from "../../shared/lib/contracts/multicall"; +import { toNEAR, toYocto } from "../../shared/lib/converter"; +import { IconLabel, NEARIcon, Table, Tile, Tooltip } from "../../shared/ui/design"; +import { MI } from "../../entities"; import "./configure-scheduling.ui.scss"; @@ -20,7 +20,7 @@ interface ConfigureSchedulingUIProps extends Omit, "on } export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: ConfigureSchedulingUIProps) => { - const multicallInstance = useContext(MulticallInstance.Context); + const multicallInstance = useContext(MI.Context); const error = multicallInstance.data.ready && multicallInstance.data.jobBond === "" @@ -119,7 +119,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config id: "jobBond", content: [ - MulticallInstance.SettingsDiffMeta.jobBond.description, + MI.SettingsDiffMeta.jobBond.description, editModeEnabled ? ( = { + static methods: Record<"dao" | "multicall", { title: string; type: keyof typeof ExtAuthParams.methods }> = { dao: { title: "Login in dApps as DAO", type: "dao" }, multicall: { title: "Login in dApps as Multicall", type: "multicall" }, }; diff --git a/src/features/external-login/model/external-login.model.ts b/src/features/external-auth/ext-auth.service.ts similarity index 83% rename from src/features/external-login/model/external-login.model.ts rename to src/features/external-auth/ext-auth.service.ts index 0003b7ef..20d9af5e 100644 --- a/src/features/external-login/model/external-login.model.ts +++ b/src/features/external-auth/ext-auth.service.ts @@ -1,10 +1,11 @@ /** - * !TODO: Use 3rd party solution for dialogs management + * !TODO: Use 3rd party solution for dialogs management. + * !UI-specific logic should not be described within services! */ import { useCallback, useEffect, useState } from "react"; -import { ModuleContext } from "../module-context"; +import { ExtAuthParams } from "./ext-auth.params"; const _dialogOpenRequested = "dialogOpenRequested"; @@ -13,7 +14,7 @@ type DialogOpenRequestedEvent = CustomEventInit<{ }>; const dialogOpenRequested = { - dispatch: (dialogKey: keyof typeof ModuleContext.methods) => + dispatch: (dialogKey: keyof typeof ExtAuthParams.methods) => document.dispatchEvent(new CustomEvent(_dialogOpenRequested, { detail: { dialogKey } })), subscribe: (callback: EventListener) => { @@ -23,12 +24,12 @@ const dialogOpenRequested = { }, }; -export class ELModel { +export class ExtAuthService { static dialogOpenRequested = dialogOpenRequested.dispatch; static useDialogsState = () => { const [dialogsVisibility, dialogVisibilitySwitch] = useState< - Record + Record >({ dao: false, multicall: false, diff --git a/src/features/external-login/ui/external-login.dialog.scss b/src/features/external-auth/ext-auth.ui.scss similarity index 97% rename from src/features/external-login/ui/external-login.dialog.scss rename to src/features/external-auth/ext-auth.ui.scss index 0910bb75..149f355e 100644 --- a/src/features/external-login/ui/external-login.dialog.scss +++ b/src/features/external-auth/ext-auth.ui.scss @@ -1,7 +1,7 @@ @use "sass/size"; @use "sass/mixin"; -.ELDialog { +.ExtAuthDialog { &-stepByStepGuide { padding: 0 size.$gap; list-style-type: decimal; diff --git a/src/features/external-auth/ext-auth.ui.tsx b/src/features/external-auth/ext-auth.ui.tsx new file mode 100644 index 00000000..9e28fd2b --- /dev/null +++ b/src/features/external-auth/ext-auth.ui.tsx @@ -0,0 +1,114 @@ +import { InfoOutlined, PreviewOutlined } from "@mui/icons-material"; +import clsx from "clsx"; +import { ComponentProps, useMemo, useReducer } from "react"; + +import { ArgsError, ArgsString } from "../../shared/lib/args-old"; +import { STORAGE } from "../../shared/lib/persistent"; +import { Validation } from "../../shared/lib/validation"; +import { Dialog, PopupMenu, TextInput, Tooltip } from "../../shared/ui/design"; +import { ExtAuthParams } from "./ext-auth.params"; +import { ExtAuthService } from "./ext-auth.service"; + +import "./ext-auth.ui.scss"; + +interface IExtAuthDialog extends Pick, "className" | "onClose" | "open" | "title"> { + method: "dao" | "multicall"; +} + +const _ExtAuthDialog = "ExtAuthDialog"; + +export const ExtAuthDialog = ({ className, method, onClose, open, title }: IExtAuthDialog) => { + const dAppURL = useMemo(() => new ArgsString(""), []); + + const URLInvalid = ArgsError.useInstance("Invalid URL", Validation.isUrl, true); + + const [requestURL, requestURLUpdate] = useReducer<(currentValue: string, input: string) => string>( + (currentValue, value) => { + if (URLInvalid.$detected) { + return currentValue; + } else { + const url = new URL(value); + url.searchParams.set("account_id", STORAGE.addresses[method]); + url.searchParams.set("public_key", ExtAuthParams.keys.public); + url.searchParams.set("all_keys", ExtAuthParams.keys.all); + return url.toString(); + } + }, + "" + ); + + return ( + window.open(requestURL, "_blank")} + {...{ onClose, open, title }} + > +
      + {ExtAuthParams.stepByStepGuide.map((step) => ( +
    • + + {step.text} + + {step.hint && ( + + + + )} + +
    • + ))} +
    + + requestURLUpdate(target.value)} + value={dAppURL} + variant="filled" + /> +
    + ); +}; + +export const ExtAuthDialogs = (): JSX.Element => { + const { dialogsVisibility, closeHandlerBinding } = ExtAuthService.useDialogsState(); + + return ( + <> + {Object.values(ExtAuthParams.methods).map((loginMethod) => ( + + ))} + + ); +}; + +interface IExtAuthMenu extends Pick, "triggerClassName"> { + FeatureFlags: { + ExternalAuth: Record; + }; +} + +export const ExtAuthMenu = ({ FeatureFlags, triggerClassName }: IExtAuthMenu) => ( + } + items={Object.values(ExtAuthParams.methods).map(({ title, type }) => ({ + disabled: !FeatureFlags.ExternalAuth[type], + key: type, + onClick: () => ExtAuthService.dialogOpenRequested(type), + title, + }))} + {...{ triggerClassName }} + /> +); diff --git a/src/features/external-auth/index.ts b/src/features/external-auth/index.ts new file mode 100644 index 00000000..cc8726b4 --- /dev/null +++ b/src/features/external-auth/index.ts @@ -0,0 +1,7 @@ +import { ExtAuthParams } from "./ext-auth.params"; +import { ExtAuthDialogs, ExtAuthMenu } from "./ext-auth.ui"; + +export class ExternalAuth extends ExtAuthParams { + static Dialogs = ExtAuthDialogs; + static Menu = ExtAuthMenu; +} diff --git a/src/features/external-login/index.ts b/src/features/external-login/index.ts deleted file mode 100644 index 6b8e23b7..00000000 --- a/src/features/external-login/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ModuleContext } from "./module-context"; -import { ELDialogs } from "./ui/external-login.dialogs"; -import { ELMenu } from "./ui/external-login.menu"; - -export class ExternalLogin extends ModuleContext { - static Dialogs = ELDialogs; - static Menu = ELMenu; -} diff --git a/src/features/external-login/ui/external-login.dialog.tsx b/src/features/external-login/ui/external-login.dialog.tsx deleted file mode 100644 index 0ff69d05..00000000 --- a/src/features/external-login/ui/external-login.dialog.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { InfoOutlined } from "@mui/icons-material"; -import clsx from "clsx"; -import { ComponentProps, useMemo, useReducer } from "react"; - -import { ArgsError, ArgsString } from "../../../shared/lib/args-old"; -import { STORAGE } from "../../../shared/lib/persistent"; -import { Validation } from "../../../shared/lib/validation"; -import { Dialog, TextInput, Tooltip } from "../../../shared/ui/design"; -import { ModuleContext } from "../module-context"; - -import "./external-login.dialog.scss"; - -interface ELDialogProps extends Pick, "className" | "onClose" | "open" | "title"> { - method: "dao" | "multicall"; -} - -const _ELDialog = "ELDialog"; - -export const ELDialog = ({ className, method, onClose, open, title }: ELDialogProps) => { - const dAppURL = useMemo(() => new ArgsString(""), []); - - const URLInvalid = ArgsError.useInstance("Invalid URL", Validation.isUrl, true); - - const [requestURL, requestURLUpdate] = useReducer<(currentValue: string, input: string) => string>( - (currentValue, value) => { - if (URLInvalid.$detected) { - return currentValue; - } else { - const url = new URL(value); - url.searchParams.set("account_id", STORAGE.addresses[method]); - url.searchParams.set("public_key", ModuleContext.keys.public); - url.searchParams.set("all_keys", ModuleContext.keys.all); - return url.toString(); - } - }, - "" - ); - - return ( - window.open(requestURL, "_blank")} - {...{ onClose, open, title }} - > -
      - {ModuleContext.stepByStepGuide.map((step) => ( -
    • - - {step.text} - - {step.hint && ( - - - - )} - -
    • - ))} -
    - - requestURLUpdate(target.value)} - value={dAppURL} - variant="filled" - /> -
    - ); -}; diff --git a/src/features/external-login/ui/external-login.dialogs.tsx b/src/features/external-login/ui/external-login.dialogs.tsx deleted file mode 100644 index 8fb2f359..00000000 --- a/src/features/external-login/ui/external-login.dialogs.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { ModuleContext } from "../module-context"; -import { ELModel } from "../model/external-login.model"; - -import { ELDialog } from "./external-login.dialog"; - -export const ELDialogs = (): JSX.Element => { - const { dialogsVisibility, closeHandlerBinding } = ELModel.useDialogsState(); - - return ( - <> - {Object.values(ModuleContext.methods).map((loginMethod) => ( - - ))} - - ); -}; diff --git a/src/features/external-login/ui/external-login.menu.tsx b/src/features/external-login/ui/external-login.menu.tsx deleted file mode 100644 index 1f37ae3a..00000000 --- a/src/features/external-login/ui/external-login.menu.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { PreviewOutlined } from "@mui/icons-material"; -import { ComponentProps } from "react"; - -import { PopupMenu } from "../../../shared/ui/design"; -import { ModuleContext } from "../module-context"; -import { ELModel } from "../model/external-login.model"; - -interface ELMenuProps extends Pick, "triggerClassName"> { - FeatureFlags: { - ExternalLogin: Record; - }; -} - -export const ELMenu = ({ FeatureFlags, triggerClassName }: ELMenuProps) => ( - } - items={Object.values(ModuleContext.methods).map(({ title, type }) => ({ - disabled: !FeatureFlags.ExternalLogin[type], - key: type, - onClick: () => ELModel.dialogOpenRequested(type), - title, - }))} - {...{ triggerClassName }} - /> -); diff --git a/src/features/index.ts b/src/features/index.ts index eb723152..2c3506a5 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,4 +1,6 @@ -export { ExternalLogin } from "./external-login"; export { ConfigureScheduling } from "./configure-scheduling"; +export { EditTask } from "./edit-task"; +export { ExternalAuth } from "./external-auth"; export { ManageTokenWhitelist } from "./manage-token-whitelist"; export { ProposeSettings } from "./propose-settings"; +export { WorkflowExport } from "./workflow-export"; diff --git a/src/features/manage-token-whitelist/index.ts b/src/features/manage-token-whitelist/index.ts index c47bdada..8149f1db 100644 --- a/src/features/manage-token-whitelist/index.ts +++ b/src/features/manage-token-whitelist/index.ts @@ -1,4 +1,4 @@ -import { ManageTokenWhitelistUI } from "./ui/manage-token-whitelist.ui"; +import { ManageTokenWhitelistUI } from "./manage-token-whitelist.ui"; export class ManageTokenWhitelist { public static readonly UI = ManageTokenWhitelistUI; diff --git a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss b/src/features/manage-token-whitelist/manage-token-whitelist.ui.scss similarity index 100% rename from src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.scss rename to src/features/manage-token-whitelist/manage-token-whitelist.ui.scss diff --git a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx b/src/features/manage-token-whitelist/manage-token-whitelist.ui.tsx similarity index 90% rename from src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx rename to src/features/manage-token-whitelist/manage-token-whitelist.ui.tsx index 2a95fddd..ab0d215c 100644 --- a/src/features/manage-token-whitelist/ui/manage-token-whitelist.ui.tsx +++ b/src/features/manage-token-whitelist/manage-token-whitelist.ui.tsx @@ -4,11 +4,11 @@ import { Form, Formik, FormikHelpers } from "formik"; import { HTMLProps, useCallback, useEffect, useState } from "react"; import { InferType } from "yup"; -import { args } from "../../../shared/lib/args/args"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { Tooltip } from "../../../shared/ui/design"; -import { TextField } from "../../../shared/ui/form"; -import { MulticallInstance } from "../../../entities"; +import { args } from "../../shared/lib/args/args"; +import { Multicall } from "../../shared/lib/contracts/multicall"; +import { Tooltip } from "../../shared/ui/design"; +import { TextField } from "../../shared/ui/form"; +import { MI } from "../../entities"; import "./manage-token-whitelist.ui.scss"; @@ -85,11 +85,11 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag {...{ onReset, onSubmit }} > - - (included.has(id) && MulticallInstance.SettingsDiffMeta.addTokens.color) || - (discarded.has(id) && MulticallInstance.SettingsDiffMeta.removeTokens.color) || + (included.has(id) && MI.SettingsDiffMeta.addTokens.color) || + (discarded.has(id) && MI.SettingsDiffMeta.removeTokens.color) || null, slots: { diff --git a/src/features/propose-settings/index.ts b/src/features/propose-settings/index.ts index 85f03d09..a4a885e6 100644 --- a/src/features/propose-settings/index.ts +++ b/src/features/propose-settings/index.ts @@ -1,4 +1,4 @@ -import { ProposeSettingsUI } from "./ui/propose-settings.ui"; +import { ProposeSettingsUI } from "./propose-settings.ui"; export class ProposeSettings { public static readonly UI = ProposeSettingsUI; diff --git a/src/features/propose-settings/ui/propose-settings.ui.scss b/src/features/propose-settings/propose-settings.ui.scss similarity index 100% rename from src/features/propose-settings/ui/propose-settings.ui.scss rename to src/features/propose-settings/propose-settings.ui.scss diff --git a/src/features/propose-settings/ui/propose-settings.ui.tsx b/src/features/propose-settings/propose-settings.ui.tsx similarity index 88% rename from src/features/propose-settings/ui/propose-settings.ui.tsx rename to src/features/propose-settings/propose-settings.ui.tsx index 4edf6c5e..435a5727 100644 --- a/src/features/propose-settings/ui/propose-settings.ui.tsx +++ b/src/features/propose-settings/propose-settings.ui.tsx @@ -3,14 +3,14 @@ import { Form, Formik, FormikHelpers } from "formik"; import { HTMLProps, useCallback, useContext } from "react"; import { InferType } from "yup"; -import { args } from "../../../shared/lib/args/args"; -import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; -import { toNEAR } from "../../../shared/lib/converter"; -import { signAndSendTxs } from "../../../shared/lib/wallet"; -import { Button, ButtonGroup, NEARIcon, Tile } from "../../../shared/ui/design"; -import { TextField } from "../../../shared/ui/form"; -import { MulticallInstance } from "../../../entities"; +import { args } from "../../shared/lib/args/args"; +import { Multicall } from "../../shared/lib/contracts/multicall"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; +import { toNEAR } from "../../shared/lib/converter"; +import { signAndSendTxs } from "../../shared/lib/wallet"; +import { Button, ButtonGroup, NEARIcon, Tile } from "../../shared/ui/design"; +import { TextField } from "../../shared/ui/form"; +import { MI } from "../../entities"; import "./propose-settings.ui.scss"; @@ -26,7 +26,7 @@ export interface ProposeSettingsUIProps extends HTMLProps { } export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, onCancel }: ProposeSettingsUIProps) => { - const multicallInstance = useContext(MulticallInstance.Context); + const multicallInstance = useContext(MI.Context); const schema = args.object().shape({ description: args.string().default("").required("Proposal description is required"), @@ -71,7 +71,7 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on

    - {Object.entries(MulticallInstance.SettingsDiffMeta).map( + {Object.entries(MI.SettingsDiffMeta).map( ([key, { color, description }]) => diff[key as keyof MISettingsDiff].length > 0 && (
    { +export class WorkflowExportUI extends Component { static contextType = Ctx; declare context: ContextType; @@ -194,7 +195,7 @@ export class Export extends Component { if (!walletSelector.isSignedIn()) { return (
    )} - {(!nearTokenBalances || !fungibleTokenBalances) &&
    } + {(!nearBalances || !fungibleTokenBalances) &&
    }
    ); diff --git a/src/widgets/funds-overview/index.tsx b/src/widgets/funds-overview/index.tsx index 565ee8b6..cd0a2d15 100644 --- a/src/widgets/funds-overview/index.tsx +++ b/src/widgets/funds-overview/index.tsx @@ -1,18 +1,18 @@ import { ComponentProps } from "react"; -import { FT, NEARToken } from "../../entities"; +import { FT, NEAR } from "../../entities"; -import { FundsOverviewUI, FundsOverviewUIProps } from "./ui/funds-overview.ui"; +import { FundsOverviewUI, FundsOverviewUIProps } from "./funds-overview.ui"; -export interface FundsOverviewProps +export interface IFundsOverview extends ComponentProps, - ComponentProps, + ComponentProps, FundsOverviewUIProps {} -export const FundsOverview = ({ accountId, ...props }: FundsOverviewProps) => ( - +export const FundsOverview = ({ accountId, ...props }: IFundsOverview) => ( + - + ); diff --git a/src/widgets/index.ts b/src/widgets/index.ts index f43a7de6..605b883c 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -1,10 +1,6 @@ -export { Builder } from "./builder/builder.jsx"; -export { Column } from "./column/column.jsx"; export { DialogsLayer } from "./dialogs-layer"; -export { Editor } from "./editor/editor.jsx"; -export { Export } from "./export"; -export { FundsOverview, type FundsOverviewProps } from "./funds-overview"; -export { Menu } from "./menu/menu.jsx"; -export { ScheduleOverview, type ScheduleOverviewProps } from "./schedule-overview"; -export { SettingsManager, type SettingsManagerProps } from "./settings-manager"; -export { Sidebar } from "./sidebar/sidebar.jsx"; +export { WorkflowEditorMenu } from "./workflow-editor"; +export { FundsOverview, type IFundsOverview } from "./funds-overview"; +export { ScheduleOverview, type IScheduleOverview } from "./schedule-overview"; +export { SettingsManager, type ISettingsManager } from "./settings-manager"; +export { Sidebar } from "./sidebar"; diff --git a/src/widgets/menu/index.ts b/src/widgets/menu/index.ts deleted file mode 100644 index 1f577526..00000000 --- a/src/widgets/menu/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { Menu } from "./menu"; diff --git a/src/widgets/schedule-overview/index.tsx b/src/widgets/schedule-overview/index.tsx index 5a4efffa..0634c888 100644 --- a/src/widgets/schedule-overview/index.tsx +++ b/src/widgets/schedule-overview/index.tsx @@ -1,15 +1,15 @@ import { ComponentProps } from "react"; -import { MulticallInstance } from "../../entities"; +import { MI } from "../../entities"; -import { ScheduleOverviewUI, ScheduleOverviewUIProps } from "./ui/schedule-overview.ui"; +import { ScheduleOverviewUI, ScheduleOverviewUIProps } from "./schedule-overview.ui"; -export interface ScheduleOverviewProps extends ScheduleOverviewUIProps { - accountId: ComponentProps["daoAddress"]; +export interface IScheduleOverview extends ScheduleOverviewUIProps { + accountId: ComponentProps["daoAddress"]; } -export const ScheduleOverview = ({ accountId, ...props }: ScheduleOverviewProps) => ( - +export const ScheduleOverview = ({ accountId, ...props }: IScheduleOverview) => ( + - + ); diff --git a/src/widgets/schedule-overview/ui/schedule-overview.ui.scss b/src/widgets/schedule-overview/schedule-overview.ui.scss similarity index 100% rename from src/widgets/schedule-overview/ui/schedule-overview.ui.scss rename to src/widgets/schedule-overview/schedule-overview.ui.scss diff --git a/src/widgets/schedule-overview/ui/schedule-overview.ui.tsx b/src/widgets/schedule-overview/schedule-overview.ui.tsx similarity index 80% rename from src/widgets/schedule-overview/ui/schedule-overview.ui.tsx rename to src/widgets/schedule-overview/schedule-overview.ui.tsx index e68326df..b74d3eef 100644 --- a/src/widgets/schedule-overview/ui/schedule-overview.ui.tsx +++ b/src/widgets/schedule-overview/schedule-overview.ui.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import { HTMLProps, useContext } from "react"; -import { Job, MulticallInstance } from "../../../entities"; +import { Job, MI } from "../../entities"; import "./schedule-overview.ui.scss"; @@ -10,7 +10,7 @@ const _ScheduleOverview = "ScheduleOverview"; export interface ScheduleOverviewUIProps extends HTMLProps {} export const ScheduleOverviewUI = ({ className, ...props }: ScheduleOverviewUIProps) => { - const multicallInstance = useContext(MulticallInstance.Context); + const multicallInstance = useContext(MI.Context); return (
    ["daoAddress"]; +export interface ISettingsManager extends SettingsManagerUIProps { + accountId: ComponentProps["daoAddress"]; } -export const SettingsManager = ({ accountId, ...props }: SettingsManagerProps) => ( - +export const SettingsManager = ({ accountId, ...props }: ISettingsManager) => ( + - + ); diff --git a/src/widgets/settings-manager/ui/settings-manager.ui.scss b/src/widgets/settings-manager/settings-manager.ui.scss similarity index 100% rename from src/widgets/settings-manager/ui/settings-manager.ui.scss rename to src/widgets/settings-manager/settings-manager.ui.scss diff --git a/src/widgets/settings-manager/ui/settings-manager.ui.tsx b/src/widgets/settings-manager/settings-manager.ui.tsx similarity index 86% rename from src/widgets/settings-manager/ui/settings-manager.ui.tsx rename to src/widgets/settings-manager/settings-manager.ui.tsx index a83936dd..502ca019 100644 --- a/src/widgets/settings-manager/ui/settings-manager.ui.tsx +++ b/src/widgets/settings-manager/settings-manager.ui.tsx @@ -1,10 +1,10 @@ import clsx from "clsx"; import { useCallback, useState, useEffect, useContext, HTMLProps, ComponentProps } from "react"; -import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; -import { Tile } from "../../../shared/ui/design"; -import { MulticallInstance, Wallet } from "../../../entities"; -import { ConfigureScheduling, ManageTokenWhitelist, ProposeSettings } from "../../../features"; +import { SputnikDAO } from "../../shared/lib/contracts/sputnik-dao"; +import { Tile } from "../../shared/ui/design"; +import { MI, Wallet } from "../../entities"; +import { ConfigureScheduling, ManageTokenWhitelist, ProposeSettings } from "../../features"; import "./settings-manager.ui.scss"; @@ -15,8 +15,8 @@ export interface SettingsManagerUIProps extends HTMLProps { } export const SettingsManagerUI = ({ className, dao }: SettingsManagerUIProps) => { - const wallet = useContext(Wallet.SelectorContext), - multicallInstance = useContext(MulticallInstance.Context); + const wallet = useContext(Wallet.Context), + multicallInstance = useContext(MI.Context); const canCreateProposals = !wallet?.accountId || dao.checkUserPermission(wallet?.accountId, "AddProposal", "FunctionCall"); @@ -68,7 +68,7 @@ export const SettingsManagerUI = ({ className, dao }: SettingsManagerUIProps) => error={multicallInstance.error} /> - {false && } + {false && }
    - diff --git a/src/widgets/sidebar/sidebar.scss b/src/widgets/sidebar/sidebar.ui.scss similarity index 100% rename from src/widgets/sidebar/sidebar.scss rename to src/widgets/sidebar/sidebar.ui.scss diff --git a/src/widgets/workflow-editor/index.ts b/src/widgets/workflow-editor/index.ts new file mode 100644 index 00000000..3d64934f --- /dev/null +++ b/src/widgets/workflow-editor/index.ts @@ -0,0 +1,9 @@ +import { WorkflowEditorMenu } from "./workflow-editor.ui"; + +export { WorkflowEditorMenu }; + +declare global { + interface Window { + MENU: WorkflowEditorMenu; + } +} diff --git a/src/widgets/menu/menu.jsx b/src/widgets/workflow-editor/workflow-editor.ui.jsx similarity index 74% rename from src/widgets/menu/menu.jsx rename to src/widgets/workflow-editor/workflow-editor.ui.jsx index 2e2311cc..8b86beee 100644 --- a/src/widgets/menu/menu.jsx +++ b/src/widgets/workflow-editor/workflow-editor.ui.jsx @@ -2,13 +2,13 @@ import Icon from "@mui/material/Icon"; import clsx from "clsx"; import { Component } from "react"; +import { Task } from "../../entities"; +import { EditTask, WorkflowExport } from "../../features"; import { Tabs } from "../../shared/ui/design"; -import { Builder } from "../builder/builder.jsx"; -import { Editor } from "../editor/editor.jsx"; -import { Export } from "../export/export"; -import "./menu.scss"; -export class Menu extends Component { +import "./workflow-editor.ui.scss"; + +export class WorkflowEditorMenu extends Component { constructor(props) { super(props); @@ -33,22 +33,22 @@ export class Menu extends Component { const LAYOUT = this.props.layout; return ( -
    -
    +
    +
    @@ -56,11 +56,11 @@ export class Menu extends Component { }, { name: "Edit", - ui: , + ui: , }, { name: "Export", - ui: , + ui: , }, ]} /> diff --git a/src/widgets/menu/menu.scss b/src/widgets/workflow-editor/workflow-editor.ui.scss similarity index 99% rename from src/widgets/menu/menu.scss rename to src/widgets/workflow-editor/workflow-editor.ui.scss index 5053507b..7cf9180b 100644 --- a/src/widgets/menu/menu.scss +++ b/src/widgets/workflow-editor/workflow-editor.ui.scss @@ -3,7 +3,7 @@ @use "sass/mixin"; @use "sass/animation"; -.Menu { +.WorkflowEditorMenu { position: fixed; top: size.$gap; right: size.$gap; From 0327f0f15e8e9f81b7a4804fa23369a6d24360b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 20 Jan 2023 19:17:34 +0400 Subject: [PATCH 505/537] fix: Add missing rounded corners --- .../configure-scheduling/configure-scheduling.ui.tsx | 4 +--- src/shared/ui/design/table/row.scss | 5 +++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index f6c3d1de..43647b77 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -38,9 +38,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config type Schema = InferType; - const onReset = useCallback(() => { - void editModeSwitch(false); - }, [editModeSwitch]); + const onReset = useCallback(() => editModeSwitch(false), [editModeSwitch]); const onSubmit = useCallback( (values: Schema) => { diff --git a/src/shared/ui/design/table/row.scss b/src/shared/ui/design/table/row.scss index caf8de61..03e85a38 100644 --- a/src/shared/ui/design/table/row.scss +++ b/src/shared/ui/design/table/row.scss @@ -64,6 +64,11 @@ gap: size.$gap; font-size: size.$small-text; + &:first-of-type { + border-top-left-radius: size.$task-radius; + border-top-right-radius: size.$task-radius; + } + &:last-of-type { border-bottom-left-radius: size.$task-radius; border-bottom-right-radius: size.$task-radius; From 7a0b3a07e5aaac0c0ccdf4d0e1fb146c5ac380f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 20 Jan 2023 21:14:38 +0400 Subject: [PATCH 506/537] chore: Update branch --- .../configure-scheduling/configure-scheduling.ui.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index 43647b77..00ea31f6 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -1,7 +1,7 @@ import { CancelOutlined, EditOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; import { Form, Formik } from "formik"; -import { HTMLProps, useCallback, useContext, useEffect, useState } from "react"; +import { HTMLProps, useCallback, useContext, useEffect, useMemo, useState } from "react"; import { InferType } from "yup"; import { MI } from "../../entities"; @@ -36,6 +36,8 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config jobBond: args.string().default(mi.data.ready ? toNEAR(mi.data.jobBond) : "0.001"), }); + console.log(`Job bond: ${mi.data.ready ? toNEAR(mi.data.jobBond) : "0.001"} ${NEARIcon.NativeTokenCharacter}`); + type Schema = InferType; const onReset = useCallback(() => editModeSwitch(false), [editModeSwitch]); @@ -56,8 +58,6 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config useEffect(() => resetTrigger.subscribe(onReset), [onReset, resetTrigger]); - console.log({ jobBond: mi.data.jobBond }); - return ( Date: Fri, 20 Jan 2023 21:27:14 +0400 Subject: [PATCH 507/537] chore: Remove obsolete `console.log` calls --- src/entities/wallet/ui/wallet.providers.tsx | 6 +----- src/entities/wallet/ui/wallet.selector.tsx | 8 +------- src/shared/lib/args/args.ts | 2 -- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/entities/wallet/ui/wallet.providers.tsx b/src/entities/wallet/ui/wallet.providers.tsx index 1528f001..9eb767ce 100644 --- a/src/entities/wallet/ui/wallet.providers.tsx +++ b/src/entities/wallet/ui/wallet.providers.tsx @@ -61,11 +61,7 @@ export const WalletContextProvider: FC = ({ children }) => { map((state) => state.accounts), distinctUntilChanged() ) - .subscribe((nextAccounts) => { - console.log("Accounts Update", nextAccounts); - - setAccounts(nextAccounts); - }); + .subscribe((nextAccounts) => setAccounts(nextAccounts)); return () => subscription.unsubscribe(); }, [selector]); diff --git a/src/entities/wallet/ui/wallet.selector.tsx b/src/entities/wallet/ui/wallet.selector.tsx index e325f565..6d0a1cbe 100644 --- a/src/entities/wallet/ui/wallet.selector.tsx +++ b/src/entities/wallet/ui/wallet.selector.tsx @@ -114,13 +114,7 @@ export class WalletSelector extends Component { } async signOut() { - const { selector } = this.context!; - const wallet = await selector.wallet(); - - wallet.signOut().catch((err) => { - console.log("Failed to sign out"); - console.error(err); - }); + (await this.context!.selector.wallet()).signOut().catch((err) => console.error(err)); } connectDao(dao: SputnikDAO["address"]) { diff --git a/src/shared/lib/args/args.ts b/src/shared/lib/args/args.ts index 00055a2b..5d57612e 100644 --- a/src/shared/lib/args/args.ts +++ b/src/shared/lib/args/args.ts @@ -15,5 +15,3 @@ export const args = { object: () => new ObjectSchema(), string: () => new StringSchema(), }; - -console.log(args); From 40e3facc30393cc5b10467b3dfe24e3cf987fed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 20 Jan 2023 22:42:06 +0400 Subject: [PATCH 508/537] fix: Track job bond reactively --- .../configure-scheduling/configure-scheduling.ui.tsx | 11 ++++++----- src/features/configure-scheduling/index.ts | 3 ++- src/features/configure-scheduling/params.ts | 3 +++ 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 src/features/configure-scheduling/params.ts diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index 00ea31f6..3c346951 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -12,6 +12,7 @@ import { Props } from "../../shared/lib/props"; import { TextField } from "../../shared/ui/form"; import { NEARIcon, Table, Tile, Tooltip } from "../../shared/ui/design"; +import { ConfigureSchedulingParams } from "./params"; import "./configure-scheduling.ui.scss"; const _ConfigureScheduling = "ConfigureScheduling"; @@ -25,7 +26,8 @@ interface ConfigureSchedulingUIProps extends Omit, "on export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: ConfigureSchedulingUIProps) => { const [editModeEnabled, editModeSwitch] = useState(false), - mi = useContext(MI.Context); + mi = useContext(MI.Context), + jobBondInitial = mi.data.ready ? toNEAR(mi.data.jobBond) : ConfigureSchedulingParams.minJobBondNEAR.toString(); const error = mi.data.ready && mi.data.jobBond === "" @@ -33,11 +35,9 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config : mi.error; const schema = args.object().shape({ - jobBond: args.string().default(mi.data.ready ? toNEAR(mi.data.jobBond) : "0.001"), + jobBond: args.string().default(jobBondInitial), }); - console.log(`Job bond: ${mi.data.ready ? toNEAR(mi.data.jobBond) : "0.001"} ${NEARIcon.NativeTokenCharacter}`); - type Schema = InferType; const onReset = useCallback(() => editModeSwitch(false), [editModeSwitch]); @@ -103,13 +103,14 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config , ], }, diff --git a/src/features/configure-scheduling/index.ts b/src/features/configure-scheduling/index.ts index bbf37874..bf424116 100644 --- a/src/features/configure-scheduling/index.ts +++ b/src/features/configure-scheduling/index.ts @@ -1,5 +1,6 @@ import { ConfigureSchedulingUI } from "./configure-scheduling.ui"; +import { ConfigureSchedulingParams } from "./params"; -export class ConfigureScheduling { +export class ConfigureScheduling extends ConfigureSchedulingParams { public static readonly UI = ConfigureSchedulingUI; } diff --git a/src/features/configure-scheduling/params.ts b/src/features/configure-scheduling/params.ts new file mode 100644 index 00000000..402408c5 --- /dev/null +++ b/src/features/configure-scheduling/params.ts @@ -0,0 +1,3 @@ +export class ConfigureSchedulingParams { + public static readonly minJobBondNEAR = 0.001; +} From ad0f315f2cd6dfebc5cf78d36a0f6f80c715fe6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 20 Jan 2023 23:20:26 +0400 Subject: [PATCH 509/537] wip: Move minimal job bond parameter to MI entity --- src/entities/mi/mi.params.ts | 4 +++- .../configure-scheduling.ui.tsx | 21 ++++++++++--------- src/features/configure-scheduling/index.ts | 3 +-- src/features/configure-scheduling/params.ts | 3 --- src/pages/dao/dao-page.ui.tsx | 2 +- 5 files changed, 16 insertions(+), 17 deletions(-) delete mode 100644 src/features/configure-scheduling/params.ts diff --git a/src/entities/mi/mi.params.ts b/src/entities/mi/mi.params.ts index ea64c82d..9a8a4725 100644 --- a/src/entities/mi/mi.params.ts +++ b/src/entities/mi/mi.params.ts @@ -5,7 +5,9 @@ export class MIParams { /** * Minimum balance needed for storage + state. */ - public static readonly MIN_BALANCE = toYocto(1); + public static readonly minBalanceYocto = toYocto(1); + + public static readonly minJobBondNEAR = 0.001; public static readonly SettingsDiffMeta = { addTokens: { diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index 3c346951..e1c2c29c 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -12,7 +12,6 @@ import { Props } from "../../shared/lib/props"; import { TextField } from "../../shared/ui/form"; import { NEARIcon, Table, Tile, Tooltip } from "../../shared/ui/design"; -import { ConfigureSchedulingParams } from "./params"; import "./configure-scheduling.ui.scss"; const _ConfigureScheduling = "ConfigureScheduling"; @@ -26,16 +25,18 @@ interface ConfigureSchedulingUIProps extends Omit, "on export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: ConfigureSchedulingUIProps) => { const [editModeEnabled, editModeSwitch] = useState(false), - mi = useContext(MI.Context), - jobBondInitial = mi.data.ready ? toNEAR(mi.data.jobBond) : ConfigureSchedulingParams.minJobBondNEAR.toString(); + mi = useContext(MI.Context); - const error = - mi.data.ready && mi.data.jobBond === "" - ? new Error("Error while getting Multicall Instance job bond") - : mi.error; + const error = useMemo( + () => + mi.data.ready && mi.data.jobBond === "" + ? new Error("Error while getting Multicall Instance job bond") + : mi.error, + [mi.data.ready] + ); const schema = args.object().shape({ - jobBond: args.string().default(jobBondInitial), + jobBond: args.string().default(MI.minJobBondNEAR.toString()), }); type Schema = InferType; @@ -88,6 +89,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config ), }} + loading={mi.loading} {...{ error }} >
    , ], }, diff --git a/src/features/configure-scheduling/index.ts b/src/features/configure-scheduling/index.ts index bf424116..bbf37874 100644 --- a/src/features/configure-scheduling/index.ts +++ b/src/features/configure-scheduling/index.ts @@ -1,6 +1,5 @@ import { ConfigureSchedulingUI } from "./configure-scheduling.ui"; -import { ConfigureSchedulingParams } from "./params"; -export class ConfigureScheduling extends ConfigureSchedulingParams { +export class ConfigureScheduling { public static readonly UI = ConfigureSchedulingUI; } diff --git a/src/features/configure-scheduling/params.ts b/src/features/configure-scheduling/params.ts deleted file mode 100644 index 402408c5..00000000 --- a/src/features/configure-scheduling/params.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class ConfigureSchedulingParams { - public static readonly minJobBondNEAR = 0.001; -} diff --git a/src/pages/dao/dao-page.ui.tsx b/src/pages/dao/dao-page.ui.tsx index bb2a6b46..3501f990 100644 --- a/src/pages/dao/dao-page.ui.tsx +++ b/src/pages/dao/dao-page.ui.tsx @@ -151,7 +151,7 @@ export default class DAOPageUI extends Component { return null; } - const depo = Big(this.fee).plus(MI.MIN_BALANCE); + const depo = Big(this.fee).plus(MI.minBalanceYocto); /** * Can user propose a FunctionCall to DAO? From afcf3e0906a3c8d6544d42c5c4af699bb3d2bf59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 20 Jan 2023 23:33:41 +0400 Subject: [PATCH 510/537] fix: Compute MI connection state properly --- src/entities/mi/mi.service.ts | 2 +- .../configure-scheduling.ui.tsx | 70 +++++++++---------- .../propose-settings/propose-settings.ui.tsx | 1 + 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/entities/mi/mi.service.ts b/src/entities/mi/mi.service.ts index 9fea5061..549ecdf7 100644 --- a/src/entities/mi/mi.service.ts +++ b/src/entities/mi/mi.service.ts @@ -27,7 +27,7 @@ export class MIService { await Multicall.init(Multicall.getInstanceAddress(daoAddress)).then((multicallInstance) => ({ data: multicallInstance, error: multicallInstance.ready ? null : new Error("Unable to connect to Multicall Instance"), - loading: false, + loading: !multicallInstance.ready, })) ); diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index e1c2c29c..28e6cdb2 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -36,7 +36,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config ); const schema = args.object().shape({ - jobBond: args.string().default(MI.minJobBondNEAR.toString()), + jobBond: args.string().default(mi.loading ? MI.minJobBondNEAR.toString() : toNEAR(mi.data.jobBond)), }); type Schema = InferType; @@ -60,38 +60,38 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config useEffect(() => resetTrigger.subscribe(onReset), [onReset, resetTrigger]); return ( - + + + + + ) : ( + + + void editModeSwitch(true)} + {...{ disabled }} + > + + + + + ), + }} + loading={mi.loading} + {...{ error }} > - - - - - - - ) : ( - - - void editModeSwitch(true)} - {...{ disabled }} - > - - - - - ), - }} - loading={mi.loading} - {...{ error }} - > + +
    (id === "jobBond" ? null : "blue") }} displayMode="compact" @@ -117,8 +117,8 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config }, ]} /> - - - + + + ); }; diff --git a/src/features/propose-settings/propose-settings.ui.tsx b/src/features/propose-settings/propose-settings.ui.tsx index 025e957e..06ac9315 100644 --- a/src/features/propose-settings/propose-settings.ui.tsx +++ b/src/features/propose-settings/propose-settings.ui.tsx @@ -62,6 +62,7 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on content: clsx(_ProposeSettings, { "is-inEditMode": Boolean(editMode) }, className), }} heading={editMode ? "Summary" : null} + {...mi} >

    {disabled From 4f7be6df962c96d2c77dbc855b38a251b9bf27db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 20 Jan 2023 23:36:13 +0400 Subject: [PATCH 511/537] chore: Remove redundant code --- .../configure-scheduling/configure-scheduling.ui.tsx | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index 28e6cdb2..52ce12a3 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -27,14 +27,6 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config const [editModeEnabled, editModeSwitch] = useState(false), mi = useContext(MI.Context); - const error = useMemo( - () => - mi.data.ready && mi.data.jobBond === "" - ? new Error("Error while getting Multicall Instance job bond") - : mi.error, - [mi.data.ready] - ); - const schema = args.object().shape({ jobBond: args.string().default(mi.loading ? MI.minJobBondNEAR.toString() : toNEAR(mi.data.jobBond)), }); @@ -83,8 +75,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config ), }} - loading={mi.loading} - {...{ error }} + {...mi} > Date: Fri, 20 Jan 2023 23:37:18 +0400 Subject: [PATCH 512/537] chore: Remove unused import --- src/features/configure-scheduling/configure-scheduling.ui.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index 52ce12a3..3d30426c 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -1,7 +1,7 @@ import { CancelOutlined, EditOutlined } from "@mui/icons-material"; import { IconButton } from "@mui/material"; import { Form, Formik } from "formik"; -import { HTMLProps, useCallback, useContext, useEffect, useMemo, useState } from "react"; +import { HTMLProps, useCallback, useContext, useEffect, useState } from "react"; import { InferType } from "yup"; import { MI } from "../../entities"; From f4b4d30251e331c4fea7d25f1fc820a35998deeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Fri, 20 Jan 2023 23:43:42 +0400 Subject: [PATCH 513/537] chore: Remove redundant styling --- .../configure-scheduling/configure-scheduling.ui.scss | 4 ---- src/features/configure-scheduling/configure-scheduling.ui.tsx | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/features/configure-scheduling/configure-scheduling.ui.scss b/src/features/configure-scheduling/configure-scheduling.ui.scss index de1fd26b..d2026d61 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.scss +++ b/src/features/configure-scheduling/configure-scheduling.ui.scss @@ -2,8 +2,4 @@ grid-area: ConfigureScheduling; display: flex; flex-flow: column; - - &-controls { - flex: auto; - } } diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index 3d30426c..bfb65381 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -82,7 +82,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config validationSchema={schema} {...{ onReset, onSubmit }} > -
    +

    (id === "jobBond" ? null : "blue") }} displayMode="compact" From cc265946e1c61990f057e1e22789352d12e4de31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 21 Jan 2023 16:21:58 +0400 Subject: [PATCH 514/537] wip --- src/entities/mi/mi.service.ts | 2 ++ src/features/configure-scheduling/configure-scheduling.ui.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/entities/mi/mi.service.ts b/src/entities/mi/mi.service.ts index 549ecdf7..4418e17b 100644 --- a/src/entities/mi/mi.service.ts +++ b/src/entities/mi/mi.service.ts @@ -36,6 +36,8 @@ export class MIService { useEffect(() => void MIService.propertiesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); + // TODO: onAddressUpdated -> { loading: true } + useEffect(() => { state.error instanceof Error && void console.error(state.error); }, [state.error]); diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index bfb65381..5937618e 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -28,7 +28,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config mi = useContext(MI.Context); const schema = args.object().shape({ - jobBond: args.string().default(mi.loading ? MI.minJobBondNEAR.toString() : toNEAR(mi.data.jobBond)), + jobBond: args.string().default(() => (mi.loading ? MI.minJobBondNEAR.toString() : toNEAR(mi.data.jobBond))), }); type Schema = InferType; From 733c62e9864f431e864d605194723c40f5dddacd Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Sat, 21 Jan 2023 14:20:00 +0100 Subject: [PATCH 515/537] update minor dep versions, fix failed build --- package-lock.json | 14319 ++++++++++++++++++++++++++------------------ 1 file changed, 8333 insertions(+), 5986 deletions(-) diff --git a/package-lock.json b/package-lock.json index bac7015e..06d09856 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,91 +100,33 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/code-frame/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==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/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==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/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==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/@babel/compat-data": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", - "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==", + "version": "7.20.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz", + "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", - "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", + "version": "7.20.12", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", + "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.5", - "@babel/parser": "^7.20.5", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5", + "@babel/generator": "^7.20.7", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helpers": "^7.20.7", + "@babel/parser": "^7.20.7", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.12", + "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", + "json5": "^2.2.2", "semver": "^6.3.0" }, "engines": { @@ -196,11 +138,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", - "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", + "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", "dependencies": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -232,14 +174,27 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz", - "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", "dependencies": { - "@babel/compat-data": "^7.20.0", + "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "engines": { @@ -250,16 +205,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.5.tgz", - "integrity": "sha512-3RCdA/EmEaikrhayahwToF0fpweU/8o2p8vhc1c/1kftHOdTKuC65kik/TLc+qfbS8JKw4qqJbne4ovICDhmww==", + "version": "7.20.12", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz", + "integrity": "sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.20.7", "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.19.1", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/helper-split-export-declaration": "^7.18.6" }, "engines": { @@ -308,6 +264,17 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-function-name": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", @@ -332,11 +299,11 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz", + "integrity": "sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==", "dependencies": { - "@babel/types": "^7.18.9" + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -354,18 +321,18 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", - "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", + "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.10", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -408,15 +375,16 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz", - "integrity": "sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", + "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.20.7", "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -455,6 +423,14 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", @@ -486,22 +462,35 @@ } }, "node_modules/@babel/helpers": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", - "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", + "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", - "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", + "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -524,13 +513,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", - "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", + "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-proposal-optional-chaining": "^7.18.9" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -540,12 +529,12 @@ } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.1.tgz", - "integrity": "sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-remap-async-to-generator": "^7.18.9", "@babel/plugin-syntax-async-generators": "^7.8.4" }, @@ -572,12 +561,12 @@ } }, "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", - "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.20.7.tgz", + "integrity": "sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -633,11 +622,11 @@ } }, "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", - "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", + "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -678,15 +667,15 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.2.tgz", - "integrity": "sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", "dependencies": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.1" + "@babel/plugin-transform-parameters": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -711,12 +700,12 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", - "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz", + "integrity": "sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -1003,11 +992,11 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", - "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", + "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1017,13 +1006,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", - "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", + "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", "dependencies": { "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1047,9 +1036,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.5.tgz", - "integrity": "sha512-WvpEIW9Cbj9ApF3yJCjIEEf1EiNJLtXagOrL5LNWEZOo3jv8pmPoYTSNJQvqej8OavVlgOoOPw6/htGZro6IkA==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.11.tgz", + "integrity": "sha512-tA4N427a7fjf1P0/2I4ScsHGc5jcHPbb30xMbaTke2gxDuWpUfXDuX1FEymJwKk4tuGUvGcejAR6HdZVqmmPyw==", "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -1061,17 +1050,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.2.tgz", - "integrity": "sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz", + "integrity": "sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-optimise-call-expression": "^7.18.6", "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.19.1", + "@babel/helper-replace-supers": "^7.20.7", "@babel/helper-split-export-declaration": "^7.18.6", "globals": "^11.1.0" }, @@ -1083,11 +1072,12 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", - "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", + "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -1097,9 +1087,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.2.tgz", - "integrity": "sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz", + "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==", "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -1154,29 +1144,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator/node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator/node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.18.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", @@ -1236,12 +1203,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.19.6.tgz", - "integrity": "sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", + "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", "dependencies": { - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1251,13 +1218,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz", - "integrity": "sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz", + "integrity": "sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw==", "dependencies": { - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-simple-access": "^7.19.4" + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-simple-access": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1267,13 +1234,13 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.6.tgz", - "integrity": "sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", + "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", "dependencies": { "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-validator-identifier": "^7.19.1" }, "engines": { @@ -1343,9 +1310,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.5.tgz", - "integrity": "sha512-h7plkOmcndIUWXZFLgpbrh2+fXAi47zcUX7IrOQuZdLD0I0KvjJ6cvo3BEcAOsDOcZhVKGJqv07mkSqK0y2isQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", + "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -1386,16 +1353,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz", - "integrity": "sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.20.7.tgz", + "integrity": "sha512-Tfq7qqD+tRj3EoDhY00nn2uP2hsRxgYGi5mLQ5TimKav0a9Lrpd4deE+fcLXU8zFYRjlKPHZhpCvfEA6qnBxqQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.19.0" + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -1450,14 +1417,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-regenerator/node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", @@ -1506,12 +1465,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz", - "integrity": "sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", + "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" }, "engines": { "node": ">=6.9.0" @@ -1563,11 +1522,11 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.2.tgz", - "integrity": "sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.7.tgz", + "integrity": "sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.20.2", + "@babel/helper-create-class-features-plugin": "^7.20.7", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-typescript": "^7.20.0" }, @@ -1747,9 +1706,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", - "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", + "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -1758,31 +1717,31 @@ } }, "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", - "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", + "version": "7.20.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz", + "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", + "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.5", - "@babel/types": "^7.20.5", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1791,9 +1750,9 @@ } }, "node_modules/@babel/types": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", - "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", + "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -1803,21 +1762,11 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/types/node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types/node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true }, "node_modules/@date-io/core": { "version": "2.16.0", @@ -1910,25 +1859,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@emotion/babel-plugin/node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, "node_modules/@emotion/cache": { "version": "11.10.5", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz", @@ -1941,11 +1871,6 @@ "stylis": "4.1.3" } }, - "node_modules/@emotion/cache/node_modules/@emotion/sheet": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", - "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" - }, "node_modules/@emotion/hash": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", @@ -2003,10 +1928,10 @@ "csstype": "^3.0.2" } }, - "node_modules/@emotion/serialize/node_modules/@emotion/unitless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", - "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + "node_modules/@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" }, "node_modules/@emotion/styled": { "version": "11.10.5", @@ -2034,6 +1959,11 @@ } } }, + "node_modules/@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", @@ -2052,222 +1982,208 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "node_modules/@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/core": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.3.tgz", - "integrity": "sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==", + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "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/@eslint/eslintrc/node_modules/globals": { + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dev": true, "dependencies": { - "@jest/console": "^28.1.3", - "@jest/reporters": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^28.1.3", - "jest-config": "^28.1.3", - "jest-haste-map": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-resolve-dependencies": "^28.1.3", - "jest-runner": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "jest-watcher": "^28.1.3", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "type-fest": "^0.20.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=8" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/core/node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@jest/core/node_modules/@jest/reporters": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.3.tgz", - "integrity": "sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==", + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@jridgewell/trace-mapping": "^0.3.13", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "jest-worker": "^28.1.3", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.1" + "argparse": "^2.0.1" }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=10" }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "engines": { + "node": ">=10.10.0" } }, - "node_modules/@jest/core/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==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jest/core/node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "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/@jest/core/node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/@jest/core/node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", "dev": true, "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/@jest/core/node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/core/node_modules/jest-changed-files": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.1.3.tgz", - "integrity": "sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==", + "node_modules/@jest/console/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": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/core/node_modules/jest-resolve-dependencies": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz", - "integrity": "sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==", + "node_modules/@jest/console/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": { - "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.1.3" + "color-name": "~1.1.4" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=7.0.0" } }, - "node_modules/@jest/core/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==", + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/@jest/core/node_modules/supports-color": { + "node_modules/@jest/console/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==", @@ -2279,47 +2195,122 @@ "node": ">=8" } }, - "node_modules/@jest/core/node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "node_modules/@jest/core": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.3.tgz", + "integrity": "sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "@jest/console": "^28.1.3", + "@jest/reporters": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^28.1.3", + "jest-config": "^28.1.3", + "jest-haste-map": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.3", + "jest-resolve-dependencies": "^28.1.3", + "jest-runner": "^28.1.3", + "jest-runtime": "^28.1.3", + "jest-snapshot": "^28.1.3", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "jest-watcher": "^28.1.3", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=8" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@jest/core/node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/core/node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "node_modules/@jest/core/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": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=10.12.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/@jest/environment": { @@ -2393,6 +2384,120 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/@jest/reporters": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.3.tgz", + "integrity": "sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "@jridgewell/trace-mapping": "^0.3.13", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "jest-worker": "^28.1.3", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/schemas": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", @@ -2475,42 +2580,173 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/@jest/transform/node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "node_modules/@jest/transform/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": { - "@jest/schemas": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "node_modules/@jest/transform/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": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6.0.0" + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/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/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -2529,6 +2765,28 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", @@ -2544,18 +2802,31 @@ } }, "node_modules/@ledgerhq/devices": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-7.0.5.tgz", - "integrity": "sha512-2o2zD2Yv1Hgd3+R2aLCvlyT7NxBz2nltawTCPSXaf3+8MDIyZbiJlXi43hLEISRFBG3u3bYwAQuiOisimN9C6Q==", + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-7.0.7.tgz", + "integrity": "sha512-PZ9TtaTGBYUm/g0qNKPbECZt7DDNvqM3ILS5wAtOMna2cBR+mrywUGXrkjuOWlHpuqZ8wenaAKveQBbzF2ba8w==", "dev": true, "optional": true, "dependencies": { - "@ledgerhq/errors": "^6.12.1", + "@ledgerhq/errors": "^6.12.3", "@ledgerhq/logs": "^6.10.1", "rxjs": "6", "semver": "^7.3.5" } }, + "node_modules/@ledgerhq/devices/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, + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@ledgerhq/devices/node_modules/rxjs": { "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", @@ -2585,384 +2856,367 @@ "node": ">=10" } }, + "node_modules/@ledgerhq/devices/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, + "optional": true + }, "node_modules/@ledgerhq/errors": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.12.1.tgz", - "integrity": "sha512-2qeUSUCpQbMhV9eLJDLI8wycFwTcWszP8g3cJycBt9Jf1VczC5MRERwAQv5AYhPa4rcy+jLKBOVZYxc35r5l7g==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.12.3.tgz", + "integrity": "sha512-djiMSgB/7hnK3aLR/c5ZMMivxjcI7o2+y3VKcsZZpydPoVf9+FXqeJPRfOwmJ0JxbQ//LinUfWpIfHew8LkaVw==", "dev": true, "optional": true }, "node_modules/@ledgerhq/hw-transport": { - "version": "6.27.8", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.27.8.tgz", - "integrity": "sha512-WSUgF1W3tAikSnAfeNAT2e2dgTdEQd5Vi/095C2mR5Fr0/POCSl9X4T9rlBhK5NSVD+nGXI0rN2ISj08zai8HQ==", + "version": "6.27.10", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.27.10.tgz", + "integrity": "sha512-3cmwQZsiRKe6VcHA1kAtC8+Wt0xjCa9Y0TO/Ns2k4BmEhIlG143I4H1dJntkX6XhDpE1pK9Xn2niBQsTTeGhqA==", "dev": true, "optional": true, "dependencies": { - "@ledgerhq/devices": "^7.0.5", - "@ledgerhq/errors": "^6.12.1", + "@ledgerhq/devices": "^7.0.7", + "@ledgerhq/errors": "^6.12.3", "events": "^3.3.0" } }, "node_modules/@ledgerhq/hw-transport-node-hid": { - "version": "6.27.8", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.27.8.tgz", - "integrity": "sha512-l0YNHf4aNk5ReMbPZY2afxtZnxNdnm+TSMpbTgSVPTA/2k5aQr0RY8MLrRbgBdUNK8yS+SeVBzMJrnAe6q3nSg==", + "version": "6.27.10", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.27.10.tgz", + "integrity": "sha512-+08Js51ED1OvnqS+qMnC0bxTYVQ1X3GBvKXRbh3w2IOAdp7ji8srD2VnSe1fz2iXJ19OR7KZL5quRpcv+TOWQw==", "dev": true, "optional": true, "dependencies": { - "@ledgerhq/devices": "^7.0.5", - "@ledgerhq/errors": "^6.12.1", - "@ledgerhq/hw-transport": "^6.27.8", - "@ledgerhq/hw-transport-node-hid-noevents": "^6.27.8", + "@ledgerhq/devices": "^7.0.7", + "@ledgerhq/errors": "^6.12.3", + "@ledgerhq/hw-transport": "^6.27.10", + "@ledgerhq/hw-transport-node-hid-noevents": "^6.27.10", "@ledgerhq/logs": "^6.10.1", "lodash": "^4.17.21", "node-hid": "^2.1.2", "usb": "^1.7.0" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/@ledgerhq/hw-transport-node-hid-noevents": { - "version": "6.27.8", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.27.8.tgz", - "integrity": "sha512-z5OP8ehnewN2EfoC+7q2jdfLl/j+5R23Rzj4Q0E1E2IYskJw7sJJisUOPtU1qfhsG7iJLdOxNXYjw6eb4ZlotQ==", + "node_modules/@ledgerhq/hw-transport-node-hid-noevents": { + "version": "6.27.10", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.27.10.tgz", + "integrity": "sha512-IyZO88VJubSnfDePSiOG83Ly1n7xfvvErtf7ESQxFhwCrkObkUczQDarYo8XJLCJBDuRr2UgiOfb/yAZrlf+vA==", "dev": true, "optional": true, "dependencies": { - "@ledgerhq/devices": "^7.0.5", - "@ledgerhq/errors": "^6.12.1", - "@ledgerhq/hw-transport": "^6.27.8", + "@ledgerhq/devices": "^7.0.7", + "@ledgerhq/errors": "^6.12.3", + "@ledgerhq/hw-transport": "^6.27.10", "@ledgerhq/logs": "^6.10.1", - "node-hid": "2.1.1" + "node-hid": "^2.1.2" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/@ledgerhq/hw-transport-node-hid-noevents/node_modules/node-hid": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-2.1.1.tgz", - "integrity": "sha512-Skzhqow7hyLZU93eIPthM9yjot9lszg9xrKxESleEs05V2NcbUptZc5HFqzjOkSmL0sFlZFr3kmvaYebx06wrw==", + "node_modules/@ledgerhq/hw-transport-u2f": { + "version": "5.36.0-deprecated", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-5.36.0-deprecated.tgz", + "integrity": "sha512-T/+mGHIiUK/ZQATad6DMDmobCMZ1mVST952009jKzhaE1Et2Uy2secU+QhRkx3BfEAkvwa0zSRSYCL9d20Iqjg==", + "deprecated": "@ledgerhq/hw-transport-u2f is deprecated. Please use @ledgerhq/hw-transport-webusb or @ledgerhq/hw-transport-webhid. https://github.com/LedgerHQ/ledgerjs/blob/master/docs/migrate_webusb.md", "dev": true, - "hasInstallScript": true, "optional": true, "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^3.0.2", - "prebuild-install": "^6.0.0" - }, - "bin": { - "hid-showdevices": "src/show-devices.js" - }, - "engines": { - "node": ">=10" + "@ledgerhq/errors": "^5.34.0", + "@ledgerhq/hw-transport": "^5.34.0", + "@ledgerhq/logs": "^5.30.0", + "u2f-api": "0.2.7" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "node_modules/@ledgerhq/hw-transport-u2f/node_modules/@ledgerhq/devices": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz", + "integrity": "sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==", "dev": true, "optional": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@ledgerhq/errors": "^5.50.0", + "@ledgerhq/logs": "^5.50.0", + "rxjs": "6", + "semver": "^7.3.5" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "node_modules/@ledgerhq/hw-transport-u2f/node_modules/@ledgerhq/errors": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz", + "integrity": "sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==", "dev": true, "optional": true }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "node_modules/@ledgerhq/hw-transport-u2f/node_modules/@ledgerhq/hw-transport": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz", + "integrity": "sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==", "dev": true, "optional": true, "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/@ledgerhq/hw-transport-node-hid/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": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" + "@ledgerhq/devices": "^5.51.1", + "@ledgerhq/errors": "^5.50.0", + "events": "^3.3.0" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "optional": true - }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "node_modules/@ledgerhq/hw-transport-u2f/node_modules/@ledgerhq/logs": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz", + "integrity": "sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==", "dev": true, "optional": true }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "node_modules/@ledgerhq/hw-transport-u2f/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, "optional": true, "dependencies": { - "mimic-response": "^2.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "optional": true - }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "node_modules/@ledgerhq/hw-transport-u2f/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, "optional": true, "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "optional": true - }, - "node_modules/@ledgerhq/hw-transport-node-hid/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": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "node_modules/@ledgerhq/hw-transport-u2f/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "optional": true, "dependencies": { - "number-is-nan": "^1.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "node_modules/@ledgerhq/hw-transport-u2f/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, "optional": true }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "node_modules/@ledgerhq/hw-transport-webhid": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-5.51.1.tgz", + "integrity": "sha512-w/2qSU0vwFY+D/4ucuYRViO7iS3Uuxmj9sI/Iiqkoiax9Xppb0/6H5m3ffKv6iPMmRYbgwCgXorqx4SLLSD8Kg==", "dev": true, "optional": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", - "dev": true, + "dependencies": { + "@ledgerhq/devices": "^5.51.1", + "@ledgerhq/errors": "^5.50.0", + "@ledgerhq/hw-transport": "^5.51.1", + "@ledgerhq/logs": "^5.50.0" + } + }, + "node_modules/@ledgerhq/hw-transport-webhid/node_modules/@ledgerhq/devices": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz", + "integrity": "sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==", + "dev": true, "optional": true, "dependencies": { - "semver": "^5.4.1" + "@ledgerhq/errors": "^5.50.0", + "@ledgerhq/logs": "^5.50.0", + "rxjs": "6", + "semver": "^7.3.5" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "node_modules/@ledgerhq/hw-transport-webhid/node_modules/@ledgerhq/errors": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz", + "integrity": "sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==", "dev": true, "optional": true }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "node_modules/@ledgerhq/hw-transport-webhid/node_modules/@ledgerhq/hw-transport": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz", + "integrity": "sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==", "dev": true, "optional": true, "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "@ledgerhq/devices": "^5.51.1", + "@ledgerhq/errors": "^5.50.0", + "events": "^3.3.0" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/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": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "node_modules/@ledgerhq/hw-transport-webhid/node_modules/@ledgerhq/logs": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz", + "integrity": "sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==", + "dev": true, + "optional": true + }, + "node_modules/@ledgerhq/hw-transport-webhid/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, "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "node_modules/@ledgerhq/hw-transport-webhid/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, "optional": true, "dependencies": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@ledgerhq/hw-transport-webhid/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "optional": true, + "dependencies": { + "lru-cache": "^6.0.0" }, "bin": { - "prebuild-install": "bin.js" + "semver": "bin/semver.js" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/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==", + "node_modules/@ledgerhq/hw-transport-webhid/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, "optional": true }, - "node_modules/@ledgerhq/hw-transport-node-hid/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==", + "node_modules/@ledgerhq/hw-transport-webusb": { + "version": "5.53.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.53.1.tgz", + "integrity": "sha512-A/f+xcrkIAZiJrvPpDvsrjxQX4cI2kbdiunQkwsYmOG3Bp4z89ZnsBiC7YBst4n2/g+QgTg0/KPVtODU5djooQ==", "dev": true, "optional": 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" + "@ledgerhq/devices": "^5.51.1", + "@ledgerhq/errors": "^5.50.0", + "@ledgerhq/hw-transport": "^5.51.1", + "@ledgerhq/logs": "^5.50.0" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/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, - "optional": true - }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/@ledgerhq/hw-transport-webusb/node_modules/@ledgerhq/devices": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz", + "integrity": "sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==", "dev": true, "optional": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "@ledgerhq/errors": "^5.50.0", + "@ledgerhq/logs": "^5.50.0", + "rxjs": "6", + "semver": "^7.3.5" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/simple-get": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", - "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "node_modules/@ledgerhq/hw-transport-webusb/node_modules/@ledgerhq/errors": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz", + "integrity": "sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==", + "dev": true, + "optional": true + }, + "node_modules/@ledgerhq/hw-transport-webusb/node_modules/@ledgerhq/hw-transport": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz", + "integrity": "sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==", "dev": true, "optional": true, "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" + "@ledgerhq/devices": "^5.51.1", + "@ledgerhq/errors": "^5.50.0", + "events": "^3.3.0" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "node_modules/@ledgerhq/hw-transport-webusb/node_modules/@ledgerhq/logs": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz", + "integrity": "sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==", + "dev": true, + "optional": true + }, + "node_modules/@ledgerhq/hw-transport-webusb/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, "optional": true, "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "node_modules/@ledgerhq/hw-transport-webusb/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, "optional": true, "dependencies": { - "ansi-regex": "^2.0.0" + "tslib": "^1.9.0" }, "engines": { - "node": ">=0.10.0" + "npm": ">=2.0.0" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/usb": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/usb/-/usb-1.9.2.tgz", - "integrity": "sha512-dryNz030LWBPAf6gj8vyq0Iev3vPbCLHCT8dBw3gQRXRzVNsIdeuU+VjPp3ksmSPkeMAl1k+kQ14Ij0QHyeiAg==", + "node_modules/@ledgerhq/hw-transport-webusb/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, - "hasInstallScript": true, "optional": true, "dependencies": { - "node-addon-api": "^4.2.0", - "node-gyp-build": "^4.3.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=10.16.0" + "node": ">=10" } }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/usb/node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "node_modules/@ledgerhq/hw-transport-webusb/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, "optional": true }, - "node_modules/@ledgerhq/hw-transport-node-hid/node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "optional": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/@ledgerhq/logs": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.10.1.tgz", @@ -3068,6 +3322,54 @@ "node": ">=12.0.0" } }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.2.0.tgz", + "integrity": "sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.2.0.tgz", + "integrity": "sha512-vq0tT8sjZsy4JdSqmadWVw6f66UXqUCabLmUVHZwUFzMgtgoIIQjT4VVRHKvlof3P/dMCkbMJ5hB1oJ9OWHaaw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.2.0.tgz", + "integrity": "sha512-SaJ3Qq4lX9Syd2xEo9u3qPxi/OB+5JO/ngJKK97XDpa1C587H9EWYO6KD8995DAjSinWvdHKRrCOXVUC5fvGOg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.2.0.tgz", + "integrity": "sha512-hlxxLdRmPyq16QCutUtP8Tm6RDWcyaLsRssaHROatgnkOxdleMTgetf9JsdncL8vLh7FVy/RN9i3XR5dnb9cRA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.2.0.tgz", @@ -3080,15 +3382,27 @@ "linux" ] }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.2.0.tgz", + "integrity": "sha512-XrC0JzsqQSvOyM3t04FMLO6z5gCuhPE6k4FXuLK5xf52ZbdvcFe1yBmo7meCew9B8G2f0T9iu9t3kfTYRYROgA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@mui/base": { - "version": "5.0.0-alpha.110", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.110.tgz", - "integrity": "sha512-q4TH9T3sTBknTXXTEf2zO8F3nbHg5iGgiaRx9XErTbXvHrmLrQXbQ4hmrLERocSTBFCFWkKyne/qZj0diWlPtA==", + "version": "5.0.0-alpha.114", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.114.tgz", + "integrity": "sha512-ZpsG2I+zTOAnVTj3Un7TxD2zKRA2OhEPGMcWs/9ylPlS6VuGQSXowPooZiqarjT7TZ0+1bOe8titk/t8dLFiGw==", "dependencies": { - "@babel/runtime": "^7.20.6", + "@babel/runtime": "^7.20.7", "@emotion/is-prop-valid": "^1.2.0", "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.0", + "@mui/utils": "^5.11.2", "@popperjs/core": "^2.11.6", "clsx": "^1.2.1", "prop-types": "^15.8.1", @@ -3112,13 +3426,13 @@ } } }, - "node_modules/@mui/base/node_modules/@popperjs/core": { - "version": "2.11.6", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", - "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "node_modules/@mui/core-downloads-tracker": { + "version": "5.11.5", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.5.tgz", + "integrity": "sha512-MIuWGjitOsugpRhp64CQY3ZEVMIu9M/L9ioql6QLSkz73+bGIlC9FEhfi670/GZ8pQIIGmtiGGwofYzlwEWjig==", "funding": { "type": "opencollective", - "url": "https://opencollective.com/popperjs" + "url": "https://opencollective.com/mui" } }, "node_modules/@mui/icons-material": { @@ -3147,15 +3461,15 @@ } }, "node_modules/@mui/lab": { - "version": "5.0.0-alpha.112", - "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.112.tgz", - "integrity": "sha512-XKxxUevHup9l9THXWhPcWxm8LZj+E8KDOz6cWqXOnXfSZwFYsvK/nB2R4PCiy/wobURk/+qxIAzryBA9pnSk2g==", + "version": "5.0.0-alpha.116", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.116.tgz", + "integrity": "sha512-TJHXYuJnZWzHNtQ8VlFIbRB2ZrhOkc1N5yBANKn9UvT0ktpCgtnfkLsY5ckDE/PX54L0mg3kaZ6An5j4mvEzkQ==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@mui/base": "5.0.0-alpha.110", - "@mui/system": "^5.11.0", + "@babel/runtime": "^7.20.7", + "@mui/base": "5.0.0-alpha.114", + "@mui/system": "^5.11.5", "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.0", + "@mui/utils": "^5.11.2", "clsx": "^1.2.1", "prop-types": "^15.8.1", "react-is": "^18.2.0" @@ -3188,16 +3502,16 @@ } }, "node_modules/@mui/material": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.0.tgz", - "integrity": "sha512-8Zl34lb89rLKTTi50Kakki675/LLHMKKnkp8Ee3rAZ2qmisQlRODsGh1MBjENKp0vwhQnNSvlsCfJteVTfotPQ==", - "dependencies": { - "@babel/runtime": "^7.20.6", - "@mui/base": "5.0.0-alpha.110", - "@mui/core-downloads-tracker": "^5.11.0", - "@mui/system": "^5.11.0", + "version": "5.11.5", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.5.tgz", + "integrity": "sha512-5fzjBbRYaB5MoEpvA32oalAWltOZ3/kSyuovuVmPc6UF6AG42lTtbdMLpdCygurFSGUMZYTg4Cjij52fKlDDgg==", + "dependencies": { + "@babel/runtime": "^7.20.7", + "@mui/base": "5.0.0-alpha.114", + "@mui/core-downloads-tracker": "^5.11.5", + "@mui/system": "^5.11.5", "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.0", + "@mui/utils": "^5.11.2", "@types/react-transition-group": "^4.4.5", "clsx": "^1.2.1", "csstype": "^3.1.1", @@ -3231,26 +3545,39 @@ } } }, - "node_modules/@mui/material/node_modules/@mui/core-downloads-tracker": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.0.tgz", - "integrity": "sha512-Bmogung451ezVv2YI1RvweOIVsTj2RQ4Fk61+e/+8LFPLTFEwVGbL0YhNy1VB5tri8pzGNV228kxtWVTFooQkg==", + "node_modules/@mui/private-theming": { + "version": "5.11.2", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.2.tgz", + "integrity": "sha512-qZwMaqRFPwlYmqwVKblKBGKtIjJRAj3nsvX93pOmatsXyorW7N/0IPE/swPgz1VwChXhHO75DwBEx8tB+aRMNg==", + "dependencies": { + "@babel/runtime": "^7.20.7", + "@mui/utils": "^5.11.2", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@mui/system": { + "node_modules/@mui/styled-engine": { "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.0.tgz", - "integrity": "sha512-HFUT7Dlmyq6Wfuxsw8QBXZxXDYIQQaJ4YHaZd7s+nDMcjerLnILxjh2g3a6umtOUM+jEcRaFJAtvLZvlGfa5fw==", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.0.tgz", + "integrity": "sha512-AF06K60Zc58qf0f7X+Y/QjaHaZq16znliLnGc9iVrV/+s8Ln/FCoeNuFvhlCbZZQ5WQcJvcy59zp0nXrklGGPQ==", "dependencies": { "@babel/runtime": "^7.20.6", - "@mui/private-theming": "^5.11.0", - "@mui/styled-engine": "^5.11.0", - "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.0", - "clsx": "^1.2.1", + "@emotion/cache": "^11.10.5", "csstype": "^3.1.1", "prop-types": "^15.8.1" }, @@ -3262,9 +3589,8 @@ "url": "https://opencollective.com/mui" }, "peerDependencies": { - "@emotion/react": "^11.5.0", + "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { @@ -3273,19 +3599,21 @@ }, "@emotion/styled": { "optional": true - }, - "@types/react": { - "optional": true } } }, - "node_modules/@mui/system/node_modules/@mui/private-theming": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.0.tgz", - "integrity": "sha512-UFQLb9x5Sj4pg2GhhCGw3Ls/y1Hw/tz9RsBrULvUF0Vgps1z19o7XTq2xqUvp7pN7fJTW7eVIT2gwVg2xlk8PQ==", + "node_modules/@mui/system": { + "version": "5.11.5", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.5.tgz", + "integrity": "sha512-KNVsJ0sgRRp2XBqhh4wPS5aacteqjwxgiYTVwVnll2fgkgunZKo3DsDiGMrFlCg25ZHA3Ax58txWGE9w58zp0w==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@mui/utils": "^5.11.0", + "@babel/runtime": "^7.20.7", + "@mui/private-theming": "^5.11.2", + "@mui/styled-engine": "^5.11.0", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.2", + "clsx": "^1.2.1", + "csstype": "^3.1.1", "prop-types": "^15.8.1" }, "engines": { @@ -3296,43 +3624,20 @@ "url": "https://opencollective.com/mui" }, "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", "@types/react": "^17.0.0 || ^18.0.0", "react": "^17.0.0 || ^18.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/system/node_modules/@mui/styled-engine": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.0.tgz", - "integrity": "sha512-AF06K60Zc58qf0f7X+Y/QjaHaZq16znliLnGc9iVrV/+s8Ln/FCoeNuFvhlCbZZQ5WQcJvcy59zp0nXrklGGPQ==", - "dependencies": { - "@babel/runtime": "^7.20.6", - "@emotion/cache": "^11.10.5", - "csstype": "^3.1.1", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0" - }, "peerDependenciesMeta": { "@emotion/react": { "optional": true }, "@emotion/styled": { "optional": true + }, + "@types/react": { + "optional": true } } }, @@ -3350,11 +3655,11 @@ } }, "node_modules/@mui/utils": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.0.tgz", - "integrity": "sha512-DP/YDaVVCVzJpZ5FFPLKNmaJkeaYRviTyIZkL/D5/FmPXQiA6ecd6z0/+VwoNQtp7aXAQWaRhvz4FM25yqFlHA==", + "version": "5.11.2", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.2.tgz", + "integrity": "sha512-AyizuHHlGdAtH5hOOXBW3kriuIwUIKUIgg0P7LzMvzf6jPhoQbENYqY6zJqfoZ7fAWMNNYT8mgN5EftNGzwE2w==", "dependencies": { - "@babel/runtime": "^7.20.6", + "@babel/runtime": "^7.20.7", "@types/prop-types": "^15.7.5", "@types/react-is": "^16.7.1 || ^17.0.0", "prop-types": "^15.8.1", @@ -3371,18 +3676,10 @@ "react": "^17.0.0 || ^18.0.0" } }, - "node_modules/@mui/utils/node_modules/@types/react-is": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", - "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@mui/x-date-pickers": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-5.0.11.tgz", - "integrity": "sha512-YxUpyepbtzo6mu42KaaoJrfBHvlLobEdkP5EcEQ+OSaY5xxCEHqfSgi1NioXcxzZUi6ome5jcrjAopUHzFGk0g==", + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-5.0.15.tgz", + "integrity": "sha512-jQPwiB961fYT79H419/sfSqWRefo9aCx5MEDGZOifMuRv6k5gcZCrSFjmLC5Lt4PZ20BsitJYvSKpmvYZYh+mg==", "dependencies": { "@babel/runtime": "^7.18.9", "@date-io/core": "^2.15.0", @@ -3438,9 +3735,9 @@ } }, "node_modules/@near-wallet-selector/core": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@near-wallet-selector/core/-/core-7.3.0.tgz", - "integrity": "sha512-kmW3/taTfX3KjsXkaAbPtQUYTSpax5HY8aFE/66wlGgmm7PboEOPYys04PkG/f6SJ3UJoTn49Ek87C0eu5hSDA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@near-wallet-selector/core/-/core-7.5.0.tgz", + "integrity": "sha512-rE80wOvqTyN1ezL04USdBxd5lmyk1HhS3K8HL24fyYUIhvIx3/qfrmdVjN3nrLlCh/JMBux1KBPIZugf2DSe3A==", "dependencies": { "rxjs": "^7.5.7" }, @@ -3449,44 +3746,47 @@ } }, "node_modules/@near-wallet-selector/modal-ui": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@near-wallet-selector/modal-ui/-/modal-ui-7.3.0.tgz", - "integrity": "sha512-zh9YCE805nvHHBOOpZDj4dzEXPuggfmTfOIrs7NQ3yQ22CHJ7M3KYh3HtLhDSEqq7DS+qfKiwOql39L9Y6zf2w==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@near-wallet-selector/modal-ui/-/modal-ui-7.5.0.tgz", + "integrity": "sha512-62QCIrXOld5yL1zPP0xYsy0pTUZZnQgqGJJ+cMAqn9dgG8LYQWoF1C+3cxwGlxZeV0hWMTgkOpqOV6lH+pIU7w==", "dependencies": { - "@near-wallet-selector/core": "7.3.0", - "copy-to-clipboard": "^3.3.2", + "@near-wallet-selector/core": "7.5.0", + "copy-to-clipboard": "^3.3.3", "qrcode": "^1.5.1", "react": "18.2.0", "react-dom": "18.2.0" } }, "node_modules/@near-wallet-selector/my-near-wallet": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@near-wallet-selector/my-near-wallet/-/my-near-wallet-7.3.0.tgz", - "integrity": "sha512-Eo+r+wQySKyTh9Aq60r7V1umjdJd8WkHyLyhk6O6jiYJeh9FLHKmssoJ23CeQZIP/bGyKeeBOU+/8kaFox9fiQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@near-wallet-selector/my-near-wallet/-/my-near-wallet-7.5.0.tgz", + "integrity": "sha512-hkY12bc1U3rYYvkuWQrhTU4NLMTpbuIOJD8bhh/nYWbdCpV16GmnmR3AWnWqcwjDHwruq+1GLB04HN0oOxz9lg==", "dependencies": { - "@near-wallet-selector/core": "7.3.0", - "@near-wallet-selector/wallet-utils": "7.3.0" + "@near-wallet-selector/core": "7.5.0", + "@near-wallet-selector/wallet-utils": "7.5.0" }, "peerDependencies": { "near-api-js": "^0.44.2 || ^1.0.0" } }, "node_modules/@near-wallet-selector/near-wallet": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@near-wallet-selector/near-wallet/-/near-wallet-7.3.0.tgz", - "integrity": "sha512-Zo85ECu/1a/iM6j0dJAubQiwT8SqDngzX6bwBMK9k64EcaotoGHsdEgo8YF/yW32hEivteSHT9satDUcQL6I1A==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@near-wallet-selector/near-wallet/-/near-wallet-7.5.0.tgz", + "integrity": "sha512-q6f14+bliH1Yfiz+Acw/V2LvA6NKkFyq67+Wu5O451zhMAK8fjV6lCneZAViSNCOrewTQHdpyy+b2O7DCTVDww==", "dependencies": { - "@near-wallet-selector/core": "7.3.0", - "@near-wallet-selector/my-near-wallet": "7.3.0" + "@near-wallet-selector/core": "7.5.0", + "@near-wallet-selector/my-near-wallet": "7.5.0" + }, + "peerDependencies": { + "near-api-js": "^0.44.2 || ^1.0.0" } }, "node_modules/@near-wallet-selector/sender": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@near-wallet-selector/sender/-/sender-7.3.0.tgz", - "integrity": "sha512-XSDVNxV2xll4YdVRf900cRey0hBaUDRc3uw+gURRygSD8UfWiOVow/n9oWREAnxHxWNqbauMxNSTWZ8T2kQG/Q==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@near-wallet-selector/sender/-/sender-7.5.0.tgz", + "integrity": "sha512-ARpidCWETrZEivtLzzZoft451I2bvNjzM5R8dzK1LQ2wwu3m6e6dtIOi9X1s0Oi/JqKI0kAQuWttiEchGelObQ==", "dependencies": { - "@near-wallet-selector/core": "7.3.0", + "@near-wallet-selector/core": "7.5.0", "is-mobile": "^3.1.1" }, "peerDependencies": { @@ -3494,11 +3794,11 @@ } }, "node_modules/@near-wallet-selector/wallet-utils": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@near-wallet-selector/wallet-utils/-/wallet-utils-7.3.0.tgz", - "integrity": "sha512-G502AecZqIXKcINpngeWMpbEoxXEyt/z9qpszhOrG9bnC6ecKMY+hth3SzUDI9etyx01Hc39J3Q/74t1worQCg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@near-wallet-selector/wallet-utils/-/wallet-utils-7.5.0.tgz", + "integrity": "sha512-knL9tOeK5o9WcFZri8IftTk/WtKgRywXjMq1hNXurJiRI+czHNioE/zND6FwJ9vMjHEAcdSIfn+xcgBhP92n7w==", "dependencies": { - "@near-wallet-selector/core": "7.3.0", + "@near-wallet-selector/core": "7.5.0", "bn.js": "^5.2.0" }, "peerDependencies": { @@ -3506,9 +3806,9 @@ } }, "node_modules/@netlify/plugin-lighthouse": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@netlify/plugin-lighthouse/-/plugin-lighthouse-4.0.3.tgz", - "integrity": "sha512-wfl4Cy8pEypm7jXSTateD3u/jXPUm/l+Yw9v04vc70Z8iItwFHAyYyZtbxE45N5SM9fa5vifPEtb4hhRfHvtSg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@netlify/plugin-lighthouse/-/plugin-lighthouse-4.0.5.tgz", + "integrity": "sha512-L73Z3oJW1YDjkkzqHPaj4GOD3dBQIeCcrKo21rb5yuzZIMfJvlnxcqyct/SlPf9+pO+e+ze7v45WHO9arkrmrg==", "dev": true, "dependencies": { "chalk": "^4.1.0", @@ -3524,6 +3824,76 @@ "node": ">=14.15 <19" } }, + "node_modules/@netlify/plugin-lighthouse/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@netlify/plugin-lighthouse/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@netlify/plugin-lighthouse/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@netlify/plugin-lighthouse/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@netlify/plugin-lighthouse/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@netlify/plugin-lighthouse/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/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3559,14 +3929,35 @@ "node": ">= 8" } }, + "node_modules/@parcel/bundler-default": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.8.3.tgz", + "integrity": "sha512-yJvRsNWWu5fVydsWk3O2L4yIy3UZiKWO2cPDukGOIWMgp/Vbpp+2Ct5IygVRtE22bnseW/E/oe0PV3d2IkEJGg==", + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/graph": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@parcel/cache": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.8.2.tgz", - "integrity": "sha512-kiyoOgh1RXp5qp+wlb8Pi/Z7o9D82Oj5RlHnKSAauyR7jgnI8Vq8JTeBmlLqrf+kHxcDcp2p86hidSeANhlQNg==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.8.3.tgz", + "integrity": "sha512-k7xv5vSQrJLdXuglo+Hv3yF4BCSs1tQ/8Vbd6CHTkOhf7LcGg6CPtLw053R/KdMpd/4GPn0QrAsOLdATm1ELtQ==", "dependencies": { - "@parcel/fs": "2.8.2", - "@parcel/logger": "2.8.2", - "@parcel/utils": "2.8.2", + "@parcel/fs": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/utils": "2.8.3", "lmdb": "2.5.2" }, "engines": { @@ -3577,137 +3968,175 @@ "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.8.2" + "@parcel/core": "^2.8.3" } }, - "node_modules/@parcel/config-default": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.8.2.tgz", - "integrity": "sha512-1ELJAHx37fKSZZkYKWy6UdcuLRv5vrZJc89tVS6eRvvMt+udbIoSgIUzPXu7XemkcchF7Tryw3u2pRyxyLyL3w==", - "dependencies": { - "@parcel/bundler-default": "2.8.2", - "@parcel/compressor-raw": "2.8.2", - "@parcel/namer-default": "2.8.2", - "@parcel/optimizer-css": "2.8.2", - "@parcel/optimizer-htmlnano": "2.8.2", - "@parcel/optimizer-image": "2.8.2", - "@parcel/optimizer-svgo": "2.8.2", - "@parcel/optimizer-terser": "2.8.2", - "@parcel/packager-css": "2.8.2", - "@parcel/packager-html": "2.8.2", - "@parcel/packager-js": "2.8.2", - "@parcel/packager-raw": "2.8.2", - "@parcel/packager-svg": "2.8.2", - "@parcel/reporter-dev-server": "2.8.2", - "@parcel/resolver-default": "2.8.2", - "@parcel/runtime-browser-hmr": "2.8.2", - "@parcel/runtime-js": "2.8.2", - "@parcel/runtime-react-refresh": "2.8.2", - "@parcel/runtime-service-worker": "2.8.2", - "@parcel/transformer-babel": "2.8.2", - "@parcel/transformer-css": "2.8.2", - "@parcel/transformer-html": "2.8.2", - "@parcel/transformer-image": "2.8.2", - "@parcel/transformer-js": "2.8.2", - "@parcel/transformer-json": "2.8.2", - "@parcel/transformer-postcss": "2.8.2", - "@parcel/transformer-posthtml": "2.8.2", - "@parcel/transformer-raw": "2.8.2", - "@parcel/transformer-react-refresh-wrap": "2.8.2", - "@parcel/transformer-svg": "2.8.2" + "node_modules/@parcel/codeframe": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.8.3.tgz", + "integrity": "sha512-FE7sY53D6n/+2Pgg6M9iuEC6F5fvmyBkRE4d9VdnOoxhTXtkEqpqYgX7RJ12FAQwNlxKq4suBJQMgQHMF2Kjeg==", + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "@parcel/core": "^2.8.2" } }, - "node_modules/@parcel/config-default/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "node_modules/@parcel/codeframe/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@parcel/config-default/node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "node_modules/@parcel/codeframe/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/bundler-default": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.8.2.tgz", - "integrity": "sha512-/7ao0vc/v8WGHZaS1SyS5R8wzqmmXEr9mhIIB2cbLQ4LA2WUtKsYcvZ2gjJuiAAN1CHC6GxqwYjIJScQCk/QXg==", + "node_modules/@parcel/codeframe/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==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/graph": "2.8.2", - "@parcel/hash": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", - "nullthrows": "^1.1.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">=7.0.0" + } + }, + "node_modules/@parcel/codeframe/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/@parcel/codeframe/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/codeframe/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==", + "dependencies": { + "has-flag": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=8" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/compressor-raw": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.8.2.tgz", - "integrity": "sha512-EFPTer/P+3axifH6LtYHS3E6ABgdZnjZomJZ/Nl19lypZh/NgZzmMZlINlEVqyYhCggoKfXzgeTgkIHPN2d5Vw==", + "node_modules/@parcel/compressor-raw": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.8.3.tgz", + "integrity": "sha512-bVDsqleBUxRdKMakWSlWC9ZjOcqDKE60BE+Gh3JSN6WJrycJ02P5wxjTVF4CStNP/G7X17U+nkENxSlMG77ySg==", "dependencies": { - "@parcel/plugin": "2.8.2" + "@parcel/plugin": "2.8.3" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/namer-default": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.8.2.tgz", - "integrity": "sha512-sMLW/bDWXA6IE7TQKOsBnA5agZGNvZ9qIXKZEUTsTloUjMdAWI8NYA1s0i9HovnGxI5uGlgevrftK4S5V4AdkA==", - "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/plugin": "2.8.2", - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node_modules/@parcel/config-default": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.8.3.tgz", + "integrity": "sha512-o/A/mbrO6X/BfGS65Sib8d6SSG45NYrNooNBkH/o7zbOBSRQxwyTlysleK1/3Wa35YpvFyLOwgfakqCtbGy4fw==", + "dependencies": { + "@parcel/bundler-default": "2.8.3", + "@parcel/compressor-raw": "2.8.3", + "@parcel/namer-default": "2.8.3", + "@parcel/optimizer-css": "2.8.3", + "@parcel/optimizer-htmlnano": "2.8.3", + "@parcel/optimizer-image": "2.8.3", + "@parcel/optimizer-svgo": "2.8.3", + "@parcel/optimizer-terser": "2.8.3", + "@parcel/packager-css": "2.8.3", + "@parcel/packager-html": "2.8.3", + "@parcel/packager-js": "2.8.3", + "@parcel/packager-raw": "2.8.3", + "@parcel/packager-svg": "2.8.3", + "@parcel/reporter-dev-server": "2.8.3", + "@parcel/resolver-default": "2.8.3", + "@parcel/runtime-browser-hmr": "2.8.3", + "@parcel/runtime-js": "2.8.3", + "@parcel/runtime-react-refresh": "2.8.3", + "@parcel/runtime-service-worker": "2.8.3", + "@parcel/transformer-babel": "2.8.3", + "@parcel/transformer-css": "2.8.3", + "@parcel/transformer-html": "2.8.3", + "@parcel/transformer-image": "2.8.3", + "@parcel/transformer-js": "2.8.3", + "@parcel/transformer-json": "2.8.3", + "@parcel/transformer-postcss": "2.8.3", + "@parcel/transformer-posthtml": "2.8.3", + "@parcel/transformer-raw": "2.8.3", + "@parcel/transformer-react-refresh-wrap": "2.8.3", + "@parcel/transformer-svg": "2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/node-resolver-core": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-2.8.2.tgz", - "integrity": "sha512-D/NJEz/h/C3RmUOWSTg0cLwG3uRVHY9PL+3YGO/c8tKu8PlS2j55XtntdiVfwkK+P6avLCnrJnv/gwTa79dOPw==", + "node_modules/@parcel/core": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.8.3.tgz", + "integrity": "sha512-Euf/un4ZAiClnlUXqPB9phQlKbveU+2CotZv7m7i+qkgvFn5nAGnrV4h1OzQU42j9dpgOxWi7AttUDMrvkbhCQ==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/utils": "2.8.2", + "@mischnic/json-sourcemap": "^0.1.0", + "@parcel/cache": "2.8.3", + "@parcel/diagnostic": "2.8.3", + "@parcel/events": "2.8.3", + "@parcel/fs": "2.8.3", + "@parcel/graph": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/package-manager": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "abortcontroller-polyfill": "^1.1.9", + "base-x": "^3.0.8", + "browserslist": "^4.6.6", + "clone": "^2.1.1", + "dotenv": "^7.0.0", + "dotenv-expand": "^5.1.0", + "json5": "^2.2.0", + "msgpackr": "^1.5.4", "nullthrows": "^1.1.1", "semver": "^5.7.1" }, @@ -3719,802 +4148,752 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/optimizer-css": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.8.2.tgz", - "integrity": "sha512-pQEuKhk0PJuYI3hrXlf4gpuuPy+MZUDzC44ulQM7kVcVJ0OofuJQQeHfTLE+v5wClFDd29ZQZ7RsLP5RyUQ+Lg==", + "node_modules/@parcel/core/node_modules/dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@parcel/core/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@parcel/diagnostic": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.8.3.tgz", + "integrity": "sha512-u7wSzuMhLGWZjVNYJZq/SOViS3uFG0xwIcqXw12w54Uozd6BH8JlhVtVyAsq9kqnn7YFkw6pXHqAo5Tzh4FqsQ==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.2", - "browserslist": "^4.6.6", - "lightningcss": "^1.16.1", + "@mischnic/json-sourcemap": "^0.1.0", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/optimizer-htmlnano": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.8.2.tgz", - "integrity": "sha512-4+3wi+Yi+hsf5/LolX59JXFe/7bLpI6NetUBgtoxOVm/EzFg1NGSNOcrthzEcgGj6+MMSdzBAxRTPObAfDxJCA==", - "dependencies": { - "@parcel/plugin": "2.8.2", - "htmlnano": "^2.0.0", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "svgo": "^2.4.0" - }, + "node_modules/@parcel/events": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.8.3.tgz", + "integrity": "sha512-hoIS4tAxWp8FJk3628bsgKxEvR7bq2scCVYHSqZ4fTi/s0+VymEATrRCUqf+12e5H47uw1/ZjoqrGtBI02pz4w==", "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/optimizer-image": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.8.2.tgz", - "integrity": "sha512-/ICYG0smbMkli+su4m/ENQPxQDCPYYTJTjseKwl+t1vyj6wqNF99mNI4c0RE2TIPuDneGwSz7PlHhC2JmdgxfQ==", + "node_modules/@parcel/fs": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.8.3.tgz", + "integrity": "sha512-y+i+oXbT7lP0e0pJZi/YSm1vg0LDsbycFuHZIL80pNwdEppUAtibfJZCp606B7HOjMAlNZOBo48e3hPG3d8jgQ==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", - "@parcel/workers": "2.8.2", - "detect-libc": "^1.0.3" + "@parcel/fs-search": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/watcher": "^2.0.7", + "@parcel/workers": "2.8.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/optimizer-svgo": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.8.2.tgz", - "integrity": "sha512-nFWyM+CBtgBixqknpbN4R92v8PK7Gjlrsb8vxN/IIr/3Pjk+DfoT51DnynhU7AixvDylYkgjjqrQ7uFYYl0OKA==", + "node_modules/@parcel/fs-search": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/fs-search/-/fs-search-2.8.3.tgz", + "integrity": "sha512-DJBT2N8knfN7Na6PP2mett3spQLTqxFrvl0gv+TJRp61T8Ljc4VuUTb0hqBj+belaASIp3Q+e8+SgaFQu7wLiQ==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", - "svgo": "^2.4.0" + "detect-libc": "^1.0.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/optimizer-terser": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-terser/-/optimizer-terser-2.8.2.tgz", - "integrity": "sha512-jFAOh9WaO6oNc8B9qDsCWzNkH7nYlpvaPn0w3ZzpMDi0HWD+w+xgO737rWLJWZapqUDSOs0Q/hDFEZ82/z0yxA==", + "node_modules/@parcel/graph": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-2.8.3.tgz", + "integrity": "sha512-26GL8fYZPdsRhSXCZ0ZWliloK6DHlMJPWh6Z+3VVZ5mnDSbYg/rRKWmrkhnr99ZWmL9rJsv4G74ZwvDEXTMPBg==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.2", - "nullthrows": "^1.1.1", - "terser": "^5.2.0" + "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/packager-css": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.8.2.tgz", - "integrity": "sha512-l2fR5qr1moUWLOqQZPxtH6DBKbaKcxzEPAmQ+f15dHt8eQxU15MyQ4DHX41b5B7HwaumgCqe0NkuTF3DedpJKg==", + "node_modules/@parcel/hash": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/hash/-/hash-2.8.3.tgz", + "integrity": "sha512-FVItqzjWmnyP4ZsVgX+G00+6U2IzOvqDtdwQIWisCcVoXJFCqZJDy6oa2qDDFz96xCCCynjRjPdQx2jYBCpfYw==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.2", - "nullthrows": "^1.1.1" + "detect-libc": "^1.0.3", + "xxhash-wasm": "^0.4.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/packager-html": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.8.2.tgz", - "integrity": "sha512-/oiTsKZ5OyF9OwAVGHANNuW2TB3k3cVub1QfttSKJgG3sAhrOifb1dP8zBHMxvUrB0CJdYhGlgi1Jth9kjACCg==", + "node_modules/@parcel/logger": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.8.3.tgz", + "integrity": "sha512-Kpxd3O/Vs7nYJIzkdmB6Bvp3l/85ydIxaZaPfGSGTYOfaffSOTkhcW9l6WemsxUrlts4za6CaEWcc4DOvaMOPA==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/types": "2.8.2", - "@parcel/utils": "2.8.2", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5" + "@parcel/diagnostic": "2.8.3", + "@parcel/events": "2.8.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/packager-js": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.8.2.tgz", - "integrity": "sha512-48LtHP4lJn8J1aBeD4Ix/YjsRxrBUkzbx7czdUeRh2PlCqY4wwIhciVlEFipj/ANr3ieSX44lXyVPk/ttnSdrw==", + "node_modules/@parcel/markdown-ansi": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.8.3.tgz", + "integrity": "sha512-4v+pjyoh9f5zuU/gJlNvNFGEAb6J90sOBwpKJYJhdWXLZMNFCVzSigxrYO+vCsi8G4rl6/B2c0LcwIMjGPHmFQ==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/hash": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.2", - "globals": "^13.2.0", - "nullthrows": "^1.1.1" + "chalk": "^4.1.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/packager-raw": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.8.2.tgz", - "integrity": "sha512-dGonfFptNV1lgqKaD17ecXBUyIfoG6cJI1cCE1sSoYCEt7r+Rq56X/Gq8oiA3+jjMC7QTls+SmFeMZh26fl77Q==", + "node_modules/@parcel/markdown-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@parcel/plugin": "2.8.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/packager-svg": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.8.2.tgz", - "integrity": "sha512-k7LymTJ4XQA+UcPwFYqJfWs5/Awa4GirNxRWfiFflLqH3F1XvMiKSCIQXmrDM6IaeIqqDDsu6+P5U6YDAzzM3A==", + "node_modules/@parcel/markdown-ansi/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/types": "2.8.2", - "@parcel/utils": "2.8.2", - "posthtml": "^0.16.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/resolver-default": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.8.2.tgz", - "integrity": "sha512-mlowJMjFjyps9my8wd13kgeExJ5EgkPAuIxRSSWW+GPR7N3uA5DBJ+SB/CzdhCkPrXR6kwVWxNkkOch38pzOQQ==", + "node_modules/@parcel/markdown-ansi/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==", "dependencies": { - "@parcel/node-resolver-core": "2.8.2", - "@parcel/plugin": "2.8.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=7.0.0" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/runtime-browser-hmr": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.8.2.tgz", - "integrity": "sha512-VRM8mxakMglqRB0f5eAuwCigjJ5vlaJMwHy+JuzOsn/yVSELOb+6psRKl2B9hhxp9sJPt4IU6KDdH2IOrgx87Q==", + "node_modules/@parcel/markdown-ansi/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/@parcel/markdown-ansi/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@parcel/markdown-ansi/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==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/runtime-js": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.8.2.tgz", - "integrity": "sha512-Vk3Gywn2M9qP5X4lF6tu8QXP4xNI90UOSOhKHQ9W5pCu+zvD0Gdvu7qwQPFuFjIAq08xU7+PvZzGnlnM+8NyRw==", + "node_modules/@parcel/namer-default": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.8.3.tgz", + "integrity": "sha512-tJ7JehZviS5QwnxbARd8Uh63rkikZdZs1QOyivUhEvhN+DddSAVEdQLHGPzkl3YRk0tjFhbqo+Jci7TpezuAMw==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/runtime-react-refresh": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.8.2.tgz", - "integrity": "sha512-JjaMvBVx6v0zB1KHa7AopciIsl3FpjUMttr2tb6L7lzocti2muQGE6GBfinXOmD5oERwCf8HwGJ8SNFcIF0rKA==", + "node_modules/@parcel/node-resolver-core": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-2.8.3.tgz", + "integrity": "sha512-12YryWcA5Iw2WNoEVr/t2HDjYR1iEzbjEcxfh1vaVDdZ020PiGw67g5hyIE/tsnG7SRJ0xdRx1fQ2hDgED+0Ww==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", - "react-error-overlay": "6.0.9", - "react-refresh": "^0.9.0" + "@parcel/diagnostic": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1", + "semver": "^5.7.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/runtime-service-worker": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.8.2.tgz", - "integrity": "sha512-KSxbOKV8nuH5JjFvcUlCtBYnVVlmxreXpMxRUPphPwJnyxRGA4E0jofbQxWY5KPgp7x/ZnZU/nyzCvqURH3kHA==", + "node_modules/@parcel/node-resolver-core/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@parcel/optimizer-css": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.8.3.tgz", + "integrity": "sha512-JotGAWo8JhuXsQDK0UkzeQB0UR5hDAKvAviXrjqB4KM9wZNLhLleeEAW4Hk8R9smCeQFP6Xg/N/NkLDpqMwT3g==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "browserslist": "^4.6.6", + "lightningcss": "^1.16.1", "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-babel": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.8.2.tgz", - "integrity": "sha512-oL2BpvrPMwFiU9jUZ9UYGD1gRgvq9jLsOq+/PJl4GvPbOBVedIBE2nbHP/mYuWRpRnTTTiJQ/ItyOS0R2VQl7A==", + "node_modules/@parcel/optimizer-htmlnano": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.8.3.tgz", + "integrity": "sha512-L8/fHbEy8Id2a2E0fwR5eKGlv9VYDjrH9PwdJE9Za9v1O/vEsfl/0T/79/x129l5O0yB6EFQkFa20MiK3b+vOg==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.2", - "browserslist": "^4.6.6", - "json5": "^2.2.0", + "@parcel/plugin": "2.8.3", + "htmlnano": "^2.0.0", "nullthrows": "^1.1.1", - "semver": "^5.7.0" + "posthtml": "^0.16.5", + "svgo": "^2.4.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-css": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.8.2.tgz", - "integrity": "sha512-q8UDlX/TTCbuFBMU45q12/p92JNIz8MHkkH104dWDzXbRtvMKMg8jgNmr8S2bouZjtXMsSb2c54EO88DSM9G4A==", + "node_modules/@parcel/optimizer-image": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.8.3.tgz", + "integrity": "sha512-SD71sSH27SkCDNUNx9A3jizqB/WIJr3dsfp+JZGZC42tpD/Siim6Rqy9M4To/BpMMQIIiEXa5ofwS+DgTEiEHQ==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.2", - "browserslist": "^4.6.6", - "lightningcss": "^1.16.1", - "nullthrows": "^1.1.1" + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "detect-libc": "^1.0.3" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-html": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.8.2.tgz", - "integrity": "sha512-QDgDw6+DAcllaRQiRteMX0VgPIsxRUTXFS8jcXhbGio41LbUkLcT09M04L/cfJAAzvIKhXqiOxfNnyajTvCPDQ==", + "node_modules/@parcel/optimizer-svgo": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.8.3.tgz", + "integrity": "sha512-9KQed99NZnQw3/W4qBYVQ7212rzA9EqrQG019TIWJzkA9tjGBMIm2c/nXpK1tc3hQ3e7KkXkFCQ3C+ibVUnHNA==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/hash": "2.8.2", - "@parcel/plugin": "2.8.2", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "svgo": "^2.4.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-image": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.8.2.tgz", - "integrity": "sha512-B/D9v/BVyN5jxoi+wHPbIRfMIylmC6adp8GP+BtChjbuRjukgGT8RlAVz4vDm1l0bboeyPL2IuoWRQgXKGuPVg==", + "node_modules/@parcel/optimizer-terser": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-terser/-/optimizer-terser-2.8.3.tgz", + "integrity": "sha512-9EeQlN6zIeUWwzrzu6Q2pQSaYsYGah8MtiQ/hog9KEPlYTP60hBv/+utDyYEHSQhL7y5ym08tPX5GzBvwAD/dA==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", - "@parcel/workers": "2.8.2", - "nullthrows": "^1.1.1" + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1", + "terser": "^5.2.0" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, - "peerDependencies": { - "@parcel/core": "^2.8.2" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-js": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.8.2.tgz", - "integrity": "sha512-mLksi6gu/20JdCFDNPl7Y0HTwJOAvf2ybC2HaJcy69PJCeUrrstgiFTjsCwv1eKcesgEHi9kKX+sMHVAH3B/dA==", - "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.2", - "@parcel/workers": "2.8.2", - "@swc/helpers": "^0.4.12", - "browserslist": "^4.6.6", - "detect-libc": "^1.0.3", - "nullthrows": "^1.1.1", - "regenerator-runtime": "^0.13.7", + "node_modules/@parcel/package-manager": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.8.3.tgz", + "integrity": "sha512-tIpY5pD2lH53p9hpi++GsODy6V3khSTX4pLEGuMpeSYbHthnOViobqIlFLsjni+QA1pfc8NNNIQwSNdGjYflVA==", + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/fs": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", "semver": "^5.7.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.8.2" + "@parcel/core": "^2.8.3" + } + }, + "node_modules/@parcel/package-manager/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-json": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.8.2.tgz", - "integrity": "sha512-eZuaY5tMxcMDJwpHJbPVTgSaBIO4mamwAa3VulN9kRRaf29nc+Q0iM7zMFVHWFQAi/mZZ194IIQXbDX3r6oSSQ==", + "node_modules/@parcel/packager-css": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.8.3.tgz", + "integrity": "sha512-WyvkMmsurlHG8d8oUVm7S+D+cC/T3qGeqogb7sTI52gB6uiywU7lRCizLNqGFyFGIxcVTVHWnSHqItBcLN76lA==", "dependencies": { - "@parcel/plugin": "2.8.2", - "json5": "^2.2.0" + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-postcss": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.8.2.tgz", - "integrity": "sha512-0Vb4T2e0QinNDps1/PxYsZwEzWieVxoW++AAUD3gzg0MfSyRc72MPc27CLOnziiRDyOUl+62gqpnNzq9xaKExA==", + "node_modules/@parcel/packager-html": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.8.3.tgz", + "integrity": "sha512-OhPu1Hx1RRKJodpiu86ZqL8el2Aa4uhBHF6RAL1Pcrh2EhRRlPf70Sk0tC22zUpYL7es+iNKZ/n0Rl+OWSHWEw==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/hash": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", - "clone": "^2.1.1", + "@parcel/plugin": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", "nullthrows": "^1.1.1", - "postcss-value-parser": "^4.2.0", - "semver": "^5.7.1" + "posthtml": "^0.16.5" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-posthtml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.8.2.tgz", - "integrity": "sha512-Ub7o6QlH7+xHHHdhvR7MxTqjyLVqeJopPSzy4yP+Bd72tWVjaVm7f76SUl+p7VjhLTMkmczr9OxG3k0SFHEbGw==", + "node_modules/@parcel/packager-js": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.8.3.tgz", + "integrity": "sha512-0pGKC3Ax5vFuxuZCRB+nBucRfFRz4ioie19BbDxYnvBxrd4M3FIu45njf6zbBYsI9eXqaDnL1b3DcZJfYqtIzw==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "globals": "^13.2.0", + "nullthrows": "^1.1.1" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-raw": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.8.2.tgz", - "integrity": "sha512-xSzyZtrfisbx0R7xkuFJ/FksKyWaUFN18F9/0bLF8wo5LrOTQoYQatjun7/Rbq5mELBK/0ZPp7uJ02OqLRd2mA==", + "node_modules/@parcel/packager-js/node_modules/globals": { + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dependencies": { - "@parcel/plugin": "2.8.2" + "type-fest": "^0.20.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@parcel/packager-js/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-react-refresh-wrap": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.8.2.tgz", - "integrity": "sha512-UXBILYFXaj5zh1DzoYXoS3Wuq1+6WjoRQaFTUA5xrF3pjJb6LAXxWru3R20zR5INHIZXPxdQJB0b+epnmyjK4w==", + "node_modules/@parcel/packager-raw": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.8.3.tgz", + "integrity": "sha512-BA6enNQo1RCnco9MhkxGrjOk59O71IZ9DPKu3lCtqqYEVd823tXff2clDKHK25i6cChmeHu6oB1Rb73hlPqhUA==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2", - "react-refresh": "^0.9.0" + "@parcel/plugin": "2.8.3" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@parcel/transformer-svg": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.8.2.tgz", - "integrity": "sha512-FyliRrNHOF6tGzwHSzA2CTbkq3iMvS27eozf1kFj6gbO8gfJ5HXYoppQrTb237YZ/WXCHqe/3HVmGyJDZiLr+Q==", + "node_modules/@parcel/packager-svg": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.8.3.tgz", + "integrity": "sha512-mvIoHpmv5yzl36OjrklTDFShLUfPFTwrmp1eIwiszGdEBuQaX7JVI3Oo2jbVQgcN4W7J6SENzGQ3Q5hPTW3pMw==", "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/hash": "2.8.2", - "@parcel/plugin": "2.8.2", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" + "@parcel/plugin": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "posthtml": "^0.16.4" }, "engines": { "node": ">= 12.0.0", - "parcel": "^2.8.2" + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "node_modules/@parcel/plugin": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.3.tgz", + "integrity": "sha512-jZ6mnsS4D9X9GaNnvrixDQwlUQJCohDX2hGyM0U0bY2NWU8Km97SjtoCpWjq+XBCx/gpC4g58+fk9VQeZq2vlw==", "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@parcel/config-default/node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@parcel/config-default/node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/@parcel/config-default/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==", + "@parcel/types": "2.8.3" + }, "engines": { - "node": ">= 10" - } - }, - "node_modules/@parcel/config-default/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "node_modules/@parcel/reporter-cli": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.8.3.tgz", + "integrity": "sha512-3sJkS6tFFzgIOz3u3IpD/RsmRxvOKKiQHOTkiiqRt1l44mMDGKS7zANRnJYsQzdCsgwc9SOP30XFgJwtoVlMbw==", "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "@parcel/plugin": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "chalk": "^4.1.0", + "term-size": "^2.2.1" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@parcel/config-default/node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "node_modules/@parcel/reporter-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "css-tree": "^1.1.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@parcel/config-default/node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "node_modules/@parcel/reporter-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "type-fest": "^0.20.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@parcel/config-default/node_modules/htmlnano": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.0.3.tgz", - "integrity": "sha512-S4PGGj9RbdgW8LhbILNK7W9JhmYP8zmDY7KDV/8eCiJBQJlbmltp5I0gv8c5ntLljfdxxfmJ+UJVSqyH4mb41A==", + "node_modules/@parcel/reporter-cli/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==", "dependencies": { - "cosmiconfig": "^7.0.1", - "posthtml": "^0.16.5", - "timsort": "^0.3.0" - }, - "peerDependencies": { - "cssnano": "^5.0.11", - "postcss": "^8.3.11", - "purgecss": "^5.0.0", - "relateurl": "^0.2.7", - "srcset": "4.0.0", - "svgo": "^2.8.0", - "terser": "^5.10.0", - "uncss": "^0.17.3" + "color-name": "~1.1.4" }, - "peerDependenciesMeta": { - "cssnano": { - "optional": true - }, - "postcss": { - "optional": true - }, - "purgecss": { - "optional": true - }, - "relateurl": { - "optional": true - }, - "srcset": { - "optional": true - }, - "svgo": { - "optional": true - }, - "terser": { - "optional": true - }, - "uncss": { - "optional": true - } + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@parcel/config-default/node_modules/is-json": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", - "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==" + "node_modules/@parcel/reporter-cli/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/@parcel/reporter-cli/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==", + "engines": { + "node": ">=8" + } }, - "node_modules/@parcel/config-default/node_modules/lightningcss": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.17.1.tgz", - "integrity": "sha512-DwwM/YYqGwLLP3he41wzDXT/m+8jdEZ80i9ViQNLRgyhey3Vm6N7XHn+4o3PY6wSnVT23WLuaROIpbpIVTNOjg==", + "node_modules/@parcel/reporter-cli/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==", "dependencies": { - "detect-libc": "^1.0.3" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">=8" + } + }, + "node_modules/@parcel/reporter-dev-server": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.8.3.tgz", + "integrity": "sha512-Y8C8hzgzTd13IoWTj+COYXEyCkXfmVJs3//GDBsH22pbtSFMuzAZd+8J9qsCo0EWpiDow7V9f1LischvEh3FbQ==", + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/resolver-default": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.8.3.tgz", + "integrity": "sha512-k0B5M/PJ+3rFbNj4xZSBr6d6HVIe6DH/P3dClLcgBYSXAvElNDfXgtIimbjCyItFkW9/BfcgOVKEEIZOeySH/A==", + "dependencies": { + "@parcel/node-resolver-core": "2.8.3", + "@parcel/plugin": "2.8.3" }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.17.1", - "lightningcss-darwin-x64": "1.17.1", - "lightningcss-linux-arm-gnueabihf": "1.17.1", - "lightningcss-linux-arm64-gnu": "1.17.1", - "lightningcss-linux-arm64-musl": "1.17.1", - "lightningcss-linux-x64-gnu": "1.17.1", - "lightningcss-linux-x64-musl": "1.17.1", - "lightningcss-win32-x64-msvc": "1.17.1" - } - }, - "node_modules/@parcel/config-default/node_modules/lightningcss-linux-x64-gnu": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.17.1.tgz", - "integrity": "sha512-OyE802IAp4DB9vZrHlOyWunbHLM9dN08tJIKN/HhzzLKIHizubOWX6NMzUXMZLsaUrYwVAHHdyEA+712p8mMzA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">= 12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/lightningcss-linux-x64-musl": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.17.1.tgz", - "integrity": "sha512-ydwGgV3Usba5P53RAOqCA9MsRsbb8jFIEVhf7/BXFjpKNoIQyijVTXhwIgQr/oGwUNOHfgQ3F8ruiUjX/p2YKw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@parcel/runtime-browser-hmr": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.8.3.tgz", + "integrity": "sha512-2O1PYi2j/Q0lTyGNV3JdBYwg4rKo6TEVFlYGdd5wCYU9ZIN9RRuoCnWWH2qCPj3pjIVtBeppYxzfVjPEHINWVg==", + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3" + }, "engines": { - "node": ">= 12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/@parcel/config-default/node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/@parcel/runtime-js": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.8.3.tgz", + "integrity": "sha512-IRja0vNKwvMtPgIqkBQh0QtRn0XcxNC8HU1jrgWGRckzu10qJWO+5ULgtOeR4pv9krffmMPqywGXw6l/gvJKYQ==", "dependencies": { - "boolbase": "^1.0.0" + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/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==" - }, - "node_modules/@parcel/config-default/node_modules/posthtml": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", - "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", + "node_modules/@parcel/runtime-react-refresh": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.8.3.tgz", + "integrity": "sha512-2v/qFKp00MfG0234OdOgQNAo6TLENpFYZMbVbAsPMY9ITiqG73MrEsrGXVoGbYiGTMB/Toer/lSWlJxtacOCuA==", "dependencies": { - "posthtml-parser": "^0.11.0", - "posthtml-render": "^3.0.0" + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "react-error-overlay": "6.0.9", + "react-refresh": "^0.9.0" }, "engines": { - "node": ">=12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/posthtml-render": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", - "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "node_modules/@parcel/runtime-service-worker": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.8.3.tgz", + "integrity": "sha512-/Skkw+EeRiwzOJso5fQtK8c9b452uWLNhQH1ISTodbmlcyB4YalAiSsyHCtMYD0c3/t5Sx4ZS7vxBAtQd0RvOw==", "dependencies": { - "is-json": "^2.0.1" + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1" }, "engines": { - "node": ">=12" + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/posthtml/node_modules/posthtml-parser": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", - "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "node_modules/@parcel/source-map": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", + "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", "dependencies": { - "htmlparser2": "^7.1.1" + "detect-libc": "^1.0.3" }, "engines": { - "node": ">=12" + "node": "^12.18.3 || >=14" } }, - "node_modules/@parcel/config-default/node_modules/react-error-overlay": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", - "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==" - }, - "node_modules/@parcel/config-default/node_modules/react-refresh": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", - "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", + "node_modules/@parcel/transformer-babel": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.8.3.tgz", + "integrity": "sha512-L6lExfpvvC7T/g3pxf3CIJRouQl+sgrSzuWQ0fD4PemUDHvHchSP4SNUVnd6gOytF3Y1KpnEZIunQGi5xVqQCQ==", + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "browserslist": "^4.6.6", + "json5": "^2.2.0", + "nullthrows": "^1.1.1", + "semver": "^5.7.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/semver": { + "node_modules/@parcel/transformer-babel/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", @@ -4522,149 +4901,108 @@ "semver": "bin/semver" } }, - "node_modules/@parcel/config-default/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==", + "node_modules/@parcel/transformer-css": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.8.3.tgz", + "integrity": "sha512-xTqFwlSXtnaYen9ivAgz+xPW7yRl/u4QxtnDyDpz5dr8gSeOpQYRcjkd4RsYzKsWzZcGtB5EofEk8ayUbWKEUg==", + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "browserslist": "^4.6.6", + "lightningcss": "^1.16.1", + "nullthrows": "^1.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/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==", + "node_modules/@parcel/transformer-html": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.8.3.tgz", + "integrity": "sha512-kIZO3qsMYTbSnSpl9cnZog+SwL517ffWH54JeB410OSAYF1ouf4n5v9qBnALZbuCCmPwJRGs4jUtE452hxwN4g==", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1", + "srcset": "4" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/config-default/node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + "node_modules/@parcel/transformer-html/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } }, - "node_modules/@parcel/config-default/node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "node_modules/@parcel/transformer-image": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.8.3.tgz", + "integrity": "sha512-cO4uptcCGTi5H6bvTrAWEFUsTNhA4kCo8BSvRSCHA2sf/4C5tGQPHt3JhdO0GQLPwZRCh/R41EkJs5HZ8A8DAg==", "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "nullthrows": "^1.1.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" } }, - "node_modules/@parcel/config-default/node_modules/terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "node_modules/@parcel/transformer-js": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.8.3.tgz", + "integrity": "sha512-9Qd6bib+sWRcpovvzvxwy/PdFrLUXGfmSW9XcVVG8pvgXsZPFaNjnNT8stzGQj1pQiougCoxMY4aTM5p1lGHEQ==", "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "@swc/helpers": "^0.4.12", + "browserslist": "^4.6.6", + "detect-libc": "^1.0.3", + "nullthrows": "^1.1.1", + "regenerator-runtime": "^0.13.7", + "semver": "^5.7.1" }, "engines": { - "node": ">=10" + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" } }, - "node_modules/@parcel/config-default/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==" - }, - "node_modules/@parcel/config-default/node_modules/timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==" - }, - "node_modules/@parcel/config-default/node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, - "node_modules/@parcel/config-default/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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@parcel/core": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.8.2.tgz", - "integrity": "sha512-ZGuq6p+Lzx6fgufaVsuOBwgpU3hgskTvIDIMdIDi9gOZyhGPK7U2srXdX+VYUL5ZSGbX04/P6QlB9FMAXK+nEg==", - "dependencies": { - "@mischnic/json-sourcemap": "^0.1.0", - "@parcel/cache": "2.8.2", - "@parcel/diagnostic": "2.8.2", - "@parcel/events": "2.8.2", - "@parcel/fs": "2.8.2", - "@parcel/graph": "2.8.2", - "@parcel/hash": "2.8.2", - "@parcel/logger": "2.8.2", - "@parcel/package-manager": "2.8.2", - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/types": "2.8.2", - "@parcel/utils": "2.8.2", - "@parcel/workers": "2.8.2", - "abortcontroller-polyfill": "^1.1.9", - "base-x": "^3.0.8", - "browserslist": "^4.6.6", - "clone": "^2.1.1", - "dotenv": "^7.0.0", - "dotenv-expand": "^5.1.0", - "json5": "^2.2.0", - "msgpackr": "^1.5.4", - "nullthrows": "^1.1.1", - "semver": "^5.7.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/core/node_modules/abortcontroller-polyfill": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", - "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==" - }, - "node_modules/@parcel/core/node_modules/dotenv": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", - "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@parcel/core/node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" - }, - "node_modules/@parcel/core/node_modules/semver": { + "node_modules/@parcel/transformer-js/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", @@ -4672,165 +5010,161 @@ "semver": "bin/semver" } }, - "node_modules/@parcel/diagnostic": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.8.2.tgz", - "integrity": "sha512-tGSMwM2rSYLjJW0fCd9gb3tNjfCX/83PZ10/5u2E33UZVkk8OIHsQmsrtq2H2g4oQL3rFxkfEx6nGPDGHwlx7A==", + "node_modules/@parcel/transformer-json": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.8.3.tgz", + "integrity": "sha512-B7LmVq5Q7bZO4ERb6NHtRuUKWGysEeaj9H4zelnyBv+wLgpo4f5FCxSE1/rTNmP9u1qHvQ3scGdK6EdSSokGPg==", "dependencies": { - "@mischnic/json-sourcemap": "^0.1.0", - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">= 12.0.0" + "@parcel/plugin": "2.8.3", + "json5": "^2.2.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/events": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.8.2.tgz", - "integrity": "sha512-o5etrsKm16y8iRPnjtEBNy4lD0WAigD66yt/RZl9Rx0vPVDly/63Rr9+BrXWVW7bJ7x0S0VVpWW4j3f/qZOsXg==", "engines": { - "node": ">= 12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/fs": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.8.2.tgz", - "integrity": "sha512-aN8znbMndSqn1xwZEmMblzqmJsxcExv2jKLl/a9RUHAP7LaPYcPZIykDL3YwGCiKTCzjmRpXnNoyosjFFeBaHA==", + "node_modules/@parcel/transformer-postcss": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.8.3.tgz", + "integrity": "sha512-e8luB/poIlz6jBsD1Izms+6ElbyzuoFVa4lFVLZnTAChI3UxPdt9p/uTsIO46HyBps/Bk8ocvt3J4YF84jzmvg==", "dependencies": { - "@parcel/fs-search": "2.8.2", - "@parcel/types": "2.8.2", - "@parcel/utils": "2.8.2", - "@parcel/watcher": "^2.0.7", - "@parcel/workers": "2.8.2" + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "clone": "^2.1.1", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "semver": "^5.7.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "@parcel/core": "^2.8.2" } }, - "node_modules/@parcel/fs/node_modules/@parcel/fs-search": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/fs-search/-/fs-search-2.8.2.tgz", - "integrity": "sha512-ovQnupRm/MoE/tbgH0Ivknk0QYenXAewjcog+T5umDmUlTmnIRZjURrgDf5Xtw8T/CD5Xv+HmIXpJ9Ez/LzJpw==", - "dependencies": { - "detect-libc": "^1.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node_modules/@parcel/transformer-postcss/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" } }, - "node_modules/@parcel/fs/node_modules/@parcel/watcher": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.7.tgz", - "integrity": "sha512-gc3hoS6e+2XdIQ4HHljDB1l0Yx2EWh/sBBtCEFNKGSMlwASWeAQsOY/fPbxOBcZ/pg0jBh4Ga+4xHlZc4faAEQ==", - "hasInstallScript": true, + "node_modules/@parcel/transformer-posthtml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.8.3.tgz", + "integrity": "sha512-pkzf9Smyeaw4uaRLsT41RGrPLT5Aip8ZPcntawAfIo+KivBQUV0erY1IvHYjyfFzq1ld/Fo2Ith9He6mxpPifA==", "dependencies": { - "node-addon-api": "^3.2.1", - "node-gyp-build": "^4.3.0" + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" }, "engines": { - "node": ">= 10.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/fs/node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + "node_modules/@parcel/transformer-posthtml/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } }, - "node_modules/@parcel/graph": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-2.8.2.tgz", - "integrity": "sha512-SLEvBQBgfkXgU4EBu30+CNanpuKjcNuEv/x8SwobCF0i3Rk+QKbe7T36bNR7727mao++2Ha69q93Dd9dTPw0kQ==", + "node_modules/@parcel/transformer-raw": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.8.3.tgz", + "integrity": "sha512-G+5cXnd2/1O3nV/pgRxVKZY/HcGSseuhAe71gQdSQftb8uJEURyUHoQ9Eh0JUD3MgWh9V+nIKoyFEZdf9T0sUQ==", "dependencies": { - "nullthrows": "^1.1.1" + "@parcel/plugin": "2.8.3" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/hash": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/hash/-/hash-2.8.2.tgz", - "integrity": "sha512-NBnP8Hu0xvAqAfZXRaMM66i8nJyxpKS86BbhwkbgTGbwO1OY87GERliHeREJfcER0E0ZzwNow7MNR8ZDm6IvJQ==", + "node_modules/@parcel/transformer-react-refresh-wrap": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.8.3.tgz", + "integrity": "sha512-q8AAoEvBnCf/nPvgOwFwKZfEl/thwq7c2duxXkhl+tTLDRN2vGmyz4355IxCkavSX+pLWSQ5MexklSEeMkgthg==", "dependencies": { - "detect-libc": "^1.0.3", - "xxhash-wasm": "^0.4.2" + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "react-refresh": "^0.9.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/logger": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.8.2.tgz", - "integrity": "sha512-zlhK6QHxfFJMlVJxxcCw0xxBDrYPFPOhMxSD6p6b0z9Yct1l3NdpmfabgjKX8wnZmHokFsil6daleM+M80n2Ew==", + "node_modules/@parcel/transformer-sass": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-sass/-/transformer-sass-2.8.3.tgz", + "integrity": "sha512-ak196rjvXdsBOGi5aTkBEKv6i4LKQgOkHuaKEjeT8g2a3CU6Z36J+j2GbZzsznfws/hH+CRTf8bAsbkxtKlkjQ==", + "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/events": "2.8.2" + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "sass": "^1.38.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/package-manager": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.8.2.tgz", - "integrity": "sha512-hx4Imi0yhsSS0aNZkEANPYNNKqBuR63EUNWSxMyHh4ZOvbHoOXnMn1ySGdx6v0oi9HvKymNsLMQ1T5CuI4l4Bw==", - "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/fs": "2.8.2", - "@parcel/logger": "2.8.2", - "@parcel/types": "2.8.2", - "@parcel/utils": "2.8.2", - "@parcel/workers": "2.8.2", + "node_modules/@parcel/transformer-svg": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.8.3.tgz", + "integrity": "sha512-3Zr/gBzxi1ZH1fftH/+KsZU7w5GqkmxlB0ZM8ovS5E/Pl1lq1t0xvGJue9m2VuQqP8Mxfpl5qLFmsKlhaZdMIQ==", + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", "semver": "^5.7.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 12.0.0", + "parcel": "^2.8.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "@parcel/core": "^2.8.2" } }, - "node_modules/@parcel/package-manager/node_modules/semver": { + "node_modules/@parcel/transformer-svg/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", @@ -4838,12 +5172,32 @@ "semver": "bin/semver" } }, - "node_modules/@parcel/plugin": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.2.tgz", - "integrity": "sha512-YG7TWfKsoNm72jbz3b3TLec0qJHVkuAWSzGzowdIhX37cP1kRfp6BU2VcH+qYPP/KYJLzhcZa9n3by147mGcxw==", - "dependencies": { - "@parcel/types": "2.8.2" + "node_modules/@parcel/types": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.8.3.tgz", + "integrity": "sha512-FECA1FB7+0UpITKU0D6TgGBpGxYpVSMNEENZbSJxFSajNy3wrko+zwBKQmFOLOiPcEtnGikxNs+jkFWbPlUAtw==", + "dependencies": { + "@parcel/cache": "2.8.3", + "@parcel/diagnostic": "2.8.3", + "@parcel/fs": "2.8.3", + "@parcel/package-manager": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/workers": "2.8.3", + "utility-types": "^3.10.0" + } + }, + "node_modules/@parcel/utils": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.8.3.tgz", + "integrity": "sha512-IhVrmNiJ+LOKHcCivG5dnuLGjhPYxQ/IzbnF2DKNQXWBTsYlHkJZpmz7THoeLtLliGmSOZ3ZCsbR8/tJJKmxjA==", + "dependencies": { + "@parcel/codeframe": "2.8.3", + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/markdown-ansi": "2.8.3", + "@parcel/source-map": "^2.1.1", + "chalk": "^4.1.0" }, "engines": { "node": ">= 12.0.0" @@ -4853,143 +5207,83 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/reporter-cli": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.8.2.tgz", - "integrity": "sha512-OIRlBqpKqPpMWRHATT8az8fUAqfceLWlWqgX/CW5cG1i6gefbBWFq2qYxDVBEk1bPDLIUCtqNLhfO8hLyweMjA==", + "node_modules/@parcel/utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/types": "2.8.2", - "@parcel/utils": "2.8.2", - "chalk": "^4.1.0", - "term-size": "^2.2.1" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "color-convert": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/reporter-cli/node_modules/term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@parcel/reporter-dev-server": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.8.2.tgz", - "integrity": "sha512-A16pAQSAT8Yilo1yCPZcrtWbRhwyiMopEz0mOyGobA1ZDy6B3j4zjobIWzdPQCSIY7+v44vtWMDGbdGrxt6M1Q==", + "node_modules/@parcel/utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/utils": "2.8.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/source-map": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", - "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", - "dependencies": { - "detect-libc": "^1.0.3" - }, - "engines": { - "node": "^12.18.3 || >=14" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@parcel/transformer-sass": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/transformer-sass/-/transformer-sass-2.8.2.tgz", - "integrity": "sha512-GiTuLpkIIVjLUYM7kEWkGetQZSS6tSysokEvipSvST5LH3mXS7hV9d1kTE2DrvvN4SSgV1uougY7c4t1CexJZA==", - "dev": true, + "node_modules/@parcel/utils/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==", "dependencies": { - "@parcel/plugin": "2.8.2", - "@parcel/source-map": "^2.1.1", - "sass": "^1.38.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=7.0.0" } }, - "node_modules/@parcel/types": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.8.2.tgz", - "integrity": "sha512-HAYhokWxM10raIhqaYj9VR9eAvJ+xP2sNfQ1IcQybHpq3qblcBe/4jDeuUpwIyKeQ4gorp7xY+q8KDoR20j43w==", - "dependencies": { - "@parcel/cache": "2.8.2", - "@parcel/diagnostic": "2.8.2", - "@parcel/fs": "2.8.2", - "@parcel/package-manager": "2.8.2", - "@parcel/source-map": "^2.1.1", - "@parcel/workers": "2.8.2", - "utility-types": "^3.10.0" - } + "node_modules/@parcel/utils/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/@parcel/utils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.8.2.tgz", - "integrity": "sha512-Ufax7wZxC9FNsUpR0EU7Z22LEY/q9jjsDTwswctCdfpWb7TE/NudOfM9myycfRvwBVEYN50lPbkt1QltEVnXQQ==", - "dependencies": { - "@parcel/codeframe": "2.8.2", - "@parcel/diagnostic": "2.8.2", - "@parcel/hash": "2.8.2", - "@parcel/logger": "2.8.2", - "@parcel/markdown-ansi": "2.8.2", - "@parcel/source-map": "^2.1.1", - "chalk": "^4.1.0" - }, + "node_modules/@parcel/utils/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==", "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/@parcel/utils/node_modules/@parcel/codeframe": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.8.2.tgz", - "integrity": "sha512-U2GT9gq1Zs3Gr83j8JIs10bLbGOHFl57Y8D57nrdR05F4iilV/UR6K7jkhdoiFc9WiHh3ewvrko5+pSdAVFPgQ==", + "node_modules/@parcel/utils/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==", "dependencies": { - "chalk": "^4.1.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/@parcel/utils/node_modules/@parcel/markdown-ansi": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.8.2.tgz", - "integrity": "sha512-5y29TXgRgG0ybuXaDsDk4Aofg/nDUeAAyVl9/toYCDDhxpQV4yZt8WNPu4PaNYKGLuNgXwsmz+ryZQHGmfbAIQ==", + "node_modules/@parcel/watcher": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.1.0.tgz", + "integrity": "sha512-8s8yYjd19pDSsBpbkOHnT6Z2+UJSuLQx61pCFM0s5wSRvKCEMDjd/cHY3/GI1szHIWbpXpsJdg3V6ISGGx9xDw==", + "hasInstallScript": true, "dependencies": { - "chalk": "^4.1.0" + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 10.0.0" }, "funding": { "type": "opencollective", @@ -4997,14 +5291,14 @@ } }, "node_modules/@parcel/workers": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.8.2.tgz", - "integrity": "sha512-Eg6CofIrJSNBa2fjXwvnzVLPKwR/6fkfQTFAm3Jl+4JYLVknBtTSFzQNp/Fa+HUEG889H9ucTk2CBi/fVPBAFw==", - "dependencies": { - "@parcel/diagnostic": "2.8.2", - "@parcel/logger": "2.8.2", - "@parcel/types": "2.8.2", - "@parcel/utils": "2.8.2", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.8.3.tgz", + "integrity": "sha512-+AxBnKgjqVpUHBcHLWIHcjYgKIvHIpZjN33mG5LG9XXvrZiqdWvouEzqEXlVLq5VzzVbKIQQcmsvRy138YErkg==", + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", "chrome-trace-event": "^1.0.2", "nullthrows": "^1.1.1" }, @@ -5016,23 +5310,145 @@ "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.8.2" + "@parcel/core": "^2.8.3" } }, - "node_modules/@remix-run/router": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.1.0.tgz", - "integrity": "sha512-rGl+jH/7x1KBCQScz9p54p0dtPLNeKGb3e0wD2H5/oZj41bwQUnXdzbj2TbUAFhvD7cp9EyEQA4dEgpUFa1O7Q==", + "node_modules/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@remix-run/router": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.0.tgz", + "integrity": "sha512-nwQoYb3m4DDpHTeOwpJEuDt8lWVcujhYYSFGLluC+9es2PyLjm+jjq3IeRBQbwBtPLJE/lkuHuGHr8uQLgmJRA==", "engines": { "node": ">=14" } }, + "node_modules/@segment/loosely-validate-event": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz", + "integrity": "sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==", + "dev": true, + "dependencies": { + "component-type": "^1.2.1", + "join-component": "^1.1.0" + } + }, + "node_modules/@sentry/core": { + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", + "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", + "dev": true, + "dependencies": { + "@sentry/hub": "6.19.7", + "@sentry/minimal": "6.19.7", + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub": { + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", + "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", + "dev": true, + "dependencies": { + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal": { + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", + "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", + "dev": true, + "dependencies": { + "@sentry/hub": "6.19.7", + "@sentry/types": "6.19.7", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/node": { + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz", + "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==", + "dev": true, + "dependencies": { + "@sentry/core": "6.19.7", + "@sentry/hub": "6.19.7", + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/node/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@sentry/types": { + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", + "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils": { + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", + "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", + "dev": true, + "dependencies": { + "@sentry/types": "6.19.7", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@sinclair/typebox": { "version": "0.24.51", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", "dev": true }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -5051,14 +5467,47 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@swc/helpers/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@types/babel__core": { - "version": "7.1.20", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", - "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", + "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", "dev": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" @@ -5099,14 +5548,23 @@ "dev": true }, "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "dependencies": { "@types/node": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -5146,15 +5604,15 @@ } }, "node_modules/@types/luxon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.1.0.tgz", - "integrity": "sha512-gCd/HcCgjqSxfMrgtqxCgYk/22NBQfypwFUG7ZAyG/4pqs51WLTcUzVp1hqTbieDYeHS3WoVEh2Yv/2l+7B0Vg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.2.0.tgz", + "integrity": "sha512-lGmaGFoaXHuOLXFvuju2bfvZRqxAqkHPx9Y9IQdQABrinJJshJwfNCKV+u7rR3kJbiqfTF/NhOkcxxAFrObyaA==", "dev": true }, "node_modules/@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", "dev": true }, "node_modules/@types/parse-json": { @@ -5163,9 +5621,9 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "node_modules/@types/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", + "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", "dev": true }, "node_modules/@types/prop-types": { @@ -5174,9 +5632,9 @@ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" }, "node_modules/@types/react": { - "version": "18.0.26", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", - "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", + "version": "18.0.27", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.27.tgz", + "integrity": "sha512-3vtRKHgVxu3Jp9t718R9BuzoD4NcQ8YJ5XRzsSKxNDiDonD2MXIT1TmSkenxuCycZJoQT5d2vE8LwWJxBC1gmA==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -5184,14 +5642,33 @@ } }, "node_modules/@types/react-dom": { - "version": "18.0.9", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.9.tgz", - "integrity": "sha512-qnVvHxASt/H7i+XG1U1xMiY5t+IHcPGUK7TDMDzom08xa7e86eCeKOiLZezwCKVxJn6NEiiy2ekgX8aQssjIKg==", + "version": "18.0.10", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", + "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", "dev": true, "dependencies": { "@types/react": "*" } }, + "node_modules/@types/react-is": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", + "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-redux": { + "version": "7.1.25", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", + "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -5212,9 +5689,9 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.17.tgz", - "integrity": "sha512-72bWxFKTK6uwWJAVT+3rF6Jo6RTojiJ27FQo8Rf60AL+VZbzoVPnMFhKsUnbjR8A3BTCYQ7Mv3hnl8T0A+CX9g==", + "version": "17.0.20", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.20.tgz", + "integrity": "sha512-eknWrTHofQuPk2iuqDm1waA7V6xPlbgBoaaXEgYkClhLOnB0TtbW+srJaOToAgawPxPlHQzwypFA2bhZaUGP5A==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -5237,14 +5714,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz", - "integrity": "sha512-RelQ5cGypPh4ySAtfIMBzBGyrNerQcmfA1oJvPj5f+H4jI59rl9xxpn4bonC0tQvUKOEN7eGBFWxFLK3Xepneg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.2.tgz", + "integrity": "sha512-38zMsKsG2sIuM5Oi/olurGwYJXzmtdsHhn5mI/pQogP+BjYVkK5iRazCQ8RGS0V+YLk282uWElN70zAAUmaYHw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.46.1", - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/typescript-estree": "5.46.1", + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/typescript-estree": "5.48.2", "debug": "^4.3.4" }, "engines": { @@ -5264,13 +5741,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.46.1.tgz", - "integrity": "sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.2.tgz", + "integrity": "sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/visitor-keys": "5.46.1" + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -5281,9 +5758,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", - "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -5294,13 +5771,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz", - "integrity": "sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", + "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/visitor-keys": "5.46.1", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -5320,6 +5797,18 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", @@ -5335,28 +5824,19 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/typescript-estree/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": { - "tslib": "^1.8.1" - }, - "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/@typescript-eslint/typescript-estree/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/@typescript-eslint/visitor-keys": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.46.1.tgz", - "integrity": "sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", + "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/types": "5.48.2", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -5367,6 +5847,17 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/abortcontroller-polyfill": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", + "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -5391,6 +5882,15 @@ "node": ">=0.4.0" } }, + "node_modules/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, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -5403,6 +5903,35 @@ "node": ">= 6.0.0" } }, + "node_modules/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": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/analytics-node": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/analytics-node/-/analytics-node-6.2.0.tgz", @@ -5422,164 +5951,44 @@ "node": ">=4" } }, - "node_modules/analytics-node/node_modules/@segment/loosely-validate-event": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz", - "integrity": "sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==", + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, "dependencies": { - "component-type": "^1.2.1", - "join-component": "^1.1.0" + "string-width": "^4.1.0" } }, - "node_modules/analytics-node/node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/analytics-node/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/analytics-node/node_modules/axios-retry": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.2.0.tgz", - "integrity": "sha512-RK2cLMgIsAQBDhlIsJR5dOhODPigvel18XUv1dDXW+4k1FzebyfRk+C+orot6WPZOYFKSfhLwHPwVmTVOODQ5w==", - "dev": true, - "dependencies": { - "is-retry-allowed": "^1.1.0" - } - }, - "node_modules/analytics-node/node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/analytics-node/node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/analytics-node/node_modules/component-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.2.1.tgz", - "integrity": "sha512-Kgy+2+Uwr75vAi6ChWXgHuLvd+QLD7ssgpaRq2zCvt80ptvAfMc/hijcJxXkBa2wMlEZcJvC2H8Ubo+A9ATHIg==", + "node_modules/ansi-align/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/analytics-node/node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/analytics-node/node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/analytics-node/node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "node_modules/ansi-align/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, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "node": ">=8" } }, - "node_modules/analytics-node/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "node_modules/ansi-align/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": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/analytics-node/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/analytics-node/node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/analytics-node/node_modules/join-component": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz", - "integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==", - "dev": true - }, - "node_modules/analytics-node/node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "dev": true - }, - "node_modules/analytics-node/node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "dev": true, - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" + "node": ">=8" } }, - "node_modules/analytics-node/node_modules/remove-trailing-slash": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz", - "integrity": "sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA==", - "dev": true - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -5613,17 +6022,14 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "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==", "dependencies": { - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, "node_modules/anymatch": { @@ -5640,9 +6046,18 @@ } }, "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "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/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, "node_modules/array-union": { @@ -5654,12 +6069,30 @@ "node": ">=8" } }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ascii-table": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/ascii-table/-/ascii-table-0.0.9.tgz", "integrity": "sha512-xpkr6sCDIYTPqzvjG8M3ncw1YOTaloWZOyrUmicoEifBEKzQzt+ooUpRpQ/AbOoJfO/p2ZKiyp79qHThzJDulQ==", "dev": true }, + "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/async": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", @@ -5669,6 +6102,12 @@ "lodash": "^4.17.14" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -5681,6 +6120,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axe-core": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", + "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/axios-retry": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.2.0.tgz", + "integrity": "sha512-RK2cLMgIsAQBDhlIsJR5dOhODPigvel18XUv1dDXW+4k1FzebyfRk+C+orot6WPZOYFKSfhLwHPwVmTVOODQ5w==", + "dev": true, + "dependencies": { + "is-retry-allowed": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz", @@ -5702,170 +6169,119 @@ "@babel/core": "^7.8.0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/babel-plugin-istanbul/node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/babel-jest/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": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/babel-plugin-istanbul/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/babel-jest/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": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, + "color-name": "~1.1.4" + }, "engines": { - "node": ">=6" + "node": ">=7.0.0" } }, - "node_modules/babel-plugin-istanbul/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" - }, - "engines": { - "node": ">=4" - } + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/babel-plugin-istanbul/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/babel-jest/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": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/babel-plugin-istanbul/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/babel-plugin-istanbul/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==", + "node_modules/babel-jest/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": { - "p-locate": "^4.1.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/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==", + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/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==", + "node_modules/babel-plugin-jest-hoist": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz", + "integrity": "sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/babel-plugin-istanbul/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/babel-plugin-istanbul/node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" }, "engines": { - "node": ">=8" + "node": ">=10", + "npm": ">=6" } }, "node_modules/babel-plugin-polyfill-corejs2": { @@ -5943,20 +6359,11 @@ "@babel/core": "^7.0.0" } }, - "node_modules/babel-preset-jest/node_modules/babel-plugin-jest-hoist": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz", - "integrity": "sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base-x": { "version": "3.0.9", @@ -5998,6 +6405,15 @@ "url": "https://opencollective.com/bigjs" } }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -6008,6 +6424,34 @@ "file-uri-to-path": "1.0.0" } }, + "node_modules/bip39": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz", + "integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==", + "dev": true, + "dependencies": { + "@types/node": "11.11.6", + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1" + } + }, + "node_modules/bip39-light": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/bip39-light/-/bip39-light-1.0.7.tgz", + "integrity": "sha512-WDTmLRQUsiioBdTs9BmSEmkJza+8xfJmptsNJjxnoq3EydSa/ZBXT6rm66KoT3PJIRYMnhSKNR7S9YL1l7R40Q==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9" + } + }, + "node_modules/bip39/node_modules/@types/node": { + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", + "dev": true + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -6024,6 +6468,59 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/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/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, "node_modules/borsh": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", @@ -6034,40 +6531,194 @@ "text-encoding-utf-8": "^1.0.2" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], + "node_modules/boxen/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "bin": { - "browserslist": "cli.js" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/boxen/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/boxen/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/boxen/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/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/boxen/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/boxen/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/boxen/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/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" @@ -6137,6 +6788,48 @@ "node": ">= 0.8" } }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/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": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -6158,22 +6851,28 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", "dev": true, + "dependencies": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001439", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz", - "integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==", + "version": "1.0.30001446", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001446.tgz", + "integrity": "sha512-fEoga4PrImGcwUUGEol/PoFCSBnSkA9drgdkxXkJLsUBOnJ8rs3zDv6ApqYXGQFOyMPsjh79naWhF4DAxbF8rw==", "funding": [ { "type": "opencollective", @@ -6191,37 +6890,24 @@ "integrity": "sha512-rsJZYVCgXd08sPqwmaIqjAd5SUTfonV0z/gDJ8D6cN8wQphky1kkAYEqQ+hmDxTw7UihvBfjUVUSY+DBEe44jg==" }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/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==", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/chalk/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==", - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=8" + "node": ">=0.8.0" } }, "node_modules/char-regex": { @@ -6233,6 +6919,15 @@ "node": ">=10" } }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -6260,37 +6955,16 @@ "fsevents": "~2.3.2" } }, - "node_modules/chokidar/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/chokidar/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": { - "picomatch": "^2.2.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=8.10.0" + "node": ">= 6" } }, "node_modules/chownr": { @@ -6326,20 +7000,90 @@ } }, "node_modules/ci-info": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", - "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", + "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "engines": { "node": ">=8" } }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/cjs-module-lexer": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "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": ">= 4.0" + } + }, + "node_modules/clean-css/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/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": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cli-truncate": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", @@ -6407,6 +7151,27 @@ "node": ">=0.8" } }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/clsx": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", @@ -6432,20 +7197,17 @@ "dev": true }, "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==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "color-name": "1.1.3" } }, "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==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/colorette": { "version": "2.0.19", @@ -6453,6 +7215,18 @@ "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -6462,6 +7236,30 @@ "node": ">= 6" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/component-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.2.1.tgz", + "integrity": "sha512-Kgy+2+Uwr75vAi6ChWXgHuLvd+QLD7ssgpaRq2zCvt80ptvAfMc/hijcJxXkBa2wMlEZcJvC2H8Ubo+A9ATHIg==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/compression": { "version": "1.7.4", "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", @@ -6480,18 +7278,6 @@ "node": ">= 0.8.0" } }, - "node_modules/compression/node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/compression/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -6507,21 +7293,18 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/compression/node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/compression/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/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "node_modules/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -6551,6 +7334,27 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -6565,6 +7369,12 @@ "node": ">= 0.6" } }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, "node_modules/copy-to-clipboard": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", @@ -6573,15 +7383,10 @@ "toggle-selection": "^1.0.6" } }, - "node_modules/copy-to-clipboard/node_modules/toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" - }, "node_modules/core-js-compat": { - "version": "3.26.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.26.1.tgz", - "integrity": "sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A==", + "version": "3.27.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.27.2.tgz", + "integrity": "sha512-welaYuF7ZtbYKGrIy7y3eb40d37rG1FvzEOfe7hSLd2iD6duMDqUhRfSvCGyC46HhR6Y8JXXdZ2lnRUMkPBpvg==", "dependencies": { "browserslist": "^4.21.4" }, @@ -6593,7 +7398,7 @@ "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuEAuthMwkRMVH1EpIkX5bTZGRB3eCA==", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -6605,20 +7410,39 @@ "node": ">=10" } }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "node_modules/cron-parser": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.7.0.tgz", - "integrity": "sha512-BdAELR+MCT2ZWsIBhZKDuUqIUCBjHHulPJnm53OfdRLA4EWBjva3R+KM5NeidJuGsNXdEcZkjC7SCnkW5rAFSA==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.7.1.tgz", + "integrity": "sha512-WguFaoQ0hQ61SgsCZLHUcNbAvlK0lypKXu62ARguefYmjzaOXIVRNrAmyXzabTwUn4sQvQLkk6bjH+ipGfw8bA==", "dependencies": { - "luxon": "^3.1.0" + "luxon": "^3.2.1" }, "engines": { "node": ">=12.0.0" @@ -6633,6 +7457,26 @@ "node-fetch": "2.6.7" } }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6647,46 +7491,13 @@ "node": ">= 8" } }, - "node_modules/cross-spawn/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/cross-spawn/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/cross-spawn/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/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, "engines": { - "node": ">= 8" + "node": "*" } }, "node_modules/crypto-random-string": { @@ -6698,6 +7509,12 @@ "node": ">=8" } }, + "node_modules/csp_evaluator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/csp_evaluator/-/csp_evaluator-1.1.1.tgz", + "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==", + "dev": true + }, "node_modules/css-box-model": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", @@ -6706,10 +7523,77 @@ "tiny-invariant": "^1.0.6" } }, - "node_modules/css-box-model/node_modules/tiny-invariant": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", - "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.1.tgz", + "integrity": "sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A==", + "dev": true, + "dependencies": { + "cssom": "0.3.x" + } }, "node_modules/csstype": { "version": "3.1.1", @@ -6732,6 +7616,14 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -6777,6 +7669,30 @@ "node": ">=0.10.0" } }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6785,6 +7701,16 @@ "node": ">= 0.8" } }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -6820,6 +7746,11 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/dijkstrajs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", + "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -6832,6 +7763,27 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -6912,12 +7864,29 @@ "node": ">=12" } }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -6947,6 +7916,20 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -7021,6 +8004,21 @@ "node": ">=6" } }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -7033,12 +8031,12 @@ } }, "node_modules/eslint": { - "version": "8.30.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.30.0.tgz", - "integrity": "sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz", + "integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.4.0", + "@eslint/eslintrc": "^1.4.1", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7109,149 +8107,217 @@ } } }, - "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==", + "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": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.0.tgz", - "integrity": "sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A==", + "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": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "eslint-visitor-keys": "^2.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" } }, - "node_modules/eslint/node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "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, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" + "node": ">=10" } }, - "node_modules/eslint/node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" + "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, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint/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==", + "node_modules/eslint/node_modules/argparse": { + "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/eslint/node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/eslint/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, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/eslint/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": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/eslint/node_modules/globals": { + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/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==", + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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" }, - "peerDependencies": { - "eslint": ">=5" + "engines": { + "node": ">=8" } }, - "node_modules/eslint/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==", + "node_modules/eslint/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/eslint/node_modules/espree": { + "node_modules/espree": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", @@ -7268,7 +8334,20 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/esquery": { + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", @@ -7280,7 +8359,7 @@ "node": ">=0.10" } }, - "node_modules/eslint/node_modules/esrecurse": { + "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==", @@ -7292,7 +8371,7 @@ "node": ">=4.0" } }, - "node_modules/eslint/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -7301,263 +8380,60 @@ "node": ">=4.0" } }, - "node_modules/eslint/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/eslint/node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/eslint/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": { - "flat-cache": "^3.0.4" - }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=0.10.0" } }, - "node_modules/eslint/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/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 0.6" } }, - "node_modules/eslint/node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "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": { - "is-glob": "^4.0.3" - }, + "optional": true, "engines": { - "node": ">=10.13.0" + "node": ">=0.8.x" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "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": { - "type-fest": "^0.20.2" + "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": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/eslint/node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/eslint/node_modules/js-sdsl": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", - "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/eslint/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/eslint/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": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/eslint/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/eslint/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/eslint/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/eslint/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/eslint/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/eslint/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, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint/node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/eslint/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/eslint/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/eslint/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/eslint/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/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "optional": true, - "engines": { - "node": ">=0.8.x" - } - }, - "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/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" @@ -7631,2085 +8507,3103 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "node_modules/express/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": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "ms": "2.0.0" } }, - "node_modules/express/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, - "node_modules/express/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, "dependencies": { - "safe-buffer": "5.2.1" + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" }, "engines": { - "node": ">= 0.6" + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" } }, - "node_modules/express/node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "node_modules/extract-zip/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": { + "pump": "^3.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/express/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "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/express/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/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.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, + "@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", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=8.6.0" } }, - "node_modules/express/node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/express/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "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": ">= 0.8" + "node": ">= 6" } }, - "node_modules/express/node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "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/express/node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, - "node_modules/express/node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" + "reusify": "^1.0.4" } }, - "node_modules/express/node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "engines": { - "node": ">= 0.6" + "dependencies": { + "bser": "2.1.1" } }, - "node_modules/express/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, - "engines": { - "node": ">= 0.6" + "dependencies": { + "pend": "~1.2.0" } }, - "node_modules/express/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==", + "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": { - "safer-buffer": ">= 2.1.2 < 3" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=0.10.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/express/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "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, - "engines": { - "node": ">= 0.10" - } + "optional": true }, - "node_modules/express/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/express/node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/express/node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "dev": true, + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/express/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" + "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==", + "dependencies": { + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/express/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dev": true, "dependencies": { - "ee-first": "1.1.1" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, - "node_modules/express/node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/finalhandler/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, - "engines": { - "node": ">= 0.8" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/express/node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/express/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "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==", "dependencies": { - "side-channel": "^1.0.4" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/express/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "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==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">= 0.10" } }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "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": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" }, "engines": { - "node": ">= 0.8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/express/node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, - "node_modules/express/node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 6" } }, - "node_modules/express/node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "node_modules/formik": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz", + "integrity": "sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "dependencies": { + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^1.10.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true }, - "node_modules/express/node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6 <7 || >=8" } }, - "node_modules/express/node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-port": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", + "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "engines": { + "node": ">=6" + } + }, + "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/gh-pages": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-4.0.0.tgz", + "integrity": "sha512-p8S0T3aGJc68MtwOcZusul5qPSNZCalap3NWbhRUZYu1YOdp+EjZ+4kPmRM8h3NNRdqw00yuevRjlkuSzCn7iQ==", "dev": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gh-pages/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/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/gh-pages/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "optional": true + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "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.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "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/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/got/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/got/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "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==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "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, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-minifier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", + "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", + "dev": true, + "dependencies": { + "camel-case": "^3.0.0", + "clean-css": "^4.2.1", + "commander": "^2.19.0", + "he": "^1.2.0", + "param-case": "^2.1.1", + "relateurl": "^0.2.7", + "uglify-js": "^3.5.1" + }, + "bin": { + "html-minifier": "cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/html-minifier/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/htmlnano": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.0.3.tgz", + "integrity": "sha512-S4PGGj9RbdgW8LhbILNK7W9JhmYP8zmDY7KDV/8eCiJBQJlbmltp5I0gv8c5ntLljfdxxfmJ+UJVSqyH4mb41A==", + "dependencies": { + "cosmiconfig": "^7.0.1", + "posthtml": "^0.16.5", + "timsort": "^0.3.0" + }, + "peerDependencies": { + "cssnano": "^5.0.11", + "postcss": "^8.3.11", + "purgecss": "^5.0.0", + "relateurl": "^0.2.7", + "srcset": "4.0.0", + "svgo": "^2.8.0", + "terser": "^5.10.0", + "uncss": "^0.17.3" + }, + "peerDependenciesMeta": { + "cssnano": { + "optional": true + }, + "postcss": { + "optional": true + }, + "purgecss": { + "optional": true + }, + "relateurl": { + "optional": true + }, + "srcset": { + "optional": true + }, + "svgo": { + "optional": true + }, + "terser": { + "optional": true + }, + "uncss": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-link-header": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-0.8.0.tgz", + "integrity": "sha512-qsh/wKe1Mk1vtYEFr+LpQBFWTO1gxZQBdii2D0Umj+IUQ23r5sT088Rhpq4XzpSyIpaX7vwjB8Rrtx8u9JTg+Q==", + "dev": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "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/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "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/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/image-ssim": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", + "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", + "dev": true + }, + "node_modules/immutable": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", + "integrity": "sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==", + "dev": true + }, + "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==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "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": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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/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/intl-messageformat": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-4.4.0.tgz", + "integrity": "sha512-z+Bj2rS3LZSYU4+sNitdHrwnBhr0wO80ZJSW8EzKDBowwUe3Q/UsvgCGjrwa+HPzoGCLEb9HAjfJgo4j2Sac8w==", + "dev": true, + "dependencies": { + "intl-messageformat-parser": "^1.8.1" + } + }, + "node_modules/intl-messageformat-parser": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.8.1.tgz", + "integrity": "sha512-IMSCKVf0USrM/959vj3xac7s8f87sc+80Y/ipBzdKy4ifBv5Gsj2tZ41EAaURVg01QU71fYr77uA8Meh6kELbg==", + "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser", + "dev": true + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-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-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-ci/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==" + }, + "node_modules/is-mobile": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-3.1.1.tgz", + "integrity": "sha512-RRoXXR2HNFxNkUnxtaBdGBXtFlUMFa06S0NUKf/LCF+MuGLu13gi9iBCkoEmc6+rpXuwi5Mso5V8Zf7mNynMBQ==" + }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "node_modules/is2": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", + "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" }, "engines": { - "node": ">= 0.6" + "node": ">=v0.10.0" } }, - "node_modules/express/node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, - "node_modules/express/node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, "engines": { - "node": ">= 0.4.0" + "node": ">=8" } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "node": ">=8" } }, - "node_modules/extract-zip/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/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "dependencies": { - "pump": "^3.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "node_modules/istanbul-lib-report/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": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, "engines": { - "node": ">=8.6.0" + "node": ">=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/fastq": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", - "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", + "node_modules/istanbul-lib-report/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": { - "reusify": "^1.0.4" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { - "bser": "2.1.1" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "node_modules/istanbul-lib-source-maps/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, - "dependencies": { - "pend": "~1.2.0" + "engines": { + "node": ">=0.10.0" } }, - "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/filenamify": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "node_modules/istanbul-reports": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/filenamify/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" } }, - "node_modules/filenamify/node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "node_modules/jest": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", + "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", "dev": true, + "dependencies": { + "@jest/core": "^28.1.3", + "@jest/types": "^28.1.3", + "import-local": "^3.0.2", + "jest-cli": "^28.1.3" + }, + "bin": { + "jest": "bin/jest.js" + }, "engines": { - "node": ">=4" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/filenamify/node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "node_modules/jest-changed-files": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.1.3.tgz", + "integrity": "sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.2" + "execa": "^5.0.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/filenamify/node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "node_modules/jest-circus": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.3.tgz", + "integrity": "sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.2" + "@jest/environment": "^28.1.3", + "@jest/expect": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^28.1.3", + "jest-matcher-utils": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-runtime": "^28.1.3", + "jest-snapshot": "^28.1.3", + "jest-util": "^28.1.3", + "p-limit": "^3.1.0", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "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==", + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "node_modules/jest-circus/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": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/find-cache-dir/node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/jest-circus/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": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=7.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/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/jest-circus/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": { - "is-callable": "^1.1.3" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/formik": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz", - "integrity": "sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==", - "funding": [ - { - "type": "individual", - "url": "https://opencollective.com/formik" - } - ], + "node_modules/jest-cli": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", + "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", + "dev": true, "dependencies": { - "deepmerge": "^2.1.1", - "hoist-non-react-statics": "^3.3.0", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "react-fast-compare": "^2.0.1", - "tiny-warning": "^1.0.2", - "tslib": "^1.10.0" + "@jest/core": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^28.1.3", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "prompts": "^2.0.1", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" }, "peerDependencies": { - "react": ">=16.8.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-extra/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/fs-extra/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/jest-cli/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, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=7.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=8" } }, - "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "node_modules/jest-cli/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": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-port": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", - "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", "engines": { - "node": ">=6" + "node": ">=8" } }, - "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==", + "node_modules/jest-config": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.3.tgz", + "integrity": "sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==", "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^28.1.3", + "@jest/types": "^28.1.3", + "babel-jest": "^28.1.3", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^28.1.3", + "jest-environment-node": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.3", + "jest-runner": "^28.1.3", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/gh-pages": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-4.0.0.tgz", - "integrity": "sha512-p8S0T3aGJc68MtwOcZusul5qPSNZCalap3NWbhRUZYu1YOdp+EjZ+4kPmRM8h3NNRdqw00yuevRjlkuSzCn7iQ==", + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "async": "^2.6.1", - "commander": "^2.18.0", - "email-addresses": "^3.0.1", - "filenamify": "^4.3.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "^8.1.0", - "globby": "^6.1.0" - }, - "bin": { - "gh-pages": "bin/gh-pages.js", - "gh-pages-clean": "bin/gh-pages-clean.js" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/gh-pages/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "node_modules/jest-config/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": { - "array-uniq": "^1.0.1" + "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/gh-pages/node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "node_modules/jest-config/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/gh-pages/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==", + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/gh-pages/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "node_modules/jest-config/node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/gh-pages/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/gh-pages/node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "node_modules/jest-config/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": ">=0.10.0" + "node": ">=8" } }, - "node_modules/gh-pages/node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "node_modules/jest-diff": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", + "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", "dev": true, "dependencies": { - "pinkie": "^2.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "optional": true + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/jest-diff/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": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "*" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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/jest-diff/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": { - "is-glob": "^4.0.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 6" + "node": ">=7.0.0" } }, - "node_modules/glob/node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/glob/node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/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": { - "once": "^1.3.0", - "wrappy": "1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/glob/node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/jest-docblock": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", + "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/jest-each": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.3.tgz", + "integrity": "sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "chalk": "^4.0.0", + "jest-get-type": "^28.0.2", + "jest-util": "^28.1.3", + "pretty-format": "^28.1.3" + }, "engines": { - "node": ">=4" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "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" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/jest-each/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": { - "get-intrinsic": "^1.1.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/jest-each/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": { - "function-bind": "^1.1.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 0.4.0" + "node": ">=7.0.0" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "node_modules/jest-each/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-symbols": "^1.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" + "node": ">=8" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/html-minifier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", - "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", + "node_modules/jest-environment-node": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.3.tgz", + "integrity": "sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==", "dev": true, "dependencies": { - "camel-case": "^3.0.0", - "clean-css": "^4.2.1", - "commander": "^2.19.0", - "he": "^1.2.0", - "param-case": "^2.1.1", - "relateurl": "^0.2.7", - "uglify-js": "^3.5.1" - }, - "bin": { - "html-minifier": "cli.js" + "@jest/environment": "^28.1.3", + "@jest/fake-timers": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "jest-mock": "^28.1.3", + "jest-util": "^28.1.3" }, "engines": { - "node": ">=6" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/html-minifier/node_modules/camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", + "node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/html-minifier/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==", + "node_modules/jest-haste-map": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", + "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", "dev": true, "dependencies": { - "source-map": "~0.6.0" + "@jest/types": "^28.1.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.3", + "jest-worker": "^28.1.3", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">= 4.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/html-minifier/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/html-minifier/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==", + "node_modules/jest-leak-detector": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz", + "integrity": "sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==", "dev": true, - "bin": { - "he": "bin/he" + "dependencies": { + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/html-minifier/node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", - "dev": true - }, - "node_modules/html-minifier/node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "node_modules/jest-matcher-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", + "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", "dev": true, "dependencies": { - "lower-case": "^1.1.1" + "chalk": "^4.0.0", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/html-minifier/node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "no-case": "^2.2.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/html-minifier/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==", + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/html-minifier/node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "node_modules/jest-matcher-utils/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, - "bin": { - "uglifyjs": "bin/uglifyjs" + "dependencies": { + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.8.0" + "node": ">=7.0.0" } }, - "node_modules/html-minifier/node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/htmlparser2": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", - "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.2", - "domutils": "^2.8.0", - "entities": "^3.0.1" + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/jest-matcher-utils/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": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, "dependencies": { - "agent-base": "6", - "debug": "4" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">= 6" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "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==", + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10.17.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/husky": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.2.tgz", - "integrity": "sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg==", + "node_modules/jest-message-util/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, - "bin": { - "husky": "lib/bin.js" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/typicode" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "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/ignore": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.2.tgz", - "integrity": "sha512-m1MJSy4Z2NAcyhoYpxQeBsc1ZdNQwYjN0wGbLBlnVArdJ90Gtr8IhNSfZZcCoR0fM/0E0BJ0mf1KnLNDOCJP4w==", + "node_modules/jest-message-util/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": ">= 4" + "node": ">=7.0.0" } }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/jest-message-util/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": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-local/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==", + "node_modules/jest-mock": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz", + "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==", "dev": true, "dependencies": { - "resolve-from": "^5.0.0" + "@jest/types": "^28.1.3", + "@types/node": "*" }, "engines": { - "node": ">=8" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/import-local/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==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "engines": { - "node": ">=8" + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", "dev": true, "engines": { - "node": ">=0.8.19" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "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/jest-resolve": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.3.tgz", + "integrity": "sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.3", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "node_modules/jest-resolve-dependencies": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz", + "integrity": "sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==", "dev": true, + "dependencies": { + "jest-regex-util": "^28.0.2", + "jest-snapshot": "^28.1.3" + }, "engines": { - "node": ">= 0.10" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "node_modules/jest-resolve/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": { - "ci-info": "^2.0.0" + "color-name": "~1.1.4" }, - "bin": { - "is-ci": "bin.js" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/is-ci/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/jest-resolve/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, - "bin": { - "is-docker": "cli.js" + "dependencies": { + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.3.tgz", + "integrity": "sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==", + "dev": true, + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/environment": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "graceful-fs": "^4.2.9", + "jest-docblock": "^28.1.1", + "jest-environment-node": "^28.1.3", + "jest-haste-map": "^28.1.3", + "jest-leak-detector": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-resolve": "^28.1.3", + "jest-runtime": "^28.1.3", + "jest-util": "^28.1.3", + "jest-watcher": "^28.1.3", + "jest-worker": "^28.1.3", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "node_modules/jest-runner/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": { - "has-tostringtag": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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==", + "node_modules/jest-runner/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": { - "is-extglob": "^2.1.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/is-mobile": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-3.1.1.tgz", - "integrity": "sha512-RRoXXR2HNFxNkUnxtaBdGBXtFlUMFa06S0NUKf/LCF+MuGLu13gi9iBCkoEmc6+rpXuwi5Mso5V8Zf7mNynMBQ==" + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=0.12.0" + "node": ">=8" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "node_modules/jest-runner/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/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==", + "node_modules/jest-runtime": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.3.tgz", + "integrity": "sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==", "dev": true, + "dependencies": { + "@jest/environment": "^28.1.3", + "@jest/fake-timers": "^28.1.3", + "@jest/globals": "^28.1.3", + "@jest/source-map": "^28.1.2", + "@jest/test-result": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-mock": "^28.1.3", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.3", + "jest-snapshot": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "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==", + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "node_modules/jest-runtime/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": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/jest-runtime/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": { - "is-docker": "^2.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=8" + "node": ">=7.0.0" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/jest-runtime/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": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, "engines": { "node": ">=8" } }, - "node_modules/jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", - "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", + "node_modules/jest-runtime/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": { - "@jest/core": "^28.1.3", - "@jest/types": "^28.1.3", - "import-local": "^3.0.2", - "jest-cli": "^28.1.3" - }, - "bin": { - "jest": "bin/jest.js" + "has-flag": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=8" } }, - "node_modules/jest-circus": { + "node_modules/jest-snapshot": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.3.tgz", - "integrity": "sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", + "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/expect": "^28.1.3", - "@jest/test-result": "^28.1.3", + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^28.1.3", + "@jest/transform": "^28.1.3", "@jest/types": "^28.1.3", - "@types/node": "*", + "@types/babel__traverse": "^7.0.6", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^28.1.3", + "expect": "^28.1.3", + "graceful-fs": "^4.2.9", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-haste-map": "^28.1.3", "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-snapshot": "^28.1.3", + "jest-message-util": "^28.1.3", "jest-util": "^28.1.3", - "p-limit": "^3.1.0", + "natural-compare": "^1.4.0", "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "semver": "^7.3.5" }, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-cli": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", - "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@jest/core": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" + "color-convert": "^2.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=8" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-cli/node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-cli/node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/jest-snapshot/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": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 6" + "node": ">=7.0.0" } }, - "node_modules/jest-cli/node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/jest-config": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.3.tgz", - "integrity": "sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==", + "node_modules/jest-snapshot/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": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^28.1.3", - "@jest/types": "^28.1.3", - "babel-jest": "^28.1.3", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^28.1.3", - "jest-environment-node": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-runner": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "node": ">=8" } }, - "node_modules/jest-config/node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "node_modules/jest-snapshot/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": ">=0.10.0" + "node": ">=10" } }, - "node_modules/jest-diff": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=10" } }, - "node_modules/jest-docblock": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", - "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", + "node_modules/jest-snapshot/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": { - "detect-newline": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" } }, - "node_modules/jest-each": { + "node_modules/jest-snapshot/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/jest-util": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.3.tgz", - "integrity": "sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, "dependencies": { "@jest/types": "^28.1.3", + "@types/node": "*", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "jest-util": "^28.1.3", - "pretty-format": "^28.1.3" + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-environment-node": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.3.tgz", - "integrity": "sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==", + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "jest-mock": "^28.1.3", - "jest-util": "^28.1.3" + "color-convert": "^2.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-haste-map": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", - "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", + "node_modules/jest-util/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": { - "@jest/types": "^28.1.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.3", - "jest-worker": "^28.1.3", - "micromatch": "^4.0.4", - "walker": "^1.0.8" + "color-name": "~1.1.4" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "node": ">=7.0.0" } }, - "node_modules/jest-leak-detector": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz", - "integrity": "sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==", + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/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": { - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" } }, - "node_modules/jest-matcher-utils": { + "node_modules/jest-validate": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.3.tgz", + "integrity": "sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==", "dev": true, "dependencies": { + "@jest/types": "^28.1.3", + "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-diff": "^28.1.3", "jest-get-type": "^28.0.2", + "leven": "^3.1.0", "pretty-format": "^28.1.3" }, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-message-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "color-convert": "^2.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-mock": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz", - "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*" - }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/jest-validate/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, - "engines": { - "node": ">=6" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "peerDependencies": { - "jest-resolve": "*" + "engines": { + "node": ">=10" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "node_modules/jest-validate/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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=7.0.0" } }, - "node_modules/jest-resolve": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.3.tgz", - "integrity": "sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==", + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-validate/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": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" } }, - "node_modules/jest-runner": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.3.tgz", - "integrity": "sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==", + "node_modules/jest-validate/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": { - "@jest/console": "^28.1.3", - "@jest/environment": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "graceful-fs": "^4.2.9", - "jest-docblock": "^28.1.1", - "jest-environment-node": "^28.1.3", - "jest-haste-map": "^28.1.3", - "jest-leak-detector": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-resolve": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-util": "^28.1.3", - "jest-watcher": "^28.1.3", - "jest-worker": "^28.1.3", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" + "has-flag": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" } }, - "node_modules/jest-runtime": { + "node_modules/jest-watcher": { "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.3.tgz", - "integrity": "sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/globals": "^28.1.3", - "@jest/source-map": "^28.1.2", "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-mock": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-snapshot": "^28.1.3", + "emittery": "^0.10.2", "jest-util": "^28.1.3", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "string-length": "^4.0.1" }, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-snapshot": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", - "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^28.1.3", - "graceful-fs": "^4.2.9", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-haste-map": "^28.1.3", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "natural-compare": "^1.4.0", - "pretty-format": "^28.1.3", - "semver": "^7.3.5" + "color-convert": "^2.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/jest-watcher/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": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "node_modules/jest-watcher/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": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "color-name": "~1.1.4" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=7.0.0" } }, - "node_modules/jest-validate": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.3.tgz", - "integrity": "sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==", - "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "leven": "^3.1.0", - "pretty-format": "^28.1.3" - }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" } }, - "node_modules/jest-watcher": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "node_modules/jest-watcher/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": { - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.3", - "string-length": "^4.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=8" } }, "node_modules/jest-worker": { @@ -9750,10 +11644,41 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/join-component": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz", + "integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==", + "dev": true + }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "dev": true + }, "node_modules/js-base64": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.3.tgz", - "integrity": "sha512-PAr6Xg2jvd7MCR6Ld9Jg3BmTcjYsHEBx1VlwEwULb/qowPf5VD9kEMagj23Gm7JRnSvE/Da/57nChZjnvL8v6A==" + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.4.tgz", + "integrity": "sha512-wpM/wi20Tl+3ifTyi0RdDckS4YTD4Lf953mBRrpG8547T7hInHNPEj8+ck4gB8VDcGyeAWFK++Wb/fU1BeavKQ==" + }, + "node_modules/js-library-detector": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.5.0.tgz", + "integrity": "sha512-Kq7VckJ5kb26kHMAu1sDO8t2qr7M5Uw6Gf7fVGtu1YceoHdqTcobwnB5kStcktusPuPmiCE8PbCaiLzhiBsSAw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } }, "node_modules/js-sha256": { "version": "0.9.0", @@ -9766,12 +11691,13 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "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": "^2.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -9788,15 +11714,33 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "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": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json5": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz", - "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "bin": { "json5": "lib/cli.js" }, @@ -9804,6 +11748,45 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -9813,6 +11796,19 @@ "node": ">=6" } }, + "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/lighthouse": { "version": "9.6.8", "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-9.6.8.tgz", @@ -9869,236 +11865,24 @@ "node_modules/lighthouse-logger/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/lighthouse-logger/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/lighthouse/node_modules/@sentry/core": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", - "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", - "dev": true, - "dependencies": { - "@sentry/hub": "6.19.7", - "@sentry/minimal": "6.19.7", - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lighthouse/node_modules/@sentry/hub": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", - "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", - "dev": true, - "dependencies": { - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lighthouse/node_modules/@sentry/minimal": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", - "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", - "dev": true, - "dependencies": { - "@sentry/hub": "6.19.7", - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lighthouse/node_modules/@sentry/node": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz", - "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==", - "dev": true, - "dependencies": { - "@sentry/core": "6.19.7", - "@sentry/hub": "6.19.7", - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lighthouse/node_modules/@sentry/types": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", - "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/lighthouse/node_modules/@sentry/utils": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", - "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", - "dev": true, - "dependencies": { - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lighthouse/node_modules/axe-core": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", - "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/lighthouse/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/lighthouse/node_modules/csp_evaluator": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/csp_evaluator/-/csp_evaluator-1.1.1.tgz", - "integrity": "sha512-N3ASg0C4kNPUaNxt1XAvzHIVuzdtr8KLgfk1O8WDyimp1GisPAHESupArO2ieHk9QWbrJ/WkQODyh21Ps/xhxw==", - "dev": true - }, - "node_modules/lighthouse/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/lighthouse/node_modules/cssstyle": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.1.tgz", - "integrity": "sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A==", - "dev": true, - "dependencies": { - "cssom": "0.3.x" - } - }, - "node_modules/lighthouse/node_modules/http-link-header": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-0.8.0.tgz", - "integrity": "sha512-qsh/wKe1Mk1vtYEFr+LpQBFWTO1gxZQBdii2D0Umj+IUQ23r5sT088Rhpq4XzpSyIpaX7vwjB8Rrtx8u9JTg+Q==", - "dev": true - }, - "node_modules/lighthouse/node_modules/image-ssim": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", - "integrity": "sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==", - "dev": true - }, - "node_modules/lighthouse/node_modules/intl-messageformat": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-4.4.0.tgz", - "integrity": "sha512-z+Bj2rS3LZSYU4+sNitdHrwnBhr0wO80ZJSW8EzKDBowwUe3Q/UsvgCGjrwa+HPzoGCLEb9HAjfJgo4j2Sac8w==", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "intl-messageformat-parser": "^1.8.1" + "ms": "2.0.0" } }, - "node_modules/lighthouse/node_modules/intl-messageformat-parser": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.8.1.tgz", - "integrity": "sha512-IMSCKVf0USrM/959vj3xac7s8f87sc+80Y/ipBzdKy4ifBv5Gsj2tZ41EAaURVg01QU71fYr77uA8Meh6kELbg==", - "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser", - "dev": true - }, - "node_modules/lighthouse/node_modules/jpeg-js": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "node_modules/lighthouse-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/lighthouse/node_modules/js-library-detector": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.5.0.tgz", - "integrity": "sha512-Kq7VckJ5kb26kHMAu1sDO8t2qr7M5Uw6Gf7fVGtu1YceoHdqTcobwnB5kStcktusPuPmiCE8PbCaiLzhiBsSAw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/lighthouse/node_modules/lighthouse-stack-packs": { + "node_modules/lighthouse-stack-packs": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/lighthouse-stack-packs/-/lighthouse-stack-packs-1.8.2.tgz", "integrity": "sha512-vlCUxxQAB8Nu6LQHqPpDRiMi06Du593/my/6JbMttQeEfJ7pf4OS8obSTh5xSOS80U/O7fq59Q8rQGAUxQatUQ==", "dev": true }, - "node_modules/lighthouse/node_modules/lookup-closest-locale": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", - "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", - "dev": true - }, - "node_modules/lighthouse/node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true - }, - "node_modules/lighthouse/node_modules/metaviewport-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.2.0.tgz", - "integrity": "sha512-qL5NtY18LGs7lvZCkj3ep2H4Pes9rIiSLZRUyfDdvVw7pWFA0eLwmqaIxApD74RGvUrNEtk9e5Wt1rT+VlCvGw==", - "dev": true - }, - "node_modules/lighthouse/node_modules/parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", - "dev": true - }, - "node_modules/lighthouse/node_modules/ps-list": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-8.1.0.tgz", - "integrity": "sha512-NoGBqJe7Ou3kfQxEvDzDyKGAyEgwIuD3YrfXinjcCmBRv0hTld0Xb71hrXvtsNPj7HSFATfemvzB8PPJtq6Yag==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lighthouse/node_modules/robots-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.0.tgz", - "integrity": "sha512-6xkze3WRdneibICBAzMKcXyTKQw5shA3GbwoEJy7RSvxpZNGF0GMuYKE1T0VMP4fwx/fQs0n0mtriOqRtk5L1w==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, "node_modules/lighthouse/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -10108,30 +11892,35 @@ "semver": "bin/semver" } }, - "node_modules/lighthouse/node_modules/speedline-core": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/speedline-core/-/speedline-core-1.4.3.tgz", - "integrity": "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==", - "dev": true, + "node_modules/lightningcss": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.18.0.tgz", + "integrity": "sha512-uk10tNxi5fhZqU93vtYiQgx/8a9f0Kvtj5AXIm+VlOXY+t/DWDmCZWJEkZJmmALgvbS6aAW8or+Kq85eJ6TDTw==", "dependencies": { - "@types/node": "*", - "image-ssim": "^0.2.0", - "jpeg-js": "^0.4.1" + "detect-libc": "^1.0.3" }, "engines": { - "node": ">=8.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.18.0", + "lightningcss-darwin-x64": "1.18.0", + "lightningcss-linux-arm-gnueabihf": "1.18.0", + "lightningcss-linux-arm64-gnu": "1.18.0", + "lightningcss-linux-arm64-musl": "1.18.0", + "lightningcss-linux-x64-gnu": "1.18.0", + "lightningcss-linux-x64-musl": "1.18.0", + "lightningcss-win32-x64-msvc": "1.18.0" } }, - "node_modules/lighthouse/node_modules/third-party-web": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.17.1.tgz", - "integrity": "sha512-X9Mha8cVeBwakunlZXkXL6xRzw8VCcDGWqT59EzeTYAJIi8ien3CuufnEGEx4ZUFahumNQdoOwf4H2T9Ca6lBg==", - "dev": true - }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.17.1.tgz", - "integrity": "sha512-YTAHEy4XlzI3sMbUVjbPi9P7+N7lGcgl2JhCZhiQdRAEKnZLQch8kb5601sgESxdGXjgei7JZFqi/vVEk81wYg==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.18.0.tgz", + "integrity": "sha512-OqjydwtiNPgdH1ByIjA1YzqvDG/OMR6L3LPN6wRl1729LB0y4Mik7L06kmZaTb+pvUHr+NmDd2KCwnlrQ4zO3w==", "cpu": [ "arm64" ], @@ -10148,9 +11937,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.17.1.tgz", - "integrity": "sha512-UhXPUS2+yTTf5sXwUV0+8QY2x0bPGLgC/uhcknWSQMqWn1zGty4fFvH04D7f7ij0ujwSuN+Q0HtU7lgmMrPz0A==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.18.0.tgz", + "integrity": "sha512-mNiuPHj89/JHZmJMp+5H8EZSt6EL5DZRWJ31O6k3DrLLnRIQjXuXdDdN8kP7LoIkeWI5xvyD60CsReJm+YWYAw==", "cpu": [ "x64" ], @@ -10167,9 +11956,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.17.1.tgz", - "integrity": "sha512-alUZumuznB6K/9yZ0zuZkODXUm8uRnvs9t0CL46CXN16Y2h4gOx5ahUCMlelUb7inZEsgJIoepgLsJzBUrSsBw==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.18.0.tgz", + "integrity": "sha512-S+25JjI6601HiAVoTDXW6SqH+E94a+FHA7WQqseyNHunOgVWKcAkNEc2LJvVxgwTq6z41sDIb9/M3Z9wa9lk4A==", "cpu": [ "arm" ], @@ -10186,9 +11975,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.17.1.tgz", - "integrity": "sha512-/1XaH2cOjDt+ivmgfmVFUYCA0MtfNWwtC4P8qVi53zEQ7P8euyyZ1ynykZOyKXW9Q0DzrwcLTh6+hxVLcbtGBg==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.18.0.tgz", + "integrity": "sha512-JSqh4+21dCgBecIQUet35dtE4PhhSEMyqe3y0ZNQrAJQ5kyUPSQHiw81WXnPJcOSTTpG0TyMLiC8K//+BsFGQA==", "cpu": [ "arm64" ], @@ -10205,9 +11994,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.17.1.tgz", - "integrity": "sha512-/IgE7lYWFHCCQFTMIwtt+fXLcVOha8rcrNze1JYGPWNorO6NBc6MJo5u5cwn5qMMSz9fZCCDIlBBU4mGwjQszQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.18.0.tgz", + "integrity": "sha512-2FWHa8iUhShnZnqhn2wfIcK5adJat9hAAaX7etNsoXJymlliDIOFuBQEsba2KBAZSM4QqfQtvRdR7m8i0I7ybQ==", "cpu": [ "arm64" ], @@ -10223,10 +12012,48 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.18.0.tgz", + "integrity": "sha512-plCPGQJtDZHcLVKVRLnQVF2XRsIC32WvuJhQ7fJ7F6BV98b/VZX0OlX05qUaOESD9dCDHjYSfxsgcvOKgCWh7A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.18.0.tgz", + "integrity": "sha512-na+BGtVU6fpZvOHKhnlA0XHeibkT3/46nj6vLluG3kzdJYoBKU6dIl7DSOk++8jv4ybZyFJ0aOFMMSc8g2h58A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.17.1.tgz", - "integrity": "sha512-Ngqtx9NazaiAOk71XWwSsqgAuwYF+8PO6UYsoU7hAukdrSS98kwaBMEDw1igeIiZy1XD/4kh5KVnkjNf7ZOxVQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.18.0.tgz", + "integrity": "sha512-5qeAH4RMNy2yMNEl7e5TI6upt/7xD2ZpHWH4RkT8iJ7/6POS5mjHbXWUO9Q1hhDhqkdzGa76uAdMzEouIeCyNw==", "cpu": [ "x64" ], @@ -10286,64 +12113,15 @@ "url": "https://opencollective.com/lint-staged" } }, - "node_modules/lint-staged/node_modules/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": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lint-staged/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/lint-staged/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": ">=6" - } - }, - "node_modules/lint-staged/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==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/lint-staged/node_modules/commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, "engines": { "node": "^12.20.0 || >=14" } }, - "node_modules/lint-staged/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/lint-staged/node_modules/execa": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", @@ -10376,123 +12154,16 @@ "node": ">=12.20.0" } }, - "node_modules/lint-staged/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/lint-staged/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/lint-staged/node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/listr2": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.6.tgz", - "integrity": "sha512-u60KxKBy1BR2uLJNTWNptzWQ1ob/gjMzIJPZffAENzpZqbMZ/5PrXXOomDcevIS/+IB7s1mmCEtSlT2qHWMqag==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.19", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.7", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/lint-staged/node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lint-staged/node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lint-staged/node_modules/mimic-fn": { @@ -10537,25 +12208,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/p-map": { + "node_modules/lint-staged/node_modules/path-key": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, "engines": { "node": ">=12" @@ -10564,53 +12232,110 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/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==", + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", + "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/listr2": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.7.tgz", + "integrity": "sha512-MD+qXHPmtivrHIDRwPYdfNkrzqDiuaKU/rfBcec3WMyMF3xylQj3jMq344OtvQxz7zaCFViRAeqlr2AFhPvXHw==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "cli-truncate": "^2.1.0", + "colorette": "^2.0.19", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.8.0", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=8" + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } } }, - "node_modules/lint-staged/node_modules/restore-cursor/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==", + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/lint-staged/node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/listr2/node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" }, "engines": { - "node": ">=6" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "node_modules/listr2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/listr2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/lint-staged/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==", + "node_modules/listr2/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/listr2/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/listr2/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -10618,13 +12343,10 @@ "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=8" } }, - "node_modules/lint-staged/node_modules/string-width": { + "node_modules/listr2/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==", @@ -10638,18 +12360,6 @@ "node": ">=8" } }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lmdb": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.5.2.tgz", @@ -10671,19 +12381,20 @@ "@lmdb/lmdb-win32-x64": "2.5.2" } }, + "node_modules/lmdb/node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + }, "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dependencies": { - "p-locate": "^5.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/lodash": { @@ -10701,6 +12412,135 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "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/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-update/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-update/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/log-update/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/log-update/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/log-update/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/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lookup-closest-locale": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", + "integrity": "sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==", + "dev": true + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -10712,6 +12552,12 @@ "loose-envify": "cli.js" } }, + "node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", + "dev": true + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -10721,22 +12567,24 @@ "node": ">=0.10.0" } }, + "node_modules/lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "dev": true + }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "yallist": "^3.0.2" } }, "node_modules/luxon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.1.1.tgz", - "integrity": "sha512-Ah6DloGmvseB/pX1cAmjbFvyU/pKuwQMQqz7d0yvuDlVYLTs2WeDHQMpC8tGjm1da+BriHROW/OEIT/KfYg6xw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.2.1.tgz", + "integrity": "sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg==", "engines": { "node": ">=12" } @@ -10771,11 +12619,53 @@ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", "dev": true }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dev": true, + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/memoize-one": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -10791,11 +12681,25 @@ "node": ">= 8" } }, + "node_modules/metaviewport-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.2.0.tgz", + "integrity": "sha512-qL5NtY18LGs7lvZCkj3ep2H4Pes9rIiSLZRUyfDdvVw7pWFA0eLwmqaIxApD74RGvUrNEtk9e5Wt1rT+VlCvGw==", + "dev": true + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -10804,6 +12708,18 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -10859,28 +12775,6 @@ "node": "*" } }, - "node_modules/minimatch/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/minimatch/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/minimatch/node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, "node_modules/minimist": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", @@ -11036,606 +12930,422 @@ "stoppable": "^1.1.0", "tcp-port-used": "^1.0.1", "update-notifier": "^5.0.0", - "uuid": "^8.0.0", - "v8flags": "^3.1.3", - "yargs": "^16.0.3" - }, - "bin": { - "near": "bin/near" - }, - "engines": { - "node": ">= 12" - }, - "optionalDependencies": { - "@ledgerhq/hw-transport-node-hid": "^6.1.0", - "near-ledger-js": "^0.2.0" - } - }, - "node_modules/near-cli/node_modules/@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/near-cli/node_modules/@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/near-cli/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/near-cli/node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/near-cli/node_modules/@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/near-cli/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/near-cli/node_modules/borsh": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.6.0.tgz", - "integrity": "sha512-sl5k89ViqsThXQpYa9XDtz1sBl3l1lI313cFUY1HKr+wvMILnb+58xpkqTNrYbelh99dY7K8usxoCusQmqix9Q==", - "dev": true, - "dependencies": { - "bn.js": "^5.2.0", - "bs58": "^4.0.0", - "text-encoding-utf-8": "^1.0.2" - } - }, - "node_modules/near-cli/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/near-cli/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/near-cli/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/near-cli/node_modules/http-errors/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/near-cli/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, + "uuid": "^8.0.0", + "v8flags": "^3.1.3", + "yargs": "^16.0.3" + }, + "bin": { + "near": "bin/near" + }, "engines": { - "node": ">=8" + "node": ">= 12" + }, + "optionalDependencies": { + "@ledgerhq/hw-transport-node-hid": "^6.1.0", + "near-ledger-js": "^0.2.0" } }, - "node_modules/near-cli/node_modules/jest-environment-node": { + "node_modules/near-cli/node_modules/@jest/environment": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", "@jest/fake-timers": "^27.5.1", "@jest/types": "^27.5.1", "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/near-cli/node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "jest-mock": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/near-cli/node_modules/jest-mock": { + "node_modules/near-cli/node_modules/@jest/fake-timers": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", "dev": true, "dependencies": { "@jest/types": "^27.5.1", - "@types/node": "*" + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/near-cli/node_modules/jest-util": { + "node_modules/near-cli/node_modules/@jest/types": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/near-cli/node_modules/near-api-js": { - "version": "0.44.2", - "resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-0.44.2.tgz", - "integrity": "sha512-eMnc4V+geggapEUa3nU2p8HSHn/njtloI4P2mceHQWO8vDE1NGpnAw8FuTBrLmXSgIv9m6oocgFc9t3VNf5zwg==", + "node_modules/near-cli/node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", "dev": true, "dependencies": { - "bn.js": "5.2.0", - "borsh": "^0.6.0", - "bs58": "^4.0.0", - "depd": "^2.0.0", - "error-polyfill": "^0.1.3", - "http-errors": "^1.7.2", - "js-sha256": "^0.9.0", - "mustache": "^4.0.0", - "node-fetch": "^2.6.1", - "text-encoding-utf-8": "^1.0.2", - "tweetnacl": "^1.0.1" + "@sinonjs/commons": "^1.7.0" } }, - "node_modules/near-cli/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/near-cli/node_modules/@types/yargs": { + "version": "16.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", + "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/near-cli/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/near-cli/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" + "@types/yargs-parser": "*" } }, - "node_modules/near-cli/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==", + "node_modules/near-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/near-cli/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/near-cli/node_modules/borsh": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.6.0.tgz", + "integrity": "sha512-sl5k89ViqsThXQpYa9XDtz1sBl3l1lI313cFUY1HKr+wvMILnb+58xpkqTNrYbelh99dY7K8usxoCusQmqix9Q==", "dev": true, "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" } }, - "node_modules/near-cli/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/near-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/near-ledger-js": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/near-ledger-js/-/near-ledger-js-0.2.1.tgz", - "integrity": "sha512-8anZb6e96gJNBOKUR/HReLN/x8BmBhCpyPq+XxFbx8jxmsRz+M1Hxq085+ROYaMI2EDJqatrjjLAdArk13BOhA==", + "node_modules/near-cli/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, - "optional": true, "dependencies": { - "@ledgerhq/hw-transport-u2f": "^5.36.0-deprecated", - "@ledgerhq/hw-transport-webhid": "^5.51.1", - "@ledgerhq/hw-transport-webusb": "^5.53.1", - "bs58": "^4.0.1", - "platform": "^1.3.6" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/near-ledger-js/node_modules/@ledgerhq/devices": { - "version": "5.51.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz", - "integrity": "sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==", + "node_modules/near-cli/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, - "optional": true, "dependencies": { - "@ledgerhq/errors": "^5.50.0", - "@ledgerhq/logs": "^5.50.0", - "rxjs": "6", - "semver": "^7.3.5" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/near-ledger-js/node_modules/@ledgerhq/errors": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz", - "integrity": "sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==", - "dev": true, - "optional": true - }, - "node_modules/near-ledger-js/node_modules/@ledgerhq/hw-transport": { - "version": "5.51.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz", - "integrity": "sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==", - "dev": true, - "optional": true, - "dependencies": { - "@ledgerhq/devices": "^5.51.1", - "@ledgerhq/errors": "^5.50.0", - "events": "^3.3.0" - } + "node_modules/near-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/near-ledger-js/node_modules/@ledgerhq/hw-transport-u2f": { - "version": "5.36.0-deprecated", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-5.36.0-deprecated.tgz", - "integrity": "sha512-T/+mGHIiUK/ZQATad6DMDmobCMZ1mVST952009jKzhaE1Et2Uy2secU+QhRkx3BfEAkvwa0zSRSYCL9d20Iqjg==", - "deprecated": "@ledgerhq/hw-transport-u2f is deprecated. Please use @ledgerhq/hw-transport-webusb or @ledgerhq/hw-transport-webhid. https://github.com/LedgerHQ/ledgerjs/blob/master/docs/migrate_webusb.md", - "dev": true, - "optional": true, - "dependencies": { - "@ledgerhq/errors": "^5.34.0", - "@ledgerhq/hw-transport": "^5.34.0", - "@ledgerhq/logs": "^5.30.0", - "u2f-api": "0.2.7" - } + "node_modules/near-cli/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/near-ledger-js/node_modules/@ledgerhq/hw-transport-webhid": { - "version": "5.51.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-5.51.1.tgz", - "integrity": "sha512-w/2qSU0vwFY+D/4ucuYRViO7iS3Uuxmj9sI/Iiqkoiax9Xppb0/6H5m3ffKv6iPMmRYbgwCgXorqx4SLLSD8Kg==", + "node_modules/near-cli/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, - "optional": true, - "dependencies": { - "@ledgerhq/devices": "^5.51.1", - "@ledgerhq/errors": "^5.50.0", - "@ledgerhq/hw-transport": "^5.51.1", - "@ledgerhq/logs": "^5.50.0" + "engines": { + "node": ">=8" } }, - "node_modules/near-ledger-js/node_modules/@ledgerhq/hw-transport-webusb": { - "version": "5.53.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.53.1.tgz", - "integrity": "sha512-A/f+xcrkIAZiJrvPpDvsrjxQX4cI2kbdiunQkwsYmOG3Bp4z89ZnsBiC7YBst4n2/g+QgTg0/KPVtODU5djooQ==", + "node_modules/near-cli/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, - "optional": true, "dependencies": { - "@ledgerhq/devices": "^5.51.1", - "@ledgerhq/errors": "^5.50.0", - "@ledgerhq/hw-transport": "^5.51.1", - "@ledgerhq/logs": "^5.50.0" + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/near-ledger-js/node_modules/@ledgerhq/logs": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz", - "integrity": "sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==", + "node_modules/near-cli/node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, - "optional": true + "engines": { + "node": ">= 0.6" + } }, - "node_modules/near-ledger-js/node_modules/platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "node_modules/near-cli/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, - "optional": true + "engines": { + "node": ">=8" + } }, - "node_modules/near-ledger-js/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "node_modules/near-cli/node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", "dev": true, - "optional": true, "dependencies": { - "tslib": "^1.9.0" + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" }, "engines": { - "npm": ">=2.0.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/near-ledger-js/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/near-cli/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", "dev": true, - "optional": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=10" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/near-ledger-js/node_modules/u2f-api": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/u2f-api/-/u2f-api-0.2.7.tgz", - "integrity": "sha512-fqLNg8vpvLOD5J/z4B6wpPg4Lvowz1nJ9xdHcCzdUPKcFE/qNCceV2gNZxSJd5vhAZemHr/K/hbzVA0zxB5mkg==", - "dev": true, - "optional": true - }, - "node_modules/near-seed-phrase": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/near-seed-phrase/-/near-seed-phrase-0.2.0.tgz", - "integrity": "sha512-NpmrnejpY1AdlRpDZ0schJQJtfBaoUheRfiYtQpcq9TkwPgqKZCRULV5L3hHmLc0ep7KRtikbPQ9R2ztN/3cyQ==", + "node_modules/near-cli/node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", "dev": true, "dependencies": { - "bip39-light": "^1.0.7", - "bs58": "^4.0.1", - "near-hd-key": "^1.2.1", - "tweetnacl": "^1.0.2" + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/near-seed-phrase/node_modules/bip39": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz", - "integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==", + "node_modules/near-cli/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", "dev": true, "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/near-seed-phrase/node_modules/bip39-light": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/bip39-light/-/bip39-light-1.0.7.tgz", - "integrity": "sha512-WDTmLRQUsiioBdTs9BmSEmkJza+8xfJmptsNJjxnoq3EydSa/ZBXT6rm66KoT3PJIRYMnhSKNR7S9YL1l7R40Q==", + "node_modules/near-cli/node_modules/near-api-js": { + "version": "0.44.2", + "resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-0.44.2.tgz", + "integrity": "sha512-eMnc4V+geggapEUa3nU2p8HSHn/njtloI4P2mceHQWO8vDE1NGpnAw8FuTBrLmXSgIv9m6oocgFc9t3VNf5zwg==", "dev": true, "dependencies": { - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9" + "bn.js": "5.2.0", + "borsh": "^0.6.0", + "bs58": "^4.0.0", + "depd": "^2.0.0", + "error-polyfill": "^0.1.3", + "http-errors": "^1.7.2", + "js-sha256": "^0.9.0", + "mustache": "^4.0.0", + "node-fetch": "^2.6.1", + "text-encoding-utf-8": "^1.0.2", + "tweetnacl": "^1.0.1" } }, - "node_modules/near-seed-phrase/node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "node_modules/near-cli/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/near-seed-phrase/node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "node_modules/near-cli/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/near-seed-phrase/node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "node_modules/near-cli/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/near-cli/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "engines": { + "node": ">= 0.6" } }, - "node_modules/near-seed-phrase/node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "node_modules/near-cli/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": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/near-seed-phrase/node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "node_modules/near-cli/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": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/near-seed-phrase/node_modules/near-hd-key": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/near-hd-key/-/near-hd-key-1.2.1.tgz", - "integrity": "sha512-SIrthcL5Wc0sps+2e1xGj3zceEa68TgNZDLuCx0daxmfTP7sFTB3/mtE2pYhlFsCxWoMn+JfID5E1NlzvvbRJg==", + "node_modules/near-cli/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { - "bip39": "3.0.2", - "create-hmac": "1.1.7", - "tweetnacl": "1.0.3" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" } }, - "node_modules/near-seed-phrase/node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "node_modules/near-cli/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, "engines": { - "node": ">=0.12" + "node": ">=10" } }, - "node_modules/near-seed-phrase/node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/near-hd-key": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/near-hd-key/-/near-hd-key-1.2.1.tgz", + "integrity": "sha512-SIrthcL5Wc0sps+2e1xGj3zceEa68TgNZDLuCx0daxmfTP7sFTB3/mtE2pYhlFsCxWoMn+JfID5E1NlzvvbRJg==", "dev": true, "dependencies": { - "safe-buffer": "^5.1.0" + "bip39": "3.0.2", + "create-hmac": "1.1.7", + "tweetnacl": "1.0.3" } }, - "node_modules/near-seed-phrase/node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "node_modules/near-ledger-js": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/near-ledger-js/-/near-ledger-js-0.2.1.tgz", + "integrity": "sha512-8anZb6e96gJNBOKUR/HReLN/x8BmBhCpyPq+XxFbx8jxmsRz+M1Hxq085+ROYaMI2EDJqatrjjLAdArk13BOhA==", "dev": true, + "optional": true, "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "@ledgerhq/hw-transport-u2f": "^5.36.0-deprecated", + "@ledgerhq/hw-transport-webhid": "^5.51.1", + "@ledgerhq/hw-transport-webusb": "^5.53.1", + "bs58": "^4.0.1", + "platform": "^1.3.6" } }, - "node_modules/near-seed-phrase/node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "node_modules/near-seed-phrase": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/near-seed-phrase/-/near-seed-phrase-0.2.0.tgz", + "integrity": "sha512-NpmrnejpY1AdlRpDZ0schJQJtfBaoUheRfiYtQpcq9TkwPgqKZCRULV5L3hHmLc0ep7KRtikbPQ9R2ztN/3cyQ==", "dev": true, "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" + "bip39-light": "^1.0.7", + "bs58": "^4.0.1", + "near-hd-key": "^1.2.1", + "tweetnacl": "^1.0.2" } }, "node_modules/negotiator": { @@ -11647,10 +13357,19 @@ "node": ">= 0.6" } }, + "node_modules/no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "dependencies": { + "lower-case": "^1.1.1" + } + }, "node_modules/node-abi": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.30.0.tgz", - "integrity": "sha512-qWO5l3SCqbwQavymOmtTVuCWZE23++S+rxyoHjXqUmPyzRcaoI4lA2gO55/drddGnedAyjA7sk76SfQ5lfUMnw==", + "version": "3.31.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.31.0.tgz", + "integrity": "sha512-eSKV6s+APenqVh8ubJyiu/YhZgxQpGP66ntzUb3lY1xB9ukSRaGnx0AIxI+IM+1+IVYC1oWobgG5L3Lt9ARykQ==", "dev": true, "optional": true, "dependencies": { @@ -11660,6 +13379,19 @@ "node": ">=10" } }, + "node_modules/node-abi/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, + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-abi/node_modules/semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", @@ -11676,15 +13408,22 @@ "node": ">=10" } }, + "node_modules/node-abi/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, + "optional": true + }, "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", + "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -11701,9 +13440,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -11739,13 +13478,6 @@ "node": ">=10" } }, - "node_modules/node-hid/node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "optional": true - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -11803,6 +13535,21 @@ "semver": "bin/semver" } }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -11812,6 +13559,15 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -11824,6 +13580,17 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nullthrows": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", @@ -11854,14 +13621,35 @@ } }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -11903,13 +13691,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/open/node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "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": ">=8" + "node": ">= 0.8.0" } }, "node_modules/ordered-binary": { @@ -11917,6 +13713,15 @@ "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.4.0.tgz", "integrity": "sha512-EHQ/jk4/a9hLupIKxTfUsQRej1Yd/0QLQs3vGvIqg5ZtCYSzNhkzHoZc7Zf4e4kUlDaC3Uw8Q/1opOLNN2OKRQ==" }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -11933,59 +13738,153 @@ } }, "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/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==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", + "dev": true, + "dependencies": { + "no-case": "^2.2.0" + } + }, + "node_modules/parcel": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.8.3.tgz", + "integrity": "sha512-5rMBpbNE72g6jZvkdR5gS2nyhwIXaJy8i65osOqs/+5b7zgf3eMKgjSsDrv6bhz3gzifsba6MBJiZdBckl+vnA==", + "dependencies": { + "@parcel/config-default": "2.8.3", + "@parcel/core": "2.8.3", + "@parcel/diagnostic": "2.8.3", + "@parcel/events": "2.8.3", + "@parcel/fs": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/package-manager": "2.8.3", + "@parcel/reporter-cli": "2.8.3", + "@parcel/reporter-dev-server": "2.8.3", + "@parcel/utils": "2.8.3", + "chalk": "^4.1.0", + "commander": "^7.0.0", + "get-port": "^4.2.0", + "v8-compile-cache": "^2.0.0" + }, + "bin": { + "parcel": "lib/bin.js" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/parcel/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/parcel/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.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==", - "engines": { - "node": ">=6" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/parcel": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.8.2.tgz", - "integrity": "sha512-XMVf3Ip9Iokv0FC3ulN/B0cb5O21qaw0RhUPz7zULQlY794ZpFP9mNtN7HvCVEgjl5/q2sYMcTA8l+5QJ2zZ/Q==", - "dependencies": { - "@parcel/config-default": "2.8.2", - "@parcel/core": "2.8.2", - "@parcel/diagnostic": "2.8.2", - "@parcel/events": "2.8.2", - "@parcel/fs": "2.8.2", - "@parcel/logger": "2.8.2", - "@parcel/package-manager": "2.8.2", - "@parcel/reporter-cli": "2.8.2", - "@parcel/reporter-dev-server": "2.8.2", - "@parcel/utils": "2.8.2", - "chalk": "^4.1.0", - "commander": "^7.0.0", - "get-port": "^4.2.0", - "v8-compile-cache": "^2.0.0" - }, - "bin": { - "parcel": "lib/bin.js" + "node_modules/parcel/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==", + "dependencies": { + "color-name": "~1.1.4" }, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=7.0.0" } }, + "node_modules/parcel/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/parcel/node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -11994,6 +13893,25 @@ "node": ">= 10" } }, + "node_modules/parcel/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/parcel/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -12005,6 +13923,12 @@ "node": ">=6" } }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", + "dev": true + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -12022,6 +13946,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -12030,6 +13972,15 @@ "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": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -12044,6 +13995,12 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -12052,6 +14009,22 @@ "node": ">=8" } }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -12067,7 +14040,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -12087,6 +14059,45 @@ "node": ">=0.10" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "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": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "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": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -12099,62 +14110,64 @@ "node": ">=8" } }, - "node_modules/pkg-dir/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/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, + "optional": true + }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/pkg-dir/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, + "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==" + }, + "node_modules/posthtml": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", + "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", "dependencies": { - "p-locate": "^4.1.0" + "posthtml-parser": "^0.11.0", + "posthtml-render": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" } }, - "node_modules/pkg-dir/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, + "node_modules/posthtml-parser": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", + "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", "dependencies": { - "p-try": "^2.0.0" + "htmlparser2": "^7.1.1" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/pkg-dir/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, + "node_modules/posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", "dependencies": { - "p-limit": "^2.2.0" + "is-json": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/posthtml-parser": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", - "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", + "node_modules/posthtml/node_modules/posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", "dependencies": { "htmlparser2": "^7.1.1" }, @@ -12199,10 +14212,28 @@ "node": ">=8" } }, + "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/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/prettier": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz", - "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", + "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -12226,12 +14257,6 @@ "node": ">=6.0.0" } }, - "node_modules/prettier-linter-helpers/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/pretty-format": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", @@ -12277,6 +14302,19 @@ "node": ">=0.4.0" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -12297,12 +14335,37 @@ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, + "node_modules/ps-list": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz", + "integrity": "sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -12319,6 +14382,27 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/puppeteer": { "version": "18.2.1", "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-18.2.1.tgz", @@ -12444,12 +14528,18 @@ "node": ">=10.13.0" } }, - "node_modules/qrcode/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/qrcode/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/qrcode/node_modules/cliui": { @@ -12462,41 +14552,27 @@ "wrap-ansi": "^6.2.0" } }, - "node_modules/qrcode/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "node_modules/qrcode/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==", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/qrcode/node_modules/dijkstrajs": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", - "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" + "node_modules/qrcode/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/qrcode/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==" }, - "node_modules/qrcode/node_modules/encode-utf8": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" - }, - "node_modules/qrcode/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==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/qrcode/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", @@ -12505,55 +14581,6 @@ "node": ">=8" } }, - "node_modules/qrcode/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==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/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==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/qrcode/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==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/qrcode/node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, "node_modules/qrcode/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -12567,11 +14594,6 @@ "node": ">=8" } }, - "node_modules/qrcode/node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" - }, "node_modules/qrcode/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -12623,6 +14645,21 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -12648,6 +14685,48 @@ "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" }, + "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/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -12713,6 +14792,11 @@ "react": "^18.2.0" } }, + "node_modules/react-error-overlay": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==" + }, "node_modules/react-fast-compare": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", @@ -12755,37 +14839,25 @@ } } }, - "node_modules/react-redux/node_modules/@types/hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, - "node_modules/react-redux/node_modules/@types/react-redux": { - "version": "7.1.24", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz", - "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==", - "dependencies": { - "@types/hoist-non-react-statics": "^3.3.0", - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0", - "redux": "^4.0.0" - } - }, "node_modules/react-redux/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-refresh": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", + "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-router": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.5.0.tgz", - "integrity": "sha512-fqqUSU0NC0tSX0sZbyuxzuAzvGqbjiZItBQnyicWlOUmzhAU8YuLgRbaCL2hf3sJdtRy4LP/WBrWtARkMvdGPQ==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.7.0.tgz", + "integrity": "sha512-KNWlG622ddq29MAM159uUsNMdbX8USruoKnwMMQcs/QWZgFUayICSn2oB7reHce1zPj6CG18kfkZIunSSRyGHg==", "dependencies": { - "@remix-run/router": "1.1.0" + "@remix-run/router": "1.3.0" }, "engines": { "node": ">=14" @@ -12795,12 +14867,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.5.0.tgz", - "integrity": "sha512-/XzRc5fq80gW1ctiIGilyKFZC/j4kfe75uivMsTChFbkvrK4ZrF3P3cGIc1f/SSkQ4JiJozPrf+AwUHHWVehVg==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.7.0.tgz", + "integrity": "sha512-jQtXUJyhso3kFw430+0SPCbmCmY1/kJv8iRffGHwHy3CkoomGxeYzMkmeSPYo6Egzh3FKJZRAL22yg5p2tXtfg==", "dependencies": { - "@remix-run/router": "1.1.0", - "react-router": "6.5.0" + "@remix-run/router": "1.3.0", + "react-router": "6.7.0" }, "engines": { "node": ">=14" @@ -12852,15 +14924,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/react-transition-group/node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -12875,6 +14938,18 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -12916,20 +14991,64 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, - "node_modules/regexpu-core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz", - "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==", + "node_modules/regenerator-transform": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", + "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "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, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz", + "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsgen": "^0.7.1", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" + "rc": "^1.2.8" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/regjsgen": { @@ -12965,6 +15084,12 @@ "node": ">= 0.10" } }, + "node_modules/remove-trailing-slash": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz", + "integrity": "sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA==", + "dev": true + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -12973,6 +15098,11 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -12989,23 +15119,58 @@ "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-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "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": ">=4" + "node": ">=8" } }, "node_modules/resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", "dev": true, "engines": { "node": ">=10" } }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "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/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -13016,6 +15181,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "node_modules/rifm": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/rifm/-/rifm-0.12.1.tgz", @@ -13039,6 +15210,25 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/robots-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.0.tgz", + "integrity": "sha512-6xkze3WRdneibICBAzMKcXyTKQw5shA3GbwoEJy7RSvxpZNGF0GMuYKE1T0VMP4fwx/fQs0n0mtriOqRtk5L1w==", + "dev": true, + "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", @@ -13094,10 +15284,16 @@ } ] }, + "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/sass": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.57.0.tgz", - "integrity": "sha512-IZNEJDTK1cF5B1cGA593TPAV/1S0ysUDxq9XHjX/+SMy0QfUny+nfUsq5ZP7wWSl4eEf7wDJcEZ8ABYFmh3m/w==", + "version": "1.57.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz", + "integrity": "sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -13111,21 +15307,6 @@ "node": ">=12.0.0" } }, - "node_modules/sass/node_modules/immutable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", - "dev": true - }, - "node_modules/sass/node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -13142,6 +15323,78 @@ "semver": "bin/semver.js" } }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/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/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -13152,6 +15405,40 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "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/shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", @@ -13169,6 +15456,20 @@ "node": ">=4" } }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -13243,6 +15544,12 @@ "semver": "bin/semver.js" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -13288,6 +15595,15 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", @@ -13307,6 +15623,43 @@ "node": ">=0.10.0" } }, + "node_modules/speedline-core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/speedline-core/-/speedline-core-1.4.3.tgz", + "integrity": "sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==", + "dev": true, + "dependencies": { + "@types/node": "*", + "image-ssim": "^0.2.0", + "jpeg-js": "^0.4.1" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -13348,20 +15701,14 @@ } }, "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==", + "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": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, - "node_modules/string_decoder/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/string-argv": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", @@ -13455,816 +15802,726 @@ "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/stylis": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", - "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" - }, - "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==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tcp-port-used": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", - "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", - "dev": true, - "dependencies": { - "debug": "4.3.1", - "is2": "^2.0.6" - } - }, - "node_modules/tcp-port-used/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/tcp-port-used/node_modules/ip-regex": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", - "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tcp-port-used/node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, - "node_modules/tcp-port-used/node_modules/is2": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", - "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "ip-regex": "^4.1.0", - "is-url": "^1.2.4" - }, - "engines": { - "node": ">=v0.10.0" - } - }, - "node_modules/text-encoding-utf-8": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", - "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" - }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/touch/node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/touch/node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "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==", + } + }, + "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": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "dev": true, "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "escape-string-regexp": "^1.0.2" }, "engines": { - "node": ">=4.2.0" + "node": ">=0.10.0" } }, - "node_modules/u3": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/u3/-/u3-0.1.1.tgz", - "integrity": "sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w==" - }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "node_modules/strip-outer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "engines": { - "node": ">=4" + "node": ">=0.8.0" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, + "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==", "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "node_modules/supports-hyperlinks/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": { - "crypto-random-string": "^2.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" }, "bin": { - "browserslist-lint": "cli.js" + "svgo": "bin/svgo" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "dependencies": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, + "node_modules/svgo/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==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" + "node": ">= 10" } }, - "node_modules/update-notifier/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" } }, - "node_modules/update-notifier/node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "dependencies": { - "defer-to-connect": "^1.0.1" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "engines": { "node": ">=6" } }, - "node_modules/update-notifier/node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "node_modules/tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", "dev": true, "dependencies": { - "string-width": "^4.1.0" + "debug": "4.3.1", + "is2": "^2.0.6" } }, - "node_modules/update-notifier/node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "node_modules/tcp-port-used/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/update-notifier/node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, + "node_modules/terser": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/update-notifier/node_modules/cacheable-request/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/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==" + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { - "pump": "^3.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/update-notifier/node_modules/cacheable-request/node_modules/lowercase-keys": { + "node_modules/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/third-party-web": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/third-party-web/-/third-party-web-0.17.1.tgz", + "integrity": "sha512-X9Mha8cVeBwakunlZXkXL6xRzw8VCcDGWqT59EzeTYAJIi8ien3CuufnEGEx4ZUFahumNQdoOwf4H2T9Ca6lBg==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==" + }, + "node_modules/tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/update-notifier/node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", "dev": true, "engines": { "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/update-notifier/node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dependencies": { - "mimic-response": "^1.0.0" + "is-number": "^7.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8.0" } }, - "node_modules/update-notifier/node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { - "node": ">=4" + "node": ">=0.6" } }, - "node_modules/update-notifier/node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" }, - "node_modules/update-notifier/node_modules/duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", - "dev": true + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } }, - "node_modules/update-notifier/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/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, - "node_modules/update-notifier/node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/update-notifier/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "node_modules/trim-repeated/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=0.8.0" } }, - "node_modules/update-notifier/node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "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": { - "ini": "2.0.0" + "tslib": "^1.8.1" }, "engines": { - "node": ">=10" + "node": ">= 6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "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/update-notifier/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, + "optional": true, "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "safe-buffer": "^5.0.1" }, "engines": { - "node": ">=8.6" + "node": "*" } }, - "node_modules/update-notifier/node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "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": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/update-notifier/node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/update-notifier/node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/update-notifier/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "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/update-notifier/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==", + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/update-notifier/node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.2.0" } }, - "node_modules/update-notifier/node_modules/is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "node_modules/u2f-api": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/u2f-api/-/u2f-api-0.2.7.tgz", + "integrity": "sha512-fqLNg8vpvLOD5J/z4B6wpPg4Lvowz1nJ9xdHcCzdUPKcFE/qNCceV2gNZxSJd5vhAZemHr/K/hbzVA0zxB5mkg==", "dev": true, - "engines": { - "node": ">=10" + "optional": true + }, + "node_modules/u3": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/u3/-/u3-0.1.1.tgz", + "integrity": "sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w==" + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "bin": { + "uglifyjs": "bin/uglifyjs" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/update-notifier/node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } }, - "node_modules/update-notifier/node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, - "node_modules/update-notifier/node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" } }, - "node_modules/update-notifier/node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dependencies": { - "package-json": "^6.3.0" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/update-notifier/node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "engines": { "node": ">=4" } }, - "node_modules/update-notifier/node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/update-notifier/node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 4.0.0" } }, - "node_modules/update-notifier/node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/update-notifier/node_modules/package-json/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, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, "bin": { - "semver": "bin/semver.js" + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/update-notifier/node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", "dev": true, + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" } }, - "node_modules/update-notifier/node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "node_modules/update-notifier/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "escape-goat": "^2.0.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/update-notifier/node_modules/registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "node_modules/update-notifier/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": { - "rc": "1.2.8" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6.0.0" + "node": ">=7.0.0" } }, - "node_modules/update-notifier/node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "node_modules/update-notifier/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/update-notifier/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": { - "rc": "^1.2.8" - }, "engines": { "node": ">=8" } }, - "node_modules/update-notifier/node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "node_modules/update-notifier/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": { - "lowercase-keys": "^1.0.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, "node_modules/update-notifier/node_modules/semver": { @@ -14282,63 +16539,40 @@ "node": ">=10" } }, - "node_modules/update-notifier/node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "node_modules/update-notifier/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": { - "semver": "^6.3.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/update-notifier/node_modules/semver-diff/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/update-notifier/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/update-notifier/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/update-notifier/node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } + "node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", + "dev": true }, - "node_modules/update-notifier/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==", + "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, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/update-notifier/node_modules/url-parse-lax": { + "node_modules/url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", @@ -14350,18 +16584,28 @@ "node": ">=4" } }, - "node_modules/update-notifier/node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "node_modules/usb": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/usb/-/usb-1.9.2.tgz", + "integrity": "sha512-dryNz030LWBPAf6gj8vyq0Iev3vPbCLHCT8dBw3gQRXRzVNsIdeuU+VjPp3ksmSPkeMAl1k+kQ14Ij0QHyeiAg==", "dev": true, + "hasInstallScript": true, + "optional": true, "dependencies": { - "string-width": "^4.0.0" + "node-addon-api": "^4.2.0", + "node-gyp-build": "^4.3.0" }, "engines": { - "node": ">=8" + "node": ">=10.16.0" } }, + "node_modules/usb/node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, + "optional": true + }, "node_modules/use-memo-one": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", @@ -14397,6 +16641,15 @@ "node": ">= 4" } }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -14411,37 +16664,30 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "node_modules/v8-to-istanbul": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", + "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", "dev": true, "dependencies": { - "homedir-polyfill": "^1.0.1" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10.12.0" } }, - "node_modules/v8flags/node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "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": { - "parse-passwd": "^1.0.0" + "homedir-polyfill": "^1.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/v8flags/node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, "node_modules/vary": { @@ -14481,6 +16727,26 @@ "webidl-conversions": "^3.0.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": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" + }, "node_modules/which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", @@ -14501,6 +16767,56 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/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/widest-line/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/widest-line/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/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": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -14518,6 +16834,39 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/wrap-ansi/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -14611,18 +16960,16 @@ } }, "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 + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", - "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", - "dev": true, + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "engines": { - "node": ">= 14" + "node": ">= 6" } }, "node_modules/yargs": { From 9cc079d9305a9fd536c55782e22fefd81d0b072f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 21 Jan 2023 18:09:53 +0400 Subject: [PATCH 516/537] wip --- src/entities/wallet/index.ts | 10 ++++----- src/entities/wallet/ui/wallet.providers.tsx | 6 +++--- src/entities/wallet/ui/wallet.selector.tsx | 6 +++--- src/entities/wallet/wallet.service.ts | 24 +++++++++++++++------ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/entities/wallet/index.ts b/src/entities/wallet/index.ts index 62623718..12b65c38 100644 --- a/src/entities/wallet/index.ts +++ b/src/entities/wallet/index.ts @@ -3,13 +3,11 @@ import { WalletSelectorModal } from "@near-wallet-selector/modal-ui"; import { WalletContextProvider } from "./ui/wallet.providers"; import { WalletSelector } from "./ui/wallet.selector"; -import { WalletContext, tryWalletContext } from "./wallet.service"; +import { WalletService } from "./wallet.service"; -export class Wallet { - static Selector = WalletSelector; - static Context = WalletContext; - static ContextProvider = WalletContextProvider; - static tryContext = tryWalletContext; +export class Wallet extends WalletService { + public static readonly Selector = WalletSelector; + public static readonly ContextProvider = WalletContextProvider; } declare global { diff --git a/src/entities/wallet/ui/wallet.providers.tsx b/src/entities/wallet/ui/wallet.providers.tsx index 9eb767ce..50598a00 100644 --- a/src/entities/wallet/ui/wallet.providers.tsx +++ b/src/entities/wallet/ui/wallet.providers.tsx @@ -10,7 +10,7 @@ import { FC, useCallback, useEffect, useState } from "react"; import { map, distinctUntilChanged } from "rxjs"; import { Multicall } from "../../../shared/lib/contracts/multicall"; -import { WalletContext } from "../wallet.service"; +import { WalletService } from "../wallet.service"; export const WalletContextProvider: FC = ({ children }) => { const [selector, setSelector] = useState(null); @@ -73,7 +73,7 @@ export const WalletContextProvider: FC = ({ children }) => { const accountId = accounts.find((account) => account.active)?.accountId || null; return ( - = ({ children }) => { }} > {children} - + ); }; diff --git a/src/entities/wallet/ui/wallet.selector.tsx b/src/entities/wallet/ui/wallet.selector.tsx index 6d0a1cbe..0749de87 100644 --- a/src/entities/wallet/ui/wallet.selector.tsx +++ b/src/entities/wallet/ui/wallet.selector.tsx @@ -9,7 +9,7 @@ import { fields } from "../../../shared/lib/args/args-types/args-object"; import { SputnikDAO } from "../../../shared/lib/contracts/sputnik-dao"; import { Multicall } from "../../../shared/lib/contracts/multicall"; import { STORAGE } from "../../../shared/lib/persistent"; -import { WalletContext, tryWalletContext } from "../wallet.service"; +import { WalletService } from "../wallet.service"; import "./wallet.selector.scss"; @@ -34,7 +34,7 @@ interface State { /* TODO: Decompose code */ export class WalletSelector extends Component { - static contextType = tryWalletContext(); + static contextType = WalletService.tryContext(); declare context: ContextType; schema = args @@ -79,7 +79,7 @@ export class WalletSelector extends Component { 400 ); - constructor(props: Props, context: ContextType) { + constructor(props: Props, context: ContextType) { super(props); const { accountId } = context!; diff --git a/src/entities/wallet/wallet.service.ts b/src/entities/wallet/wallet.service.ts index 2b7710a7..3db4c735 100644 --- a/src/entities/wallet/wallet.service.ts +++ b/src/entities/wallet/wallet.service.ts @@ -2,12 +2,22 @@ import { createContext } from "react"; import { WalletModel } from "./wallet.model"; -export const WalletContext = createContext(null); +export class WalletService { + public static readonly onAddressesUpdated = { + subscribe: (callback: EventListener) => { + document.addEventListener("onaddressesupdated", callback); -export const tryWalletContext = () => { - if (!WalletContext) { - throw new Error("tryWalletContext must be used within a WalletContextProvider"); - } + return () => document.removeEventListener("onaddressesupdated", callback); + }, + }; - return WalletContext; -}; + public static readonly Context = createContext(null); + + public static readonly tryContext = () => { + if (!WalletService.Context) { + throw new Error("tryWalletContext must be used within a WalletContextProvider"); + } + + return WalletService.Context; + }; +} From 74f6f0663afc3bd88ac736830cc539541d7cb6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 21 Jan 2023 18:27:26 +0400 Subject: [PATCH 517/537] chore: Update AccountId type --- src/app/global.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/global.d.ts b/src/app/global.d.ts index 0d5f097a..dd94385e 100644 --- a/src/app/global.d.ts +++ b/src/app/global.d.ts @@ -1,4 +1,4 @@ -import { Account, NetworkId } from "@near-wallet-selector/core"; +import { NetworkId } from "@near-wallet-selector/core"; import { Component } from "react"; import { Task, TaskCardCopy, TaskCardInfo, Wallet } from "../entities"; @@ -38,7 +38,7 @@ declare global { /** * NEAR Protocol account ID */ - declare type AccountId = Account["accountId"]; + declare type AccountId = string; interface Window { EXPORT: Component; From 851fedf2ecd6a56c6cac0e11682552608d8234f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sat, 21 Jan 2023 19:44:13 +0400 Subject: [PATCH 518/537] fix: Use `AccountId = string` for NEAR account ID type everywhere --- src/entities/ft/ft.service.ts | 5 +++-- src/entities/near/near.service.ts | 5 +++-- src/shared/lib/standards/fungibleToken.ts | 4 +--- src/shared/ui/design/near-link/near-link.tsx | 4 +--- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/entities/ft/ft.service.ts b/src/entities/ft/ft.service.ts index b6c6adbe..acd79cf0 100644 --- a/src/entities/ft/ft.service.ts +++ b/src/entities/ft/ft.service.ts @@ -1,4 +1,3 @@ -import { Account } from "@near-wallet-selector/core"; import { createContext, useEffect, useMemo, useState } from "react"; import { Multicall } from "../../shared/lib/contracts/multicall"; @@ -7,7 +6,9 @@ import { FungibleToken } from "../../shared/lib/standards/fungibleToken"; import { FTSchema } from "./ft.model"; -export interface IFTService extends Pick {} +export interface IFTService { + accountId: AccountId; +} export class FTService { public static readonly BalancesContext = createContext(FTSchema.balances); diff --git a/src/entities/near/near.service.ts b/src/entities/near/near.service.ts index 723231e6..6d7f1474 100644 --- a/src/entities/near/near.service.ts +++ b/src/entities/near/near.service.ts @@ -1,4 +1,3 @@ -import { Account } from "@near-wallet-selector/core"; import { createContext, useEffect, useMemo, useState } from "react"; import { Big } from "../../shared/lib/converter"; @@ -7,7 +6,9 @@ import { Multicall } from "../../shared/lib/contracts/multicall"; import { NEARSchema } from "./near.model"; -export interface INEARService extends Pick {} +export interface INEARService { + accountId: AccountId; +} export class NEARService { public static readonly BalancesContext = createContext(NEARSchema.balances); diff --git a/src/shared/lib/standards/fungibleToken.ts b/src/shared/lib/standards/fungibleToken.ts index c1cf22f8..3f9f15cf 100644 --- a/src/shared/lib/standards/fungibleToken.ts +++ b/src/shared/lib/standards/fungibleToken.ts @@ -1,5 +1,3 @@ -import { Account } from "@near-wallet-selector/core"; - import { view } from "../wallet"; import { StorageBalanceBounds, StorageManagement } from "./storageManagement"; @@ -18,7 +16,7 @@ type FungibleTokenMetadata = { // Fungible token core follow NEP-141. See: https://nomicon.io/Standards/Tokens/FungibleToken/Core // Also implements NEP-145 for storage management. See: https://nomicon.io/Standards/StorageManagement class FungibleToken extends StorageManagement { - address: Account["accountId"]; + address: AccountId; // needs initialization, but start with empty metadata metadata: FungibleTokenMetadata = { spec: "", name: "", symbol: "", decimals: -1 }; // storage balance bounds. Needs initialization, but starts with "0" values diff --git a/src/shared/ui/design/near-link/near-link.tsx b/src/shared/ui/design/near-link/near-link.tsx index 015472bf..98a2c2e2 100644 --- a/src/shared/ui/design/near-link/near-link.tsx +++ b/src/shared/ui/design/near-link/near-link.tsx @@ -1,12 +1,10 @@ -import { Account } from "@near-wallet-selector/core"; - import { args } from "../../../lib/args/args"; import { Link, LinkProps } from "../link"; import "./near-link.scss"; export interface NEARLinkProps extends Omit { - address: Account["accountId"]; + address: AccountId; } const _NEARLink = "NEARLink"; From a0cd09c2cb893bbb4382380305e79a87719ef76e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 22 Jan 2023 00:34:36 +0400 Subject: [PATCH 519/537] fix: Implement state reset between service inputs updates --- src/entities/ft/ft.service.ts | 5 ++++- src/entities/job/job.service.ts | 5 ++++- src/entities/mi/mi.service.ts | 7 ++++--- src/entities/near/near.service.ts | 5 ++++- src/entities/wallet/wallet.service.ts | 8 -------- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/entities/ft/ft.service.ts b/src/entities/ft/ft.service.ts index acd79cf0..8d5a7c9b 100644 --- a/src/entities/ft/ft.service.ts +++ b/src/entities/ft/ft.service.ts @@ -61,7 +61,10 @@ export class FTService { public static readonly useBalancesState = (inputs: IFTService) => { const [state, stateUpdate] = useState(FTSchema.balances); - useEffect(() => void FTService.balancesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); + useEffect(() => { + stateUpdate(FTSchema.balances); + void FTService.balancesFetch(inputs, stateUpdate); + }, [...Object.values(inputs), stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/job/job.service.ts b/src/entities/job/job.service.ts index 56ac4572..a35a1e3d 100644 --- a/src/entities/job/job.service.ts +++ b/src/entities/job/job.service.ts @@ -38,7 +38,10 @@ export class JobService { public static readonly useAllEntriesState = (inputs: IJobService) => { const [state, stateUpdate] = useState(JobsSchema); - useEffect(() => void JobService.allEntriesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); + useEffect(() => { + stateUpdate(JobsSchema); + void JobService.allEntriesFetch(inputs, stateUpdate); + }, [...Object.values(inputs), stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/mi/mi.service.ts b/src/entities/mi/mi.service.ts index 4418e17b..f8076d14 100644 --- a/src/entities/mi/mi.service.ts +++ b/src/entities/mi/mi.service.ts @@ -34,9 +34,10 @@ export class MIService { public static readonly usePropertiesState = (inputs: IMIService) => { const [state, stateUpdate] = useState(MISchema); - useEffect(() => void MIService.propertiesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); - - // TODO: onAddressUpdated -> { loading: true } + useEffect(() => { + stateUpdate(MISchema); + void MIService.propertiesFetch(inputs, stateUpdate); + }, [...Object.values(inputs), stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/near/near.service.ts b/src/entities/near/near.service.ts index 6d7f1474..2559ef8f 100644 --- a/src/entities/near/near.service.ts +++ b/src/entities/near/near.service.ts @@ -37,7 +37,10 @@ export class NEARService { public static readonly useBalancesState = (inputs: INEARService) => { const [state, stateUpdate] = useState(NEARSchema.balances); - useEffect(() => void NEARService.balancesFetch(inputs, stateUpdate), [...Object.values(inputs), stateUpdate]); + useEffect(() => { + stateUpdate(NEARSchema.balances); + void NEARService.balancesFetch(inputs, stateUpdate); + }, [...Object.values(inputs), stateUpdate]); useEffect(() => { state.error instanceof Error && void console.error(state.error); diff --git a/src/entities/wallet/wallet.service.ts b/src/entities/wallet/wallet.service.ts index 3db4c735..f1720124 100644 --- a/src/entities/wallet/wallet.service.ts +++ b/src/entities/wallet/wallet.service.ts @@ -3,14 +3,6 @@ import { createContext } from "react"; import { WalletModel } from "./wallet.model"; export class WalletService { - public static readonly onAddressesUpdated = { - subscribe: (callback: EventListener) => { - document.addEventListener("onaddressesupdated", callback); - - return () => document.removeEventListener("onaddressesupdated", callback); - }, - }; - public static readonly Context = createContext(null); public static readonly tryContext = () => { From 6548ac54e99d29a18a75a9dee87f577cf0395045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 22 Jan 2023 00:37:53 +0400 Subject: [PATCH 520/537] fix: Update imports --- src/features/edit-task/edit-task.ui.jsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/features/edit-task/edit-task.ui.jsx b/src/features/edit-task/edit-task.ui.jsx index 441d8583..192a94a9 100644 --- a/src/features/edit-task/edit-task.ui.jsx +++ b/src/features/edit-task/edit-task.ui.jsx @@ -1,8 +1,6 @@ -import { Component } from "react"; -import hash from "object-hash"; -import EditOutlinedIcon from "@mui/icons-material/EditOutlined"; -import AutoAwesomeOutlinedIcon from "@mui/icons-material/AutoAwesomeOutlined"; +import { AutoAwesomeOutlinedIcon, EditOutlinedIcon } from "@mui/icons-material"; import { Formik } from "formik"; +import hash from "object-hash"; import { Component } from "react"; import "./edit-task.ui.scss"; From 63a7a08314ffbd46742e2e4aec29adf9c4931be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Sun, 22 Jan 2023 00:40:03 +0400 Subject: [PATCH 521/537] wip: Fix imports --- src/features/edit-task/edit-task.ui.jsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/features/edit-task/edit-task.ui.jsx b/src/features/edit-task/edit-task.ui.jsx index 192a94a9..ac36357b 100644 --- a/src/features/edit-task/edit-task.ui.jsx +++ b/src/features/edit-task/edit-task.ui.jsx @@ -1,4 +1,4 @@ -import { AutoAwesomeOutlinedIcon, EditOutlinedIcon } from "@mui/icons-material"; +import { AutoAwesomeOutlined, EditOutlined } from "@mui/icons-material"; import { Formik } from "formik"; import hash from "object-hash"; import { Component } from "react"; @@ -48,10 +48,9 @@ export class EditTaskUI extends Component { ) : (
    - +

    - Click the icon in the top right corner of a task to start - editing! + Click the icon in the top right corner of a task to start editing!

    ); From fdb9402c6dace792daef66696f0dee6fb0ba7bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Mon, 23 Jan 2023 14:32:42 +0400 Subject: [PATCH 522/537] chore: Rename workflow tools pane widget --- src/pages/app/app-page.ui.jsx | 5 +++-- src/widgets/index.ts | 2 +- src/widgets/workflow-editor/index.ts | 9 --------- src/widgets/workflow-tools/index.ts | 9 +++++++++ .../workflow-tools.ui.jsx} | 14 +++++++------- .../workflow-tools.ui.scss} | 2 +- 6 files changed, 21 insertions(+), 20 deletions(-) delete mode 100644 src/widgets/workflow-editor/index.ts create mode 100644 src/widgets/workflow-tools/index.ts rename src/widgets/{workflow-editor/workflow-editor.ui.jsx => workflow-tools/workflow-tools.ui.jsx} (83%) rename src/widgets/{workflow-editor/workflow-editor.ui.scss => workflow-tools/workflow-tools.ui.scss} (99%) diff --git a/src/pages/app/app-page.ui.jsx b/src/pages/app/app-page.ui.jsx index 538b88ec..5f67fa3b 100644 --- a/src/pages/app/app-page.ui.jsx +++ b/src/pages/app/app-page.ui.jsx @@ -6,7 +6,7 @@ import { Task } from "../../entities"; import { WorkflowEditorConfig } from "../../shared/params/workflow-editor.params"; import { STORAGE } from "../../shared/lib/persistent"; import { fromCall } from "../../shared/lib/call"; -import { WorkflowEditorMenu } from "../../widgets"; +import { WorkflowTools } from "../../widgets"; import "./app-page.ui.scss"; @@ -531,7 +531,8 @@ export default class AppPageUI extends Component { )} - + + ); } diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 605b883c..66cac6dd 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -1,5 +1,5 @@ export { DialogsLayer } from "./dialogs-layer"; -export { WorkflowEditorMenu } from "./workflow-editor"; +export { WorkflowTools } from "./workflow-tools"; export { FundsOverview, type IFundsOverview } from "./funds-overview"; export { ScheduleOverview, type IScheduleOverview } from "./schedule-overview"; export { SettingsManager, type ISettingsManager } from "./settings-manager"; diff --git a/src/widgets/workflow-editor/index.ts b/src/widgets/workflow-editor/index.ts deleted file mode 100644 index 3d64934f..00000000 --- a/src/widgets/workflow-editor/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { WorkflowEditorMenu } from "./workflow-editor.ui"; - -export { WorkflowEditorMenu }; - -declare global { - interface Window { - MENU: WorkflowEditorMenu; - } -} diff --git a/src/widgets/workflow-tools/index.ts b/src/widgets/workflow-tools/index.ts new file mode 100644 index 00000000..758340fa --- /dev/null +++ b/src/widgets/workflow-tools/index.ts @@ -0,0 +1,9 @@ +import { WorkflowTools } from "./workflow-tools.ui"; + +export { WorkflowTools }; + +declare global { + interface Window { + MENU: WorkflowTools; + } +} diff --git a/src/widgets/workflow-editor/workflow-editor.ui.jsx b/src/widgets/workflow-tools/workflow-tools.ui.jsx similarity index 83% rename from src/widgets/workflow-editor/workflow-editor.ui.jsx rename to src/widgets/workflow-tools/workflow-tools.ui.jsx index 8b86beee..5802c61e 100644 --- a/src/widgets/workflow-editor/workflow-editor.ui.jsx +++ b/src/widgets/workflow-tools/workflow-tools.ui.jsx @@ -6,9 +6,9 @@ import { Task } from "../../entities"; import { EditTask, WorkflowExport } from "../../features"; import { Tabs } from "../../shared/ui/design"; -import "./workflow-editor.ui.scss"; +import "./workflow-tools.ui.scss"; -export class WorkflowEditorMenu extends Component { +export class WorkflowTools extends Component { constructor(props) { super(props); @@ -33,16 +33,16 @@ export class WorkflowEditorMenu extends Component { const LAYOUT = this.props.layout; return ( -
    -
    +
    +
    Date: Mon, 23 Jan 2023 23:07:18 +0400 Subject: [PATCH 523/537] chore: Format --- src/entities/wallet/ui/wallet.selector.tsx | 3 + .../workflow-export/workflow-export.ui.tsx | 240 +++++++++--------- 2 files changed, 120 insertions(+), 123 deletions(-) diff --git a/src/entities/wallet/ui/wallet.selector.tsx b/src/entities/wallet/ui/wallet.selector.tsx index 0749de87..618a51e4 100644 --- a/src/entities/wallet/ui/wallet.selector.tsx +++ b/src/entities/wallet/ui/wallet.selector.tsx @@ -46,15 +46,18 @@ export class WalletSelector extends Component { .test({ name: "hasPermission", message: "User does not have required permissions on this dao", + test: (value) => value == null || this.state.currentDao.checkUserPermission(value, "AddProposal", "FunctionCall"), }) .retain(), + dao: args .object() .shape({ noDao: args.string().sputnikDao().retain({ initial: true }), + noMulticall: args.string().multicall().retain({ customMessage: "DAO does not have a multicall instance", initial: true, diff --git a/src/features/workflow-export/workflow-export.ui.tsx b/src/features/workflow-export/workflow-export.ui.tsx index 02d4e411..5f8ebf30 100644 --- a/src/features/workflow-export/workflow-export.ui.tsx +++ b/src/features/workflow-export/workflow-export.ui.tsx @@ -61,6 +61,7 @@ export class WorkflowExportUI extends Component { gas: args.big().gas(), depo: args.big().token(), attachment: args.array(), + tokenAddress: args .string() .ft() @@ -74,10 +75,12 @@ export class WorkflowExportUI extends Component { ctx.options.context.tokensWhitelist.includes(value), }) .requiredWhen("attachment", (attachment) => attachment.includes("ft")), + tokenAmount: args .big() .token() .requiredWhen("attachment", (attachment) => attachment.includes("ft")), + hasErrors: args.boolean().retain({ dummy: true }), }) .transform(({ attachment, gas, gasUnit, depo, depoUnit, tokenAddress, tokenAmount, ...rest }) => ({ @@ -124,21 +127,100 @@ export class WorkflowExportUI extends Component { } setFormData(newFormData: Partial, callback?: () => void) { - this.setState( - { - formData: { - ...this.state.formData, - ...newFormData, - }, - }, - callback - ); + this.setState({ formData: { ...this.state.formData, ...newFormData } }, callback); } onAddressesUpdated(e: CustomEvent) { this.tryUpdateFt(); } + onSubmit = async ({ multicallArgs }: { multicallArgs: MulticallArgs }) => { + const { currentDao: dao, currentMulticall: multicall } = window.WALLET_COMPONENT.state; + + const { + attachment, + execution, + gas, + gasUnit, + depo, + depoUnit, + description, + tokenAddress, + tokenAmount, + dateTime, + } = this.state.formData; + + // Case 1: immediate execution => basic multicall + if (!execution.includes("scheduled")) { + // multicall with attached FT + if (attachment.includes("ft")) { + const tx = await dao.proposeMulticallFT( + description, + multicallArgs, + args.big().intoParsed(gasUnit).cast(gas).toFixed(), + tokenAddress, + args.big().intoParsed(this.state.token.metadata.decimals).cast(tokenAmount).toFixed() + ); + signAndSendTxs([tx]); + } + // multicall with attached NEAR + else { + const tx = await dao.proposeMulticall( + description, + multicallArgs, + // if attach NEAR disabled, ignore depo amount and attach 1 yocto. + attachment.includes("near") ? args.big().intoParsed(depoUnit).cast(depo).toFixed() : "1", + args.big().intoParsed(gasUnit).cast(gas).toFixed() + ); + signAndSendTxs([tx]); + } + } + // Case2: scheduled execution => use jobs + else { + // Job with attached FT + if (attachment.includes("ft")) { + const jobCount = await multicall.getJobCount(); + + const [addJobTx, proposeJobTx] = await Promise.all([ + multicall.addJob( + // TODO: support jobs with multiple multicalls + [multicallArgs], + dateTime, + args.big().intoParsed(gasUnit).cast(gas).toFixed() + ), + dao.proposeJobActivationFT( + description, + jobCount, + tokenAddress, + args.big().intoParsed(this.state.token.metadata.decimals).cast(tokenAmount).toFixed() + ), + ]); + + signAndSendTxs([addJobTx, proposeJobTx]); + } + // Job with attached NEAR + else { + const jobCost = attachment.includes("near") + ? args.big().intoParsed(depoUnit).cast(depo).add(Multicall.CRONCAT_FEE).toFixed() + : Multicall.CRONCAT_FEE; + + const jobCount = await multicall.getJobCount(); + + const [addJobTx, proposeJobTx] = await Promise.all([ + multicall.addJob( + // TODO: support jobs with multiple multicalls + [multicallArgs], + dateTime, + args.big().intoParsed(gasUnit).cast(gas).toFixed() + ), + dao.proposeJobActivation(description, jobCount, jobCost), + ]); + + signAndSendTxs([addJobTx, proposeJobTx]); + } + } + }; + updateCopyIcon(e: React.MouseEvent) { const target = e.target as HTMLElement; if (target.innerHTML === "done") return; @@ -163,6 +245,7 @@ export class WorkflowExportUI extends Component { private tryUpdateFt(): Promise { const multicall = window.WALLET_COMPONENT.state.currentMulticall; + return new Promise((resolve) => { this.schema .check(this.state.formData, { @@ -215,19 +298,8 @@ export class WorkflowExportUI extends Component { } // normal propose multicall to DAO functionality else { - const { - attachment, - execution, - gas, - gasUnit, - depo, - depoUnit, - description, - tokenAddress, - tokenAmount, - dateTime, - } = this.state.formData; const schema = fields(this.schema); + const isProposeDisabled = wallet.schema.isBad() || schema.depo.isBad() || @@ -240,83 +312,7 @@ export class WorkflowExportUI extends Component { +

    or

    + +

    or

    +
    {showArgs ? (
    {multicallArgsText}
    - ) : ( - <> - )} + ) : null}
    {this.renderProposeButton(multicallArgs)} From 25ede10ca8afd7d0ec8c33caf8f98a0ddb9540d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20=F0=9F=A6=8A=F0=9F=AA=90=F0=9F=98=88=20Akaia?= Date: Tue, 24 Jan 2023 20:28:12 +0400 Subject: [PATCH 524/537] chore: Propose draft for #189 --- src/app/global.d.ts | 2 +- src/entities/index.ts | 2 +- src/entities/task/index.ts | 24 +++++++------------ .../task/{ui/task.card.jsx => task.jsx} | 8 +++---- .../{ui/task.cards-list.jsx => task.ui.jsx} | 22 ++++++++--------- .../{ui/task.cards-list.scss => task.ui.scss} | 12 ++++++++-- src/entities/task/ui/task.card.scss | 10 -------- src/features/index.ts | 2 +- src/features/propose-automation/index.ts | 5 ++++ .../propose-automation.ui.scss} | 2 +- .../propose-automation.ui.tsx} | 22 ++++++++--------- src/features/workflow-export/index.ts | 5 ---- src/pages/app/app-page.ui.jsx | 12 +++++----- src/shared/lib/persistent.ts | 4 ++-- src/shared/lib/wallet.ts | 4 ++-- ...r.params.ts => automation-tools.params.ts} | 2 +- ...near-protocol.params.ts => near.config.ts} | 2 +- .../ui/design/column/column.jsx} | 10 ++++---- .../ui/design/column/column.scss} | 0 src/shared/ui/design/column/index.ts | 1 + src/shared/ui/design/index.ts | 3 +++ .../automation-tools.ui.jsx} | 22 ++++++++--------- .../automation-tools.ui.scss} | 2 +- src/widgets/automation-tools/index.ts | 9 +++++++ src/widgets/index.ts | 2 +- src/widgets/workflow-tools/index.ts | 9 ------- 26 files changed, 97 insertions(+), 101 deletions(-) rename src/entities/task/{ui/task.card.jsx => task.jsx} (98%) rename src/entities/task/{ui/task.cards-list.jsx => task.ui.jsx} (85%) rename src/entities/task/{ui/task.cards-list.scss => task.ui.scss} (83%) delete mode 100644 src/entities/task/ui/task.card.scss create mode 100644 src/features/propose-automation/index.ts rename src/features/{workflow-export/workflow-export.ui.scss => propose-automation/propose-automation.ui.scss} (99%) rename src/features/{workflow-export/workflow-export.ui.tsx => propose-automation/propose-automation.ui.tsx} (96%) delete mode 100644 src/features/workflow-export/index.ts rename src/shared/params/{workflow-editor.params.ts => automation-tools.params.ts} (98%) rename src/shared/params/{near-protocol.params.ts => near.config.ts} (97%) rename src/{entities/task/ui/task.sequence.jsx => shared/ui/design/column/column.jsx} (94%) rename src/{entities/task/ui/task.sequence.scss => shared/ui/design/column/column.scss} (100%) create mode 100644 src/shared/ui/design/column/index.ts rename src/widgets/{workflow-tools/workflow-tools.ui.jsx => automation-tools/automation-tools.ui.jsx} (76%) rename src/widgets/{workflow-tools/workflow-tools.ui.scss => automation-tools/automation-tools.ui.scss} (99%) create mode 100644 src/widgets/automation-tools/index.ts delete mode 100644 src/widgets/workflow-tools/index.ts diff --git a/src/app/global.d.ts b/src/app/global.d.ts index dd94385e..b2d4f7f2 100644 --- a/src/app/global.d.ts +++ b/src/app/global.d.ts @@ -1,7 +1,7 @@ import { NetworkId } from "@near-wallet-selector/core"; import { Component } from "react"; -import { Task, TaskCardCopy, TaskCardInfo, Wallet } from "../entities"; +import { Task, TaskCopy, TaskInfo, Wallet } from "../entities"; import { EditTask } from "../features"; import { AppPage } from "../pages/app"; import { Sidebar } from "../widgets"; diff --git a/src/entities/index.ts b/src/entities/index.ts index 3c90bdee..c9b708de 100644 --- a/src/entities/index.ts +++ b/src/entities/index.ts @@ -2,5 +2,5 @@ export { FT } from "./ft"; export { Job } from "./job"; export { MI } from "./mi"; export { NEAR } from "./near"; -export { Task } from "./task"; +export { Task, TaskTemplates } from "./task"; export { Wallet } from "./wallet"; diff --git a/src/entities/task/index.ts b/src/entities/task/index.ts index 26c28401..b46a1bbe 100644 --- a/src/entities/task/index.ts +++ b/src/entities/task/index.ts @@ -1,34 +1,28 @@ -import { TaskParams } from "./task.params"; -import { TaskCard } from "./ui/task.card"; -import { TaskCardsList } from "./ui/task.cards-list"; -import { TaskSequenceColumn } from "./ui/task.sequence"; +import { Task } from "./task"; +import { TaskTemplates } from "./task.ui"; -export class Task extends TaskParams { - public static readonly Card = TaskCard; - public static readonly CardsList = TaskCardsList; - public static readonly SequenceColumn = TaskSequenceColumn; -} +export { Task, TaskTemplates }; -type TaskCardInfo = { +type TaskInfo = { formData: object; showArgs: boolean; isEdited: boolean; options: object; }; -type TaskCardCopy = { +type TaskCopy = { from: string; to: string; - payload?: Omit; + payload?: Omit; }; declare global { interface Window { // Temporary storage for moving and cloning cards - TEMP: TaskCardInfo | null; - COPY: TaskCardCopy | null; + TEMP: TaskInfo | null; + COPY: TaskCopy | null; // List of all mounted tasks - TASKS: Array; + TASKS: Array; } } diff --git a/src/entities/task/ui/task.card.jsx b/src/entities/task/task.jsx similarity index 98% rename from src/entities/task/ui/task.card.jsx rename to src/entities/task/task.jsx index ea31f19a..002bdba1 100644 --- a/src/entities/task/ui/task.card.jsx +++ b/src/entities/task/task.jsx @@ -1,12 +1,12 @@ import React, { Component } from "react"; import { Draggable } from "react-beautiful-dnd"; -import { Family } from "../../../families"; +import { Family } from "../../families"; -import "./task.card.scss"; +import "./task.ui.scss"; /* TODO: Separate model and service from view */ -export class TaskCard extends Component { +export class Task extends Component { id; constructor(props) { @@ -338,7 +338,7 @@ export class TaskCard extends Component { > {(provided, snapshot) => (
    str.replace("_", " ").replace("-", " ").toLowerCase(); -const _TaskCardsList = "TaskCardsList"; +const _TaskTemplates = "TaskTemplates"; -export class TaskCardsList extends Component { +export class TaskTemplates extends Component { resolveDebounced = debounce((resolve) => resolve(), 400); constructor(props) { @@ -52,7 +50,7 @@ export class TaskCardsList extends Component { const menuColumn = LAYOUT.getColumns()["menu"]; return ( -
    +
    { @@ -67,7 +65,7 @@ export class TaskCardsList extends Component { }} onSubmit={() => {}} > - + {(provided) => (
    -
    - + LAYOUT.getTasks()[taskId])} diff --git a/src/entities/task/ui/task.cards-list.scss b/src/entities/task/task.ui.scss similarity index 83% rename from src/entities/task/ui/task.cards-list.scss rename to src/entities/task/task.ui.scss index 7169154f..d5c8a61c 100644 --- a/src/entities/task/ui/task.cards-list.scss +++ b/src/entities/task/task.ui.scss @@ -3,7 +3,15 @@ @use "sass/color"; @use "sass/base"; -.TaskCardsList { +.Task { + width: size.$task-width; + min-height: size.$task-height; + border-radius: size.$task-radius; + margin-bottom: size.$gap; + overflow: hidden; +} + +.TaskTemplates { @include mixin.center-items(flex-start); gap: size.$gap; @@ -33,7 +41,7 @@ .tasks-wrapper { flex: 1 1 0; box-shadow: inset 0px 0px 30px 0px rgba(color.$white, 0.1); - .TaskCard:last-of-type { + .Task:last-of-type { margin-bottom: 0 !important; } .icon { diff --git a/src/entities/task/ui/task.card.scss b/src/entities/task/ui/task.card.scss deleted file mode 100644 index 287d3cf1..00000000 --- a/src/entities/task/ui/task.card.scss +++ /dev/null @@ -1,10 +0,0 @@ -@use "sass/size"; -@use "sass/color"; - -.TaskCard { - width: size.$task-width; - min-height: size.$task-height; - border-radius: size.$task-radius; - margin-bottom: size.$gap; - overflow: hidden; -} diff --git a/src/features/index.ts b/src/features/index.ts index 2c3506a5..7d370d73 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -2,5 +2,5 @@ export { ConfigureScheduling } from "./configure-scheduling"; export { EditTask } from "./edit-task"; export { ExternalAuth } from "./external-auth"; export { ManageTokenWhitelist } from "./manage-token-whitelist"; +export { ProposeAutomation } from "./propose-automation"; export { ProposeSettings } from "./propose-settings"; -export { WorkflowExport } from "./workflow-export"; diff --git a/src/features/propose-automation/index.ts b/src/features/propose-automation/index.ts new file mode 100644 index 00000000..842b4629 --- /dev/null +++ b/src/features/propose-automation/index.ts @@ -0,0 +1,5 @@ +import { ProposeAutomationUI } from "./propose-automation.ui"; + +export class ProposeAutomation { + public static readonly UI = ProposeAutomationUI; +} diff --git a/src/features/workflow-export/workflow-export.ui.scss b/src/features/propose-automation/propose-automation.ui.scss similarity index 99% rename from src/features/workflow-export/workflow-export.ui.scss rename to src/features/propose-automation/propose-automation.ui.scss index e9dea03d..3a097620 100644 --- a/src/features/workflow-export/workflow-export.ui.scss +++ b/src/features/propose-automation/propose-automation.ui.scss @@ -4,7 +4,7 @@ @use "sass/mixin"; @use "sass/font"; -.WorkflowExport { +.ProposeAutomation { @include mixin.full; @include mixin.no-scrollbar; display: flex; diff --git a/src/features/workflow-export/workflow-export.ui.tsx b/src/features/propose-automation/propose-automation.ui.tsx similarity index 96% rename from src/features/workflow-export/workflow-export.ui.tsx rename to src/features/propose-automation/propose-automation.ui.tsx index 5f8ebf30..65785547 100644 --- a/src/features/workflow-export/workflow-export.ui.tsx +++ b/src/features/propose-automation/propose-automation.ui.tsx @@ -19,7 +19,7 @@ import { signAndSendTxs } from "../../shared/lib/wallet"; import { DateTimePicker } from "../../shared/ui/design"; import { ChoiceField, TextField, UnitField } from "../../shared/ui/form"; -import "./workflow-export.ui.scss"; +import "./propose-automation.ui.scss"; const Ctx = Wallet.tryContext(); @@ -46,9 +46,9 @@ interface State { token: FungibleToken; } -const _WorkflowExport = "WorkflowExport"; +const _ProposeAutomation = "ProposeAutomation"; -export class WorkflowExportUI extends Component { +export class ProposeAutomationUI extends Component { static contextType = Ctx; declare context: ContextType; @@ -278,7 +278,7 @@ export class WorkflowExportUI extends Component { if (!walletSelector.isSignedIn()) { return ( -

    or

    - -

    or

    -
    ; interface ConfigureSchedulingUIProps extends Omit, "onChange"> { @@ -53,7 +51,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config return ( , "className" method: "dao" | "multicall"; } -const _ExtAuthDialog = "ExtAuthDialog"; - export const ExtAuthDialog = ({ className, method, onClose, open, title }: IExtAuthDialog) => { const dAppURL = useMemo(() => new ArgsString(""), []); @@ -39,13 +37,13 @@ export const ExtAuthDialog = ({ className, method, onClose, open, title }: IExtA return ( window.open(requestURL, "_blank")} {...{ onClose, open, title }} > -
      +
        {ExtAuthParams.stepByStepGuide.map((step) => (
      • diff --git a/src/features/manage-token-whitelist/manage-token-whitelist.ui.tsx b/src/features/manage-token-whitelist/manage-token-whitelist.ui.tsx index ca786b4c..6d046785 100644 --- a/src/features/manage-token-whitelist/manage-token-whitelist.ui.tsx +++ b/src/features/manage-token-whitelist/manage-token-whitelist.ui.tsx @@ -12,10 +12,8 @@ import { MI } from "../../entities"; import "./manage-token-whitelist.ui.scss"; -const _ManageTokenWhitelist = "ManageTokenWhitelist"; - type MITokenWhitelistDiff = Pick< - Arguments[0], + Arguments<(typeof Multicall)["configDiffToProposalActions"]>[0], "addTokens" | "removeTokens" >; @@ -84,7 +82,7 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag validationSchema={schema} {...{ onReset, onSubmit }} > - + @@ -106,7 +104,7 @@ export const ManageTokenWhitelistUI = ({ disabled, onEdit, resetTrigger }: Manag : void null, }, }} - className={`${_ManageTokenWhitelist}-controls`} + className="ManageTokenWhitelist-controls" headerSlots={{ end: editModeEnabled ? ( diff --git a/src/features/propose-settings/propose-settings.ui.tsx b/src/features/propose-settings/propose-settings.ui.tsx index 06ac9315..d14ffdaf 100644 --- a/src/features/propose-settings/propose-settings.ui.tsx +++ b/src/features/propose-settings/propose-settings.ui.tsx @@ -14,9 +14,7 @@ import { MI } from "../../entities"; import "./propose-settings.ui.scss"; -const _ProposeSettings = "ProposeSettings"; - -type MISettingsDiff = Arguments[0]; +type MISettingsDiff = Arguments<(typeof Multicall)["configDiffToProposalActions"]>[0]; export interface ProposeSettingsUIProps extends HTMLProps { dao: SputnikDAO; @@ -59,38 +57,36 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on > -

        +

        {disabled ? "Your account has no permission to create proposals" : "Start editing to draft changes proposal"}

        -
        +
        {Object.entries(MI.SettingsDiffMeta).map( ([key, { color, description }]) => diff[key as keyof MISettingsDiff].length > 0 && (
        -

        - {description + ":"} -

        +

        {description + ":"}

        -
          +
            {(Array.isArray(diff[key as keyof MISettingsDiff]) ? Array.from(diff[key as keyof MISettingsDiff]) : [diff[key as keyof MISettingsDiff]] ).map((data) => (
          • @@ -105,7 +101,7 @@ export const ProposeSettingsUI = ({ className, dao, diff, disabled, editMode, on )}
        - +
        str.replace("_", " ").replace("-", " ").toLowerCase(); -const _WorkspaceBuilder = "WorkspaceBuilder"; - export class WorkspaceBuilder extends Component { resolveDebounced = debounce((resolve) => resolve(), 400); @@ -52,7 +50,7 @@ export class WorkspaceBuilder extends Component { const menuColumn = LAYOUT.getColumns()["menu"]; return ( -
        +
        { @@ -67,7 +65,7 @@ export class WorkspaceBuilder extends Component { }} onSubmit={() => {}} > - + {(provided) => (
        -
        +
        { static contextType = Ctx; declare context: ContextType; @@ -195,7 +193,7 @@ export class WorkspaceExport extends Component { if (!walletSelector.isSignedIn()) { return ( ); diff --git a/src/shared/ui/design/data-inspector/data-inspector.tsx b/src/shared/ui/design/data-inspector/data-inspector.tsx index 5fa427bd..797a7dd6 100644 --- a/src/shared/ui/design/data-inspector/data-inspector.tsx +++ b/src/shared/ui/design/data-inspector/data-inspector.tsx @@ -6,8 +6,6 @@ import { ModuleContext as ModuleContext } from "./data-inspector.params"; import { DataInspectorNode } from "./data-inspector.node"; import "./data-inspector.scss"; -const _DataInspector = "DataInspector"; - interface DataInspectorProps extends ComponentProps { classes?: { root?: string; body?: string; label?: string }; expanded?: boolean; @@ -31,17 +29,17 @@ export const DataInspector = ({ classes, expanded = false, expandLevel = 1, labe return (
        {label ?? dynamicLabel} -
        +
        , @@ -34,8 +32,8 @@ export const DateTimePicker = ({ }: DateTimePickerProps) => ( ( )} {...props} diff --git a/src/shared/ui/design/dialog/dialog.tsx b/src/shared/ui/design/dialog/dialog.tsx index 558ccd6b..33679f78 100644 --- a/src/shared/ui/design/dialog/dialog.tsx +++ b/src/shared/ui/design/dialog/dialog.tsx @@ -24,8 +24,6 @@ interface DialogProps extends PropsWithChildren { title: string; } -const _Dialog = "Dialog"; - export const Dialog = ({ cancelRename, children, @@ -40,13 +38,13 @@ export const Dialog = ({ title, }: DialogProps) => ( - {title} - {children} + {title} + {children} - +
    - + {header.map((headerCell, index) => ( {headerCell} @@ -103,7 +101,7 @@ export const Table = ({ )} {compactModeRequired && ( -
    +
    {rows && rows.map((row, index) => ( { invertedColors?: boolean; onClick: VoidFunction; @@ -14,7 +11,7 @@ export interface TabsItemButtonProps extends React.HTMLAttributes ( - , + +
    + {job.multicalls.map((multicall, idx) => ( +
    + #{idx} + + + + setTimeout(() => window.LAYOUT.fromJSON(multicall.calls), 0)} + > + Open in Editor + +
    + ))} +
    +
    , ], id: id.toString(), @@ -91,7 +99,7 @@ export const JobEntriesTable = ({ className, ...jobServiceInputs }: IJobEntriesT return (
    Date: Thu, 9 Feb 2023 07:20:17 +0400 Subject: [PATCH 531/537] chore: Format --- src/entities/job/job.service.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/entities/job/job.service.ts b/src/entities/job/job.service.ts index e6573250..d6137847 100644 --- a/src/entities/job/job.service.ts +++ b/src/entities/job/job.service.ts @@ -20,14 +20,7 @@ export class JobService { await multicallInstance .getJobs() .then((data) => ({ - data: data.reduce( - (jobsIndexedById, job) => ({ - ...jobsIndexedById, - [job.id]: JobLib.toDecoded(job), - }), - {} - ), - + data: data.reduce((jobs, job) => ({ ...jobs, [job.id]: JobLib.toDecoded(job) }), {}), error: null, loading: false, })) From f5cedecc9b15e52cad94d99662346882a09e6f07 Mon Sep 17 00:00:00 2001 From: "Akaia Carina | root.akaia.near#0878" Date: Fri, 10 Mar 2023 20:58:06 +0400 Subject: [PATCH 532/537] fix: Use strings for job bond amount value --- src/entities/mi/mi.params.ts | 2 +- .../configure-scheduling/configure-scheduling.ui.tsx | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/entities/mi/mi.params.ts b/src/entities/mi/mi.params.ts index 9a8a4725..f6b18594 100644 --- a/src/entities/mi/mi.params.ts +++ b/src/entities/mi/mi.params.ts @@ -7,7 +7,7 @@ export class MIParams { */ public static readonly minBalanceYocto = toYocto(1); - public static readonly minJobBondNEAR = 0.001; + public static readonly minJobBondNEAR = "0.001"; public static readonly SettingsDiffMeta = { addTokens: { diff --git a/src/features/configure-scheduling/configure-scheduling.ui.tsx b/src/features/configure-scheduling/configure-scheduling.ui.tsx index 0d3bfedb..d0be6e33 100644 --- a/src/features/configure-scheduling/configure-scheduling.ui.tsx +++ b/src/features/configure-scheduling/configure-scheduling.ui.tsx @@ -26,7 +26,7 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config mi = useContext(MI.Context); const schema = args.object().shape({ - jobBond: args.string().default(() => (mi.loading ? MI.minJobBondNEAR.toString() : toNEAR(mi.data.jobBond))), + jobBond: args.string().default(() => (mi.loading ? MI.minJobBondNEAR : toNEAR(mi.data.jobBond))), }); type Schema = InferType; @@ -92,15 +92,11 @@ export const ConfigureSchedulingUI = ({ disabled, onEdit, resetTrigger }: Config content: [ , ], }, From 592e880af2946c4def2816612059683ecb9e6d08 Mon Sep 17 00:00:00 2001 From: "Akaia Carina | root.akaia.near#0878" Date: Mon, 10 Apr 2023 04:07:38 +0400 Subject: [PATCH 533/537] fix: No point in lazy loading of the root page --- src/app/index.tsx | 6 +++--- src/pages/app/app-page.ui.jsx | 15 +++++---------- src/pages/app/index.ts | 4 +--- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/app/index.tsx b/src/app/index.tsx index cca8fdb4..5a9a8665 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -32,9 +32,7 @@ createRoot(appMountPoint).render( element={ <> - Loading...}> - - + } @@ -45,9 +43,11 @@ createRoot(appMountPoint).render( element={ <> + Loading...}> + } diff --git a/src/pages/app/app-page.ui.jsx b/src/pages/app/app-page.ui.jsx index 88b6dfe4..ea205bd3 100644 --- a/src/pages/app/app-page.ui.jsx +++ b/src/pages/app/app-page.ui.jsx @@ -1,12 +1,7 @@ -import React from "react"; import { Workspace } from "../../widgets"; -export default class AppPage extends React.Component { - render() { - return ( - <> - - - ); - } -} +export const AppPage = () => ( + <> + + +); diff --git a/src/pages/app/index.ts b/src/pages/app/index.ts index 32b86fc1..120c1a2c 100644 --- a/src/pages/app/index.ts +++ b/src/pages/app/index.ts @@ -1,3 +1 @@ -import { lazy } from "react"; - -export const AppPage = lazy(() => import("./app-page.ui")); +export { AppPage } from "./app-page.ui"; From a7e389ddfa026ead31db2c07fae57f41b5c51e31 Mon Sep 17 00:00:00 2001 From: "Akaia Carina | root.akaia.near#0878" Date: Mon, 10 Apr 2023 05:22:50 +0400 Subject: [PATCH 534/537] fix: Incorrect proposal creation permission status --- .../workspace-export/workspace-export.ui.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/features/workspace-export/workspace-export.ui.tsx b/src/features/workspace-export/workspace-export.ui.tsx index 138bab90..3412b85b 100644 --- a/src/features/workspace-export/workspace-export.ui.tsx +++ b/src/features/workspace-export/workspace-export.ui.tsx @@ -187,7 +187,11 @@ export class WorkspaceExport extends Component { renderProposeButton(multicallArgs: MulticallArgs) { const { selector: walletSelector } = this.context!; - const wallet = window.WALLET_COMPONENT; + + window.WALLET_COMPONENT.schema.check({ + dao: STORAGE.addresses.dao, + user: this.context?.accountId ?? "", + }); // if user not logged in, button will do login. if (!walletSelector.isSignedIn()) { @@ -201,13 +205,13 @@ export class WorkspaceExport extends Component { ); } // if specified DAO not have a multicall instance, button will re-direct to DAO page so they can get an instance. - else if (fields(wallet.schema, "dao").noMulticall.isBad()) { + else if (fields(window.WALLET_COMPONENT.schema, "dao").noMulticall.isBad()) { return ( ); } @@ -227,7 +231,7 @@ export class WorkspaceExport extends Component { } = this.state.formData; const schema = fields(this.schema); const isProposeDisabled = - wallet.schema.isBad() || + window.WALLET_COMPONENT.schema.isBad() || schema.depo.isBad() || schema.description.isBad() || schema.hasErrors.isBad() || @@ -317,7 +321,7 @@ export class WorkspaceExport extends Component { }} > {`Propose on ${STORAGE.addresses.dao}`} - {wallet.schema.isBad() ?

    {wallet.schema.message()}

    : <>} + {window.WALLET_COMPONENT.schema.isBad() ?

    {window.WALLET_COMPONENT.schema.message()}

    : <>} ); } From c1ca9f23f6a45c6762d4bac849405993a0e53b23 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Wed, 12 Apr 2023 15:01:19 +0200 Subject: [PATCH 535/537] Revert "fix: No point in lazy loading of the root page" This reverts commit 592e880af2946c4def2816612059683ecb9e6d08. --- src/app/index.tsx | 6 +++--- src/pages/app/app-page.ui.jsx | 15 ++++++++++----- src/pages/app/index.ts | 4 +++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/app/index.tsx b/src/app/index.tsx index 5a9a8665..cca8fdb4 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -32,7 +32,9 @@ createRoot(appMountPoint).render( element={ <> - + Loading...}> + + } @@ -43,11 +45,9 @@ createRoot(appMountPoint).render( element={ <> - Loading...}> - } diff --git a/src/pages/app/app-page.ui.jsx b/src/pages/app/app-page.ui.jsx index ea205bd3..88b6dfe4 100644 --- a/src/pages/app/app-page.ui.jsx +++ b/src/pages/app/app-page.ui.jsx @@ -1,7 +1,12 @@ +import React from "react"; import { Workspace } from "../../widgets"; -export const AppPage = () => ( - <> - - -); +export default class AppPage extends React.Component { + render() { + return ( + <> + + + ); + } +} diff --git a/src/pages/app/index.ts b/src/pages/app/index.ts index 120c1a2c..32b86fc1 100644 --- a/src/pages/app/index.ts +++ b/src/pages/app/index.ts @@ -1 +1,3 @@ -export { AppPage } from "./app-page.ui"; +import { lazy } from "react"; + +export const AppPage = lazy(() => import("./app-page.ui")); From 9f112dc79cf81344012d6b17866b83e03a8b67f8 Mon Sep 17 00:00:00 2001 From: mohamedalichelbi Date: Wed, 12 Apr 2023 15:52:43 +0200 Subject: [PATCH 536/537] app page ui was renamed to workspace --- src/widgets/workspace/workspace.ui.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/workspace/workspace.ui.jsx b/src/widgets/workspace/workspace.ui.jsx index 2b95f098..2ad50bc3 100644 --- a/src/widgets/workspace/workspace.ui.jsx +++ b/src/widgets/workspace/workspace.ui.jsx @@ -53,7 +53,7 @@ export class Workspace extends Component { deleteTask = (taskId) => { const layout = STORAGE.layout; - const { columnId, taskIndex } = AppPageUI.findTaskCoordinates(taskId); + const { columnId, taskIndex } = Workspace.findTaskCoordinates(taskId); if (columnId == undefined || taskIndex == undefined) { console.error("Task not found"); @@ -81,7 +81,7 @@ export class Workspace extends Component { duplicateTask = (taskId) => { const layout = STORAGE.layout; - const { columnId, taskIndex } = AppPageUI.findTaskCoordinates(taskId); + const { columnId, taskIndex } = Workspace.findTaskCoordinates(taskId); if (columnId == undefined || taskIndex == undefined) { console.error("Task not found"); From f61e0bdaa063d988290dc7ae5e0ebd6cae81e356 Mon Sep 17 00:00:00 2001 From: "Akaia Carina | root.akaia.near#0878" Date: Wed, 12 Apr 2023 18:11:22 +0400 Subject: [PATCH 537/537] fix: Use correct `ChangeConfig` parameter value --- src/shared/lib/contracts/sputnik-dao.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/lib/contracts/sputnik-dao.ts b/src/shared/lib/contracts/sputnik-dao.ts index 54274262..07be4e02 100644 --- a/src/shared/lib/contracts/sputnik-dao.ts +++ b/src/shared/lib/contracts/sputnik-dao.ts @@ -134,7 +134,7 @@ type Proposal = { }; const ProposalKindPolicyLabel: Record = { - ChangeConfig: "context", + ChangeConfig: "config", ChangePolicy: "policy", AddMemberToRole: "add_member_to_role", RemoveMemberFromRole: "remove_member_from_role",