Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[*.py]
indent_size = 4

[*.ps1]
end_of_line = crlf
indent_size = 4
34 changes: 34 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Normalize line endings. Text files are LF in the repository and checked out native on Windows,
# which is what stops git printing "LF will be replaced by CRLF" on every commit.
* text=auto

*.ts text eol=lf
*.tsx text eol=lf
*.js text eol=lf
*.jsx text eol=lf
*.json text eol=lf
*.md text eol=lf
*.css text eol=lf
*.html text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.py text eol=lf
*.ps1 text eol=crlf

# Binary, never touched.
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.svg text eol=lf
*.ico binary
*.zip binary
*.pdf binary
*.woff binary
*.woff2 binary
*.ttf binary
*.pagx binary

# Keep generated files out of diffs and out of the language statistics.
package-lock.json linguist-generated=true -diff
pnpm-lock.yaml linguist-generated=true -diff
50 changes: 50 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Bug report
description: Something in the widget does not work
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Questions about ArcGIS itself belong on Esri Community. This form is for the widget.
- type: input
id: widget-version
attributes:
label: Widget version
description: From the widget's manifest.json
placeholder: "1.4.2"
validations:
required: true
- type: input
id: exb-version
attributes:
label: Experience Builder version
description: Developer Edition version, or the build your portal reports
placeholder: "1.21 Developer Edition"
validations:
required: true
- type: input
id: portal
attributes:
label: Portal
description: ArcGIS Enterprise version, or ArcGIS Online
placeholder: "Enterprise 11.3"
validations:
required: true
- type: textarea
id: what-happened
attributes:
label: What happened
description: What you did, what happened, and what you expected instead
validations:
required: true
- type: textarea
id: console
attributes:
label: Browser console output
description: Anything logged when it went wrong. This is usually the fastest way to a fix.
render: text
- type: input
id: browser
attributes:
label: Browser
placeholder: "Chrome 141"
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: ArcGIS or Experience Builder question
url: https://community.esri.com/t5/arcgis-experience-builder/ct-p/arcgis-experience-builder
about: Questions about ArcGIS Experience Builder itself are better answered on Esri Community.
- name: Security problem
url: https://github.com/brianmcleer/saveInstanceWidget/security/advisories/new
about: Please report vulnerabilities privately instead of opening an issue.
22 changes: 22 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Feature request
description: Suggest something the widget should do
labels: ["enhancement"]
body:
- type: textarea
id: problem
attributes:
label: What are you trying to do
description: The workflow you are stuck on, not the solution you have in mind
validations:
required: true
- type: textarea
id: idea
attributes:
label: What you would like the widget to do
validations:
required: true
- type: textarea
id: workaround
attributes:
label: How you handle it today
description: Another widget, a script, doing it by hand
19 changes: 19 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## What this changes

<!-- One sentence. If it fixes an issue, say "Fixes #123". -->

## Why

<!-- The problem it solves, or the behavior it adds. -->

## How it was tested

- [ ] Built with `npm start` in the Experience Builder `client` folder
- [ ] `npx tsc -p .` in the widget folder reports no errors
- [ ] Exercised the widget in the builder and in a published app

## Checklist

- [ ] Version bumped in both `manifest.json` and `package.json`
- [ ] `CHANGELOG.md` updated
- [ ] One change per pull request
22 changes: 22 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/saveInstance"
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
groups:
all-dependencies:
patterns:
- "*"
ignore:
# Experience Builder pins these; upgrading them independently breaks the build.
- dependency-name: "jimu-*"
- dependency-name: "@arcgis/*"
- dependency-name: "react"
- dependency-name: "react-dom"
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: monthly
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.DS_Store

# Community attachment zips built by publish-all.ps1 never get committed
*.zip
7 changes: 7 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
.vs/
*.user
*.suo
.DS_Store
Thumbs.db
CHANGES.md
73 changes: 73 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Save Instance 2.0.0: what changed

Storage is still **local only** (browser `localStorage`). Everything else from the
review was implemented, and the UI was rebuilt against jimu-ui's themed,
accessible components to meet **WCAG 2.1 AA**.

## Accessibility (WCAG 2.1 AA)
- **Color & contrast**: dropped the hardcoded `blue19` ramp (several values, e.g.
`#007cd3` white text ≈ 3.9:1, failed AA) in favor of EXB theme tokens via CSS
variables (`--sys-color-primary-main` / `--sys-color-primary-text`), which EXB
pairs for AA. Light-mode fallbacks are included, and the widget now adapts to
dark themes.
- **Names for icon controls**: every icon button has a translated `aria-label`
(e.g. *"Load 'Downtown' onto the map"*); the icon itself is `aria-hidden`. No
reliance on `title` alone.
- **Forms**: inputs are associated with real `<Label for>` elements and
`aria-describedby` hints.
- **Tables**: proper `<caption>`, `<thead>`, `<th scope="col">` and
`<th scope="row">` so screen readers announce row/column context. The legend
`<tr>`-directly-in-`<table>` markup was fixed.
- **Dialogs**: `window.alert/confirm/prompt` replaced with jimu `Modal`
(focus trap, `aria-modal`, labeled by title, **Escape/backdrop close**).
- **Status**: saves, loads, errors announce through a jimu `Alert` live region.
- **Keyboard & focus**: all controls are jimu-ui components with visible focus
rings; the hidden file input is triggered from a real button.
- **Empty/error copy**: explicit empty state and actionable error messages
(active voice, plain language).

## New / expanded captured state
- **Viewpoint** (center, scale, **rotation**, and 3D **camera**): works in
`SceneView`, not just 2D. Extent is still saved for backward compatibility.
- **Definition expressions** and **label visibility** for feature layers.
- **Time extent** (time-slider position): optional, off by default.
- Existing extent / layer visibility & opacity / basemap / graphics retained.
- The **Draw/Sketch** (`jimu-draw`) graphics path is kept and guarded by config.

## Robustness / bug fixes
- **Unicode-safe base64** (`TextEncoder`/`TextDecoder`): names/attributes with
emoji or accents no longer throw on save, download, or import.
- **localStorage quota** is caught and surfaced instead of failing silently.
- **Schema versioning** (`schemaVersion`, `createdAt`) with a migration that
upgrades older instances and legacy `.txt` files on read.
- **Upload validation**: structure is checked before anything is applied.
- **Immutable rename**: no more direct mutation of objects in state.
- **Async load**: `goTo` is awaited and benign `AbortError`s are ignored; a
mismatched `webmapId` now warns the user.
- Removed dead code, the duplicate `graphics` assignment, and aligned the version
comment with the manifest.

## UX additions
- Filter box and sort control (newest/oldest/name) for the saved list.
- Saved date shown per instance; Save button is genuinely `disabled` until valid.
- Toast-style confirmation after save/load/rename/delete/import.

## Settings panel
- Removed the unused data-source code.
- Added: per-element capture toggles, a max-instances limit, and an optional
"load this instance on startup" name.

## Localization
- All UI strings moved to `src/runtime/translations/default.ts` and
`src/setting/translations/default.ts` and rendered via `hooks.useTranslation`,
so the widget can be translated (currently `en`).

---

### Build note
These are **source** files for ArcGIS Experience Builder. They can't be compiled
outside an EXB workspace (the `jimu-*` / `@arcgis/core` packages live there), so
they haven't been type-checked against the SDK here: only verified to parse.
Drop the `saveInstance` folder into your EXB `client/your-extensions/widgets/`
directory and run the normal EXB build. The CSS-variable fallbacks mean it also
renders sensibly if a token is missing.
10 changes: 10 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Code of Conduct

Be decent. Assume good faith, keep criticism about the code, and leave everything else out of it.

Harassment, personal attacks, and deliberately disruptive behavior are not welcome here. The
maintainer may edit, lock, or delete any issue, comment, or pull request that crosses that line,
and may block accounts that keep doing it.

Report a problem by opening an issue, or privately through GitHub's report abuse link on the
offending content.
27 changes: 27 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Contributing

Thanks for looking. This widget is maintained by the City of Grand Junction GIS Division and
shared as is; issues and pull requests are welcome, and there is no obligation on either side.

## Reporting a problem

Open an issue with:

- the Experience Builder version (Developer Edition or the portal's build),
- the widget version (from `manifest.json`),
- what you did, what happened, and what you expected,
- the browser console output if anything was logged.

## Pull requests

- Keep a pull request to one change.
- Match the existing style: two space indent, no semicolons where the file does without them,
and the same comment voice as the file you are editing.
- Update `CHANGELOG.md` and bump the version in both `manifest.json` and `package.json`.
- Build once with `npm start` in the Experience Builder `client` folder and exercise the widget
before opening the pull request. `npx tsc -p .` in the widget folder should report no errors.

## Repository layout

The widget itself lives in the subfolder named after it. The repository root holds the README,
the license, and the publishing script; it is not part of the widget.
6 changes: 5 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
MIT License

Copyright (c) 2025 Sven Jensen
Copyright (c) 2025 Sven Jensen (https://jensengis.com)
Copyright (c) 2025 City of Grand Junction, CO (modifications)

Original work: Save Instance Widget by Sven Jensen,
https://github.com/svenweb/saveInstanceWidget

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading