@@ -29,7 +29,7 @@ import {
2929} from "../utilities/schemaHelperUtil" ;
3030import WebExtensionContext from "../WebExtensionContext" ;
3131import { webExtensionTelemetryEventNames } from "../../../common/OneDSLoggerTelemetry/web/client/webExtensionTelemetryEvents" ;
32- import { EntityMetadataKeyCore , SchemaEntityMetadata , folderExportType , schemaEntityKey , schemaEntityName , schemaKey } from "../schema/constants" ;
32+ import { EntityMetadataKeyCore , SchemaEntityMetadata , folderExportType , schemaEntityKey , schemaEntityName , schemaKey , WEBPAGE_FOLDER_CONSTANTS } from "../schema/constants" ;
3333import { getEntityNameForExpandedEntityContent , getRequestUrlForEntities } from "../utilities/folderHelperUtility" ;
3434import { IAttributePath , IFileInfo } from "../common/interfaces" ;
3535import { portal_schema_V2 } from "../schema/portalSchema" ;
@@ -237,36 +237,10 @@ async function createContentFiles(
237237 throw new Error ( ERROR_CONSTANTS . FILE_NAME_EMPTY ) ;
238238 }
239239
240- let folderName = fileName ;
241- if ( entityName === schemaEntityName . WEBPAGES ) {
242- const webpageNames = WebExtensionContext . getWebpageNames ( ) ;
243-
244- console . log ( `Processing webpage: ${ fileName } , entityId: ${ entityId } , already exists: ${ webpageNames . has ( fileName ) } ` ) ;
245-
246- if ( webpageNames . has ( fileName ) ) {
247- // This is a duplicate - append entity ID
248- // add telemetry for duplicate folder name creation
249- WebExtensionContext . telemetry . sendInfoTelemetry (
250- webExtensionTelemetryEventNames . WEB_EXTENSION_DUPLICATE_FOLDER_NAME_CREATED ,
251- { entityName : entityName , fileName : fileName , entityId : entityId , orgId : WebExtensionContext . organizationId , envId : WebExtensionContext . environmentId }
252- ) ;
253- folderName = getDuplicateFileName ( fileName , entityId ) ;
254- console . log ( `Created duplicate folder name: ${ folderName } ` ) ;
255- } else {
256- // First occurrence - just track it
257- webpageNames . add ( fileName ) ;
258- console . log ( `Added to tracking: ${ fileName } ` ) ;
259- }
260- }
240+ const folderName = fileName ;
261241
262242 // Create folder paths
263243 filePathInPortalFS = filePathInPortalFS ?? `${ Constants . PORTALS_URI_SCHEME } :/${ portalFolderName } /${ subUri } /` ;
264- if ( exportType && exportType === folderExportType . SubFolders ) {
265- filePathInPortalFS = `${ filePathInPortalFS } ${ getSanitizedFileName ( folderName ) } /` ;
266- await portalsFS . createDirectory (
267- vscode . Uri . parse ( filePathInPortalFS , true )
268- ) ;
269- }
270244
271245 const languageCodeAttribute = entityDetails ?. get (
272246 schemaEntityKey . LANGUAGE_FIELD
@@ -316,7 +290,9 @@ async function createContentFiles(
316290 filePathInPortalFS ,
317291 portalsFS ,
318292 defaultFileInfo ,
319- rootWebPageIdAttribute )
293+ rootWebPageIdAttribute ,
294+ exportType ,
295+ folderName )
320296
321297 } catch ( error ) {
322298 const errorMsg = ( error as Error ) ?. message ;
@@ -344,7 +320,9 @@ async function processDataAndCreateFile(
344320 filePathInPortalFS : string ,
345321 portalsFS : PortalsFS ,
346322 defaultFileInfo ?: IFileInfo ,
347- rootWebPageIdAttribute ?: string
323+ rootWebPageIdAttribute ?: string ,
324+ exportType ?: string ,
325+ originalFolderName ?: string
348326) {
349327 const attributeExtensionMap = attributeExtension as unknown as Map <
350328 string ,
@@ -353,6 +331,64 @@ async function processDataAndCreateFile(
353331 let counter = 0 ;
354332 let fileUri = "" ;
355333
334+ let rootWebPageId = undefined ;
335+ if ( rootWebPageIdAttribute ) {
336+ const rootWebPageIdPath : IAttributePath = getAttributePath ( rootWebPageIdAttribute ) ;
337+ rootWebPageId = getAttributeContent ( result , rootWebPageIdPath , entityName , entityId ) ;
338+ }
339+
340+ // Handle webpage folder organization by root webpage ID
341+ let actualFolderName = originalFolderName || fileName ;
342+ if ( entityName === schemaEntityName . WEBPAGES ) {
343+ const webpageNames = WebExtensionContext . getWebpageNames ( ) ;
344+
345+ const effectiveRootWebPageId = rootWebPageId || WEBPAGE_FOLDER_CONSTANTS . NO_ROOT_PLACEHOLDER ;
346+ const rootWebPageIdKey = `${ fileName } ${ WEBPAGE_FOLDER_CONSTANTS . DELIMITER } ${ effectiveRootWebPageId } ` ;
347+
348+ if ( ! webpageNames . has ( rootWebPageIdKey ) ) {
349+ // This is a new filename+rootWebPageId combination
350+ const existingEntriesForFileName = Array . from ( webpageNames ) . filter ( key => key . startsWith ( `${ fileName } ${ WEBPAGE_FOLDER_CONSTANTS . DELIMITER } ` ) ) ;
351+
352+ if ( existingEntriesForFileName . length > 0 ) {
353+ // This filename already exists with a different root webpage ID
354+ // Create a suffixed folder name for this NEW root webpage ID group
355+ WebExtensionContext . telemetry . sendInfoTelemetry (
356+ webExtensionTelemetryEventNames . WEB_EXTENSION_DUPLICATE_FOLDER_NAME_CREATED ,
357+ { entityName : entityName , fileName : fileName , entityId : entityId , orgId : WebExtensionContext . organizationId , envId : WebExtensionContext . environmentId }
358+ ) ;
359+ // Use effective rootWebPageId for consistent naming
360+ actualFolderName = getDuplicateFileName ( fileName , effectiveRootWebPageId ) ;
361+ } else {
362+ // First occurrence of this filename - use original name
363+ }
364+
365+ webpageNames . add ( rootWebPageIdKey ) ;
366+ } else {
367+ // We've seen this exact filename+rootWebPageId combination before
368+ // Determine which folder name was used for this specific root webpage ID group
369+ const existingEntriesForFileName = Array . from ( webpageNames ) . filter ( key => key . startsWith ( `${ fileName } ${ WEBPAGE_FOLDER_CONSTANTS . DELIMITER } ` ) ) ;
370+
371+ // Extract and sort root webpage IDs to ensure consistent ordering
372+ const rootWebPageIds = existingEntriesForFileName . map ( key => key . split ( WEBPAGE_FOLDER_CONSTANTS . DELIMITER ) [ 1 ] ) . sort ( ) ;
373+ const currentEntryIndex = rootWebPageIds . indexOf ( effectiveRootWebPageId ) ;
374+
375+ if ( currentEntryIndex === 0 ) {
376+ // This is the first root webpage ID that was encountered for this filename
377+ actualFolderName = fileName ;
378+ } else {
379+ // This is a subsequent root webpage ID - use suffixed folder name
380+ actualFolderName = getDuplicateFileName ( fileName , effectiveRootWebPageId ) ;
381+ }
382+ }
383+ } // Create folder directory if needed
384+ let finalFilePathInPortalFS = filePathInPortalFS ;
385+ if ( exportType && exportType === folderExportType . SubFolders ) {
386+ finalFilePathInPortalFS = `${ filePathInPortalFS } ${ getSanitizedFileName ( actualFolderName ) } /` ;
387+ await portalsFS . createDirectory (
388+ vscode . Uri . parse ( finalFilePathInPortalFS , true )
389+ ) ;
390+ }
391+
356392 for ( counter ; counter < attributeArray . length ; counter ++ ) {
357393 const fileExtension = attributeExtensionMap ?. get (
358394 attributeArray [ counter ]
@@ -371,7 +407,7 @@ async function processDataAndCreateFile(
371407 expandedContent ,
372408 portalsFS ,
373409 dataverseOrgUrl ,
374- filePathInPortalFS ) ;
410+ finalFilePathInPortalFS ) ;
375411 }
376412 }
377413 else {
@@ -384,16 +420,8 @@ async function processDataAndCreateFile(
384420 fileNameWithExtension = defaultFileInfo ?. fileName ;
385421 }
386422
387- // Get rootpage id
388- let rootWebPageId = undefined ;
389-
390- if ( rootWebPageIdAttribute ) {
391- const rootWebPageIdPath : IAttributePath = getAttributePath ( rootWebPageIdAttribute ) ;
392- rootWebPageId = getAttributeContent ( result , rootWebPageIdPath , entityName , entityId ) ;
393- }
394-
395423 if ( fileCreationValid ) {
396- fileUri = filePathInPortalFS + fileNameWithExtension ;
424+ fileUri = finalFilePathInPortalFS + fileNameWithExtension ;
397425 await createFile (
398426 attributeArray [ counter ] ,
399427 fileExtension ,
@@ -433,7 +461,7 @@ async function processDataAndCreateFile(
433461 }
434462
435463 if ( sourceAttributeExtension ) {
436- fileUri = filePathInPortalFS + GetFileNameWithExtension ( entityName , fileName , languageCode , sourceAttributeExtension ) ;
464+ fileUri = finalFilePathInPortalFS + GetFileNameWithExtension ( entityName , fileName , languageCode , sourceAttributeExtension ) ;
437465 await WebExtensionContext . updateSingleFileUrisInContext (
438466 vscode . Uri . parse ( fileUri )
439467 ) ;
0 commit comments