Skip to content

Migrate the frontend to the Nextcloud UI framework (@nextcloud/vue) — staged epic #259

Description

@Martin-1997

Migrate the frontend to the Nextcloud UI framework (@nextcloud/vue) — staged epic

Context

The frontend is a legacy jQuery multi-page app: ~3,100 lines of hand-written jQuery across 9 webpack entry bundles (timer, clients, dashboard, projects, reports, tags, goals, timelines, timelines-admin), each hydrating a server-rendered PHP template and calling the existing controllers. Runtime dependencies are all jQuery-era plugins: jquery, jquery-migrate, jqueryui, select2, daterangepicker, moment, tabulator-tables, chart.js@2 (EOL), plus a vendored piklor.js color picker.

The PHP backend (lib/) is lean and healthy and should NOT be rewritten — there is already an AjaxController, so the backend is API-ready. This epic migrates only the frontend onto the Nextcloud UI framework (Vue + @nextcloud/vue + @nextcloud/* helpers), turning the app from "server-rendered pages + jQuery" into a Vue SPA calling the existing controllers as JSON endpoints.

Depends on: the repo-size-reduction issue (remove FontAwesome/KingTable) and the testing/CI issue (land CI first so each migration PR is checked).

Goals

  • Remove nearly all runtime npm dependencies, replacing them with the shared, server-provided @nextcloud/vue component library (weight amortised across the instance, not shipped per-app).
  • Collapse the maintenance surface: no jquery-migrate shims, no unmaintained vendored plugins, and automatic theming / dark mode / RTL / accessibility from the native components.
  • Preserve existing behaviour and the existing controller endpoints (no backend rewrite).

Dependency → native replacement map

Current Role Native replacement
jquery, jquery-migrate, jqueryui DOM, dialogs, buttons, widgets Vue + @nextcloud/vue: NcButton, NcModal/NcDialog, NcActions, NcAppNavigation, NcAppContent
select2 searchable dropdowns NcSelect
daterangepicker (+ moment) date-range picking NcDateTimePickerNative / NcDateTimePicker
moment (every view) date format/parse @nextcloud/moment (locale-aware) or dayjs; much can be native Intl
tabulator-tables data tables NcTable where it fits, otherwise a Vue table against the same endpoints
chart.js@2.9.4 (dashboard) donut/pie chart keep, but upgrade to chart.js v4; vue-chartjs wrapper
vendored piklor.js color picker NcColorPicker
PHP templates + jQuery wiring shell, nav, routing NcContent + NcAppNavigation + NcAppContent, @nextcloud/router, @nextcloud/axios, @nextcloud/l10n, @nextcloud/dialogs

Staged plan (one PR per stage; app stays working throughout)

Stage 1 — Tooling & app shell

  • Add @nextcloud/vue, @nextcloud/webpack-vue-config, @nextcloud/axios, @nextcloud/router, @nextcloud/l10n, @nextcloud/dialogs; switch webpack to the Nextcloud Vue config.
  • Create a single SPA entry with NcContentNcAppNavigation (replacing templates/navigation/) + NcAppContent.
  • Wire client-side routing (@nextcloud/router / vue-router) for the existing sections. Initially each route may still embed the legacy view; the shell is the deliverable here.
  • DoD: app loads via the new shell; navigation switches sections; existing views still function.

Stage 2 — Migrate views (one per PR, easiest first)

Each view becomes a Vue component calling the same controller endpoints via @nextcloud/axios. Suggested order:

  • tags (simplest CRUD; introduces NcTable/list pattern + edit via NcModal)
  • clients
  • projects (introduces NcColorPicker, replacing piklor.js)
  • goals
  • timer (main view; timer logic + manual-entry dialog → NcModal, entry inputs → NcTextField)
  • dashboard (chart.js v4 + vue-chartjs; date range → NcDateTimePicker)
  • reports, timelines, timelines-admin (the Tabulator-heavy grids — tackle last)
  • DoD per view: functional parity with the jQuery version (create/edit/delete/filter/aggregate all work); same endpoints; no jQuery imported by that view.

Stage 3 — Retire shared plugins

As each plugin loses its last consumer, remove it:

  • select2NcSelect everywhere, then drop from package.json
  • daterangepickerNcDateTimePicker, then drop
  • jQuery UI dialogs → NcModal/NcDialog, then drop jqueryui
  • Remove jquery + jquery-migrate once no view imports them
  • Upgrade chart.js 2 → 4

Stage 4 — Remove legacy scaffolding

  • Delete the per-page PHP templates in templates/content/ as the SPA owns routing (keep only the SPA host template).
  • Remove now-unused per-page webpack entries.

Acceptance criteria (epic complete)

  • No jquery, jquery-migrate, jqueryui, select2, daterangepicker, piklor.js in the shipped bundle.
  • All views run on @nextcloud/vue, styled/themed natively (dark mode, RTL work automatically).
  • lib/ PHP endpoints unchanged (backend not rewritten).
  • Feature parity verified per view (see testing).

Testing (live instance, per PR)

For every migrated view, verify against the previous behaviour:

  • CRUD flows: create, edit, delete work and persist
  • Filtering / aggregation (reports, timelines) returns identical results — test on PostgreSQL and MySQL/MariaDB, not just SQLite (this app has engine-specific SQL)
  • Timer start/stop and manual entry produce correct durations
  • Dashboard chart renders and matches report totals
  • Project color picker sets/persists colors (piklor → NcColorPicker)
  • No console errors; dark mode and mobile layout render correctly
  • Localisation: German strings still resolve via @nextcloud/l10n

Notes for the implementing agent

  • Split this epic into one PR per checkbox-group (shell, then each view, then each plugin removal). Keep the app shippable after every PR.
  • Do not touch lib/ beyond adding endpoints if a view genuinely needs one; the goal is a frontend swap, not a backend rewrite.
  • Reuse the existing controller routes and response shapes; where a legacy view relied on server-rendered HTML, add a small JSON endpoint rather than changing the data model.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions