Skip to content

2.0.0 - #255

Open
volarname wants to merge 69 commits into
developfrom
feature/#85491/upgrade
Open

2.0.0#255
volarname wants to merge 69 commits into
developfrom
feature/#85491/upgrade

Conversation

@volarname

@volarname volarname commented May 28, 2026

Copy link
Copy Markdown
Contributor

Added

  • Voice Family settings module (#84735) — new DAM entity (list / detail / create / edit) incl. voice bindings sub-list.
  • Active-filter chips on the asset grid — applied sidebar filters show as removable chips in a bar under the toolbar on /assets (reuses common-admin FiltersSelected, teleported from the sidebar scope). The type filter is excluded (it has the dedicated toolbar toggles); the reset button clears the chips; pressing Enter in any sidebar field submits the filter.
  • mainFileInternal asset filter + internal-image support (#73441, #84581).
  • oxlint + oxfmt toolchain (.oxlintrc.json, .oxfmtrc.json, format / lint:oxlint scripts).
  • lightningcss CSS transformer/minifier + browserslist (.browserslistrc, browserslist:update), build.target: es2019.
  • eslint-plugin-vuetify (flat/recommended-v4).
  • unplugin-auto-import — auto-imports vue / vue-router / pinia / useI18n / useVuelidate + a curated set of common-admin helpers/types; generated src/auto-imports.d.ts. Removed ~6.6k lines of import boilerplate across ~530 files.
  • Typed file-based router (vue-router/vite, generated src/typed-router.d.ts, scripts/generate-dts.mjs + generate:dts) + local ESLint rule anzu-local/valid-route-name validating route-name literals against the typed map.
  • Shared anzu ESLint plugin from common-admin (anzu/no-fatal-error-axios-check, anzu/url-params-match-template, anzu/no-deprecated-imports — the last set to warn, 391 hits, cleanup PR pending).
  • ESLint guard against bare validateAll() (no-restricted-syntax) — a bare call discards its boolean and does not block save (QA 85050); callers must gate on it (if (x.validateAll() === false) return) or pass :validation-scope.
  • Manual Rollup chunkingvue-core, vue-i18n, vuetify, common-admin, tiptap, realtime, sentry, vendor-utils chunks with readable filenames (the 1.6 MB monolith chunk is gone).
  • watch-common-admin Vite plugin for local-linked common-admin HMR; build:dev (unminified) script; lint:tsc switched to vue-tsc --build (project references, incremental).
  • Breadcrumbs reworked to explicit <ActionbarWrapper :breadcrumbs> + defineBreadcrumbs(...) (restores multi-level chains, e.g. Podcasts → Podcast detail → Episode).

Changed

  • Vuetify 3 → 4. MD2→MD3 typography, grid props → utility classes, dark/contain props removed, theme-color alpha syntax changed (rgb(var(--v-theme-X), 0.Y)rgb(var(--v-theme-X) / Y%)). A @layer vuetify-core.reset { … } block restores the v3-style universal/form-element reset that v4 dropped. Breaking.
  • vue-router 5 + file-based routing. Manual src/router/routes/ (19 files) + ROUTE constants replaced by a file-based src/pages/ tree ((coreDam) / (common) groups, per-page definePage({ meta })); router guards migrated from next() callbacks to return values. Breaking.
  • Route paths pluralized (admin-cms convention): /asset/assets, /user/users, /author/authors, /podcast/podcasts, … (all entities). Breaking: existing bookmarks to old singular URLs now 404 — no redirect layer was added.
  • @anzusystems/common-admin v2 (/labs API). Imports migrated off the deprecated barrel to @anzusystems/common-admin/labs; filters, datatables, pagination, list-editors and API helpers now use the v2 labs API. Breaking.
  • pinia 3 → 4. Breaking.
  • Domain-driven src/ restructure. New src/domains/<system>/<entity>/{api,components,composables,factory,filter,store,types,valueObject} layout (systems: system/, common/, coreDam/) + cross-system generics in src/shared/. Top-level src/{components,composables,services,stores,types,model,views,utils}/ deleted. ~800 files git mv-moved (history preserved), ~700 import sites rewritten. Breaking.
  • Runtime behaviour: ext-system config access now falls back silently (?. + ?? fallback) where it previously could throw on missing DamExtSystemConfig(Item) fields.
  • Public export create now binds to a licences array (#84735).
  • Author lists ordered by createdAt instead of id.
  • Filter persistence disabled on all admin-dam listsuseFilterHelpers(…, { populateUrlParams: false, storeFiltersLocalStorage: false }) on all 22 datatables. URL-hash / bookmark restoration is unsafe in admin-dam because the ext-system / licence context lives outside the serialized filter (a bookmark can restore filter values from a different ext-system/licence). (admin-cms keeps it on because its scope is a filter field; admin-dam's isn't.)
  • Migrated 140 Vuetify-v4 lint issues automatically + manual v4 fixes.
  • ROUTE.X.Y references (274 spots) replaced with raw route-name literals; ActionbarWrapper uses the strict typed-router types.
  • @vueuse/core / integrations pinned to exact 14.2.1; Auth.tssimpleLogin.ts (case-collision fix); @tsconfig/node22node24; many files reformatted via oxfmt.
  • Cypress e2e specs updated to the pluralized route paths (cy.visit() / cy.urlContains() across 33 spec files).
  • Dependency bumps: vuetify ^3.11.8^4.1.5, vue-router ^5.0.2^5.2.0, pinia ^3.0.4^4.0.2, vue 3.5.283.5.40, vue-i18n ^11.2.8^11.4.7, @anzusystems/common-admin 1.47.0-beta.3541.47.0-beta.dev-1784059866, @tiptap/vue-3 ^3.19.0^3.28.0, @sentry/vue ^10.38.0^10.67.0. Dev tooling also bumped (cypress, sass, vue-tsc, @vitejs/plugin-vue, @stylistic/eslint-plugin, @intlify/unplugin-vue-i18n, eslint-plugin-vue) + dotenv added.

Fixed

  • /assets 403 on hard load / refresh / deep-link. The SPA route /assets collided with the Vite build dir dist/assets/ under nginx try_files; nginx now serves index.html for /assets (docker/app/local/bin/start-command). Production (Cloudflare Pages) was unaffected.
  • Distribution-category create dialog infinite spinner. On a backend 500 for the category-select fetch the dialog hung on a loader; it now clears the loader and shows the standard error alert (distributionCategoryActions.ts). (The underlying core-dam 500 is a separate backend task.)
  • Missing i18n dialog titles. Added the missing coreDam.*.meta.create keys for podcastEpisode / authorCleanPhrase / publicExport (they rendered raw keys).
  • Voice-family detail console error. VoiceBindingsList now provides DatatablePaginationKey (fixes Incorrect provide/inject config. thrown on the detail view).
  • Post-action redirects in distributionCategoryActions / assetLicenceGroupActions fixed (wrong list/domain route — uncovered by the route-reference audit).
  • Podcast export-data temp ids stripped on save.

Removed

  • Prettier (prettier, @vue/eslint-config-prettier) — replaced by oxfmt.
  • src/router/routes/ (19 files) + ROUTE constants; AEmptyRouterView wrappers.
  • Top-level src/{components,composables,services,stores,types,model,views,utils}/ (relocated into src/domains/ / src/shared/).
  • Explicit imports of now-auto-imported symbols; dark / contain prop usages.
  • Non-functional shortestDimension asset filter.

volarname and others added 30 commits February 9, 2026 13:22
 Added:                                                                                                                                                                                                                              
  - Internal image flag support for asset licences (DamAssetLicenceExtended type, internalRule config, override/internal flag switches in asset metadata)
  - Two new job types: jobAssetFileReprocessInternalFlag and jobSynchronizeImageChanged with full create/detail UI
Co-authored-by: Tomas Hermanek <tomas.hermanek@petitpress.sk>
added `mainFileOverrideInternal` and `mainFileInternal` boolean fields in `AssetMetadataBulkItem` for asset metadata updates
… eslint, watch-common-admin, browserslist:update
Reorganize src/ into src/domains/<system>/<entity>/{api,components,
composables,factory,filter,store,types,valueObject} per entity. Three
top-level systems: system/ (auth, app shell, system views), common/
(anzuUser, log, permission, permissionConfig, permissionGroup),
coreDam/ (17 DAM entities + shared/ slot for cross-entity DAM code:
anzutap, ColorBox, FileUpload, customMetadata, ABtnAdvanced,
CachedDamUserChip, FilterClosestColor, distribution helpers,
assetFileRoute, upload service).

Cross-system generics moved to src/shared/ (apiClients/, types/,
utils/, EnvConfigService.ts, ErrorHandlerApiService.ts,
BetaTestFeaturesService.ts, systems.ts, configurationApi.ts).

Old top-level folders src/{components,composables,services,stores,
types,model,views,utils}/ deleted entirely. Every move via git mv so
git log --follow traces full history. layouts/, pages/, plugins/,
styles/, locales/, router/ stay at root.

system/auth/Auth.ts -> simpleLogin.ts (Linux case-sensitive collision
with sibling auth.ts composable rejected by TS forceConsistentCasing
InFileNames). Affects only the import path; SimpleLoginForm export
unchanged.

views/coreDam/externalProviderAsset/ consolidated into
domains/coreDam/externalProvider/components/.

eslint.config.mjs: anzu/no-deprecated-imports toggled warn -> off to
keep CI signal clean during restructure; re-enable in dedicated
cleanup PR.
common-admin chunk dropped from 1,113 kB to 4 parts (all <500 kB):
- common-admin (main, 415 kB)
- common-admin-internals (index-*.mjs, 461 kB)
- common-admin-autocomplete (AFormRemoteAutocomplete async chunk, 176 kB)
- common-admin-labs (labs.js, only loaded when used)

vue-i18n + @intlify/* pulled out of vue-core (49 kB own chunk).

New vendor-utils chunk (115 kB) for axios, @vuelidate, @floating-ui,
jwt-decode, universal-cookie, uuid, rusha, sortablejs.

No more "chunks larger than 500 kB" Rollup warning.
volar added 4 commits June 17, 2026 00:00
…mputed

Replace the one-off type alias (added to keep the TS union out of the template
binding, where oxfmt strips the parens and vue-eslint-parser then misreads `|`
as a deprecated Vue filter) with a computed that does the same narrowing in
script. Cleaner and self-explanatory; template binding stays `|`-free so oxfmt
and eslint are both stable.
…in-cms parity)

These are auto-generated by the vite plugins (unplugin-vue-router /
unplugin-auto-import) and regenerated by `generate:dts`, which runs first in
`yarn ci`. Tracking them just produces churn (e.g. ~900-line typed-router diffs)
on every regeneration. admin-cms already gitignores both; match that.
Routine version bumps (already present in the working tree): @anzusystems/common-admin
dev build, @tiptap/* 3.27, axios 1.18, vue 3.5.38, vuetify 4.1.2, @sentry/vue,
vue-i18n; dev tooling oxfmt 0.55, oxlint 1.70, eslint 10.5, vite, vue-tsc, cypress,
@types/node. yarn.lock regenerated to match.
@volarname
volarname force-pushed the feature/#85491/upgrade branch from 3b3c9a9 to 89f5aed Compare June 17, 2026 09:50
volar and others added 16 commits June 28, 2026 17:49
a8da3a0 migrated to props that don't exist in the labs v2 API (item-factory/manage-delete/update-position/@added/@add). Vue treats unknown props/events as silent fall-through, so it type-checked but the Add actions in podcast export-data and asset distributions were dead at runtime, and none of the consumer recipe was applied.

- podcast: drop dead props, restore add via external button + dialog (cancel removes the new row), sort exportData by position at ingress, renumber + adopt response + commit() to re-baseline on save, gate form on !detailLoading
- asset distributions: hide built-in add, add external button opening the type-select dialog
- distributionCategorySelect: migrate off raw useSortable to inline ASortableListEditor; validateAll() save gate, position sort at ingress, renumber + temp-id strip (id stays '' for new in the payload) + response adopt + commit() on save

yarn ci green.
New export-data rows carry a negative temp id for the list-editor key, but core-dam's deserializer treats a non-zero unknown id as a reference to an existing entity (Doctrine then fails with a cascade-persist error on Podcast#exportData). Map negative temp ids to 0 in the save payload so the backend creates them, matching the pre-migration convention and the DistributionCategoryOption handling. Verified end-to-end: add export-data -> save -> 200.
Author ids are UUIDs (DocId), so sorting by id produced an arbitrary
order. Both the author list (useAuthorListActions) and the author
select autocomplete (useAuthorSelectActions) hard-set pagination.sortBy
to 'id' on non-text fetches; default them to createdAt so the newest
authors show first, while keeping relevance ordering for fulltext search.
…ted-at

fix(author): order author list by createdAt instead of id
Route pluralization in #85491 left many singular cy.visit/urlContains
targets that now 404 (no redirect layer). Update asset, podcast,
video-show, user, public-export and distribution-category-select detail
paths plus nav hrefs to the plural routes. API URLs are left unchanged.
The "Najkratšia dimenzia" (shortestDimensionFrom/Until) filter was sent
to the search API but core-dam's AssetQueryFactory never applies it (no
ES clause, field not indexed), so it silently did nothing. Remove the
dead field from the asset list filter config, form and locales.
Conflict in author/composables/authorActions.ts (moved to src/domains on
this branch): kept the new labs-API version. Preserved main's PR #257
intent (order author lists by createdAt): AuthorDatatable.vue now
usePagination('createdAt') instead of SORT_BY_ID. Author select
autocomplete sort stays on common-admin default (pagination built there,
not controllable from admin-dam).
… dev-1782073999

Mirror the admin-cms no-restricted-syntax guard — a bare validateAll() (incl. the awaited form) reveals row errors but does NOT block the save, letting a collapsed invalid row slip through (QA 85050). Bump the @anzusystems/common-admin dev pin to the current labs build (widened ListEditorValidationScope). Audit found no validate-gate bug in admin-dam's list-editor consumers (DistributionCategorySelect gates via the callback; Podcast + asset Distribution are dialog-based).
- BUG-01: serve index.html for the exact /assets path so the main grid no
  longer returns 403 on hard load / refresh / deep-link (the SPA route
  collided with the Vite dist/assets/ build dir under nginx try_files)
- BUG-02: distribution-category create dialog no longer hangs on an infinite
  spinner when the category-select fetch fails; the loader clears and the
  standard error alert is shown (finally reset in prepareData)
- BUG-03: add missing sk/en coreDam.*.meta.create i18n keys for
  podcastEpisode, authorCleanPhrase and publicExport (dialog titles no longer
  render the raw key)
- BUG-05: provide DatatablePaginationKey in VoiceBindingsList so the voice
  bindings sub-list no longer throws "Incorrect provide/inject config." on the
  voice-family detail
- Disable filter URL-hash population and localStorage persistence on all lists
  (useFilterHelpers populateUrlParams:false, storeFiltersLocalStorage:false);
  bookmarking/URL-restoring filter state is unsafe in admin-dam because the
  ext-system/licence context lives outside the filter and is not serialized
- Render active-filter chips (common-admin FiltersSelected) in a bar under the
  toolbar on /assets, teleported from the sidebar filter's provide scope
- Exclude the `type` filter from the chips (render.selected: false, it has the
  dedicated toolbar type toggles)
- Wire the sidebar reset button to also clear the chips

Bump @anzusystems/common-admin to 1.47.0-beta.dev-1784059866: adds the
FiltersSelected export, the render.selected filter-field option, the
AFilterWrapperSidebar reset that clears the selected-filter chips, and
Enter-to-submit for the sidebar filter.
volar added 8 commits August 7, 2026 18:55
…85491)

Fixes 8 of the 10 issues from the QA report. #1 and #8 needed no code change
(both are intentional: the shortestDimension filter was dead — core-dam's
AssetQueryFactory never applied it — and the from/until date pair was
consolidated into one AFilterTimeInterval range control that still exposes
both bounds via its Custom option).

- #5/#6 (blocker): drop the wrong `apiName: 'name'` on the distributionCategorySelect
  service-slug filter. The entity is filterable by `serviceSlug`, so `filter_*[name]`
  made core-dam return 500, which broke opening/creating a distribution category
  and the "Meno" list filter.
- #7: give the anzuUser id/email/enabled/lastName filters a `type`. Without it
  createFilter defaults to 'custom' and FilterDetailItem renders AFilterEmpty —
  the bare field name with no control.
- #3: add `render: { skip: true }` to the field bound in each `#search` slot, so
  it is no longer auto-rendered a second time in the advanced panel (11 configs).
- #4: add a `#search` slot to the 7 list filters that had none, so they get a
  main filter bar again instead of only the "More" button; restore enable-top/#top
  for the mandatory `type` on both distribution-category pages, and hide-more on
  assetLicenceGroup.
- #9: build the distribution filter store per call instead of sharing one
  module-level singleton. DistributionBlockedBy writes distributionServicesIn/NotIn
  into it and never clears them, so the create dialog's refetch emitted a
  self-contradictory `eq X + notIn X` query, and the sidebar list reusing the same
  store came back empty until a full page reload.
- #10: guard JobResourceChip against an unregistered job resource —
  getJobResourceOption is a plain .find() and returns undefined, so `option.title`
  threw on /jobs.
- #2: re-tint the active-filter chips from the Vuetify theme tokens in dark theme;
  common-admin hardcodes a white chip on a light container with no dark variant.

Also updates dependencies (common-admin, vuetify, vue, tiptap, oxlint/oxfmt,
cypress, vue-tsc) and applies the resulting lint/format fixes.
- distribution-category-selects: put `serviceSlug` ("Meno") in the main filter
  bar instead of `id`. `id` is a hidden datatable column
  (datatableHiddenColumns = ['id']), so the restored search bar was filtering by
  a field the user cannot see, and it was inconsistent with the sibling
  distribution-categories page which searches by `name`. `id` stays available
  under "More".
- asset detail distribution panel: wrap getList in try/catch/finally. A failing
  fetch left showLoader() on forever — the panel span forever with no error —
  and the rejection propagated out of the component unhandled. Reproduced
  against devel by forcing the endpoint to 500.
…rs (#85491)

- DistributionCategoryWidget: wrap the category fetch in try/catch/finally. Same
  defect as the distribution sidebar — a failed request left the widget loading
  forever and swallowed the error.
- en/common/model.json: override common-admin's filterPlaceholder, which ships
  Slovak strings in its English bundle. Can be dropped once a common-admin
  release carrying the upstream fix is picked up.
- Trim the two comments added earlier down to one line each.
common-admin 1.47.0-beta.dev-1784059874 ships both fixes, so the local shadows
are dead weight: the dark-theme chip stylesheet and the English filterPlaceholder
override. Verified on devel that the library rules apply on their own.
…ield (#85491)

QA reported the jobs "Ukončenie" filter as removed (#8) and the assets date
filter as reduced to a single field (#1). Neither bound was actually lost:
startedAtFrom/startedAtUntil (and createdAtFrom/Until) are the two ends of one
range and are both reachable through the control's Custom option. The merged
control just kept the "from" label, which hid that. Relabel both to the "od - do"
wording admin-cms already uses for every range filter.

Also drop the `licences` asset filter field. Same dead-filter trap that #1 was
about: core-dam's AssetQueryFactory never reads it, so the API silently returns
unfiltered results (verified: an unknown licence id changes nothing, while
codecName correctly narrows to zero). It has no UI today, so removing it only
prevents someone from wiring up a control that would quietly do nothing.
Audit of both locales. Key parity, ordering and nesting are now identical
across all 35 sk/en file pairs (809 keys each).

User-visible breakage:
- en/error/*: 15 API error messages were placeholder text (the key name plus
  " error") and were shown to users on every forbidden-operation response.
- en asset list: all 8 table headers were raw lowercase field names.
- en distribution: showAdvanced and hideAdvanced both read "Create distribution",
  so the toggle never changed its label.
- sk assetLicence: the internal-rule labels were half English and ungrammatical
  ("Aktívny processing interné", "Procesuj príznak interné od").

Also fixed: leftover English inside Slovak strings (request, Chunky, Similarity
boost); Slovak diacritics and grammar (Klúčové→Kľúčové, Systémova→Systémová,
kontaktuje→kontaktujte, plural endings); English labels that were raw field or
PHP class names, normalised to sentence case; and inconsistent wording where one
concept had two names.

"Meno" now means a person's given name only — entities use "Názov"; author and
user first name intentionally keep "Meno". The login failure alert no longer
claims a specific cause, because it is raised from a catch-all block.

Deliberately left alone: "Appka" and "Video relácie", both consistent across the
app and judged intentional style.
…491)

The ordering dropdown was migrated to @anzusystems/common-admin/labs, whose
`variant` prop defaults to 'id' where the previous non-labs component defaulted
to 'default' (= createdAt). Lists that pass no variant therefore silently
switched from ordering by creation date to ordering by id, which QA saw as
"Najstaršie" not sorting by date and as the two options being swapped.

Sorting by id stays the convention where it is meaningful — it is the indexed
primary key and a higher id means a newer row. Only lists where id is provably
not chronological move to createdAt:
- imported data, where createdAt comes from the source system and does not
  follow the id sequence (user, anzuUser, assetLicence, assetLicenceGroup,
  extSystem) — verified against the API, id order and createdAt order differ
- UUID ids, where the data mixes UUIDv6 and UUIDv7 so lexical order is not
  chronological at all (distributionCategory, distributionCategorySelect,
  author, keyword)

permissionGroup, job, publicExport, authorCleanPhrase and podcastEpisode keep
id: their id order matches createdAt and they are already self-consistent.

Also fixed:
- keyword: every fetch overwrote the sort with a hardcoded createdAt ASC, so the
  list ignored the dropdown and could never show newest first. The sort is now
  dropped only while a text search is active, and the user's choice is restored
  when the search is cleared.
- author: the same relevance behaviour had been lost entirely in the migration,
  so a text search still ordered by date instead of by score.
- videoShowEpisode: the list loads by position but the dropdown offered only id,
  so its label claimed something the list did not do. Added a "by position"
  option matching the actual initial sort.
- ttsNarrationRequest: started with no sort while showing an id-based label.
- distributionCategory: the id filter was typed as integer although the entity
  id is a UUID, and a second category-select fetch path still pinned id.

Also bumps common-admin and dev dependencies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants