@@ -340,6 +340,99 @@ export default class ProjectFactory {
340340 }
341341 }
342342
343+ // We might add the Vault here to get the Manifest version 3
344+ static transformManifestUrl ( url , protocol ) {
345+ const parsedUrl = new URL ( url )
346+ parsedUrl . protocol = protocol
347+ if ( parsedUrl . pathname . endsWith ( "/manifest.json" ) ) {
348+ parsedUrl . pathname = parsedUrl . pathname . replace ( / \/ m a n i f e s t \. j s o n $ / , "" )
349+ }
350+ parsedUrl . search = "?version=3"
351+ return parsedUrl . toString ( )
352+ }
353+
354+ static async importTPEN28 ( projectTPEN28Data , projectTPEN3Data , userToken , protocol ) {
355+ if ( ! projectTPEN28Data || ! projectTPEN3Data ) {
356+ throw {
357+ status : 400 ,
358+ message : "Invalid project data"
359+ }
360+ }
361+
362+ const symbols = projectTPEN28Data . projectButtons . map ( button => String . fromCharCode ( button . key ) )
363+ if ( symbols && symbols . length > 0 ) {
364+ const copiedHotkeys = new Hotkeys ( projectTPEN3Data . _id , symbols )
365+ await copiedHotkeys . create ( )
366+ }
367+ let projectTools = [ ]
368+ try {
369+ projectTools = [ ...projectTPEN28Data . userTool , ...projectTPEN28Data . projectTool ]
370+ }
371+ catch ( err ) {
372+ // Just in case the spread operator didn't end up making an array due to 'undefined' or something weird.
373+ projectTools = [ ]
374+ }
375+ const toolList = projectTPEN3Data . tools . map ( ( tool ) => tool . value )
376+ const selectedTools = toolList . map ( ( tool ) => ( {
377+ value : tool ,
378+ state : projectTools . includes ( tool ) ,
379+ } ) )
380+ const project = new Project ( projectTPEN3Data . _id )
381+ if ( selectedTools && selectedTools . length > 0 ) {
382+ await project . updateTools ( selectedTools )
383+ }
384+ const allCanvases = projectTPEN3Data . layers [ 0 ] . pages . map ( ( page ) => page . target )
385+ const allPagesIds = projectTPEN3Data . layers [ 0 ] . pages . map ( ( page ) => page . id . replace ( / p r o j e c t \/ ( [ a - f 0 - 9 ] + ) / , `project/${ projectTPEN3Data . _id } ` ) )
386+ let manifestUrl = projectTPEN3Data . manifest [ 0 ]
387+ manifestUrl = this . transformManifestUrl ( manifestUrl , protocol )
388+ const responseManifest = await fetch ( manifestUrl )
389+ if ( ! responseManifest . ok ) {
390+ throw new Error ( `Failed to fetch: ${ responseManifest . statusText } ` )
391+ }
392+
393+ const manifestJson = await responseManifest . json ( )
394+ const itemsByPage = { }
395+ manifestJson . items . map ( ( item , index ) => {
396+ const canvasId = item . id
397+ if ( allCanvases . includes ( canvasId ) ) {
398+ const annotations = item . annotations ?. flatMap (
399+ ( annotation ) =>
400+ annotation . items ?. flatMap ( ( innerItems ) => ( {
401+ body : {
402+ type : innerItems . body ?. type ,
403+ format : innerItems . body ?. format ,
404+ value : innerItems . body ?. value ,
405+ } ,
406+ motivation : innerItems . motivation ,
407+ target : innerItems . target ,
408+ type : innerItems . type ,
409+ } ) ) || [ ]
410+ ) || [ ]
411+ itemsByPage [ allPagesIds [ index ] ] = annotations
412+ }
413+ } )
414+
415+ for ( const [ endpoint , annotations ] of Object . entries ( itemsByPage ) ) {
416+ try {
417+ const response = await fetch ( `${ endpoint } /line` , {
418+ method : "POST" ,
419+ headers : {
420+ "Content-Type" : "application/json" ,
421+ Authorization : `Bearer ${ userToken } ` ,
422+ } ,
423+ body : JSON . stringify ( annotations ) ,
424+ } )
425+ if ( ! response . ok ) {
426+ throw new Error ( `Failed to import annotations: ${ response . statusText } ` )
427+ }
428+ } catch ( error ) {
429+ console . error ( "Error importing annotations:" , error )
430+ }
431+ }
432+
433+ return projectTPEN3Data
434+ }
435+
343436 static async copyProject ( projectId , creator ) {
344437 if ( ! projectId ) {
345438 throw {
0 commit comments