Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,6 @@ __marimo__/
# Streamlit
.streamlit/secrets.toml

# graphify — regenerated AST cache (keep GRAPH_REPORT.md / graph artifacts tracked)
graphify-out/cache/
# graphify — regenerated locally; do not commit (the snapshots conflict on every rebase)
graphify-out/
local/
15 changes: 15 additions & 0 deletions .issueflows/03-solved-issues/issue174_original.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Issue #174 — Unclear what happens when opening a new project while already having a project loaded

Source: https://github.com/cellpy/cellpy-simple-gui/issues/174

It is unclear what happens. Does it add it to current? If not, does it properly
clean up previous project? Best would be to have option "append" in addition so
that it is clear that the new project is appended, while if not pressing
"append" it cleans away the old and loads the new.

## Comment

Also noted another thing when opening a new project when already having cells /
project. The group number for the new groups start with one. It should instead
start with a number that is not used by the already existing groups from the
first project.
37 changes: 37 additions & 0 deletions .issueflows/03-solved-issues/issue174_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Plan — #174 open project: replace vs append

## Findings

- `projects.open_project()` calls `library.clear()` first, so opening a saved
project silently **replaces** whatever is loaded (cellpy config switches to
the opened project too). Nothing in the UI says so and there is no confirm.
- A batch journal (same "Open path" control) silently **appends**, and keeps
the journal's own group numbers — so a second journal's group 1 lands in
the already-used group 1 (the comment on the issue).
- The "Close" button already confirms before clearing; Open does not.

## Approach

One explicit **mode** for every open: `replace` (default) or `append`.

1. **Core** — `open_project(library, target, progress, mode="replace")`.
`replace` clears first (as today). `append` keeps the loaded cells and
project association and offsets the incoming group numbers by the highest
group already in use (`Library.group_offset_for_append()`); group names
(#187) move with their numbers. Appending into an empty library behaves
like replace (the project becomes current).
2. **API** — `/api/projects/open` and `/api/projects/load-journal` accept
`mode` (`OpenMode = Literal["replace", "append"]`, default `replace`).
The journal job clears the library only once the journal yielded cells (a
corrupt journal must not wipe the library). cellpy project config is only
switched when the open actually replaces. Results carry `action`
(`opened` / `appended`) and `n_cells`.
3. **UI** — Project panel gains an "Append to the loaded cells" checkbox
(`openAppend`, shown once cells exist); the Open / Open path buttons read
"Append" / "Append path" when it is on. Replacing a non-empty library asks
for confirmation (mentions unsaved changes when dirty); appending does not.
Toasts say "Opened …" vs "Appended … to the loaded cells". The panel hint
explains both behaviours. Append marks the library dirty.
4. **Tests** — core (replace vs append, group offset, group names, empty
library), API (`mode` for projects and journals, journal group offset),
template/component drift tests; README + design doc updated.
40 changes: 40 additions & 0 deletions .issueflows/03-solved-issues/issue174_status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Status — #174 open project: replace vs append

- [x] Done

## What was done

- `projects.open_project(..., mode="replace"|"append")` (`projects.OpenMode`).
Replace clears first (unchanged behaviour). Append keeps the loaded cells
and current project association, offsets the incoming group numbers by
`Library.group_offset_for_append()` (highest group in use) and moves group
names (#187) with them. Append into an empty library behaves like an open.
- `POST /api/projects/open` and `POST /api/projects/load-journal` accept
`mode` (default `replace`). The open job reports `action: opened|appended`.
The journal job clears the library only after the journal yielded cells
(corrupt / empty journal never wipes the loaded set) and offsets groups on
append. cellpy project config is switched only when actually replacing.
- UI: "Append to the loaded cells" checkbox in the Project panel (shown when
cells are loaded); Open / Open path buttons read Append / Append path while
on; replacing a non-empty library asks for confirmation (notes unsaved
changes). Toast "Appended … added to the loaded cells"; append marks the
set dirty. The journal tab of *Add cells…* always appends.
- README ("Projects on disk") and the design doc
`project-refresh-and-import.md` describe both modes.

## Tests

- `tests/test_projects.py`: replace default; append keeps cells, renumbers
groups, carries names, keeps the project association; append into empty;
`group_offset_for_append`; API `mode` (append → groups 4/5, replace, 422
on unknown mode).
- `tests/test_journal.py`: journal append renumbers groups; replace is the
default; corrupt journal under replace keeps the library.
- `tests/test_gui_playwright.py` (e2e): Append toggle → no confirm, two
cells, distinct groups, dirty tag; Open → confirm text, one cell.

Full suite `uv run pytest -q -p no:warnings` green (4 skips).

## Remaining

Nothing for this issue.
28 changes: 28 additions & 0 deletions .issueflows/04-designs-and-guides/project-refresh-and-import.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,31 @@ portable app projects even though `open_project` already accepts absolute paths.

- Client-only path heuristics — rejected; need FS existence checks on the server.
- Auto-watch projects directory — out of scope.

## Open mode: replace vs append (#174)

- Every open — saved project, `project.json` / folder path, batch journal —
carries a `mode`: **`replace`** (default; clears the library first, as the
project open always did) or **`append`**. `projects.OpenMode`, accepted by
`POST /api/projects/open` and `POST /api/projects/load-journal`.
- **Append** keeps the loaded cells and the current project association
(Save still goes to the project that was open; the appended set is marked
dirty). Incoming group numbers are offset by `Library.group_offset_for_append()`
(= highest group in use), so a second project's group 1 becomes `max + 1`
and its internal grouping is preserved; group names (#187) move with the
numbers. Appending into an empty library is just an open.
- **Replace** for journals clears the library only after the journal produced
cells, so a corrupt or empty journal cannot wipe the loaded set. It also
drops the active project's cellpy config (the project is gone).
- cellpy project config (`cellpy.toml`) is only switched when the open actually
replaces; an append reads the incoming cells under the *current* project's
settings. Known limitation: cells from a project pinned to different
settings are appended under the open project's settings.
- UI: one checkbox in the Project panel ("Append to the loaded cells", shown
once cells exist) drives both Open controls; the buttons read "Append" /
"Append path" while it is on. Replacing a non-empty library asks for
confirmation (mentions unsaved changes when dirty). The journal tab of the
*Add cells…* modal always appends — "add" is its whole point.
- Alternatives considered: separate Open / Append buttons (crowds the sidebar
rows); a replace-or-append prompt on every open (one more dialog on the
common path, and it still would not explain the group renumbering).
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,12 @@ current set there and **Open** restores it (physical quantities come from the
`.cellpy` files, organisational metadata from the manifest). Changes in the UI
are **not** written until you Save.

Open **replaces** whatever is loaded (it asks first when cells are loaded). Tick
**Append to the loaded cells** to add a project or batch journal to the current
set instead: its groups are renumbered to start after the highest group already
in use, group names travel along, and the current project stays the one you
Save to. The journal tab of *Add cells…* always appends.

That split is also why Save is quick. Re-saving reuses a `.cellpy` file whenever
the cell it holds provably has not changed — nothing edited it since it was
read, the file is still there, and its size and timestamp still match. Renaming
Expand Down
Loading
Loading