Skip to content

fix(wikibase-schema-editor): bugs saving qualifiers and references#121

Merged
DaxServer merged 2 commits intomainfrom
save-qualifiers-references
Aug 8, 2025
Merged

fix(wikibase-schema-editor): bugs saving qualifiers and references#121
DaxServer merged 2 commits intomainfrom
save-qualifiers-references

Conversation

@DaxServer
Copy link
Owner

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Aug 8, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added support for editing and managing references on statements within the schema editor.
  • Bug Fixes

    • Improved handling of statement updates to ensure qualifiers and references are correctly managed and saved.
  • Tests

    • Expanded test coverage for statement updates, including cases for qualifiers and references.
  • Refactor

    • Simplified and streamlined the schema update process for more efficient data handling.

Walkthrough

This update extends the Wikibase schema editing functionality to support "references" in addition to "qualifiers" for statements. It modifies the editor component, schema store, and related composables to handle references, updates test coverage for these features, and simplifies API payloads for schema updates.

Changes

Cohort / File(s) Change Summary
WikibaseSchemaEditor references support
frontend/src/features/wikibase-schema/components/WikibaseSchemaEditor.vue
Adds handling for "references" in statement editing: extends local state, updates add/edit/cancel logic, and ensures references are passed to store actions.
Schema store and tests: qualifiers & references
frontend/src/features/wikibase-schema/stores/schema.store.ts, frontend/src/features/wikibase-schema/stores/__tests__/schema.store.test.ts
Adds updateStatement action supporting qualifiers and references; extends tests for statement updates with qualifiers and references, including edge cases and dirty state handling.
Schema API and persistence simplification
frontend/src/features/wikibase-schema/composables/useSchemaApi.ts, frontend/src/features/wikibase-schema/composables/useSchemaPersistence.ts, frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.ts
Simplifies API update payloads by passing schema data directly and removing unneeded fields; renames nested property for consistency; updates related tests to match new payload structure.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WikibaseSchemaEditor
    participant SchemaStore
    participant API

    User->>WikibaseSchemaEditor: Edit/Add Statement (with qualifiers, references)
    WikibaseSchemaEditor->>SchemaStore: updateStatement/addStatement(property, value, rank, qualifiers, references)
    SchemaStore-->>WikibaseSchemaEditor: Statement updated in store (dirty state set)
    WikibaseSchemaEditor->>API: saveSchema (includes references)
    API-->>WikibaseSchemaEditor: Save response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a83e2cc and 5f8e717.

📒 Files selected for processing (1)
  • frontend/src/features/wikibase-schema/components/WikibaseSchemaEditor.vue (7 hunks)
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch save-qualifiers-references

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.
  • 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.

Support

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

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: 3

🧹 Nitpick comments (7)
frontend/src/features/wikibase-schema/components/WikibaseSchemaEditor.vue (2)

53-54: Add default value to avoid undefined spreads

references?: ReferenceSchemaMapping[] is optional but later always spread (...). Initialise in the type the same as qualifiers to remove optionality:

references: ReferenceSchemaMapping[]

236-237: Consider DRYing the repeated default object

The default statement stub appears three times (lines 54-67, 223-237, 321-334). Extract a small factory function to keep them in sync.

frontend/src/features/wikibase-schema/stores/__tests__/schema.store.test.ts (5)

693-747: LGTM: Qualifiers update path is validated end-to-end

This test robustly covers updating property, value, rank, and qualifiers and correctly checks dirty state transitions. Consider also asserting the statement count remains 1 to guard against accidental replacement vs in-place update:

-  const updatedStatement = store.statements.find((s) => s.id === statementId)
+  expect(store.statements).toHaveLength(1)
+  const updatedStatement = store.statements.find((s) => s.id === statementId)

749-768: Non-existent update: add a guard assertion to ensure no builder calls

Solid check for no crash and no dirty state. To further ensure it’s a true no-op, assert the statement builder wasn’t invoked:

   store.updateStatement(nonExistentId, mockProperty, mockValue, 'normal')

   // Should not crash and should not mark as dirty
   expect(store.statements).toHaveLength(0)
   expect(store.isDirty).toBe(false)
+  expect(mockBuildStatement).not.toHaveBeenCalled()

770-814: LGTM: References update path is validated, including dirty state

Looks good. Optional: if updateStatement preserves existing qualifiers when not provided, you could add an assertion to document that behavior explicitly (helps prevent regressions in merge logic).

// Before updating, optionally set qualifiers:
// store.updateStatement(statementId, mockProperty, mockValue, 'normal', mockQualifiers)

// After updating with references-only, verify qualifiers remain unchanged:
// expect(updatedStatement!.qualifiers).toEqual(mockQualifiers)

816-852: Strengthen: Verify the builder receives references when adding

Since addStatement delegates to buildStatement, assert that the references are passed through (helps catch wiring regressions).

-  // Add statement with references
-  const statementId = store.addStatement(mockProperty, mockValue, 'normal', [], mockReferences)
+  // Add statement with references
+  mockBuildStatement.mockClear()
+  const statementId = store.addStatement(mockProperty, mockValue, 'normal', [], mockReferences)

+  // Ensure references were passed to the builder
+  const lastCall = mockBuildStatement.mock.calls.at(-1)
+  expect(lastCall).toEqual([mockProperty, mockValue, 'normal', [], mockReferences])

854-904: Nice: Clear references behavior covered. Consider adding symmetric test for clearing qualifiers

This is a thorough test for clearing references with an empty array and dirty-state verification. For parity and to document store semantics, consider adding a test that clears qualifiers in the same way.

Would you like me to draft the test body? Example:

it('should clear qualifiers when updating statement with empty qualifiers array', () => {
  const mockProperty: PropertyReference = { id: 'P123', label: 'Test Property', dataType: 'string' }
  const mockValue: ValueMapping = { type: 'column', source: { columnName: 'test_column', dataType: 'VARCHAR' }, dataType: 'string' }
  const mockQualifiers: PropertyValueMap[] = [{
    property: { id: 'P456', label: 'Qualifier', dataType: 'string' },
    value: { type: 'constant', source: 'test value', dataType: 'string' },
  }]

  const statementId = store.addStatement(mockProperty, mockValue, 'normal', mockQualifiers)

  // Verify qualifiers exist
  let statement = store.statements.find((s) => s.id === statementId)!
  expect(statement.qualifiers).toHaveLength(1)

  store.markAsSaved()
  expect(store.isDirty).toBe(false)

  // Clear qualifiers
  store.updateStatement(statementId, mockProperty, mockValue, 'normal', [], statement.references)

  statement = store.statements.find((s) => s.id === statementId)!
  expect(statement.qualifiers).toHaveLength(0)
  expect(store.isDirty).toBe(true)
})
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6445139 and a83e2cc.

📒 Files selected for processing (6)
  • frontend/src/features/wikibase-schema/components/WikibaseSchemaEditor.vue (7 hunks)
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.ts (1 hunks)
  • frontend/src/features/wikibase-schema/composables/useSchemaApi.ts (1 hunks)
  • frontend/src/features/wikibase-schema/composables/useSchemaPersistence.ts (1 hunks)
  • frontend/src/features/wikibase-schema/stores/__tests__/schema.store.test.ts (2 hunks)
  • frontend/src/features/wikibase-schema/stores/schema.store.ts (2 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/src/features/wikibase-schema/composables/useSchemaApi.ts
  • frontend/src/features/wikibase-schema/composables/useSchemaPersistence.ts
  • frontend/src/features/wikibase-schema/stores/schema.store.ts
  • frontend/src/features/wikibase-schema/stores/__tests__/schema.store.test.ts
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.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/src/features/wikibase-schema/composables/useSchemaApi.ts
  • frontend/src/features/wikibase-schema/composables/useSchemaPersistence.ts
  • frontend/src/features/wikibase-schema/stores/schema.store.ts
  • frontend/src/features/wikibase-schema/stores/__tests__/schema.store.test.ts
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.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/features/wikibase-schema/stores/__tests__/schema.store.test.ts
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.ts
🧠 Learnings (2)
📚 Learning: 2025-07-20T14:13:24.706Z
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

Applied to files:

  • frontend/src/features/wikibase-schema/composables/useSchemaApi.ts
📚 Learning: 2025-07-20T14:13:24.706Z
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 storeToRefs for state in components

Applied to files:

  • frontend/src/features/wikibase-schema/components/WikibaseSchemaEditor.vue
🧬 Code Graph Analysis (1)
frontend/src/features/wikibase-schema/stores/schema.store.ts (2)
frontend/auto-imports.d.ts (6)
  • UUID (368-368)
  • PropertyReference (371-371)
  • ValueMapping (371-371)
  • StatementRank (371-371)
  • PropertyValueMap (371-371)
  • ReferenceSchemaMapping (371-371)
backend/src/api/project/project.wikibase.ts (5)
  • PropertyReference (35-35)
  • ValueMapping (72-72)
  • StatementRank (97-97)
  • PropertyValueMap (80-80)
  • ReferenceSchemaMapping (88-88)
🪛 GitHub Actions: Typecheck code
frontend/src/features/wikibase-schema/components/WikibaseSchemaEditor.vue

[error] 296-296: TypeScript error TS2345: Argument of type 'string' is not assignable to parameter of type '${string}-${string}-${string}-${string}-${string}'.

🔇 Additional comments (2)
frontend/src/features/wikibase-schema/composables/useSchemaApi.ts (1)

97-100: Confirm backend accepts raw schemaData

You now send the whole object as-is. If the Eden route still expects only { name, wikibase, schema }, this will 422. Double-check the contract.

frontend/src/features/wikibase-schema/composables/useSchemaPersistence.ts (1)

37-45: Payload key renamed to schema

Just flagging: older API versions used item. Ensure backend was updated in sync, otherwise updates will fail.

Comment on lines +17 to 30
(
property: PropertyReference,
valueMapping: ValueMapping,
rank = 'normal',
qualifiers: PropertyValueMap[] = [],
references: ReferenceSchemaMapping[] = [],
) => ({
id: TEST_STATEMENT_ID,
property,
value: valueMapping,
rank,
qualifiers,
references,
}),
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Missing type imports for PropertyValueMap and ReferenceSchemaMapping (TS compile fix)

Both PropertyValueMap and ReferenceSchemaMapping are referenced in this new mock signature and return value but are not imported in this file, which will cause TypeScript errors.

Proposed import (outside this range; adjust the source module if different in your repo):

// At the top near other type imports
import type {
  ColumnMapping,
  PropertyReference,
  ValueMapping,
  PropertyValueMap,
  ReferenceSchemaMapping,
} from '@backend/api/project/project.wikibase'

If these types live elsewhere, run this to locate their definitions and correct the import:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find where these types are exported
rg -n "export (type|interface) ReferenceSchemaMapping" -A 3
rg -n "export (type|interface) PropertyValueMap" -A 3

# Inspect project.wikibase exports for related types
fd -a "project.wikibase" | xargs -r rg -n "export (type|interface) (ReferenceSchemaMapping|PropertyValueMap|PropertyReference|ValueMapping|ColumnMapping)" -A 2

Length of output: 2410


Add missing type imports for qualifiers and references

The test mock now references PropertyValueMap and ReferenceSchemaMapping but they aren’t imported, causing TS errors. Please update the top of frontend/src/features/wikibase-schema/stores/tests/schema.store.test.ts to include:

import type {
  ColumnMapping,
  PropertyReference,
  ValueMapping,
  PropertyValueMap,
  ReferenceSchemaMapping,
} from '@backend/api/project/project.wikibase'

• Verify this path matches your tsconfig “@backend/api” alias.
• (Optional) Strengthen coverage by:
– Asserting the builder receives references when adding a statement.
– Adding a symmetric test for clearing qualifiers (like you have for references).
– On non-existent updates, asserting that the mockBuildStatement isn’t called.

🤖 Prompt for AI Agents
In frontend/src/features/wikibase-schema/stores/__tests__/schema.store.test.ts
around lines 17 to 30, the types PropertyValueMap and ReferenceSchemaMapping
used in the test mock are not imported, causing TypeScript errors. Fix this by
adding an import statement at the top of the file importing these types along
with ColumnMapping, PropertyReference, and ValueMapping from
'@backend/api/project/project.wikibase'. Also verify the import path matches the
tsconfig alias. Optionally, improve test coverage by adding assertions for
references handling, clearing qualifiers, and ensuring mockBuildStatement is not
called on non-existent updates.

Comment on lines +174 to +198
const updateStatement = (
statementId: UUID,
property: PropertyReference,
value: ValueMapping,
rank: StatementRank,
qualifiers: PropertyValueMap[] = [],
references: ReferenceSchemaMapping[] = [],
) => {
const statementIndex = statements.value.findIndex((s) => s.id === statementId)

if (statementIndex !== -1) {
const existingStatement = statements.value[statementIndex]
if (existingStatement) {
statements.value[statementIndex] = {
id: existingStatement.id,
property,
value,
rank,
qualifiers,
references,
}
markDirty()
}
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

updateStatement blindly overwrites & silently no-ops

  1. The whole object is rebuilt, so any later-added fields (e.g. sources) will be lost.
  2. Nothing is returned/throwed when statementId is missing – callers can’t tell they updated nothing.

Consider:

-    if (statementIndex !== -1) {
-      const existingStatement = statements.value[statementIndex]
-      if (existingStatement) {
-        statements.value[statementIndex] = {
-          id: existingStatement.id,
-          property,
-          value,
-          rank,
-          qualifiers,
-          references,
-        }
-        markDirty()
-      }
-    }
+    if (statementIndex === -1) {
+      return false
+    }
+    const existing = statements.value[statementIndex]
+    statements.value[statementIndex] = {
+      ...existing,            // future-proof
+      property,
+      value,
+      rank,
+      qualifiers,
+      references,
+    }
+    markDirty()
+    return true
📝 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
const updateStatement = (
statementId: UUID,
property: PropertyReference,
value: ValueMapping,
rank: StatementRank,
qualifiers: PropertyValueMap[] = [],
references: ReferenceSchemaMapping[] = [],
) => {
const statementIndex = statements.value.findIndex((s) => s.id === statementId)
if (statementIndex !== -1) {
const existingStatement = statements.value[statementIndex]
if (existingStatement) {
statements.value[statementIndex] = {
id: existingStatement.id,
property,
value,
rank,
qualifiers,
references,
}
markDirty()
}
}
}
const updateStatement = (
statementId: UUID,
property: PropertyReference,
value: ValueMapping,
rank: StatementRank,
qualifiers: PropertyValueMap[] = [],
references: ReferenceSchemaMapping[] = [],
) => {
const statementIndex = statements.value.findIndex((s) => s.id === statementId)
if (statementIndex === -1) {
return false
}
const existing = statements.value[statementIndex]
statements.value[statementIndex] = {
...existing, // future-proof
property,
value,
rank,
qualifiers,
references,
}
markDirty()
return true
}
🤖 Prompt for AI Agents
In frontend/src/features/wikibase-schema/stores/schema.store.ts around lines 174
to 198, the updateStatement function overwrites the entire statement object,
causing loss of any additional fields like 'sources', and it silently does
nothing if the statementId is not found. To fix this, modify the function to
merge the updated fields into the existing statement object instead of replacing
it entirely, preserving other fields. Also, add a return value or throw an error
when the statementId is not found to inform callers that no update occurred.

@DaxServer DaxServer merged commit 9425e02 into main Aug 8, 2025
4 of 5 checks passed
@DaxServer DaxServer deleted the save-qualifiers-references branch August 8, 2025 13:38
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