Skip to content

feat: support checkbox type for extension preferences#2720

Open
flash7777 wants to merge 73 commits into
opencloud-eu:mainfrom
flash7777:feature/extension-preference-checkbox
Open

feat: support checkbox type for extension preferences#2720
flash7777 wants to merge 73 commits into
opencloud-eu:mainfrom
flash7777:feature/extension-preference-checkbox

Conversation

@flash7777

Copy link
Copy Markdown

Summary

Extension points can now declare userPreference.type: 'checkbox' to render a checkbox toggle instead of a dropdown select on the account Extensions preferences page.

Motivation

Web extensions that need simple boolean user settings (e.g. "Show Aktenzeichen in folder names") currently have no way to add a toggle to the preferences UI. The only option is a dropdown select, which is awkward for on/off settings.

Changes

File Change
types.ts Add optional type?: 'select' | 'checkbox' to ExtensionPoint.userPreference
ExtensionPreference.vue Render oc-checkbox when type === 'checkbox', existing select behavior unchanged

Usage

// In extension setup:
const extensionPoint = {
  id: 'com.example.my-toggle',
  extensionType: 'customComponent',
  userPreference: {
    label: 'Show extra info',
    description: 'Display additional metadata in folder names',
    type: 'checkbox'
  }
}

For checkbox mode, register two extensions on the point — first = checked state, second = unchecked state. Default type is 'select' (backward compatible).

Test plan

  • Existing select-based extension preferences still work unchanged
  • New checkbox preference renders as toggle on Extensions page
  • Checkbox state persists via extensionPreferencesStore

flash and others added 30 commits June 16, 2026 18:12
New sidebar tab "Metadata" that displays custom metadata (user.oc.md.*)
for the selected file or folder. Fetches data from the Graph API
endpoint GET /drives/{driveID}/items/{itemID}/metadata.

- MetadataPanel.vue: renders key-value pairs with formatted labels
- useFileSideBars.ts: registers panel, visible for single item selection
- Strips "oy." prefix and converts camelCase to Title Case for display

Depends on: OpenCloud Graph API metadata endpoint
1. Resource model: add `immutable` boolean field

2. Indicators (useResourceIndicators.ts):
   - Frozen file: snowflake icon
   - Protected folder: shield-check icon

3. Context menu actions (useFileActionsImmutable.ts):
   - "Freeze file": POST /freeze with confirmation dialog (irreversible!)
   - "Protect folder": POST /protect
   - "Remove protection": DELETE /protect

4. Actions registered in useFileActions.ts for context menu

Depends on: OpenCloud Graph API freeze/protect/unprotect endpoints
(blocked by cs3org/cs3apis#275 - Gateway SetImmutable RPC)
Read oc:immutable property from PROPFIND responses (no extra request).
Reva returns "frozen" (file) or "protected" (folder/inherited) state.

Data flow:
  Reva xattr → GetImmutableState() → oc:immutable property
  → WebDAV PROPFIND → DavProperty.Immutable
  → resource.immutableState ("frozen"|"protected"|undefined)
  → Quick Action icons + Indicator badges

Quick Actions (hover buttons in file list):
  File   | normal    | leaf icon       | click → freeze (confirmation dialog)
  File   | frozen    | snowflake icon  | disabled (irreversible)
  File   | protected | shield-fill     | disabled (parent protected)
  Folder | normal    | shield-line     | click → protect
  Folder | protected | shield-fill     | click → unprotect

Indicators (badges next to filename):
  frozen    → snowflake icon
  protected → shield-fill icon

Changes:
- DavProperty.Immutable added + included in default PROPFIND request
- Resource type: immutableState?: 'frozen' | 'protected'
- Resource builder: maps oc:immutable to immutableState
- useFileActionsImmutable: 5 actions for all state combinations
- useResourceIndicators: indicator based on immutableState
- useFileActions: registered as quickActionsExtensionPoint (not context!)
- immutableState: 'frozen' | 'protected' | 'shielded'
- Quick Actions: shield for protect/unprotect, leaf for freeze
- Indicators: shield-fill (protected), shield-line (shielded), snowflake (frozen)
- Shielded folders can still be protected/unprotected
- console.error if folder has frozen state (bug detection)
- After unprotect: check parent state → set 'shielded' if parent still protected
- Batch protect: select multiple folders → protect all
- Batch unprotect: select multiple protected folders → unprotect all
- No batch freeze (irreversible, single-item only with confirmation)
Move useFileActionsImmutable from web-pkg to web-app-files (where
v7.x actions live). Add SpecialFolderHeader component and
useSpecialFolderView composable for .special/ directory detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Architecture design for hierarchically typed folders with per-type
JSON configs in .space/views/, xattr-based typing, and Module
Federation view handlers deployed under views/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- useTypedFolderSchema: loads .space/views/<type>.json per space (cached)
- useTypedFolderActions: creates typed child folders with type xattr
- GenericSpace: loads folder type via metadata API on navigation
- Type definitions for schema, field defs

No visual changes yet — schema loading and type detection wired up,
typed view rendering comes next.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Architecture document covering:
- .type_<typename> marker files (filesystem-native, no xattr dependency)
- .space/views/<type>.json schema definitions
- .special/ for per-folder overrides
- FolderView UI adapters (generic + specific handlers)
- Schema format, flow diagrams, performance considerations
- Native desktop client compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents the complete Aktenplan structure:
- Types: aktenplan → aktenschrank → akte → vorgang → register
- Aktencode syntax with hierarchical separators (. - / #)
- Protection rules (aktenschrank protected, last level shielded)
- Akte variants (leer, thematisiert, voll)
- Schema JSON definitions for all types
- Aktencode auto-generation with namePattern and seq formatting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces Metadata API type loading with zero-cost detection from
the existing PROPFIND listing. If a .type_<name> file exists among
the folder's children, the type is extracted and the schema loaded.

Shows a typed folder bar with type label when a typed folder is
detected. No extra API call needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…oud)

OpenCloud filters dotfiles from PROPFIND listings, so .type_* markers
are invisible to the web UI. Switch to _type_* which appears in listings.
The FolderView can filter _type_* from display.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces thin badge with a prominent header similar to SpaceHeader:
- Large icon from schema (archive, folder-open, etc.)
- Folder name as heading
- Type badge (Aktenplan, Akte, etc.)
- Entry count (folders only, excluding _type_ markers)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- useFileReferences composable: loads oy.fileReference per child via Metadata API
- Current folder's Aktenzeichen shown in header (monospace)
- Children listed in a table with Aktenzeichen + Name columns
- Batched parallel loading (10 concurrent requests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Hide SpaceHeader when isTyped (no double header)
- Large icon area with space color background (16:9 aspect, like space image)
- Folder name as h2 (like space name)
- Aktenzeichen + type label + entry count inline
- Removed bordered card style, now matches space header layout

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove colored background box. Use oc-icon with variation=passive
inline with heading, matching the clean space header style.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Header shows "11 Innere Verwaltung" instead of just "Innere Verwaltung".
Each folder row in the listing gets its oy.fileReference prefixed to the
name, e.g. "11.03 Finanzverwaltung". Non-typed resources and _type_
markers are unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Aktencode is part of the folder name (e.g. "11.03 Finanzverwaltung"),
not fetched from metadata API. Removes all Metadata API calls per child,
useFileReferences composable, and typedResources computed.

Header shows folder name directly (which already contains Aktencode).
List shows folder names as-is.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t readable)

.space/views/ is not accessible via WebDAV (Reva internal).
_views/ works but clutters the listing.
.views/ is perfect: hidden from listing (dotfile filtered) but
directly readable by path via WebDAV getFileContents.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When _type_<name> is detected but .views/<name>.json is missing or
unreadable, show a warning icon (error-warning, danger) with message
instead of falling back to archive icon silently.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_type_* files are used for type detection only and should not appear
in the file listing. Filter them from displayResources when in typed
folder mode. Untyped folders show all files as before.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two new folder view modes registered at the folder view extension point:

**Tree View** (node-tree icon):
- Expandable tree with lazy-loaded children per folder
- Click arrow to expand, PROPFIND Depth:1 per opened node
- Indented rows showing full hierarchy
- Filters _type_* markers

**Metro Tiles View** (layout-grid icon):
- Colored tiles in a responsive grid
- Deterministic pastel background based on name hash
- Centered icon + name per tile
- Grid columns adapt to viewSize setting

Both views are available in folder and project space contexts
via the view mode switcher.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tree View:
- Table layout with name, size, date columns (like condensed)
- Expand arrows clickable, lazy-loads children via PROPFIND
- Reactive Set/Map for expand state
- Click row navigates to folder

Metro View:
- Colors in CSS classes (not inline styles)
- Bold titles
- Click navigates to folder (correct fileClick emit format)
- Hover scale + shadow effect

Both: correct emit signature { resources, space } matching GenericSpace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Metro:
- Fixed 4:3 aspect ratio tiles (auto-fill grid)
- Click/dblclick emits fileClick correctly
- Simplified emit declarations

Tree:
- Expand arrow separate from row click (arrow=expand, row=navigate)
- Name, size, date columns like condensed view
- Indentation per depth level
- Spinner while loading children

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
flash and others added 30 commits June 18, 2026 16:09
Metro:
- Remove resource-icon from tiles (just bold title)
- Navigate via router.push for folders, emit for files
- Import createFileRouteOptions

Tree:
- Same direct navigation via router.push
- Fixes click not working through dynamic component emit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restores ResourceTable as base (all columns, sorting, quickactions).
Indentation via invisible span with dynamic width in #image slot.
Depth map updated via Promise.resolve() to avoid computed side-effect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Handle SpaceResource items (driveType) in click handler
- Use dashboard-fill icon for Metro view selector (distinct from tiles)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uses the same ContextMenuQuickAction + OcDrop system as ResourceTable.
3-dot button and right-click both select the resource and show the
context menu dropdown with all actions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All other views just emit fileClick and GenericSpace handles
navigation via triggerDefaultAction. No custom router.push,
no ContextMenuQuickAction wrapper. 3-dot button positioned
absolute bottom-right with proper styling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…has no @file-click)

Projects.vue (space listing) doesn't bind @file-click, so emit is lost.
Detect SpaceResource via getDriveAliasAndItem and navigate directly.
Normal folder/file clicks still use emit for GenericSpace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Complete rewrite: anchor elements with real href (accessible, right-click
works). Navigation via router.push for both spaces and folders.
No emit dependency, no pointer-events issues, no context menu complexity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Inherits all functionality from ResourceTiles (clicks, context menu,
space navigation, drag&drop, selection) via pass-through props/events.
Metro styling via unscoped CSS overrides:
- 4:3 aspect ratio tiles
- No thumbnail/preview area
- Bold centered names
- Hover scale + shadow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ox/menu positions

- Background: primary color (blue)
- Text: white, bold, centered
- Checkbox: absolute top-left
- Context menu: absolute bottom-right
- Preview/thumbnail: hidden
- Tile items: position relative for absolute children

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… centered bold name

Only 7 CSS lines:
- Hide preview
- Fill tile with outline-variant color (subtle, theme-aware)
- Center content area
- Center + bold resource name
- No position hacks, no color overrides, no broken context menus

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extension points can now declare `userPreference.type: 'checkbox'`
to render a checkbox toggle instead of a dropdown select on the
account Extensions preferences page.

For checkbox mode, the extension point should have exactly two
extensions registered (enabled/disabled). The first extension
represents the "checked" state.

This enables web extensions to offer simple boolean user settings
(e.g. "Show file reference codes in folder names") without needing
custom UI components or backend settings bundles.

Changes:
- types.ts: add optional `type` field to ExtensionPoint.userPreference
- ExtensionPreference.vue: render oc-checkbox when type is 'checkbox'
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.

1 participant