Skip to content

refactor: identify artifact types by slug locally - #856

Closed
nabalone wants to merge 1 commit into
upload-pipeline-use-media-upload_2from
artifact-type-slugs-on-853
Closed

nabalone wants to merge 1 commit into
upload-pipeline-use-media-upload_2from
artifact-type-slugs-on-853

Conversation

@nabalone

Copy link
Copy Markdown
Collaborator

Re-implements the slug refactor from #510 on top of #853, so it targets #853's branch rather than develop. #510's other work, the TT-7583 autosave hardening, already landed in develop via #492.

What changed

  • Slug-first core (useArtifactType.ts, artifactTypeSlug.ts)
    • getTypeId is renamed localIdFromSlug.
    • New remoteIdNumFromSlug gives the remote id for the API boundary.
    • New localIdFromIdOrSlug resolves values read from step settings.
    • slugFromId now passes slugs through unchanged.
    • Adds artifactTypeSlugs / isArtifactTypeSlug.
    • Removes the dead addNewArtifactType, commentId and keyTermId.
  • Record/upload chain takes artifactTypeSlug instead of an artifact-type id: useMediaUpload, MediaRecord, PassageRecordPanel, ResourceUploadStep / add-resource wizard, Uploader, Careful Speech / LWC controls, ProvideRights(Mobile), titles, comments, key terms and the prompt. Slug → id conversion happens only inside useMediaUpload.
  • Step settings store slugs
    • Writers: SelectArtifactType, Transcribe / Paratext / Phrase BT step settings, and the offline workflow seed in useOfflineSetup.
    • Readers: every one goes through slugFromId or localIdFromIdOrSlug, so existing settings that hold a remote or local id keep working with no migration. That covers Grids, guided phrase record, LWC transcription/translation, Paratext integration, PBT, step complete, the route, StepEditor labels, mobile transcribe, fontChoice and the duplicate-PBT-language check.
  • Hardcoded typename literals are replaced with the enum (resourceRows, useOfflineSetup, updateBackTranslationType, integrationSlug).
  • Mobile transcribe fix: it used to pass the raw settings value (a remote id) to TranscriberProvider and the font lookup as if it were a local id. It now resolves to the local id the same way desktop does.

Compatibility risk

Step settings sync to the whole team. A teammate on an older app version will read the new slug values, and older readers resolve the stored value as a remote id, so their slug-based steps (phrase BT, LWC, Grids) may not find their recordings until they update. This was a deliberate choice: slugs plus slug-tolerant readers, accepting that older clients may misread them. Worth confirming that no server-side code reads artifactTypeId from step settings.

Test plan

  • npm run typecheck
  • Jest: the full suite was run. Every suite this PR touches passes. ProjectResourceConfigure.test.tsx fails the same way on refactor: move add-resource flow into AddResourceWizard #853 (parse error). MediaRecord, MarkVerses, AsrSettings and PendingUploadsDialog.retry failed only under full-suite load and pass when run on their own.
  • Manual: change a Transcribe / Paratext / Phrase BT step's artifact type in Edit Workflow, and check that the settings now hold a slug and the step still works.
  • Manual: record on PBT / Careful Speech / LWC steps whose settings hold a legacy remote id.
  • Manual: add a resource upload/record, a comment, a key term recording and a title recording, and check that each mediafile gets the right artifact type.
  • Manual: offline-only project setup, then a PBT transcribe step.

🤖 Generated with Claude Code

Re-implements PR #510's artifact-type slug refactor on top of #853. Local
code now identifies artifact types by ArtifactTypeSlug and converts to an id
only at the DB/API boundary: MediaRecord, useMediaUpload, Uploader and the
add-resource wizard take artifactTypeSlug instead of an artifact-type id.

Step settings now store the slug. Every settings reader goes through the
slug-tolerant slugFromId / new localIdFromIdOrSlug, so legacy settings that
hold a remote or local id keep working without a data migration. Also drops
the dead addNewArtifactType / commentId / keyTermId helpers and replaces
hardcoded typename literals with the enum.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note

Copilot was unable to complete this review at the selected tier due to model policy or plan restrictions.

🟡 Changes recommended

A critical issue remains in localIdFromIdOrSlug where an unguarded remoteIdGuid(..., memory?.keyMap as RecordKeyMap) can throw when context is undefined and may return an unmapped remote id despite the function contract, leaving callers with an invalid relationship id.

3 open issues
What changed in this PR

Refactors artifact-type handling to be slug-first across the web app, storing slugs in workflow step settings and converting to local/remote IDs only at Orbit/API boundaries.

Changes:

  • Introduces slug utilities and new useArtifactType helpers (localIdFromSlug, remoteIdNumFromSlug, localIdFromIdOrSlug) and removes dead helpers.
  • Updates recording/upload flows to pass artifactTypeSlug end-to-end with centralized slug→id conversion in useMediaUpload.
  • Updates step-settings writers to persist slugs while keeping readers tolerant of legacy stored IDs, including a mobile transcribe resolution fix.
File Description
web/​src/​utils/​integrationSlug.ts Updates integration slug construction to use ArtifactTypeSlug enum values instead of hardcoded typename strings.
web/​src/​store/​importexport/​actions.tsx Refactors import/export filtering to use localIdFromSlug in place of the prior type-id resolver.
web/​src/​routes/​PassageDetail.tsx Adjusts PassageDetail route wiring to rely on slug/id-tolerant artifact-type helpers for step-related artifact selection.
web/​src/​routes/​ElectronImport.tsx Updates Electron import flow to use localIdFromSlug for artifact-type resolution.
web/​src/​crud/​useOfflineSetup.ts Seeds offline workflow setup with slug-based artifact-type settings and replaces typename literals with enum values.
web/​src/​crud/​useMediaUpload.ts Switches upload inputs to artifactTypeSlug and performs slug→local/remote id conversion only at persistence/API boundaries.
web/​src/​crud/​useMediaUpload.test.ts Updates media upload hook tests to match the new slug-based upload contract and conversion behavior.
web/​src/​crud/​useMediaResCreate.ts Uses localIdFromSlug when creating media relationships for shared resources.
web/​src/​crud/​useArtifactType.ts Implements slug-first artifact-type helpers and removes unused legacy helpers while keeping slug/id normalization available to callers.
web/​src/​crud/​updateBackTranslationType.ts Replaces hardcoded back-translation typename checks with ArtifactTypeSlug enum comparisons.
web/​src/​crud/​fontChoice.ts Makes font selection logic tolerant of step settings containing either slugs or legacy ids.
web/​src/​crud/​artifactTypeSlug.ts Adds a centralized slug list and type guard (artifactTypeSlugs, isArtifactTypeSlug) for validated slug usage.
web/​src/​context/​TranscriberContext.tsx Updates transcriber context to resolve artifact type via slug-based helpers rather than id-based plumbing.
web/​src/​context/​PassageDetailContext.tsx Adjusts PassageDetail context filtering and lookups to use localIdFromSlug for artifact types.
web/​src/​components/​useRecordSave.test.ts Updates record-save tests to pass slug-based artifact typing through upload fields.
web/​src/​components/​Uploader.tsx Changes the uploader component API to accept artifactTypeSlug and threads it through to upload handling.
web/​src/​components/​TranscriptionTab.tsx Updates transcription/export tab filtering and selection to use slug-based artifact-type resolution.
web/​src/​components/​TitleTabs.tsx Refactors title recording tab logic to drive recording/upload behavior by slugs rather than derived ids.
web/​src/​components/​TitleRecord.tsx Updates title recording component to pass artifactTypeSlug into MediaRecord instead of an artifact-type id.
web/​src/​components/​TitleRecord.test.tsx Adjusts title record tests for the slug-based MediaRecord/upload contract.
web/​src/​components/​StepEditor/​TranscribeStepSettings.tsx Writes transcribe step settings as slugs and normalizes legacy stored ids to slug values on load.
web/​src/​components/​StepEditor/​StepEditor.tsx Updates step editor behavior to treat artifact type settings as id-or-slug and rely on normalized slug helpers.
web/​src/​components/​StepEditor/​StepEditor.cy.tsx Updates Cypress step editor coverage/comments to reflect the renamed slug-first artifact-type helpers.
web/​src/​components/​StepEditor/​PhraseBackTranslateStepSettings.tsx Stores phrase back-translation artifact type as a slug and normalizes existing legacy values when editing.
web/​src/​components/​StepEditor/​PhraseBackTranslateStepSettings.test.tsx Updates phrase back-translation settings tests to assert slug persistence and legacy-id normalization.
web/​src/​components/​StepEditor/​ParatextStepSettings.tsx Updates Paratext step settings to persist artifact types as slugs while accepting legacy ids.
web/​src/​components/​StepEditor/​isDuplicatePhraseBtLanguage.ts Refactors duplicate phrase BT language detection to compare normalized slug values rather than id mappings.
web/​src/​components/​StepEditor/​isDuplicatePhraseBtLanguage.test.ts Adds/updates tests covering duplicate detection across mixed legacy-id and slug-based settings.
web/​src/​components/​Sheet/​SelectArtifactType.tsx Updates artifact-type selector to emit slugs (or null for Vernacular) and use slug-backed options for selection.
web/​src/​components/​ProvideRights.tsx Threads artifactTypeSlug through the Provide Rights recording/upload path instead of id-based artifact typing.
web/​src/​components/​PassageRecordPanel.tsx Updates record panel contract to accept artifactTypeSlug and forward it into recording/upload components.
web/​src/​components/​PassageDetail/​Prompt/​PassageDetailPromptAdmin.tsx Refactors prompt admin recording to use a fixed ArtifactTypeSlug value for consistent upload tagging.
web/​src/​components/​PassageDetail/​PassageDetailStepComplete.tsx Uses slug/id normalization helpers to derive the step-complete artifact type consistently from settings.
web/​src/​components/​PassageDetail/​PassageDetailRecord.tsx Updates passage recording to use ArtifactTypeSlug.Vernacular (slug-first) rather than id-derived typing.
web/​src/​components/​PassageDetail/​PassageDetailRecord.test.tsx Updates PassageDetail record tests to use the slug-based artifact typing and helper APIs.
web/​src/​components/​PassageDetail/​PassageDetailPhraseBackTranslate.undo.test.tsx Adjusts undo tests to use the new slug-first helpers and settings normalization behavior.
web/​src/​components/​PassageDetail/​PassageDetailPhraseBackTranslate.tsx Refactors phrase back-translation step to resolve artifact type via slugFromId for slug-or-id settings.
web/​src/​components/​PassageDetail/​PassageDetailParatextIntegration.tsx Resolves Paratext integration artifact types using localIdFromIdOrSlug at the local DB relationship boundary.
web/​src/​components/​PassageDetail/​PassageDetailLwcTranslation.tsx Updates LWC translation flow to normalize artifact type via slug/id helpers and pass slugs to controls/recording.
web/​src/​components/​PassageDetail/​PassageDetailLwcTranslation.test.tsx Updates LWC translation tests to align with slug-based artifact typing and helper behavior.
web/​src/​components/​PassageDetail/​PassageDetailLwcTranscription.tsx Refactors LWC transcription to compute local ids via localIdFromIdOrSlug and default slugs via localIdFromSlug.
web/​src/​components/​PassageDetail/​PassageDetailLwcTranscription.test.tsx Updates LWC transcription tests for the slug-first settings and artifact-type resolution logic.
web/​src/​components/​PassageDetail/​PassageDetailItem.tsx Threads artifactTypeSlug through item-level record/upload interactions to match the new slug-first contract.
web/​src/​components/​PassageDetail/​PassageDetailGuidedPhraseRecord.tsx Updates guided phrase recording to resolve settings via localIdFromIdOrSlug and pass slug-based typing into recording.
web/​src/​components/​PassageDetail/​PassageDetailGuidedPhraseRecord.stepScope.test.tsx Updates guided phrase record step-scope tests for the slug-based artifact-type APIs.
web/​src/​components/​PassageDetail/​PassageDetailGuidedPhraseRecord.nextDuringPlayback.test.tsx Updates guided phrase record playback tests to use the new slug-first artifact-type wiring.
web/​src/​components/​PassageDetail/​PassageDetailGrids.tsx Updates grids step artifact-type resolution to use localIdFromIdOrSlug for slug-or-id settings values.
web/​src/​components/​PassageDetail/​PassageDetailCarefulSpeech.test.tsx Updates Careful Speech test mocks and helpers to match slug-first artifact-type usage.
web/​src/​components/​PassageDetail/​mobile/​transcribe/​PassageDetailTranscribeMobile.tsx Fixes mobile transcribe to resolve step settings (slug or legacy id) to the correct local id like desktop does.
web/​src/​components/​PassageDetail/​mobile/​record/​ProvideRightsMobile.tsx Updates mobile Provide Rights recording to accept artifactTypeSlug rather than an artifact-type id.
web/​src/​components/​PassageDetail/​mobile/​record/​ProvideRightsMobile.cy.tsx Updates mobile Provide Rights Cypress coverage to use slug-based artifact typing inputs.
web/​src/​components/​PassageDetail/​lwcTranslation/​LwcTranslationControls.tsx Changes LWC translation controls to accept and forward artifactTypeSlug to recording/upload components.
web/​src/​components/​PassageDetail/​lwcTranslation/​LwcTranslationControls.test.tsx Updates LWC translation controls tests for slug-based props and recording/upload expectations.
web/​src/​components/​PassageDetail/​Keyterms/​TargetWordAdd.tsx Updates key term recording to tag uploads using ArtifactTypeSlug.KeyTerm directly.
web/​src/​components/​PassageDetail/​Internalization/​useProjectResourceSave.ts Refactors project resource save logic to resolve artifact types via localIdFromSlug.
web/​src/​components/​PassageDetail/​Internalization/​useAddResourceWizard.ts Updates add-resource wizard state/logic to choose artifact typing by slug for downstream uploads.
web/​src/​components/​PassageDetail/​Internalization/​ResourceUploadStep.tsx Threads artifactTypeSlug through the resource upload step’s record/upload chain consistent with the new contract.
web/​src/​components/​PassageDetail/​Internalization/​ResourceUploadStep.test.tsx Updates resource upload step tests to validate slug-based artifact typing propagation and defaults.
web/​src/​components/​PassageDetail/​Internalization/​resourceRows.ts Replaces hardcoded resource-related typenames with slug-based enum logic used for row classification/behavior.
web/​src/​components/​PassageDetail/​Internalization/​AddResourceWizard.tsx Passes wizard-selected artifactTypeSlug into ResourceUploadStep and related internalization flows.
web/​src/​components/​PassageDetail/​Internalization/​AddResourceWizard.test.tsx Updates add-resource wizard tests for slug-based artifact typing and updated component contracts.
web/​src/​components/​PassageDetail/​carefulSpeech/​CarefulSpeechControls.tsx Updates Careful Speech controls to accept artifactTypeSlug and forward it through recording/upload.
web/​src/​components/​PassageDetail/​carefulSpeech/​CarefulSpeechControls.test.tsx Updates Careful Speech controls tests to use slug-based props and expectations.
web/​src/​components/​PassageDetail/​carefulSpeech/​CarefulSpeechControls.cy.tsx Updates Careful Speech Cypress component tests for slug-first artifact typing inputs.
web/​src/​components/​MediaRecord.tsx Updates MediaRecord to accept artifactTypeSlug and pass it into the media upload hook fields.
web/​src/​components/​MediaRecord.test.tsx Refactors MediaRecord unit tests to use the slug-based props contract and vernacular defaults.
web/​src/​components/​MediaRecord.recording.cy.tsx Updates MediaRecord recording Cypress tests to use slug-based artifact typing props.
web/​src/​components/​MediaRecord.load.test.tsx Updates MediaRecord load tests for the new artifactTypeSlug prop contract.
web/​src/​components/​MediaRecord.deleteRegion.cy.tsx Updates MediaRecord delete-region Cypress tests for slug-based props and upload behavior.
web/​src/​components/​Integration.tsx Updates integration behavior to use remoteIdNumFromSlug at the API boundary and localIdFromSlug for local filtering.
web/​src/​components/​Discussions/​DiscussionCard.addSave.test.tsx Updates discussion add/save tests to remove reliance on removed artifact-type id helpers and use slug-based behavior.
web/​src/​components/​Discussions/​CommentEditor.tsx Refactors comment recording to tag uploads using ArtifactTypeSlug.Comment instead of id-derived artifact types.
web/​src/​components/​ArtifactStatus.tsx Updates artifact status computation to resolve artifact type via localIdFromSlug rather than legacy id helpers.

Review effort: Balanced

Comment on lines +140 to +147
const localIdFromIdOrSlug = (value: string | null | undefined) => {
if (!value) return null;
if (isArtifactTypeSlug(value)) return localIdFromSlug(value);
return (
remoteIdGuid('artifacttype', value, memory?.keyMap as RecordKeyMap) ??
value
);
};
@@ -27,27 +28,20 @@ export const SelectArtifactType = (props: IProps) => {
);

const handleArtifactTypeChange = (e: any) => {
} catch {
/* ignore */
}
// eslint-disable-next-line react-hooks/exhaustive-deps
@nabalone

Copy link
Copy Markdown
Collaborator Author

I want to put this off until after we figure out the mobile transcribe step. I will close for now but not delete the branch.

@nabalone nabalone closed this Nov 11, 2026
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