Skip to content

Refactor annotation guideline implementation#1456

Open
mzur wants to merge 27 commits into
235-annotation-strategy-introductionfrom
235-annotation-strategy-introduction-patch-1
Open

Refactor annotation guideline implementation#1456
mzur wants to merge 27 commits into
235-annotation-strategy-introductionfrom
235-annotation-strategy-introduction-patch-1

Conversation

@mzur
Copy link
Copy Markdown
Member

@mzur mzur commented May 5, 2026

  • Refactor backend
  • Refactor UI
    • Implement CRUD of guideline labels
    • Implement CRUD of reference images
    • Determine what to do with the general guideline description
    • Implement read-only mode for non-admins
    • Update manual (create a new article about guidelines)
  • Handle cleanup when labels, label trees or projects are deleted (delete label reference images)
  • Implement has_reference attribute for guideline label
    • avoids unnecessary requests for reference images that may not exists
    • allows fix for deletion of reference image (currently it loads the cached image although it was deleted)

@mzur mzur marked this pull request as draft May 5, 2026 09:46
@mzur mzur changed the title Refactor annotation guideline backend Refactor annotation guideline implementation May 13, 2026
@mzur mzur requested a review from Copilot May 29, 2026 13:08
@mzur mzur marked this pull request as ready for review May 29, 2026 13:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the annotation guideline feature end-to-end (DB schema, backend APIs, authorization, storage cleanup, and UI) to support CRUD for guideline labels and reference images, plus proper cleanup when related entities are deleted.

Changes:

  • Reworked annotation guideline persistence to a annotation_guidelines model + annotation_guideline_label pivot (UUID-based) and added factories/tests.
  • Replaced the legacy guideline UI with a new Vue component and updated API resources/routes to a more RESTful structure.
  • Added observers and model hooks to delete stored reference images when projects/label trees/labels/guidelines/guideline-labels are deleted.

Reviewed changes

Copilot reviewed 43 out of 43 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/php/ProjectTest.php Adds relationship + deletion cleanup coverage for project → guideline reference images.
tests/php/Policies/AnnotationGuidelinePolicyTest.php Verifies guideline update authorization rules by role.
tests/php/LabelTreeTest.php Adds cleanup test for label tree deletion removing guideline label reference images.
tests/php/LabelTest.php Adds cleanup test for label deletion removing guideline label reference images.
tests/php/Http/Controllers/Views/Projects/AnnotationGuidelineControllerTest.php Updates view test to new project_id field naming.
tests/php/Http/Controllers/Api/Projects/AnnotationGuidelineLabelControllerTest.php Replaces old monolithic test with focused REST endpoint tests (store/destroy + reference image behaviors).
tests/php/Http/Controllers/Api/Projects/AnnotationGuidelineControllerTest.php Updates API tests for new routes, permissions, and behaviors (store/update/destroy).
tests/php/AnnotationGuidelineTest.php Adds model-level tests for constraints, relationships, and cascade behavior.
tests/php/AnnotationGuidelineLabelTest.php Adds pivot model tests (UUID, uniqueness, cascade behaviors).
routes/api.php Replaces legacy endpoints with resource routes for guidelines and guideline labels.
resources/views/projects/show/tabs.blade.php Shows the Guideline tab based on existence of a guideline via relationship query.
resources/views/projects/show/annotation-guideline.blade.php Simplifies JS bootstrap data to rely on annotationGuideline including labels/pivot data.
resources/views/manual/tutorials/projects/about.blade.php Updates the manual to document the new guideline workflow and moves/renames the anchor.
resources/assets/js/projects/components/annotationGuideline.vue New consolidated guideline UI (label selection, shape/description/image editing, manage dropdown).
resources/assets/js/projects/components/annotation_guideline/resizeImage.js Removes old image resize helper (logic moved into new component).
resources/assets/js/projects/components/annotation_guideline/annotationGuidelineLabelImage.vue Removes old subcomponent (replaced by new consolidated component).
resources/assets/js/projects/components/annotation_guideline/annotationGuidelineLabel.vue Removes old label editor component (replaced by new consolidated component).
resources/assets/js/projects/components/annotation_guideline/annotationGuideline.vue Removes old guideline component (replaced by new consolidated component).
resources/assets/js/projects/api/annotationGuidelineLabel.js Updates JS API resource to new guideline-label endpoints.
resources/assets/js/projects/api/annotationGuideline.js Updates JS API resource to new guideline endpoints (project-scoped create + id-scoped update/destroy).
resources/assets/js/projects/annotationGuidelineContainer.vue Points container to the new component path.
database/migrations/2026_03_02_103908_create_annotation_guideline_tables.php Renames/reshapes tables/columns; adds timestamps; introduces UUID pivot key.
database/factories/AnnotationGuidelineLabelFactory.php Adds factory for the guideline-label pivot with UUID.
database/factories/AnnotationGuidelineFactory.php Adds factory for guidelines.
config/projects.php Introduces config for the annotation guideline storage disk.
config/filesystems.php Renames/moves the public storage path for guideline assets.
app/Providers/EventServiceProvider.php Registers new observers for label and label tree cleanup.
app/Project.php Adds annotationGuideline() relationship.
app/Policies/AnnotationGuidelinePolicy.php Adds authorization for updating guidelines (project admin membership).
app/Observers/ProjectObserver.php Ensures guideline deletion is triggered on project deletion to clean storage.
app/Observers/LabelTreeObserver.php Deletes guideline-label pivots for labels in a tree to clean reference images.
app/Observers/LabelObserver.php Deletes guideline-label pivots for a label to clean reference images.
app/Http/Requests/StoreAnnotationGuidelineLabel.php Updates request authorization/validation for guideline-label store endpoint.
app/Http/Controllers/Views/Projects/ProjectUserController.php Removes manual guideline lookup (tab now checks relationship existence).
app/Http/Controllers/Views/Projects/ProjectStatisticsController.php Removes manual guideline lookup (tab now checks relationship existence).
app/Http/Controllers/Views/Projects/ProjectsController.php Removes manual guideline lookup (tab now checks relationship existence).
app/Http/Controllers/Views/Projects/ProjectReportsController.php Removes manual guideline lookup (tab now checks relationship existence).
app/Http/Controllers/Views/Projects/ProjectLabelTreeController.php Removes manual guideline lookup (tab now checks relationship existence).
app/Http/Controllers/Views/Projects/AnnotationGuidelineController.php Refactors view loading logic to use relationship + read-only 404 behavior for non-admins when absent.
app/Http/Controllers/Api/Projects/AnnotationGuidelineLabelController.php Implements REST store/destroy for guideline labels, reference image storage, UUID file naming.
app/Http/Controllers/Api/Projects/AnnotationGuidelineController.php Implements REST index/store/update/destroy for guidelines with updated authorization and responses.
app/AnnotationGuidelineLabel.php Converts to custom pivot model with UUID PK + storage cleanup hooks + computed URL.
app/AnnotationGuideline.php Updates model fields/relationships and adds storage directory cleanup on delete.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread resources/assets/js/projects/components/annotationGuideline.vue
Comment thread resources/assets/js/projects/components/annotationGuideline.vue
Comment thread app/Http/Requests/StoreAnnotationGuidelineLabel.php
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated 10 comments.

Comment thread resources/assets/js/projects/components/annotationGuideline.vue Outdated
Comment thread resources/assets/js/projects/components/annotationGuideline.vue Outdated
Comment thread resources/assets/js/projects/components/annotationGuideline.vue
Comment on lines +351 to +358
canvas.toBlob((blob) => {
this.referenceImage = new File([blob], file.name, {type: blob.type});
if (this.referenceImagePreview?.startsWith('blob:')) {
URL.revokeObjectURL(this.referenceImagePreview);
}
this.referenceImagePreviewLoaded = false;
this.referenceImagePreview = URL.createObjectURL(blob);
}, file.type);
Comment thread app/Policies/AnnotationGuidelinePolicy.php
Comment thread app/Observers/LabelObserver.php
Comment thread app/Observers/LabelTreeObserver.php
Comment thread app/Http/Controllers/Api/ProjectLabelTreeController.php
Comment thread app/Http/Controllers/Api/Projects/AnnotationGuidelineController.php
mzur added 3 commits May 29, 2026 16:42
With afterCommit the images are only deleted if the models were
deleted successfully. This way we don't end up with models pointing
to deleted files.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated 29 comments.

Comment on lines +216 to +220
labelDescription: '',
selectedShape: null,
referenceImage: null,
referenceImagePreviewLoaded: false,
referenceImagePreview: null,
Comment on lines +304 to +307
this.labelDescription = '';
this.selectedShape = null;
this.referenceImage = null;
this.referenceImagePreviewLoaded = false;
Comment on lines +325 to +330
addImage(event) {
const file = event.target.files[0] || null;
if (!file) {
this.referenceImage = null;
return;
}
Comment on lines +377 to +388
let formData = new FormData();
formData.append('label_id', this.selectedLabel.id);
formData.append('description', this.labelDescription || '');
if (this.selectedShape) {
formData.append('shape_id', this.selectedShape);
}
if (this.referenceImage !== null) {
formData.append('reference_image', this.referenceImage);
} else {
formData.append('reference_image', '');
}

Comment on lines +345 to +352
canvas.toBlob((blob) => {
this.referenceImage = new File([blob], file.name, {type: blob.type});
if (this.referenceImagePreview?.startsWith('blob:')) {
URL.revokeObjectURL(this.referenceImagePreview);
}
this.referenceImagePreviewLoaded = false;
this.referenceImagePreview = URL.createObjectURL(blob);
}, file.type);
Comment on lines +377 to +387
let formData = new FormData();
formData.append('label_id', this.selectedLabel.id);
formData.append('description', this.labelDescription || '');
if (this.selectedShape) {
formData.append('shape_id', this.selectedShape);
}
if (this.referenceImage !== null) {
formData.append('reference_image', this.referenceImage);
} else {
formData.append('reference_image', '');
}
annotationGuideline: null,
labelDescription: '',
selectedShape: null,
referenceImage: null,
resetForm() {
this.labelDescription = '';
this.selectedShape = null;
this.referenceImage = null;
Comment on lines +326 to +330
const file = event.target.files[0] || null;
if (!file) {
this.referenceImage = null;
return;
}
Comment on lines +377 to +387
let formData = new FormData();
formData.append('label_id', this.selectedLabel.id);
formData.append('description', this.labelDescription || '');
if (this.selectedShape) {
formData.append('shape_id', this.selectedShape);
}
if (this.referenceImage !== null) {
formData.append('reference_image', this.referenceImage);
} else {
formData.append('reference_image', '');
}
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.

2 participants