From 5ac861a955324df1783d51523468685ab3b0da90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Gether=20S=C3=B8rensen?= Date: Mon, 17 Feb 2025 14:08:08 +0100 Subject: [PATCH 1/2] Add support for specifying valid file extensions The `Sync` method in `WebResource.fs` now includes an optional `validExtensions` parameter of type `string array`, allowing the specification of valid file extensions for web resources. The `syncSolution` function in `Main.fs` has been updated to accept an additional `extensions` parameter, which is passed to the `WebResourcesHelper.syncSolution` function. The `getLocalResourcesHelper`, `getLocalWRs`, `getSyncActions`, and `syncSolution` functions in `WebResourcesHelper.fs` have been updated to accept an `extensions` parameter, allowing for more flexible extension handling. These changes collectively enable specifying valid file extensions for web resources during the synchronization process, providing more control over which files are considered. --- src/Delegate.Daxif/API/WebResource.fs | 6 ++++-- src/Delegate.Daxif/Modules/WebResources/Main.fs | 4 ++-- .../Modules/WebResources/WebResourcesHelper.fs | 16 ++++++++-------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Delegate.Daxif/API/WebResource.fs b/src/Delegate.Daxif/API/WebResource.fs index e60078c..5fc1fe9 100644 --- a/src/Delegate.Daxif/API/WebResource.fs +++ b/src/Delegate.Daxif/API/WebResource.fs @@ -14,7 +14,9 @@ type WebResource private () = /// The name of the solution to which to sync web resources /// Log Level - Error, Warning, Info, Verbose or Debug - defaults to: 'Verbose' /// The name of the patch solution to which to sync web resources. - static member Sync(env: Environment, webresourceRoot: string, solutionName: string, ?logLevel: LogLevel, ?patchSolutionName: string, ?publishAfterSync: bool) = + static member Sync(env: Environment, webresourceRoot: string, solutionName: string, ?logLevel: LogLevel, ?patchSolutionName: string, ?publishAfterSync: bool, ?validExtensions: string array) = let proxyGen = env.connect(log).GetService log.setLevelOption logLevel - Main.syncSolution proxyGen solutionName webresourceRoot patchSolutionName publishAfterSync \ No newline at end of file + + let extensions = validExtensions ?| System.Enum.GetNames(typeof) + Main.syncSolution proxyGen solutionName webresourceRoot patchSolutionName publishAfterSync extensions \ No newline at end of file diff --git a/src/Delegate.Daxif/Modules/WebResources/Main.fs b/src/Delegate.Daxif/Modules/WebResources/Main.fs index df8b10f..9d0d44f 100644 --- a/src/Delegate.Daxif/Modules/WebResources/Main.fs +++ b/src/Delegate.Daxif/Modules/WebResources/Main.fs @@ -7,7 +7,7 @@ open DG.Daxif.Common open DG.Daxif.Common.Utility open DG.Daxif.Common.InternalUtility -let syncSolution proxyGen solution webresourceRoot patchSolutionName publishAfterSync = +let syncSolution proxyGen solution webresourceRoot patchSolutionName publishAfterSync extensions = let publishAfterSync = publishAfterSync ?| true logVersion log let patchInfo = match patchSolutionName with @@ -16,5 +16,5 @@ let syncSolution proxyGen solution webresourceRoot patchSolutionName publishAfte log.Info @"Sync solution webresources: %s%s" solution patchInfo log.Verbose @"Solution: %s" solution log.Verbose @"Path to webresources: %s" webresourceRoot - WebResourcesHelper.syncSolution proxyGen webresourceRoot solution patchSolutionName publishAfterSync + WebResourcesHelper.syncSolution proxyGen webresourceRoot solution patchSolutionName publishAfterSync extensions log.Info "The solution webresources were synced successfully" \ No newline at end of file diff --git a/src/Delegate.Daxif/Modules/WebResources/WebResourcesHelper.fs b/src/Delegate.Daxif/Modules/WebResources/WebResourcesHelper.fs index d368def..b2b22e4 100644 --- a/src/Delegate.Daxif/Modules/WebResources/WebResourcesHelper.fs +++ b/src/Delegate.Daxif/Modules/WebResources/WebResourcesHelper.fs @@ -37,10 +37,10 @@ let localResourceToWebResource path name = /// Get all local webresources by enumerating all folders at given location, /// while looking for supported file types. -let getLocalResourcesHelper location crmRelease = +let getLocalResourcesHelper location (extensions: string array) crmRelease = seq { let exts = - Enum.GetNames(typeof) + extensions |> Array.map (fun x -> @"." + x.ToLower()) |> Array.toList |> List.filter (fun x -> (x <> ".svg" && x <> ".resx" ) || crmRelease >= CrmReleases.D365) @@ -70,8 +70,8 @@ let getPrefixAndUniqueName location = @"Incorrect root folder (must only contain 1 folder ex: 'publishPrefix_uniqueSolutionName'" /// Filter out any files which are labeled with "_nosync" -let getLocalWRs location prefix crmRelease = - getLocalResourcesHelper location crmRelease +let getLocalWRs location prefix extensions crmRelease = + getLocalResourcesHelper location extensions crmRelease |> Seq.filter (fun name -> not <| name.EndsWith("_nosync")) |> Seq.map (fun path -> let name = path.Substring(path.IndexOf(location) + location.Length).Replace(@"\", "/").Trim('/') @@ -79,7 +79,7 @@ let getLocalWRs location prefix crmRelease = ) |> Map.ofSeq -let getSyncActions proxy webresourceFolder solutionName patchSolutionName = +let getSyncActions proxy webresourceFolder solutionName patchSolutionName extensions = let (solutionId, prefix) = CrmDataInternal.Entities.retrieveSolutionIdAndPrefix proxy solutionName let wrBase = CrmDataInternal.Entities.retrieveWebResources proxy solutionId |> Seq.toList @@ -96,7 +96,7 @@ let getSyncActions proxy webresourceFolder solutionName patchSolutionName = let localWrPathMap = CrmDataInternal.Info.version proxy |> snd - |> getLocalWRs webresourceFolder wrPrefix + |> getLocalWRs webresourceFolder wrPrefix extensions let localWrs = localWrPathMap |> Seq.map (fun kv -> kv.Key) |> Set.ofSeq let crmWRs = @@ -152,10 +152,10 @@ let getSyncActions proxy webresourceFolder solutionName patchSolutionName = yield! update } -let syncSolution proxyGen location solutionName patchSolutionName publishAfterSync = +let syncSolution proxyGen location solutionName patchSolutionName publishAfterSync extensions = let p = proxyGen() - let syncActions = getSyncActions p location solutionName patchSolutionName + let syncActions = getSyncActions p location solutionName patchSolutionName extensions let patchSolutionNameIfExists = patchSolutionName |> Option.defaultValue solutionName let patchVerboseString = match patchSolutionName with | Some _ -> " and added to patch solution" From 3763a05df515556a0d32d5fd9957c50e4db3e49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Gether=20S=C3=B8rensen?= Date: Mon, 17 Feb 2025 14:32:04 +0100 Subject: [PATCH 2/2] Add filtering by WebResourceType to web resource retrieval Modified retrieveWebResources in CrmDataInternal.fs to accept optional WebResourceType extensions for filtering. Updated retrieveFirstMatch to filter by type if extensions are provided. Adjusted getWebresources calls in Extend.fs to include None for extensions. Added getWebresourceTypeFromExtensions helper in WebResourcesHelper.fs. Updated localResourceToWebResource and getSyncActions to use the new helper for type conversion and filtering. --- src/Delegate.Daxif/Common/CrmDataInternal.fs | 6 +++++- src/Delegate.Daxif/Modules/Solution/Extend.fs | 4 ++-- .../Modules/WebResources/WebResourcesHelper.fs | 10 +++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Delegate.Daxif/Common/CrmDataInternal.fs b/src/Delegate.Daxif/Common/CrmDataInternal.fs index 30dda23..a125af2 100644 --- a/src/Delegate.Daxif/Common/CrmDataInternal.fs +++ b/src/Delegate.Daxif/Common/CrmDataInternal.fs @@ -499,7 +499,7 @@ module CrmDataInternal = q.Criteria <- f CrmDataHelper.retrieveFirstMatch proxy q - let retrieveWebResources proxy solutionId = + let retrieveWebResources proxy solutionId (extensions: WebResourceType array option)= let (solutionId : Guid) = solutionId let ln = @"webresource" let an = @"solutionid" @@ -515,6 +515,10 @@ module CrmDataInternal = let f = FilterExpression() f.AddCondition (ConditionExpression(nm, ConditionOperator.Equal, false)) + if extensions.IsSome then + let validExtensions = extensions.Value |> Array.map (fun x -> (int)x) + f.AddCondition + (ConditionExpression("webresourcetype", ConditionOperator.In, validExtensions)) let q = QueryExpression(ln) q.ColumnSet <- ColumnSet(true) q.Criteria <- f diff --git a/src/Delegate.Daxif/Modules/Solution/Extend.fs b/src/Delegate.Daxif/Modules/Solution/Extend.fs index ee4c2b8..f07faf8 100644 --- a/src/Delegate.Daxif/Modules/Solution/Extend.fs +++ b/src/Delegate.Daxif/Modules/Solution/Extend.fs @@ -224,7 +224,7 @@ let export service solution solutionPath = ) let workflowsIdsAndOwners = workflows |> getWorkflowData service - let webResIds = getWebresources service solutionId |> getEntityIds + let webResIds = getWebresources service solutionId None |> getEntityIds let delegateSolution = { states=states @@ -356,7 +356,7 @@ let postImport service solutionName zipPath reassignWorkflows = log.Verbose "Synching Web Resource and Workflows" // Sync Webresources and workflows - let targetWebRes = getWebresources service solutionId |> getEntityIds + let targetWebRes = getWebresources service solutionId None |> getEntityIds let targetWorkflows = getWorkflows service solutionId |> getEntityIds let sourceWorkflows = extSol.keepWorkflows |> Seq.map (fun (id,name,_) -> id,name) diff --git a/src/Delegate.Daxif/Modules/WebResources/WebResourcesHelper.fs b/src/Delegate.Daxif/Modules/WebResources/WebResourcesHelper.fs index b2b22e4..bd8acca 100644 --- a/src/Delegate.Daxif/Modules/WebResources/WebResourcesHelper.fs +++ b/src/Delegate.Daxif/Modules/WebResources/WebResourcesHelper.fs @@ -18,10 +18,13 @@ type WebResourceAction = let getMatchingEntitiesByName namesToKeep = Seq.filter (fun (x: Entity) -> namesToKeep |> Set.contains (x.GetAttributeValue("name"))) +let getWebresourceTypeFromExtensions (ext: string) = + Enum.Parse(typeof, ext.ToUpper()) :?> WebResourceType + // Convert a local web resource file to an entity object. let localResourceToWebResource path name = let ext = Path.GetExtension(path).ToUpper().Replace(@".", String.Empty) - let webResourceType = Enum.Parse(typeof, ext.ToUpper()) :?> WebResourceType + let webResourceType = getWebresourceTypeFromExtensions ext let wr = Entity("webresource") wr.Attributes.Add("content", fileToBase64 path) @@ -81,11 +84,12 @@ let getLocalWRs location prefix extensions crmRelease = let getSyncActions proxy webresourceFolder solutionName patchSolutionName extensions = let (solutionId, prefix) = CrmDataInternal.Entities.retrieveSolutionIdAndPrefix proxy solutionName - let wrBase = CrmDataInternal.Entities.retrieveWebResources proxy solutionId |> Seq.toList + let extensionAsWebresourceTyoe = extensions |> Array.map getWebresourceTypeFromExtensions + let wrBase = CrmDataInternal.Entities.retrieveWebResources proxy solutionId (Some extensionAsWebresourceTyoe) |> Seq.toList let wrPatch = match patchSolutionName with | Some s -> let (sIdPatch, _) = CrmDataInternal.Entities.retrieveSolutionIdAndPrefix proxy s - CrmDataInternal.Entities.retrieveWebResources proxy sIdPatch |> Seq.toList + CrmDataInternal.Entities.retrieveWebResources proxy sIdPatch (Some extensionAsWebresourceTyoe) |> Seq.toList | None -> List.empty let wrBaseOnly = wrBase |> Seq.filter (fun a -> not (wrPatch |> Seq.exists (fun b -> b.Id = a.Id)))