utils#slugifyPreserveDashes TypeScript Examples

The following examples show how to use utils#slugifyPreserveDashes. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: cosmos_form.tsx    From commonwealth with GNU General Public License v3.0 4 votes vote down vote up
view() {
    return (
      <div class="CreateCommunityForm">
        <InputRow
          title="RPC URL"
          defaultValue={this.state.form.nodeUrl}
          placeholder="http://my-rpc.cosmos-chain.com:26657/"
          onChangeHandler={async (v) => {
            this.state.form.nodeUrl = v;
          }}
        />
        <InputRow
          title="Name"
          defaultValue={this.state.form.name}
          onChangeHandler={(v) => {
            this.state.form.name = v;
            this.state.form.id = slugifyPreserveDashes(v);
          }}
        />
        <IdRow id={this.state.form.id} />
        <InputRow
          title="Symbol"
          defaultValue={this.state.form.symbol}
          placeholder="XYZ"
          onChangeHandler={(v) => {
            this.state.form.symbol = v;
          }}
        />
        <InputRow
          title="Bech32 Prefix"
          defaultValue={this.state.form.bech32Prefix}
          placeholder="cosmos"
          onChangeHandler={async (v) => {
            this.state.form.bech32Prefix = v;
          }}
        />
        <InputRow
          title="Decimals"
          defaultValue={`${this.state.form.decimals}`}
          disabled={true}
          onChangeHandler={(v) => {
            this.state.form.decimals = +v;
          }}
        />
        {/* TODO: add alt wallet URL field */}
        {...defaultChainRows(this.state.form)}
        <CWButton
          label="Save changes"
          disabled={this.state.saving}
          onclick={async () => {
            const {
              altWalletUrl,
              bech32Prefix,
              chainString,
              ethChainId,
              nodeUrl,
            } = this.state.form;
            this.state.saving = true;
            mixpanelBrowserTrack({
              event: MixpanelCommunityCreationEvent.CREATE_COMMUNITY_ATTEMPTED,
              chainBase: null,
              isCustomDomain: app.isCustomDomain(),
              communityType: null,
            });
            try {
              const res = await $.post(`${app.serverUrl()}/createChain`, {
                alt_wallet_url: altWalletUrl,
                base: ChainBase.CosmosSDK,
                bech32_prefix: bech32Prefix,
                chain_string: chainString,
                eth_chain_id: ethChainId,
                jwt: app.user.jwt,
                network: this.state.form.id,
                node_url: nodeUrl,
                type: ChainType.Chain,
                ...this.state.form,
              });
              await initAppState(false);
              m.route.set(`/${res.result.chain?.id}`);
            } catch (err) {
              this.state.error =
                err.responseJSON?.error ||
                'Creating new Cosmos community failed';
            } finally {
              this.state.saving = false;
              m.redraw();
            }
          }}
        />
        <ValidationRow error={this.state.error} />
      </div>
    );
  }
Example #2
Source File: erc20_form.tsx    From commonwealth with GNU General Public License v3.0 4 votes vote down vote up
view(vnode) {
    const validAddress = isAddress(this.state.form.address);
    const disableField = !validAddress || !this.state.loaded;

    const updateTokenForum = async () => {
      if (!this.state.form.address || !this.state.form.ethChainId) return;
      this.state.status = '';
      this.state.error = '';
      this.state.loading = true;
      const args = {
        address: this.state.form.address,
        chain_id: this.state.form.ethChainId,
        chain_network: ChainNetwork.ERC20,
        url: this.state.form.nodeUrl,
        allowUncached: true,
      };
      try {
        console.log('Querying backend for token data');
        const res = await $.get(`${app.serverUrl()}/getTokenForum`, args);
        if (res.status === 'Success') {
          if (res?.token?.name) {
            this.state.form.name = res.token.name || '';
            this.state.form.id = res.token.id && slugify(res.token.id);
            this.state.form.symbol = res.token.symbol || '';
            this.state.form.decimals = +res.token.decimals || 18;
            this.state.form.iconUrl = res.token.icon_url || '';
            if (this.state.form.iconUrl.startsWith('/')) {
              this.state.form.iconUrl = `https://commonwealth.im${this.state.form.iconUrl}`;
            }
            this.state.form.description = res.token.description || '';
            this.state.form.website = res.token.website || '';
            this.state.form.discord = res.token.discord || '';
            this.state.form.element = res.token.element || '';
            this.state.form.telegram = res.token.telegram || '';
            this.state.form.github = res.token.github || '';
            this.state.status = 'Success!';
          } else {
            // attempt to query ERC20Detailed token info from chain
            console.log('Querying chain for ERC info');
            const provider = new Web3.providers.WebsocketProvider(args.url);
            try {
              const ethersProvider = new providers.Web3Provider(provider);
              const contract = IERC20Metadata__factory.connect(
                args.address,
                ethersProvider
              );
              const name = await contract.name();
              const symbol = await contract.symbol();
              const decimals = await contract.decimals();
              this.state.form.name = name || '';
              this.state.form.id = name && slugify(name);
              this.state.form.symbol = symbol || '';
              this.state.form.decimals = decimals || 18;
              this.state.status = 'Success!';
            } catch (e) {
              this.state.form.name = '';
              this.state.form.id = '';
              this.state.form.symbol = '';
              this.state.form.decimals = 18;
              this.state.status = 'Verified token but could not load metadata.';
            }
            this.state.form.iconUrl = '';
            this.state.form.description = '';
            this.state.form.website = '';
            this.state.form.discord = '';
            this.state.form.element = '';
            this.state.form.telegram = '';
            this.state.form.github = '';
            provider.disconnect(1000, 'finished');
          }
          this.state.loaded = true;
        } else {
          this.state.error = res.message || 'Failed to load Token Information';
        }
      } catch (err) {
        this.state.error =
          err.responseJSON?.error || 'Failed to load Token Information';
      }
      this.state.loading = false;
      m.redraw();
    };

    return (
      <div class="CreateCommunityForm">
        {...ethChainRows(vnode.attrs, this.state.form)}
        <CWButton
          label="Populate fields"
          disabled={
            this.state.saving ||
            !validAddress ||
            !this.state.form.ethChainId ||
            this.state.loading
          }
          onclick={async () => {
            await updateTokenForum();
          }}
        />
        <ValidationRow error={this.state.error} status={this.state.status} />
        <InputRow
          title="Name"
          defaultValue={this.state.form.name}
          disabled={disableField}
          onChangeHandler={(v) => {
            this.state.form.name = v;
            this.state.form.id = slugifyPreserveDashes(v);
          }}
        />
        <IdRow id={this.state.form.id} />
        <InputRow
          title="Symbol"
          disabled={disableField}
          defaultValue={this.state.form.symbol}
          placeholder="XYZ"
          onChangeHandler={(v) => {
            this.state.form.symbol = v;
          }}
        />
        {...defaultChainRows(this.state.form, disableField)}
        <CWButton
          label="Save changes"
          disabled={this.state.saving || !validAddress || !this.state.loaded}
          onclick={async () => {
            const { altWalletUrl, chainString, ethChainId, nodeUrl } =
              this.state.form;
            this.state.saving = true;
            mixpanelBrowserTrack({
              event: MixpanelCommunityCreationEvent.CREATE_COMMUNITY_ATTEMPTED,
              chainBase: null,
              isCustomDomain: app.isCustomDomain(),
              communityType: null,
            });
            try {
              const res = await $.post(`${app.serverUrl()}/createChain`, {
                alt_wallet_url: altWalletUrl,
                base: ChainBase.Ethereum,
                chain_string: chainString,
                eth_chain_id: ethChainId,
                jwt: app.user.jwt,
                network: ChainNetwork.ERC20,
                node_url: nodeUrl,
                type: ChainType.Token,
                ...this.state.form,
              });
              await initAppState(false);
              m.route.set(`/${res.result.chain?.id}`);
            } catch (err) {
              notifyError(
                err.responseJSON?.error || 'Creating new ERC20 community failed'
              );
            } finally {
              this.state.saving = false;
            }
          }}
        />
      </div>
    );
  }
Example #3
Source File: erc721_form.tsx    From commonwealth with GNU General Public License v3.0 4 votes vote down vote up
view(vnode) {
    const validAddress = isAddress(this.state.form.address);
    const disableField = !validAddress || !this.state.loaded;

    const updateTokenForum = async () => {
      if (!this.state.form.address || !this.state.form.ethChainId) return;
      this.state.status = '';
      this.state.error = '';
      this.state.loading = true;
      const args = {
        address: this.state.form.address,
        chain_id: this.state.form.ethChainId,
        chain_network: ChainNetwork.ERC721,
        url: this.state.form.nodeUrl,
        allowUncached: true,
      };
      try {
        console.log('Querying backend for token data');
        const res = await $.get(`${app.serverUrl()}/getTokenForum`, args);
        if (res.status === 'Success') {
          if (res?.token?.name) {
            this.state.form.name = res.token.name || '';
            this.state.form.id = res.token.id && slugify(res.token.id);
            this.state.form.symbol = res.token.symbol || '';
            this.state.form.iconUrl = res.token.icon_url || '';
            if (this.state.form.iconUrl.startsWith('/')) {
              this.state.form.iconUrl = `https://commonwealth.im${this.state.form.iconUrl}`;
            }
            this.state.form.description = res.token.description || '';
            this.state.form.website = res.token.website || '';
            this.state.form.discord = res.token.discord || '';
            this.state.form.element = res.token.element || '';
            this.state.form.telegram = res.token.telegram || '';
            this.state.form.github = res.token.github || '';
            this.state.status = 'Success!';
          } else {
            // attempt to query ERC721Detailed token info from chain
            console.log('Querying chain for ERC info');
            const provider = new Web3.providers.WebsocketProvider(args.url);
            try {
              const ethersProvider = new providers.Web3Provider(provider);
              const contract = IERC721Metadata__factory.connect(
                args.address,
                ethersProvider
              );
              const name = await contract.name();
              const symbol = await contract.symbol();
              const decimals = await contract.decimals();
              this.state.form.name = name || '';
              this.state.form.id = name && slugify(name);
              this.state.form.symbol = symbol || '';
              this.state.status = 'Success!';
            } catch (e) {
              this.state.form.name = '';
              this.state.form.id = '';
              this.state.form.symbol = '';
              this.state.status = 'Verified token but could not load metadata.';
            }
            this.state.form.iconUrl = '';
            this.state.form.description = '';
            this.state.form.website = '';
            this.state.form.discord = '';
            this.state.form.element = '';
            this.state.form.telegram = '';
            this.state.form.github = '';
            provider.disconnect(1000, 'finished');
          }
          this.state.loaded = true;
        } else {
          this.state.error = res.message || 'Failed to load Token Information';
        }
      } catch (err) {
        this.state.error =
          err.responseJSON?.error || 'Failed to load Token Information';
      }
      this.state.loading = false;
      m.redraw();
    };

    return (
      <div class="CreateCommunityForm">
        {...ethChainRows(vnode.attrs, this.state.form)}
        <CWButton
          label="Populate fields"
          disabled={
            this.state.saving ||
            !validAddress ||
            !this.state.form.ethChainId ||
            this.state.loading
          }
          onclick={async () => {
            await updateTokenForum();
          }}
        />
        <ValidationRow error={this.state.error} status={this.state.status} />
        <InputRow
          title="Name"
          defaultValue={this.state.form.name}
          disabled={disableField}
          onChangeHandler={(v) => {
            this.state.form.name = v;
            this.state.form.id = slugifyPreserveDashes(v);
          }}
        />
        <IdRow id={this.state.form.id} />
        <InputRow
          title="Symbol"
          disabled={disableField}
          defaultValue={this.state.form.symbol}
          placeholder="XYZ"
          onChangeHandler={(v) => {
            this.state.form.symbol = v;
          }}
        />
        {...defaultChainRows(this.state.form, disableField)}
        <CWButton
          label="Save changes"
          disabled={this.state.saving || !validAddress || !this.state.loaded}
          onclick={async () => {
            const { altWalletUrl, chainString, ethChainId, nodeUrl } =
              this.state.form;
            this.state.saving = true;
            mixpanelBrowserTrack({
              event: MixpanelCommunityCreationEvent.CREATE_COMMUNITY_ATTEMPTED,
              chainBase: null,
              isCustomDomain: app.isCustomDomain(),
              communityType: null,
            });

            try {
              const res = await $.post(`${app.serverUrl()}/createChain`, {
                alt_wallet_url: altWalletUrl,
                base: ChainBase.Ethereum,
                chain_string: chainString,
                eth_chain_id: ethChainId,
                jwt: app.user.jwt,
                network: ChainNetwork.ERC721,
                node_url: nodeUrl,
                type: ChainType.Token,
                ...this.state.form,
              });
              await initAppState(false);
              m.route.set(`/${res.result.chain?.id}`);
            } catch (err) {
              notifyError(
                err.responseJSON?.error ||
                  'Creating new ERC721 community failed'
              );
            } finally {
              this.state.saving = false;
            }
          }}
        />
      </div>
    );
  }
Example #4
Source File: eth_dao_form.tsx    From commonwealth with GNU General Public License v3.0 4 votes vote down vote up
view(vnode) {
    const validAddress = isAddress(this.state.form.address);
    const disableField = !validAddress || !this.state.loaded;

    const updateDAO = async () => {
      if (
        !this.state.form.address ||
        !this.state.form.ethChainId ||
        !this.state.form.nodeUrl
      )
        return;
      this.state.loading = true;
      this.state.status = '';
      this.state.error = '';
      try {
        if (this.state.form.network === ChainNetwork.Compound) {
          const provider = new Web3.providers.WebsocketProvider(
            this.state.form.nodeUrl
          );
          const compoundApi = new CompoundAPI(
            null,
            this.state.form.address,
            provider
          );
          await compoundApi.init(this.state.form.tokenName);
          if (!compoundApi.Token) {
            throw new Error(
              'Could not find governance token. Is "Token Name" field valid?'
            );
          }
          const govType = GovernorType[compoundApi.govType];
          const tokenType = GovernorTokenType[compoundApi.tokenType];
          this.state.status = `Found ${govType} with token type ${tokenType}`;
        } else if (this.state.form.network === ChainNetwork.Aave) {
          const provider = new Web3.providers.WebsocketProvider(
            this.state.form.nodeUrl
          );
          const aaveApi = new AaveApi(
            IAaveGovernanceV2__factory.connect,
            this.state.form.address,
            provider
          );
          await aaveApi.init();
          this.state.status = `Found Aave type DAO`;
        } else {
          throw new Error('invalid chain network');
        }
      } catch (e) {
        this.state.error = e.message;
        this.state.loading = false;
        m.redraw();
        return;
      }
      this.state.loaded = true;
      this.state.loading = false;
      m.redraw();
    };

    return (
      <div class="CreateCommunityForm">
        {...ethChainRows(vnode.attrs, this.state.form)}
        <SelectRow
          title="DAO Type"
          options={[ChainNetwork.Aave, ChainNetwork.Compound]}
          value={this.state.form.network}
          onchange={(value) => {
            this.state.form.network = value;
            this.state.loaded = false;
          }}
        />
        {this.state.form.network === ChainNetwork.Compound && (
          <InputRow
            title="Token Name (Case Sensitive)"
            defaultValue={this.state.form.tokenName}
            onChangeHandler={(v) => {
              this.state.form.tokenName = v;
              this.state.loaded = false;
            }}
          />
        )}
        <CWButton
          label="Test contract"
          disabled={
            this.state.saving ||
            !validAddress ||
            !this.state.form.ethChainId ||
            this.state.loading
          }
          onclick={async () => {
            await updateDAO();
          }}
        />
        <ValidationRow error={this.state.error} status={this.state.status} />
        <InputRow
          title="Name"
          defaultValue={this.state.form.name}
          disabled={disableField}
          onChangeHandler={(v) => {
            this.state.form.name = v;
            this.state.form.id = slugifyPreserveDashes(v);
          }}
        />
        <IdRow id={this.state.form.id} />
        <InputRow
          title="Symbol"
          disabled={disableField}
          defaultValue={this.state.form.symbol}
          placeholder="XYZ"
          onChangeHandler={(v) => {
            this.state.form.symbol = v;
          }}
        />
        {...defaultChainRows(this.state.form, disableField)}
        <CWButton
          label="Save changes"
          disabled={this.state.saving || !validAddress || !this.state.loaded}
          onclick={async () => {
            const { chainString, ethChainId, nodeUrl, tokenName } =
              this.state.form;
            this.state.saving = true;
            mixpanelBrowserTrack({
              event: MixpanelCommunityCreationEvent.CREATE_COMMUNITY_ATTEMPTED,
              chainBase: null,
              isCustomDomain: app.isCustomDomain(),
              communityType: null,
            });
            try {
              const res = await $.post(`${app.serverUrl()}/createChain`, {
                base: ChainBase.Ethereum,
                chain_string: chainString,
                eth_chain_id: ethChainId,
                jwt: app.user.jwt,
                node_url: nodeUrl,
                token_name: tokenName,
                type: ChainType.DAO,
                ...this.state.form,
              });
              await initAppState(false);
              // TODO: notify about needing to run event migration
              m.route.set(`/${res.result.chain?.id}`);
            } catch (err) {
              notifyError(
                err.responseJSON?.error ||
                  'Creating new ETH DAO community failed'
              );
            } finally {
              this.state.saving = false;
            }
          }}
        />
      </div>
    );
  }
Example #5
Source File: spl_token_form.tsx    From commonwealth with GNU General Public License v3.0 4 votes vote down vote up
view() {
    const disableField = !this.state.loaded;

    const updateTokenForum = async () => {
      this.state.status = '';
      this.state.error = '';
      let mintPubKey: solw3.PublicKey;
      try {
        mintPubKey = new solw3.PublicKey(this.state.form.mint);
      } catch (e) {
        this.state.error = 'Invalid mint address';
        return false;
      }
      if (!mintPubKey) return;
      this.state.loading = true;
      try {
        const url = solw3.clusterApiUrl(this.state.form.cluster);
        const connection = new solw3.Connection(url);
        const supply = await connection.getTokenSupply(mintPubKey);
        const { decimals, amount } = supply.value;
        this.state.form.decimals = decimals;
        this.state.loaded = true;
        this.state.status = `Found ${amount} supply!`;
      } catch (err) {
        this.state.error = `Error: ${err.message}` || 'Failed to load token';
      }
      this.state.loading = false;
      m.redraw();
    };

    return (
      <div class="CreateCommunityForm">
        <SelectRow
          title="Cluster"
          options={['mainnet-beta', 'testnet', 'devnet']}
          value={this.state.form.cluster}
          onchange={(value) => {
            this.state.form.cluster = value;
            this.state.loaded = false;
          }}
        />
        <InputRow
          title="Mint Address"
          defaultValue={this.state.form.mint}
          placeholder="2sgDUTgTP6e9CrJtexGdba7qZZajVVHf9TiaCtS9Hp3P"
          onChangeHandler={(v) => {
            this.state.form.mint = v.trim();
            this.state.loaded = false;
          }}
        />
        <CWButton
          label="Check address"
          disabled={this.state.saving || this.state.loading}
          onclick={async () => {
            await updateTokenForum();
          }}
        />
        <ValidationRow error={this.state.error} status={this.state.status} />
        <InputRow
          title="Name"
          defaultValue={this.state.form.name}
          disabled={disableField}
          onChangeHandler={(v) => {
            this.state.form.name = v;
            this.state.form.id = slugifyPreserveDashes(v);
          }}
        />
        <IdRow id={this.state.form.id} />
        <InputRow
          title="Symbol"
          disabled={disableField}
          defaultValue={this.state.form.symbol}
          placeholder="XYZ"
          onChangeHandler={(v) => {
            this.state.form.symbol = v;
          }}
        />
        <InputRow
          title="Decimals"
          defaultValue={`${this.state.form.decimals}`}
          disabled={true}
          onChangeHandler={(v) => {
            this.state.form.decimals = +v;
          }}
        />
        {...defaultChainRows(this.state.form, disableField)}
        <CWButton
          label="Save changes"
          disabled={this.state.saving || !this.state.loaded}
          onclick={async () => {
            const { cluster, iconUrl, mint } = this.state.form;
            this.state.saving = true;
            mixpanelBrowserTrack({
              event: MixpanelCommunityCreationEvent.CREATE_COMMUNITY_ATTEMPTED,
              chainBase: null,
              isCustomDomain: app.isCustomDomain(),
              communityType: null,
            });
            try {
              const res = await $.post(`${app.serverUrl()}/createChain`, {
                address: mint,
                base: ChainBase.Solana,
                icon_url: iconUrl,
                jwt: app.user.jwt,
                network: ChainNetwork.SPL,
                node_url: cluster,
                type: ChainType.Token,
                ...this.state.form,
              });
              await initAppState(false);
              m.route.set(`/${res.result.chain?.id}`);
            } catch (err) {
              notifyError(
                err.responseJSON?.error || 'Creating new ERC20 community failed'
              );
            } finally {
              this.state.saving = false;
            }
          }}
        />
      </div>
    );
  }
Example #6
Source File: starter_community_form.tsx    From commonwealth with GNU General Public License v3.0 4 votes vote down vote up
view() {
    return (
      <div class="CreateCommunityForm">
        <InputRow
          title="Name"
          placeholder="Enter the name of your community"
          defaultValue={this.state.form.name}
          onChangeHandler={(v) => {
            this.state.form.name = v;
            this.state.form.id = slugifyPreserveDashes(v);
          }}
        />
        <IdRow id={this.state.form.id} />
        <InputRow
          title="Symbol"
          defaultValue={this.state.form.symbol}
          onChangeHandler={(v) => {
            this.state.form.symbol = v;
          }}
        />
        <SelectRow
          title="Base Chain"
          options={['cosmos', 'ethereum', 'near']}
          value={this.state.form.base}
          onchange={(value) => {
            this.state.form.base = value;
            mixpanelBrowserTrack({
              event: MixpanelCommunityCreationEvent.CHAIN_SELECTED,
              chainBase: value,
              isCustomDomain: app.isCustomDomain(),
              communityType: CommunityType.StarterCommunity,
            });
          }}
        />
        {...defaultChainRows(this.state.form)}
        <CWButton
          label="Save changes"
          disabled={this.state.saving || this.state.form.id.length < 1}
          onclick={async () => {
            this.state.saving = true;
            const additionalArgs: {
              eth_chain_id?: number;
              node_url?: string;
              bech32_prefix?: string;
              alt_wallet_url?: string;
            } = {};
            mixpanelBrowserTrack({
              event: MixpanelCommunityCreationEvent.CREATE_COMMUNITY_ATTEMPTED,
              chainBase: this.state.form.base,
              isCustomDomain: app.isCustomDomain(),
              communityType: CommunityType.StarterCommunity,
            });

            // defaults to be overridden when chain is no longer "starter" type
            switch (this.state.form.base) {
              case ChainBase.CosmosSDK: {
                additionalArgs.node_url = 'https://rpc-osmosis.blockapsis.com';
                additionalArgs.bech32_prefix = 'osmo';
                additionalArgs.alt_wallet_url =
                  'https://lcd-osmosis.blockapsis.com';
                break;
              }
              case ChainBase.NEAR: {
                additionalArgs.node_url = 'https://rpc.mainnet.near.org';
                break;
              }
              case ChainBase.Solana: {
                additionalArgs.node_url = 'https://api.mainnet-beta.solana.com';
                break;
              }
              case ChainBase.Substrate: {
                additionalArgs.node_url = 'wss://mainnet.edgewa.re';
                break;
              }
              case ChainBase.Ethereum:
              default: {
                additionalArgs.eth_chain_id = 1;
                additionalArgs.node_url =
                  'wss://eth-mainnet.alchemyapi.io/v2/BCNLWCaGqaXwCDHlZymPy3HpjXSxK7j_';
                additionalArgs.alt_wallet_url =
                  'https://eth-mainnet.alchemyapi.io/v2/BCNLWCaGqaXwCDHlZymPy3HpjXSxK7j_';
                break;
              }
            }
            const {
              id,
              name,
              symbol,
              iconUrl,
              description,
              website,
              discord,
              telegram,
              github,
              element,
              base,
            } = this.state.form;
            try {
              const res = await $.post(`${app.serverUrl()}/createChain`, {
                jwt: app.user.jwt,
                address: '',
                type: ChainType.Offchain,
                network: baseToNetwork(this.state.form.base),
                icon_url: iconUrl,
                id,
                name,
                symbol,
                base,
                description,
                discord,
                element,
                github,
                telegram,
                website,
                ...additionalArgs,
              });
              await initAppState(false);
              m.route.set(`/${res.result.chain?.id}`);
            } catch (err) {
              notifyError(
                err.responseJSON?.error ||
                  'Creating new starter community failed'
              );
            } finally {
              this.state.saving = false;
            }
          }}
        />
      </div>
    );
  }