Select to view content in your preferred language

async function messing up Login

409
2
10-28-2024 09:23 AM
CW-GIS
by
Regular Contributor

Im basically trying to merge these two samples:

Login: https://developers.arcgis.com/javascript/latest/sample-code/identity-oauth-basic/live/

Related Tables: https://developers.arcgis.com/javascript/latest/sample-code/widgets-featuretable-relates/

But I'm stuck with the await (line 187 & 193). If I follow the related table example and put async function at top, then the sign in part stops working. 

I'm just not sure where to start and stop the async function.

 

<html lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
    <title>Access ArcGIS Online items using OAuth 2.0 | Sample | ArcGIS Maps SDK for JavaScript 4.30</title>

    <script type="module" src="https://js.arcgis.com/calcite-components/2.11.1/calcite.esm.js"></script>
    <link rel="stylesheet" type="text/css" href="https://js.arcgis.com/calcite-components/2.11.1/calcite.css" />
    <link rel="stylesheet" href="https://js.arcgis.com/4.30/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.30/"></script>
    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        margin: 0px;
        padding: 0px;
        display: flex;
      }

     

      #viewDiv {
        height: calc(100% - 65px);
        width: 50%;
        margin-top:65px;
      }

      .container {
        height: calc(100% - 65px);
        width: 50%;
        margin-top:65px;
      }
      calcite-modal {
        --calcite-modal-scrim-background: rgb(34, 77, 122, 0.7);
      }

      #modal hr {
        margin: 1rem 0;
        border: 0;
        border-bottom: 1px solid var(--calcite-color-border-3);
      }

      #modal ul li {
        margin-bottom: 0.5rem;
      }

      #modal calcite-notice {
        margin-bottom: 1.25rem;
      }
    </style>
    <script>
      require([

        "esri/portal/Portal",
        "esri/identity/OAuthInfo",
        "esri/identity/IdentityManager",
        "esri/portal/PortalQueryParams",
        "esri/Map",
        "esri/views/MapView",
        "esri/WebMap",
        "esri/widgets/FeatureTable",
        "esri/core/reactiveUtils",
        "esri/config"

      ], (Portal, OAuthInfo, esriId, PortalQueryParams, Map, MapView, WebMap, FeatureTable, reactiveUtils, esriConfig) => {
          console.log("startup")
        // UI elements
        const signInButton = document.getElementById("sign-in-button");
        const navLogo = document.getElementById("nav-logo");
        const navigationUser = document.getElementById("nav-user");
        const galleryPanel = document.getElementById("item-panel");
        const itemGallery = document.getElementById("item-gallery");
        signInButton.addEventListener("click", signInOrOut);
        navigationUser.addEventListener("click", signInOrOut);

        esriConfig.portalUrl = "https://webgis.cushwake.com/portal";
        //Create a new OAuthInfo object.
        const info = new OAuthInfo({
          // Swap this ID out with an app ID registered in your ArcGIS Organization.
          appId: "9jjg9al9Mm3gFiLy",
          // Add the portalUrl property if using your own portal.
          portalUrl: esriConfig.portalUrl,
          // Set the authNamespace property to prevent the user's signed in state
          // from being shared with other apps on the same domain with the same authNamespace value.
          authNamespace: "portal_oauth_inline",
          // Set popup to true to show the OAuth sign-in page in a separate popup window.
          popup: false
        });

        // Add the OAuthInfo to the IdentityManager.
        esriId.registerOAuthInfos([info]);



        // Call the checkSignIn function to see if the user is already signed in.
        checkSignIn();

        // Function to check the current sign in status and query the portal if signed in.
         function checkSignIn() {
          esriId
            .checkSignInStatus(info.portalUrl + "/sharing")
            .then(() => {
              // If signed in, show the username in the UI.
              navigationUser.hidden = false;
              signInButton.hidden = true;
              const portal = new Portal({
                authMode: "immediate"
              });
              // Check if using a portal other than ArcGIS Online.
              if (info.portalUrl !== "https://webgis.cushwake.com/portal") {
                portal.url = info.portalUrl;
              }
              // Load the portal, display the name and username, then call the query items function.
              portal.load().then(() => {
                navigationUser.fullName = portal.user.fullName;
                navigationUser.username = portal.user.username;
                navLogo.description =
                  "Gallery of queried portal items displayed below. To sign out, click on the logged in user button.";
                //queryItems(portal);
              });
            })
            .catch(() => {
              // If not signed in, then show the sign in button.
              signInButton.hidden = false;
              navigationUser.hidden = true;
              navLogo.description = "Use OAuth to log in to an ArcGIS Organization to view your items.";
            });
        }



        // Function to sign in or out of the portal used by the sign in/out button click event.
        function signInOrOut() {
          esriId
            .checkSignInStatus(info.portalUrl + "/sharing")
            .then(() => {
              // If already signed in, then destroy the credentials to sign out.
              esriId.destroyCredentials();
              window.location.reload();
            })
            .catch(() => {
              // If the user is not signed in, generate a new credential.
              esriId
                .getCredential(info.portalUrl + "/sharing", {
                  // Set the following property to false to not show a dialog
                  // before the OAuth popup window is open.
                  //oAuthPopupConfirmation: false,
                })
                .then(() => {
                  // Once a credential is returned from the promise, check the
                  // sign in status to query the portal for items.
                  checkSignIn();
                });
            });
        }

        const infoButton = document.createElement("calcite-action");
          infoButton.text = "Sample information";
          infoButton.icon = "information";
          infoButton.label = "Info";

          const modalDiv = document.getElementById("modal");

          // Add event listener to the button
          infoButton.addEventListener("click", () => {
            // Open the modal
            modalDiv.open = true;
          });
   
          let features = [];
          const webmap = new WebMap({
            portalItem: {
              id: "4c658233bb5c4dfe9aacf272a195ce75"
            }
          });
          const view = new MapView({
            container: "viewDiv",
            map: webmap,
            popupEnabled: false
          });



   
       const calciteLoader = document.getElementById("calcite-loader");
        //  await reactiveUtils.whenOnce(() => !view.updating);


          // Once the view is finished updating, get the first layer in the webmap
          const featureLayer = webmap.layers.getItemAt(0);
          // Make sure the layer is loaded before constructing the FeatureTable
         // await reactiveUtils.whenOnce(() => featureLayer.loaded);
        
         
    //do what you need here

   // Create the feature table
          // The title is created as a function that dynamically updates based on the amount of selected features within the table.
          // The actionColumnConfig property creates a new action column within the table that creates an action that zooms to the feature in that row.
          const featureTable = new FeatureTable({
            title: () => {
              if (!featureTable) {
                return;
              }

              const state = featureTable.state;
              switch (state) {
                case "loading":
                  return "Loading layer data...";
                case "loaded":
                  const title = featureTable.layer?.title;
                  const rowCount = featureTable.size;
                  const selectedCount = featureTable.highlightIds?.length ?? 0;
                  return `${title} (${selectedCount} rows selected out of ${rowCount} total)`;
                case "error":
                  return "Error loading layer.";
                default:
                  return;
              }
            },
            description: "Table Description",
            actionColumnConfig: {
              label: "Go to feature",
              icon: "zoom-to-object",
              callback: (params) => {
                view.goTo(params.feature);
              }
            },
            view: view,
            editingEnabled: true, // required to enable editing
            relatedRecordsEnabled: true, // required to enable related records
            layer: featureLayer,
            tableTemplate: {
              // TableTemplate is autocastable
              columnTemplates: [
                {
                  type: "field", // FieldColumnTemplate is autocastable, 'type' must be set
                  fieldName: "property_id",
                  label: "MNCAR",
                  icon: "key",
                  autoWidth: true // set this to have the columns automatically adjust width
                },
                {
                  type: "field",
                  fieldName: "MANUFACTURER",
                  label: "Manufacturer",
                  autoWidth: true
                },
                {
                  type: "field",
                  fieldName: "OPERABLE",
                  label: "Operable",
                  autoWidth: true
                },
                {
                  type: "field",
                  fieldName: "LASTSERVICE",
                  label: "Date of last service",
                  autoWidth: true
                },
                {
                  type: "field",
                  fieldName: "FLOW",
                  label: "Flow rate",
                  autoWidth: true
                }
              ]
            },
            container: document.getElementById("tableDiv")
          });

          reactiveUtils.when(
            () => view.stationary,
            () => {
              // Filter out and show only the visible features in the feature table.
              featureTable.filterGeometry = view.extent;
            },
            {
              initial: true
            }
          );
        

           // Listen for the view's click event.
          // Perform a hitTest on the clicked location
          // grab any features that fall within it
          view.on("click", async (event) => {
            const response = await view.hitTest(event);
            const candidate = response.results.find(
              (result) => result.graphic && result.graphic.layer === featureLayer
            );

            if (candidate) {
              const objectId = candidate.graphic.attributes.OBJECTID;
              const index = featureTable.highlightIds.indexOf(objectId);

              // If there are objectIds in the highlightIds, remove the clicked feature
              // from the array. If there are no more objectIds, remove the filter
              // to show only selected records
              if (index > -1) {
                featureTable.highlightIds.splice(index, 1);
                if (featureTable.highlightIds.length === 0) {
                  featureTable.filterBySelectionEnabled = false;
                }
              } else {
                // Add the objectId of the clicked feature into the highlightIds.
                // This selects the feature in the table and sets a filter to only display
                // the selected rows
                featureTable.highlightIds.push(objectId);
                featureTable.filterBySelectionEnabled = true;
              }
            }
          });


           // Check if the highlights (selection) are being changed on the table by
          // checking and unchecking the rows,
          // and update the features array to match the table selection by adding
          // or removing as appropriate
          featureTable.highlightIds.on("change", async (event) => {
            event.removed.forEach((item) => {
              const data = features.find((data) => {
                return data === item;
              });
              if (data) {
                features.splice(features.indexOf(data), 1);
              }
              // Check if there are no more selected rows in the table,
              // Once everything is unchecked, remove the filter for selected records
              if (featureTable.highlightIds.length === 0) {
                featureTable.filterBySelectionEnabled = false;
              }
            });

            // If the selection is added, push all added selections to array
            event.added.forEach((item) => {
              features.push(item);
            });
          });


        });
      














       
      
      
    </script>
  </head>

  <body>
    
    <calcite-shell>
      <calcite-navigation slot="header">
        <calcite-navigation-logo
          id="nav-logo"
          slot="logo"
          heading="Cushman Wakefield"
          description="Something Else"
        ></calcite-navigation-logo>
        <calcite-button id="sign-in-button" slot="user">Sign in</calcite-button>
        <calcite-navigation-user hidden id="nav-user" slot="user"> </calcite-navigation-user>
      </calcite-navigation>



      
    </calcite-shell>


    <calcite-modal id="modal">
      <div slot="header">About this application</div>
      <div slot="content">
        <calcite-notice open>
          <span slot="title"
            >This sample demonstrates how to display and edit related data using the
            <calcite-link
              target="_blank"
              href="https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html"
              >FeatureTable</calcite-link
            >
            widget.
          </span>
        </calcite-notice>
        This example illustrates the main areas of functionality:
        <ul>
          <li>
            <calcite-link
              target="_blank"
              href="https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html#related-records"
              >Working with related records in the table</calcite-link
            >
          </li>
          <li>
            <calcite-link
              target="_blank"
              href="https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html#selection"
              >Syncing selection between table and view</calcite-link
            >
          </li>
          <li>
            <calcite-link
              target="_blank"
              href="https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html#editing-in-featuretable"
              >Editing in the table</calcite-link
            >
          </li>
          <li>
            <calcite-link
              target="_blank"
              href="https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html#filtering-and-sorting"
              >Filtering in the table</calcite-link
            >
          </li>
          <li>
            <calcite-link
              target="_blank"
              href="https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html#column-configuration"
              >Configuring columns</calcite-link
            >
          </li>
        </ul>
      </div>
    </calcite-modal>

    <div id="viewDiv"></div>
    <div class="container">
      <div id="tableDiv"></div>
    </div>
  </body>
</html>

 

0 Kudos
2 Replies
KenBuja
MVP Esteemed Contributor

When I use the OAuth login, I have to wrap the code that requires the authenticated data in the checkSignInStatus method.

const portalUrl = 'my portal url';
const info = new OAuthInfo({
  appId: "myAppId", //*** Your Client ID value goes here ***//
  popup: false // inline redirects don't require any additional app configuration
      });

identityManager.registerOAuthInfos([info]);
identityManager.getCredential(portalUrl);

identityManager.checkSignInStatus(portalUrl).then(function () {
  layer = new FeatureLayer({
    portalItem: {
      id: "myPortalItem"
    },
    outFields: ["*"]
  });

  map = new Map({
    basemap: 'oceans',
    layers: [layer]
  });

  view = new MapView({
    container: "viewDiv",
    map: map,
    center: [-153, 63],
    zoom: 4,
    popup: {
      autoOpenEnabled: false
    }
  });

  //etc.
});

      
0 Kudos
RamaniGanason
Regular Contributor

Normally it would be good practice not to mix async..await and Promise when writing in JS. Maybe you can change the whole function to Promise.

0 Kudos