Repository navigation
feat(tiles): a tile opens its office network address at the office, and administrators set the office networks - #787
Open
rubenvdlinde wants to merge 45 commits into
Open
rubenvdlinde wants to merge 45 commits into
rubenvdlinde wants to merge 45 commits into
Conversation
…ly, by most or last used, or at random Most and last used read counts kept in the viewer's own browser, never sent to the server; a viewer can forget them. The order is applied when the page is viewed and never written back, and random holds for the page load. REQ-TSO-001..004, REQ-CONT-007 (launcher-tile-sorting)
…ile-sort are built
…ends a query straight to a site
search_shortcuts holds up to 30 entries {prefix, name, urlTemplate}; a prefix is !
and 1 to 10 letters or digits, unique; the address passes the https {query} check
the quick-search fallback already uses. The list reaches every page through the
workspace initial state.
REQ-QSP-001, REQ-QSP-002 (search-ai-prefix-shortcuts)
…d ? lists the shortcuts In the search widget a query whose first word is a shortcut prefix shows one result, Search TOPdesk for printer, and Enter opens the site in a new tab; an unknown prefix filters tiles as before; ! or ? lists the shortcuts. Administrators edit the list on a new admin tab. REQ-SPX-001..003 (search-ai-prefix-shortcuts)
…d-fields' into feat/launcher-tile-sorting
…ncher-tile-sorting
…ming a group of tiles The browser reads the file (Firefox, Chrome and Edge exports), shows folders and loose bookmarks to pick from, and refuses files over 5 MB or 2,000 bookmarks. The server keeps only http and https addresses and lists the rest as skipped, checks the widget quota once for the whole import (409 names the room left), and creates a container of link tiles per folder plus loose tiles at the bottom in one transaction. The entry sits in the active dashboard's menu for people who may add widgets. REQ-BMI-001..004 (launcher-bookmark-import)
…carry an address for inside the office office_networks holds IPv4 and IPv6 ranges, validated with Nextcloud's IP factory; the server decides from the request address and tells the page onOfficeNetwork. A tile's content.internalUrl must be an http or https address or a path on this Nextcloud, or the update is refused. REQ-TIA-001, REQ-TIA-002 (launcher-tile-internal-address)
…nd administrators set the office networks The tile editor gets "Address on the office network" and says which address the author gets right now; the tile opens the internal address only when the server says the request comes from an office network. A new admin tab lists the ranges and names the administrator's own address. REQ-TIA-001..003 (launcher-tile-internal-address)
…ncher-tile-sorting
… feat/search-ai-prefix-shortcuts
… into feat/launcher-bookmark-import
…e tile wrapper is not a fake control (gate-32)
… feat/search-ai-prefix-shortcuts
…ncher-tile-sorting
…ort endpoint couples to 13 types (phpmd)
…ress check under the phpmd limits
rubenvdlinde
requested review from
Rem-Dam,
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
October 5, 2026 17:28
…ncher-tile-sorting
…admin, refusals and an invalid list
Contributor
Quality Report — ConductionNL/launchpad @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 636/636 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ❌ |
Quality workflow — 2026-10-05 18:13 UTC
Download the full PDF report from the workflow artifacts.
…tile-sorting # Conflicts: # l10n/be.js # l10n/be.json # l10n/bg.js # l10n/bg.json # l10n/bs.js # l10n/bs.json # l10n/ca.js # l10n/ca.json # l10n/cs.js # l10n/cs.json # l10n/da.js # l10n/da.json # l10n/de.js # l10n/de.json # l10n/el.js # l10n/el.json # l10n/en.js # l10n/en.json # l10n/es.js # l10n/es.json # l10n/et.js # l10n/et.json # l10n/fi.js # l10n/fi.json # l10n/fr.js # l10n/fr.json # l10n/ga.js # l10n/ga.json # l10n/hr.js # l10n/hr.json # l10n/hu.js # l10n/hu.json # l10n/is.js # l10n/is.json # l10n/it.js # l10n/it.json # l10n/lb.js # l10n/lb.json # l10n/lt.js # l10n/lt.json # l10n/lv.js # l10n/lv.json # l10n/mk.js # l10n/mk.json # l10n/mt.js # l10n/mt.json # l10n/nb.js # l10n/nb.json # l10n/nl.js # l10n/nl.json # l10n/pl.js # l10n/pl.json # l10n/pt.js # l10n/pt.json # l10n/rm.js # l10n/rm.json # l10n/ro.js # l10n/ro.json # l10n/ru.js # l10n/ru.json # l10n/sk.js # l10n/sk.json # l10n/sl.js # l10n/sl.json # l10n/sq.js # l10n/sq.json # l10n/sr.js # l10n/sr.json # l10n/sv.js # l10n/sv.json # l10n/tr.js # l10n/tr.json # l10n/uk.js # l10n/uk.json
…shortcuts # Conflicts: # l10n/be.js # l10n/be.json # l10n/bg.js # l10n/bg.json # l10n/bs.js # l10n/bs.json # l10n/ca.js # l10n/ca.json # l10n/cs.js # l10n/cs.json # l10n/da.js # l10n/da.json # l10n/de.js # l10n/de.json # l10n/el.js # l10n/el.json # l10n/en.js # l10n/en.json # l10n/es.js # l10n/es.json # l10n/et.js # l10n/et.json # l10n/fi.js # l10n/fi.json # l10n/fr.js # l10n/fr.json # l10n/ga.js # l10n/ga.json # l10n/hr.js # l10n/hr.json # l10n/hu.js # l10n/hu.json # l10n/is.js # l10n/is.json # l10n/it.js # l10n/it.json # l10n/lb.js # l10n/lb.json # l10n/lt.js # l10n/lt.json # l10n/lv.js # l10n/lv.json # l10n/mk.js # l10n/mk.json # l10n/mt.js # l10n/mt.json # l10n/nb.js # l10n/nb.json # l10n/nl.js # l10n/nl.json # l10n/pl.js # l10n/pl.json # l10n/pt.js # l10n/pt.json # l10n/rm.js # l10n/rm.json # l10n/ro.js # l10n/ro.json # l10n/ru.js # l10n/ru.json # l10n/sk.js # l10n/sk.json # l10n/sl.js # l10n/sl.json # l10n/sq.js # l10n/sq.json # l10n/sr.js # l10n/sr.json # l10n/sv.js # l10n/sv.json # l10n/tr.js # l10n/tr.json # l10n/uk.js # l10n/uk.json # lib/Controller/PageController.php # lib/Db/AdminSettingKey.php # lib/Service/InitialStateBuilder.php # src/components/admin/AdminSettings.vue # src/utils/loadInitialState.js
Assisted-by: ClaudeCode:claude-opus-5-5
…kmark-import # Conflicts: # l10n/be.js # l10n/be.json # l10n/bg.js # l10n/bg.json # l10n/bs.js # l10n/bs.json # l10n/ca.js # l10n/ca.json # l10n/cs.js # l10n/cs.json # l10n/da.js # l10n/da.json # l10n/de.js # l10n/de.json # l10n/el.js # l10n/el.json # l10n/en.js # l10n/en.json # l10n/es.js # l10n/es.json # l10n/et.js # l10n/et.json # l10n/fi.js # l10n/fi.json # l10n/fr.js # l10n/fr.json # l10n/ga.js # l10n/ga.json # l10n/hr.js # l10n/hr.json # l10n/hu.js # l10n/hu.json # l10n/is.js # l10n/is.json # l10n/it.js # l10n/it.json # l10n/lb.js # l10n/lb.json # l10n/lt.js # l10n/lt.json # l10n/lv.js # l10n/lv.json # l10n/mk.js # l10n/mk.json # l10n/mt.js # l10n/mt.json # l10n/nb.js # l10n/nb.json # l10n/nl.js # l10n/nl.json # l10n/pl.js # l10n/pl.json # l10n/pt.js # l10n/pt.json # l10n/rm.js # l10n/rm.json # l10n/ro.js # l10n/ro.json # l10n/ru.js # l10n/ru.json # l10n/sk.js # l10n/sk.json # l10n/sl.js # l10n/sl.json # l10n/sq.js # l10n/sq.json # l10n/sr.js # l10n/sr.json # l10n/sv.js # l10n/sv.json # l10n/tr.js # l10n/tr.json # l10n/uk.js # l10n/uk.json # src/views/Views.vue
…internal-address # Conflicts: # l10n/be.js # l10n/be.json # l10n/bg.js # l10n/bg.json # l10n/bs.js # l10n/bs.json # l10n/ca.js # l10n/ca.json # l10n/cs.js # l10n/cs.json # l10n/da.js # l10n/da.json # l10n/de.js # l10n/de.json # l10n/el.js # l10n/el.json # l10n/en.js # l10n/en.json # l10n/es.js # l10n/es.json # l10n/et.js # l10n/et.json # l10n/fi.js # l10n/fi.json # l10n/fr.js # l10n/fr.json # l10n/ga.js # l10n/ga.json # l10n/hr.js # l10n/hr.json # l10n/hu.js # l10n/hu.json # l10n/is.js # l10n/is.json # l10n/it.js # l10n/it.json # l10n/lb.js # l10n/lb.json # l10n/lt.js # l10n/lt.json # l10n/lv.js # l10n/lv.json # l10n/mk.js # l10n/mk.json # l10n/mt.js # l10n/mt.json # l10n/nb.js # l10n/nb.json # l10n/nl.js # l10n/nl.json # l10n/pl.js # l10n/pl.json # l10n/pt.js # l10n/pt.json # l10n/rm.js # l10n/rm.json # l10n/ro.js # l10n/ro.json # l10n/ru.js # l10n/ru.json # l10n/sk.js # l10n/sk.json # l10n/sl.js # l10n/sl.json # l10n/sq.js # l10n/sq.json # l10n/sr.js # l10n/sr.json # l10n/sv.js # l10n/sv.json # l10n/tr.js # l10n/tr.json # l10n/uk.js # l10n/uk.json # lib/Controller/PageController.php # lib/Db/AdminSettingKey.php # lib/Service/InitialStateBuilder.php # src/components/admin/AdminSettings.vue # src/utils/loadInitialState.js
Contributor
Quality Report — ConductionNL/launchpad @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| format | ❌ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 107/107 | |||
| npm | ❌ | ✅ 636/636 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ❌ |
Quality workflow — 2026-10-23 05:24 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Change
launcher-tile-internal-address(archived in this PR atopenspec/changes/archive/2026-09-30-launcher-tile-internal-address). Stacked on #786 (feat/launcher-bookmark-import): this branch contains every PR below it. Land the stack in order, or land the top PR with a merge commit and the ones below close with it.GET/PUT /api/admin/office-networks, admin only.IRequest::getRemoteAddress(), trusted proxies applied) and tells the pageonOfficeNetwork; a tile with an office address opens it only then. The browser never probes internal hosts. With no ranges set nothing changes.Rows moved to
built: d-internal-url (built.change=openspec/changes/archive/2026-09-30-launcher-tile-internal-address). The spec delta is folded into the main spec; the design records what the build corrected.Tests (red first)
tests/Unit/Service/OfficeNetworkServiceTest.php(IPv4, IPv6, empty list, malformed range stores nothing, unparsable remote address), with a CIDR double;tests/Unit/Database/OfficeNetworkLiveTest.phpchecks the same ranges with Nextcloud's own IP factory where CI boots Nextcloudtests/Unit/Service/TileInternalAddressTest.phpthrough the real PlacementService, PlacementUpdater and TileUpdater (valid addresses stored, invalid ones refuse the update with nothing written)tests/Unit/Service/InitialStateBuilderTest.php,src/components/__tests__/TileWidget.internalAddress.spec.js,src/components/admin/tabs/__tests__/OfficeNetworksTab.spec.jsPlaywright tasks are not written; the specs carry
@e2e excludenaming these files.Verified
Version002012).feat/launcher-tile-internal-address): npm lint, format, check:manifest, check:schema-l10n, l10n-parity and Vitest (963 of 963) all 0 on 7579477; the later source changes are three@speccomments (eslint 0 on those files).composer check:strict(lint, phpcs, phpmd, psalm, phpstan, PHPUnit 1948 tests, 14 skipped database tests that run in CI) and phpmetrics: 0 on 4a17769, after fixing six phpmd findings the stack introduced: BookmarkImportController coupling and static access (4e44727),PageController::index()length andTileUpdatercomplexity (4a17769).--require-full-coverage) on b2005d8: 85 of 86 applicable gates pass. Gate 16 found four untagged hooks, fixed where they were introduced (tile sorting, shortcuts, bookmarks). Gate 23 fails with the one match development itself has (PermissionService,RoleFeaturePermissionService, rule consume-or-rbac-fleet-wide); inherited, not touched here, and waiting on a decision.Live check
Admin settings, LaunchPad, "Office networks": add the range your own address is in, save: the tab says your address is on the office network. Edit a tile with main address
https://zaken.gemeente.nl, set "Address on the office network" tohttp://zaken.intern: the editor says this tile opens the internal address; the tile's link ishttp://zaken.intern. Remove the range: the tile opens the main address again. Entering10.20.0.0/40is refused.