mcpField
A
arcgis-portal-content

arcgis-portal-content

github.com/saschabrunnerchDevelopment2363 installsUpdated 29w ago
Repository

About arcgis-portal-content

A reference skill for ArcGIS Maps SDK for JavaScript developers managing maps, scenes, and content in ArcGIS portals. It covers saving WebMaps and WebScenes, bookmarks and slides, and querying or updating portal items and groups.

Key features

  1. 01Load and configure WebMaps and WebScenes
  2. 02Save maps and scenes to portal items
  3. 03Create and manage bookmarks and scene slides
  4. 04Query and update portal items and groups
  5. 05Retrieve portal user and folder information

Use cases

  1. 01Save a map view as a portal item
  2. 02Organize scene presentations with slides
  3. 03Find and update items in a portal

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/saschabrunnerch/arcgis-maps-sdk-js-ai-context --skill arcgis-portal-content

After installing, type/arcgis-portal-contentin Claude Code to confirm it loaded.

Details

From the project README

ArcGIS Portal Content

Use this skill for saving maps, managing bookmarks, slides, working with portal items, and configuring WebMap/WebScene structure.

Import Patterns

Direct ESM Imports
import WebMap from "@arcgis/core/WebMap.js";
import WebScene from "@arcgis/core/WebScene.js";
import Portal from "@arcgis/core/portal/Portal.js";
import PortalItem from "@arcgis/core/portal/PortalItem.js";
import PortalQueryParams from "@arcgis/core/portal/PortalQueryParams.js";
Dynamic Imports (CDN)
const WebMap = await $arcgis.import("@arcgis/core/WebMap.js");
const Portal = await $arcgis.import("@arcgis/core/portal/Portal.js");
const [PortalItem, PortalQueryParams] = await $arcgis.import([
  "@arcgis/core/portal/PortalItem.js",
  "@arcgis/core/portal/PortalQueryParams.js",
]);

WebMap Structure

WebMap Properties
import WebMap from "@arcgis/core/WebMap.js";

const webMap = new WebMap({
  // From portal item
  portalItem: {
    id: "WEBMAP_ID",
    portal: { url: "https://www.arcgis.com" },
  },
});

// Or create from scratch
const webMap = new WebMap({
  basemap: "topo-vector",
  ground: "world-elevation",
  layers: [featureLayer, graphicsLayer],
  tables: [tableLayer],
  initialViewProperties: {
    center: [-118.805, 34.027],
    zoom: 13,
  },
  bookmarks: [bookmark1, bookmark2],
});
WebMap from JSON
const webMap = WebMap.fromJSON({
  operationalLayers: [
    {
      id: "layer1",
      layerType: "ArcGISFeatureLayer",
      url: "https://services.arcgis.com/.../FeatureServer/0",
      title: "My Layer",
      visibility: true,
      opacity: 1,
    },
  ],
  baseMap: {
    baseMapLayers: [
      {
        id: "basemap",
        layerType: "VectorTileLayer",
        styleUrl:
          "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/v2/styles/arcgis/topographic",
      },
    ],
    title: "Topographic",
  },
  initialState: {
    viewpoint: {
      targetGeometry: {
        xmin: -118.9,
        ymin: 33.8,
        xmax: -118.1,
        ymax: 34.3,
        spatialReference: { wkid: 4326 },
      },
    },
  },
});

WebScene Structure

import WebScene from "@arcgis/core/WebScene.js";

const webScene = new WebScene({
  portalItem: { id: "WEBSCENE_ID" },
});

// Or create from scratch
const webScene = new WebScene({
  basemap: "satellite",
  ground: "world-elevation",
  layers: [sceneLayer, featureLayer],
  initialViewProperties: {
    viewpoint: {
      camera: {
        position: {
          x: -118.805,
          y: 34.027,
          z: 1500,
          spatialReference: { wkid: 4326 },
        },
        heading: 45,
        tilt: 65,
      },
    },
  },
  presentation: {
    slides: [slide1, slide2],
  },
});
Local vs Global Scene
// Global scene (default)
const globalScene = new WebScene({
  basemap: "satellite",
  ground: "world-elevation",
  viewingMode: "global",
});

// Local scene (with clipping)
const localScene = new WebScene({
  basemap: "satellite",
  ground: "world-elevation",
  viewingMode: "local",
  clippingArea: {
    type: "extent",
    xmin: -118.9,
    ymin: 33.8,
    xmax: -118.1,
    ymax: 34.3,
    spatialReference: { wkid: 4326 },
  },
  clippingEnabled: true,
});

Saving WebMaps

Save As New Item
const map = new WebMap({
  portalItem: { id: "EXISTING_WEBMAP_ID" },
});

// Update map properties from view before saving
await map.updateFrom(view);

const savedItem = await map.saveAs({
  title: "My New WebMap",
  snippet: "Description of the map",
  tags: ["tag1", "tag2"],
});

console.log(
  "Saved to:",
  savedItem.portal.url + "/home/item.html?id=" + savedItem.id,
);
Save Existing WebMap
await map.updateFrom(view);
await map.save();
Map Component Save Example
<arcgis-map item-id="YOUR_WEBMAP_ID">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>

<script type="module">
  const viewElement = document.querySelector("arcgis-map");
  await viewElement.viewOnReady();

  document.getElementById("saveBtn").onclick = async () => {
    await viewElement.map.updateFrom(viewElement.view);
    await viewElement.map.save();
  };
</script>

Saving WebScenes

const scene = new WebScene({
  portalItem: { id: "EXISTING_WEBSCENE_ID" },
});

await scene.updateFrom(sceneView);
await scene.saveAs({
  title: "My New WebScene",
  snippet: "3D scene description",
});

Bookmarks

Bookmarks Component
<arcgis-map item-id="YOUR_WEBMAP_ID">
  <arcgis-expand slot="top-right" expanded>
    <arcgis-bookmarks
      drag-enabled
      show-add-bookmark-button
      show-edit-bookmark-button
      hide-time
    >
    </arcgis-bookmarks>
  </arcgis-expand>
</arcgis-map>

<script type="module">
  const bookmarks = document.querySelector("arcgis-bookmarks");

  bookmarks.addEventListener("arcgisSelect", (event) => {
    console.log("Selected:", event.detail.bookmark.name);
  });
</script>
Create Bookmarks Programmatically
import Bookmark from "@arcgis/core/webmap/Bookmark.js";

const bookmark = new Bookmark({
  name: "My Location",
  viewpoint: view.viewpoint.clone(),
});

map.bookmarks.add(bookmark);

// Go to bookmark
view.goTo(bookmark.viewpoint);

WebScene Slides

Create Slide from Current View
import Slide from "@arcgis/core/webscene/Slide.js";

const slide = await Slide.createFrom(sceneView);
slide.title = { text: "Downtown View" };

// Add to presentation
scene.presentation.slides.add(slide);
Apply Slide to View
const slide = scene.presentation.slides.getItemAt(0);

slide.applyTo(sceneView, {
  maxDuration: 3000,
  easing: "in-out-coast-cubic",
});
Remove Slide
scene.presentation.slides.remove(slide);

Portal Items

Load Portal Item
import PortalItem from "@arcgis/core/portal/PortalItem.js";

const item = new PortalItem({ id: "ITEM_ID" });
await item.load();

console.log("Title:", item.title);
console.log("Type:", item.type);
console.log("Owner:", item.owner);
console.log("Created:", item.created);
Query Portal Items
import Portal from "@arcgis/core/portal/Portal.js";
import PortalQueryParams from "@arcgis/core/portal/PortalQueryParams.js";

const portal = new Portal({ authMode: "immediate" });
await portal.load();

const queryParams = new PortalQueryParams({
  query: `owner:${portal.user.username} type:"Web Map"`,
  sortField: "modified",
  sortOrder: "desc",
  num: 20,
});

const result = await portal.queryItems(queryParams);
result.results.forEach((item) => {
  console.log(item.title, item.id);
});
Update Portal Item
const item = new PortalItem({ id: "ITEM_ID" });
await item.load();

item.title = "Updated Title";
item.snippet = "Updated description";
item.tags = ["new", "tags"];

await item.update();

Portal Groups

Query Groups
const portal = new Portal();
await portal.load();

const groups = await portal.queryGroups({ query: "title:GIS" });
groups.results.forEach((group) => {
  console.log(group.title, group.id);
});
Query Group Content
const group = (await portal.queryGroups({ query: `id:GROUP_ID` })).results[0];
const content = await group.queryItems();
content.results.forEach((item) => {
  console.log(item.title);
});

Portal User Information

const portal = new Portal({ authMode: "immediate" });
await portal.load();

console.log("Username:", portal.user.username);
console.log("Full name:", portal.user.fullName);
console.log("Email:", portal.user.email);
console.log("Role:", portal.user.role);
console.log("Org name:", portal.name);

Portal Folders

import PortalFolder from "@arcgis/core/portal/PortalFolder.js";

// Get user folders
const folders = await portal.user.fetchFolders();
folders.forEach((folder) => {
  console.log(folder.title, folder.id);
});

// Query items in a specific folder
const queryParams = new PortalQueryParams({
  query: `owner:${portal.user.username}`,
  sortField: "modified",
  num: 20,
});
queryParams.folder = folder;

const result = await portal.queryItems(queryParams);

Common Pitfalls

  1. Authentication required for saving: Saving requires user authentication. Ensure OAuth is set up before calling save() or saveAs().

  2. Forgetting updateFrom before save: Always call updateFrom(view) before saving to capture the current view state:

    // Anti-pattern: saving without updating
    await map.save(); // May save stale viewpoint
    
    // Correct: update from view first
    await map.updateFrom(view);
    await map.save();
    
  3. Enterprise portal URL: Enterprise portals need explicit portal URL:

    const portal = new Portal({
      url: "https://your-portal.com/portal",
    });
    
  4. Ownership restrictions: You can only update portal items you own. Use saveAs() to create a copy you own.

  5. Slide thumbnails: Generated automatically from Slide.createFrom() but may take time to render.

Complete Save Example

<!DOCTYPE html>
<html>
  <head>
    <script src="https://js.arcgis.com/5.0/"></script>
    <script
      type="module"
      src="https://js.arcgis.com/5.0/map-components/"
    ></script>
    <style>
      html,
      body {
        height: 100%;
        margin: 0;
      }
    </style>
  </head>
  <body>
    <arcgis-map item-id="YOUR_WEBMAP_ID">
      <arcgis-zoom slot="top-left"></arcgis-zoom>
      <arcgis-expand slot="top-right" expanded>
        <arcgis-bookmarks
          drag-enabled
          show-add-bookmark-button
          show-edit-bookmark-button
        >
        </arcgis-bookmarks>
      </arcgis-expand>
    </arcgis-map>

    <script type="module">
      const viewElement = document.querySelector("arcgis-map");
      await viewElement.viewOnReady();

      // Save map on button click
      document.getElementById("saveBtn").onclick = async () => {
        await viewElement.map.updateFrom(viewElement.view);
        await viewElement.map.save();
      };
    </script>
  </body>
</html>

Reference Samples

  • webmap-save - Saving a WebMap to portal
  • webmap-basic - Loading a WebMap from portal
  • webmap-swap - Swapping between WebMaps
  • webscene-save - Saving a WebScene to portal
  • webscene-basic - Loading a WebScene from portal
  • webscene-slides - Managing WebScene slides
  • webscene-slide-tour - Slide tour through a WebScene
  • bookmarks - Working with map bookmarks
  • widgets-bookmarks - Bookmarks widget usage
  • basemaps-portal - Loading basemaps from portal
  • layers-portal - Loading layers from portal items
  • portalitem-dragndrop - Drag and drop portal items

Related Skills

  • See arcgis-authentication for OAuth and API key setup.
  • See arcgis-core-maps for map and view creation.
  • See arcgis-layers for layer configuration.

Comments

Markdown supported