diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 5c7138f8..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,85 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -MetaVox is a Nextcloud app for adding custom metadata fields to files and groupfolders. PHP backend + Vue 3 frontend. - -- **Nextcloud compatibility**: 31-33 -- **License**: AGPL-3.0-or-later -- **App ID**: `metavox` (namespace `OCA\MetaVox`) - -## Build Commands - -```bash -npm run build # Production build -npm run dev # Development build -npm run watch # Development build with watch -npm run serve # Dev server -``` - -Built JS outputs to `/js/` directory. No test suite or linter is configured. - -## Architecture - -### Frontend (Vue 3) - -The app uses Vue 3 with `@nextcloud/vue` v9 components. No centralized state management — components manage their own state and make API calls directly via `@nextcloud/axios`. - -**Four webpack entry points** (`webpack.config.js`): -- `src/admin.js` → `MetaVoxAdmin.vue` — Admin settings with 6 tabs (Team folder Metadata, File Metadata, Manage Team folders, User Permissions, Retention, Statistics) -- `src/user.js` → `MetaVoxPersonal.vue` — Personal settings page -- `src/filesplugin/filesplugin-main.js` → `FilesSidebarTab.vue` + `RetentionSidebarTab.vue` — Files app sidebar integration (metadata + retention tabs) -- `src/flow/main.js` → `MetadataCheck.vue` — Nextcloud Workflow Engine integration - -**Field input components** in `src/components/fields/`: `DynamicFieldInput.vue` routes to type-specific inputs (Text, Textarea, Number, Date, Select, Checkbox, URL, UserGroup, FileLink). - -**NC33 backwards compatibility**: The files plugin uses a dual registration strategy — tries the new `getSidebar()` API from `@nextcloud/files` first (NC33), falls back to legacy `OCA.Files.Sidebar.registerTab` (NC31-32). The NC33 sidebar tab uses a Custom Element (``) that wraps the Vue app. - -### Backend (PHP) - -Standard Nextcloud app pattern: Controllers → Services → Database. - -- **Controllers** (`lib/Controller/`): `FieldController` (web API), `ApiFieldController` (OCS API), `PermissionController`, `UserFieldController`, `UserController`, `TelemetryController`, `RetentionController` -- **Services** (`lib/Service/`): `FieldService`, `ApiFieldService`, `PermissionService`, `UserFieldService`, `SearchIndexService`, `TelemetryService`, `RetentionService` -- **Event Listeners** (`lib/Listener/`): `FileCopyListener` (NodeCopiedEvent + NodeCreatedEvent), `CacheCleanupListener` (CacheEntryRemovedEvent — cleans metadata, search index, and retention on file removal), `RegisterFlowChecksListener` -- **Background Jobs** (`lib/BackgroundJobs/`): `CleanupDeletedMetadata` (TimedJob), `UpdateSearchIndex` (QueuedJob — added per file on metadata save), `RetentionExecutionJob` (TimedJob — hourly, executes expired retentions), `TelemetryJob` -- **Flow** (`lib/Flow/MetadataCheck.php`): Workflow Engine check with 17+ operators (is, contains, empty, before, after, greater, oneOf, etc.) -- **Search** (`lib/Search/MetadataSearchProvider.php`): Nextcloud unified search integration -- **Bootstrap** (`lib/AppInfo/Application.php`): Registers listeners, search provider, background jobs; conditionally loads filesplugin JS only on Files app pages - -### Dual API Pattern - -Both APIs share the same service layer but differ in authentication: -1. **Web API** (`/api/*`) — CSRF-protected, used by Vue frontend -2. **OCS API** (`/ocs/v2.php/apps/metavox/api/v1/*`) — Token-based, for external integrations - -Routes defined in `appinfo/routes.php`. OCS routes include batch operations (bulk update/delete/copy). - -### Database Tables - -- `metavox_gf_fields` — Groupfolder field definitions -- `metavox_gf_metadata` — Groupfolder-level metadata values -- `metavox_file_gf_meta` — File-level metadata within groupfolders -- `metavox_gf_assigns` — Field-to-groupfolder assignments -- `metavox_permissions` — User/group permissions -- `metavox_search_index` — Full-text search index -- `metavox_ret_policies` — Retention policy definitions -- `metavox_ret_terms` — Retention terms per policy (duration, action) -- `metavox_ret_assigns` — Policy-to-groupfolder assignments -- `metavox_ret_files` — Per-file retention selections (with pre-calculated expires_at) -- `metavox_ret_log` — Retention execution audit log - -Migrations in `lib/Migration/` (version-based, latest: `Version20250101000012`). - -## Internationalization - -Translations in `/l10n/` (nl.json, de.json). Use `t('metavox', 'text')` in Vue components via `@nextcloud/l10n`. - -## Removed Features (do not re-add) - -- License system (LicenseController, LicenseService) -- Filter functionality (FilterController, FilesFilterPanel) -- Global fields (only groupfolder fields are used) -- Field overrides diff --git a/package-lock.json b/package-lock.json index 33ab661f..ec1ed751 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "metavox", - "version": "1.6.0", + "version": "1.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "metavox", - "version": "1.6.0", + "version": "1.5.0", "license": "AGPL-3.0-or-later", "dependencies": { "@nextcloud/auth": "^2.5.0", @@ -68,7 +68,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -3732,7 +3731,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3759,7 +3757,6 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -4131,7 +4128,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7809,7 +7805,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -7971,9 +7966,9 @@ } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8361,7 +8356,6 @@ "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -9164,8 +9158,7 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tsyringe": { "version": "4.10.0", @@ -9502,7 +9495,6 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.27.tgz", "integrity": "sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw==", "license": "MIT", - "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.27", "@vue/compiler-sfc": "3.5.27", @@ -9657,7 +9649,6 @@ "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -9707,7 +9698,6 @@ "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1",