Skip to content

Comments

feat(wikibase-schema-editor): add qualifiers editor#94

Merged
DaxServer merged 1 commit intomainfrom
wikibase-editor-task20
Jul 31, 2025
Merged

feat(wikibase-schema-editor): add qualifiers editor#94
DaxServer merged 1 commit intomainfrom
wikibase-editor-task20

Conversation

@DaxServer
Copy link
Owner

Addresses Tasks 20, 21 of #66

@coderabbitai
Copy link

coderabbitai bot commented Jul 31, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added the ability to manage qualifiers for statements, including adding, editing, and removing qualifiers within the statement editor.
    • Introduced a dedicated Qualifiers Editor component with drag-and-drop support and validation for qualifier properties and values.
    • Qualifiers are now displayed in statement previews for enhanced visibility.
  • Bug Fixes

    • Improved synchronization between qualifier state and statement updates to ensure consistent editing experience.
  • Tests

    • Updated tests to reflect changes in statement creation and qualifier management.

Walkthrough

This change introduces full support for editing, managing, and displaying qualifiers on statements within the Wikibase schema editor. It adds a new QualifiersEditor Vue component, integrates qualifier management into StatementEditor and WikibaseSchemaEditor, updates the schema builder composable and store to handle qualifiers, and adapts related tests and type declarations.

Changes

Cohort / File(s) Change Summary
Task Checklist Update
.kiro/specs/wikibase-schema-editor/tasks.md
Marked tasks for statement rank selection, QualifiersEditor component, and qualifier value mapping as completed.
Global Component Declaration
frontend/components.d.ts
Declared QualifiersEditor as a global Vue component.
New Qualifiers Editor Component
frontend/src/components/QualifiersEditor.vue
Added a Vue 3 component for managing qualifiers on statements, with props, events, validation, and drag-and-drop support.
Statement Editor Integration
frontend/src/components/StatementEditor.vue
Integrated qualifier management and preview into the statement editor, handling local state and emitting updates.
Schema Editor Integration
frontend/src/components/WikibaseSchemaEditor.vue
Added logic to track, update, and save statements with qualifiers in the schema editor.
Schema Builder Enhancement
frontend/src/composables/useSchemaBuilder.ts
Updated buildStatement to accept qualifiers and references as parameters.
Store API and Logic Update
frontend/src/stores/schema.store.ts
Extended store API to support qualifiers in statements; added functions to add, update, and remove qualifiers.
Test Update for Store
frontend/src/stores/__tests__/schema.store.test.ts
Updated test to match new buildStatement signature with qualifiers and references parameters.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WikibaseSchemaEditor
    participant StatementEditor
    participant QualifiersEditor
    participant SchemaStore

    User->>WikibaseSchemaEditor: Edit or add statement
    WikibaseSchemaEditor->>StatementEditor: Pass statement (with qualifiers)
    StatementEditor->>QualifiersEditor: Pass qualifiers, columns, handlers

    User->>QualifiersEditor: Add/Remove/Update qualifier
    QualifiersEditor-->>StatementEditor: Emit qualifier event (add/remove/update)
    StatementEditor-->>WikibaseSchemaEditor: Emit updated statement (with qualifiers)
    WikibaseSchemaEditor->>SchemaStore: Save/update statement with qualifiers
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch wikibase-editor-task20

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (2)
frontend/src/components/WikibaseSchemaEditor.vue (1)

263-269: Direct array mutation bypasses store encapsulation.

The direct mutation of schemaStore.statements[statementIndex] bypasses the store's intended API and could cause reactivity or state management issues.

Use store methods for statement updates:

-    schemaStore.statements[statementIndex] = {
-      ...schemaStore.statements[statementIndex],
-      property: currentStatement.property,
-      value: currentStatement.value,
-      rank: currentStatement.rank,
-      qualifiers: currentStatement.qualifiers || [],
-    }
+    schemaStore.updateStatement(editingStatementId.value, {
+      property: currentStatement.property,
+      value: currentStatement.value,
+      rank: currentStatement.rank,
+      qualifiers: currentStatement.qualifiers || [],
+    })

This requires adding an updateStatement method to the schema store if it doesn't exist.

frontend/src/stores/schema.store.ts (1)

3-10: Missing import for QualifierSchemaMapping and ReferenceSchemaMapping types.

The file uses QualifierSchemaMapping and ReferenceSchemaMapping types in function signatures but doesn't import them. Based on the relevant code snippets, these types are defined in @frontend/types/wikibase-schema.

Add the missing imports:

import type {
  StatementSchemaMapping,
  ColumnMapping,
  PropertyReference,
  ValueMapping,
  StatementRank,
  Label,
+ QualifierSchemaMapping,
+ ReferenceSchemaMapping,
} from '@frontend/types/wikibase-schema'
🧹 Nitpick comments (2)
frontend/src/components/WikibaseSchemaEditor.vue (1)

238-251: Consider consolidating state management to avoid duplication.

The dual state management approach (maintaining both currentStatementWithQualifiers and calling initializeStatement) creates redundancy and potential synchronization issues.

Consider either:

  1. Fully migrating to the new state structure and updating the composable
  2. Or extending the existing composable to handle qualifiers directly

This would reduce complexity and eliminate the need for backward compatibility bridges.

frontend/src/components/QualifiersEditor.vue (1)

355-355: Direct mutation of reactive object property.

The clear column functionality directly mutates selectedValue.source.columnName, which works but is inconsistent with the pattern used in StatementEditor where a dedicated handleClearColumn method is used.

Consider creating a dedicated method for consistency:

+const handleClearColumn = () => {
+  if (selectedValue.value?.type === 'column') {
+    selectedValue.value.source.columnName = ''
+  }
+}

Then update the template:

-@click="selectedValue.source.columnName = ''"
+@click="handleClearColumn"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00b416f and 2c5831f.

📒 Files selected for processing (8)
  • .kiro/specs/wikibase-schema-editor/tasks.md (1 hunks)
  • frontend/components.d.ts (1 hunks)
  • frontend/src/components/QualifiersEditor.vue (1 hunks)
  • frontend/src/components/StatementEditor.vue (8 hunks)
  • frontend/src/components/WikibaseSchemaEditor.vue (6 hunks)
  • frontend/src/composables/useSchemaBuilder.ts (1 hunks)
  • frontend/src/stores/__tests__/schema.store.test.ts (1 hunks)
  • frontend/src/stores/schema.store.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript or JavaScript files
Do not use dotenv; Bun automatically loads .env files
Use Bun.serve() for HTTP servers and WebSockets instead of express
Use bun:sqlite for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of ws
Prefer Bun.file over node:fs's readFile/writeFile
Use Bun.$ (e.g., Bun.$ls``) instead of execa for running shell commands

Files:

  • frontend/components.d.ts
  • frontend/src/composables/useSchemaBuilder.ts
  • frontend/src/stores/__tests__/schema.store.test.ts
  • frontend/src/stores/schema.store.ts
**/*.{html,ts,tsx,css}

📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file.html|file.ts|file.css> instead of webpack or esbuild for building HTML, TypeScript, or CSS files

Files:

  • frontend/components.d.ts
  • frontend/src/composables/useSchemaBuilder.ts
  • frontend/src/stores/__tests__/schema.store.test.ts
  • frontend/src/stores/schema.store.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun test instead of jest for running tests

Files:

  • frontend/src/stores/__tests__/schema.store.test.ts
🧠 Learnings (2)
frontend/components.d.ts (11)

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.vue : Props and emits must use explicit TypeScript interfaces

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.{ts,vue} : Type safety everywhere

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.vue : Build reusable, well-structured components

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.vue : Use auto-imports for Vue, Pinia, composables, and utilities

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.vue : Use Vue 3 with Composition API and <script setup lang="ts"> in all Vue components

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.vue : Use PrimeVue as the UI library in all Vue components

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.vue : Use v-memo, shallowRef, markRaw, and Suspense for performance optimization

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.{vue,ts} : Use readonly and shallowReactive for large or expensive data

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.{vue,ts} : Use Pinia stores for global state

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.{vue,ts} : Handle errors and loading states reactively when making API calls

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.{vue,ts} : Use useApi composable (Elysia Eden) for all API calls

frontend/src/components/QualifiersEditor.vue (2)

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.vue : Use Vue 3 with Composition API and <script setup lang="ts"> in all Vue components

Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/frontend-setup.rule.md:0-0
Timestamp: 2025-07-20T14:13:24.706Z
Learning: Applies to src/**/*.vue : Props and emits must use explicit TypeScript interfaces

🧬 Code Graph Analysis (2)
frontend/src/composables/useSchemaBuilder.ts (1)
frontend/src/types/wikibase-schema.ts (3)
  • QualifierSchemaMapping (141-144)
  • ReferenceSchemaMapping (146-149)
  • StatementSchemaMapping (109-116)
frontend/src/stores/schema.store.ts (1)
frontend/src/types/wikibase-schema.ts (2)
  • QualifierSchemaMapping (141-144)
  • ReferenceSchemaMapping (146-149)
🔇 Additional comments (26)
frontend/components.d.ts (1)

34-34: LGTM! Component declaration follows established pattern.

The addition of the QualifiersEditor component declaration is correctly formatted and consistent with other component declarations in this auto-generated file.

.kiro/specs/wikibase-schema-editor/tasks.md (1)

114-132: LGTM! Task completion tracking is accurate.

The completion of tasks 19, 20, and 21 properly reflects the implementation of the qualifiers editor feature, including:

  • Statement rank selection functionality
  • QualifiersEditor component creation
  • Qualifier value mapping implementation

This aligns well with the PR objectives addressing Tasks 20 and 21 of issue #66.

frontend/src/stores/__tests__/schema.store.test.ts (1)

360-360: LGTM! Test expectation updated correctly for expanded buildStatement signature.

The test properly reflects the updated buildStatement function signature that now accepts qualifiers and references parameters, maintaining accurate test coverage.

frontend/src/composables/useSchemaBuilder.ts (1)

78-93: Good API extension design with backward compatibility.

The function signature expansion to support qualifiers and references is well-designed:

  • Maintains backward compatibility with default empty arrays
  • Clean parameter assignment to the returned object
  • Follows consistent naming conventions
frontend/src/components/WikibaseSchemaEditor.vue (1)

273-279: Good integration of qualifier support in statement creation.

The addition of qualifiers to the addStatement call properly extends the functionality while providing sensible defaults.

frontend/src/stores/schema.store.ts (5)

96-104: Good implementation of extended addStatement function.

The function signature properly defaults the new parameters to empty arrays and correctly passes them to the buildStatement function. This maintains backward compatibility while enabling qualifier support.


124-131: LGTM! Proper implementation of updateStatementQualifiers.

The function correctly finds the statement by ID, updates the qualifiers array, and marks the store as dirty. The implementation follows the established pattern used by other update functions in the store.


133-140: LGTM! Proper implementation of addQualifierToStatement.

The function correctly finds the statement and appends the qualifier to the qualifiers array. State management is handled appropriately.


142-149: Good bounds checking in removeQualifierFromStatement.

The function includes proper bounds checking to prevent array access errors and follows the established pattern for array modifications in the store.


213-215: Verify all new functions are properly exposed.

All three new qualifier management functions are correctly included in the store's return object, making them available to components.

frontend/src/components/StatementEditor.vue (8)

8-8: Good TypeScript interface design for qualifiers support.

The props interface properly includes the optional qualifiers array with correct typing, and the default value is appropriately set to an empty array.

Also applies to: 26-26


39-39: Consistent emit interface extension.

The emit interface correctly includes qualifiers in the update event, maintaining type safety and consistency with the props interface.


92-96: Proper local state management for qualifiers.

The temporary statement ID generation using crypto.randomUUID() is appropriate for qualifier management, and the local qualifiers state is properly initialized from props.


100-104: Good state synchronization in emitUpdate.

The emit function correctly spreads the local statement and includes the current qualifiers, ensuring parent components receive complete state updates.


157-179: Well-implemented qualifier event handlers.

All three qualifier handling methods properly manage the local qualifiers array and emit updates. The bounds checking in handleRemoveQualifier prevents array access errors.


198-205: Proper watcher implementation for qualifiers synchronization.

The watcher correctly synchronizes local qualifiers state with prop changes, ensuring the component stays in sync with external updates. The deep watch with immediate execution is appropriate.


425-436: Good integration of QualifiersEditor component.

The QualifiersEditor is properly integrated with all necessary props and event handlers. The use of tempStatementId for qualifier management is appropriate.


474-500: Excellent qualifiers preview implementation.

The preview section provides clear visual feedback showing qualifier properties, values, and data types. The conditional rendering and consistent styling align well with the existing UI patterns.

frontend/src/components/QualifiersEditor.vue (8)

1-28: Excellent TypeScript interfaces and component setup.

The component follows Vue 3 Composition API best practices with explicit TypeScript interfaces for props and emits. The interfaces are well-structured and type-safe, following the established patterns from the retrieved learnings.


49-66: Robust validation logic for qualifiers.

The validation functions properly check for property ID format (starting with 'P') and non-empty values. The computed property canAddQualifier correctly combines both validations to control the add button state.


81-93: Smart property change handling with data type suggestion.

The handlePropertyChange function intelligently resets the value when the property changes and auto-suggests the appropriate data type based on the property's data type. This provides good UX by reducing manual configuration.


115-131: Good integration with data type compatibility system.

The handleColumnDrop function properly uses the existing useDataTypeCompatibility composable to suggest compatible Wikibase data types, ensuring consistency with the rest of the application.


133-143: Proper qualifier creation and emission.

The addQualifier function includes validation checks, creates a properly typed qualifier object, emits the event with correct parameters, and cleans up the form state. The implementation is robust and follows good practices.


198-258: Excellent qualifiers list implementation.

The existing qualifiers list provides clear visual representation with property tags, value information, and data types. The layout is consistent and includes proper action buttons with tooltips.


260-396: Comprehensive add qualifier form.

The form includes proper validation, clear labeling with required field indicators, consistent styling, and good user experience patterns. The conditional rendering based on state is well-implemented.


398-414: User-friendly empty state design.

The empty state provides clear guidance to users about what qualifiers are and how to add them. The visual design with icons and descriptive text follows good UX practices.

Comment on lines +82 to +83
qualifiers: QualifierSchemaMapping[] = [],
references: ReferenceSchemaMapping[] = [],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing imports for new parameter types.

The function signature uses QualifierSchemaMapping and ReferenceSchemaMapping types that are not imported. This will cause TypeScript compilation errors.

Add the missing imports to the import statement:

 import type {
   WikibaseSchemaMapping,
   ItemSchemaMapping,
   TermsSchemaMapping,
   StatementSchemaMapping,
+  QualifierSchemaMapping,
+  ReferenceSchemaMapping,
   Label,
   ColumnMapping,
   PropertyReference,
   ValueMapping,
   StatementRank,
 } from '@frontend/types/wikibase-schema'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
qualifiers: QualifierSchemaMapping[] = [],
references: ReferenceSchemaMapping[] = [],
import type {
WikibaseSchemaMapping,
ItemSchemaMapping,
TermsSchemaMapping,
StatementSchemaMapping,
QualifierSchemaMapping,
ReferenceSchemaMapping,
Label,
ColumnMapping,
PropertyReference,
ValueMapping,
StatementRank,
} from '@frontend/types/wikibase-schema'
🤖 Prompt for AI Agents
In frontend/src/composables/useSchemaBuilder.ts around lines 82 to 83, the types
QualifierSchemaMapping and ReferenceSchemaMapping are used but not imported,
causing TypeScript errors. Fix this by adding import statements for these types
from their respective modules at the top of the file where other imports are
declared.

@DaxServer DaxServer merged commit 2d6fe04 into main Jul 31, 2025
5 checks passed
@DaxServer DaxServer deleted the wikibase-editor-task20 branch July 31, 2025 12:29
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