From 68224aac88c751c191d1e11c3128c0a53885f657 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:14:35 -0400 Subject: [PATCH 01/10] feat: allow editing of files via web application First pass - probably needs a bit more work around the use case where a CSP file changes. (Theory: call OnBeforeTimestamp / OnBeforeLoad at end of AfterUserAction if the name is mapped?) --- cls/SourceControl/Git/Settings.cls | 74 ++++++++++++++++++++++++++++++ cls/SourceControl/Git/Utils.cls | 7 +++ 2 files changed, 81 insertions(+) diff --git a/cls/SourceControl/Git/Settings.cls b/cls/SourceControl/Git/Settings.cls index 6a4ce435..da9fdddf 100644 --- a/cls/SourceControl/Git/Settings.cls +++ b/cls/SourceControl/Git/Settings.cls @@ -47,6 +47,9 @@ Property defaultMergeBranch As %String [ InitialExpression = {##class(SourceCont /// Compile using the configured pull event handler when "Import All" is run Property compileOnImport As %Boolean [ InitialExpression = {##class(SourceControl.Git.Utils).CompileOnImport()} ]; +/// Define a namespace-level web application allowing access to multiple git repos across separate namespaces +Property namespaceLevelGitWebApp As %Boolean [ InitialExpression = {##class(SourceControl.Git.Settings).HasNamespaceWebApp()} ]; + Property Mappings [ MultiDimensional ]; Method %OnNew() As %Status @@ -160,6 +163,75 @@ ClassMethod Configure() As %Boolean [ CodeMode = objectgenerator ] do %code.WriteLine(" quit 1") } +Method ConfigureNamespaceWebApplication() +{ + Set root = ##class(%Library.File).NormalizeDirectory(##class(SourceControl.Git.Utils).TempFolder()) + Set deleteWebApp = ..HasNamespaceWebApp(.appDirectory) && '..namespaceLevelGitWebApp + Set createWebApp = ..namespaceLevelGitWebApp && '..HasNamespaceWebApp() + Do ..WebAppOperation("/git/"_$Namespace_"/", createWebApp, deleteWebApp, root) +} + +Method WebAppOperation(name, create As %Boolean, delete As %Boolean, root As %String) [ Private ] +{ + Set namespace = $Namespace + New $Namespace + Set $Namespace = "%SYS" + If $Extract(name) = "/" { + Set name = $Extract(name,1,*-1) + } + If delete { + If ##class(Security.Applications).Exists(name) { + $$$ThrowOnError(##class(Security.Applications).Delete(name)) + Write !,"Removed web application "_name + } + Quit + } + + // These are the only things we want to coerce. + Set props("AutheEnabled")=0 // No auth methods enabled = impossible to use + Set props("InbndWebServicesEnabled")=0 + Set props("ServeFiles")=0 + Set props("Enabled")=1 + Set props("Name")=name + Set props("NameSpace")=namespace + Set props("Path")=root + Set props("Type")=2 + Set props("Recurse")=1 + If create { + Write !,"Creating web application: "_name_"... " + $$$ThrowOnError(##class(Security.Applications).Create(name,.props)) + Write "done." + } ElseIf ##class(Security.Applications).Exists(name) { + Write !,"Web application '"_name_"' already exists." + $$$ThrowOnError(##class(Security.Applications).Get(name,.existingProps)) + Set changes = 0 + Set key = "" + For { + Set key = $Order(props(key),1,value) + Quit:key="" + If (value '= $Get(existingProps(key))) { + Write !,"Changing "_key_": "_$Get(existingProps(key))_" -> "_value + Set changes = 1 + } + } + If changes { + $$$ThrowOnError(##class(Security.Applications).Modify(name,.props)) + Write !,"Web application '"_name_"' updated." + } Else { + Write !,"No changes made to web application." + } + } +} + +ClassMethod HasNamespaceWebApp(Output webAppDirectory) As %Boolean +{ + Set webAppDirectory = $System.CSP.GetFileName("/git/"_$Namespace_"/") + If (webAppDirectory '= "") { + Set webAppDirectory = ##class(%Library.File).NormalizeDirectory(webAppDirectory) + } + Quit (webAppDirectory '= "") +} + Method OnAfterConfigure() As %Boolean { set defaultPromptFlag = $$$DisableBackupCharMask + $$$TrapCtrlCMask + $$$EnableQuitCharMask + $$$DisableHelpCharMask + $$$DisableHelpContextCharMask + $$$TrapErrorMask @@ -186,6 +258,8 @@ Method OnAfterConfigure() As %Boolean } } + do ..ConfigureNamespaceWebApplication() + set gitDir = ##class(%File).NormalizeDirectory(..namespaceTemp)_".git" if '##class(%File).DirectoryExists(gitDir) { set list(1) = "Initialize empty repo" diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls index 9b6405c7..9f9e159a 100644 --- a/cls/SourceControl/Git/Utils.cls +++ b/cls/SourceControl/Git/Utils.cls @@ -1132,6 +1132,13 @@ ClassMethod NormalizeInternalName(ByRef name As %String) As %String if ($extract(name) '= "/") && (type'="csp") { quit $piece(name,".",1,*-1)_"."_$zconvert($piece(name,".",*),"U") } + + if (name [ "/") && (type = "csp") { + set cspFilename = $System.CSP.GetFileName(name) + if (cspFilename '= "") && (cspFilename [ ..TempFolder()) { + set name = ..NameToInternalName(cspFilename) + } + } if (type = "inc") || (type = "mac") || (type = "int") { set name = $extract($translate(name, "/", "."), 2, *) From 06e7e508543e8a02d365d26dfda167593e37b71d Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Thu, 29 Aug 2024 09:24:57 -0400 Subject: [PATCH 02/10] feat: add VSCode workspace download link Also tweaks some styling and fixes behavior for interop-enabled namespaces with a URLPrefix. --- cls/SourceControl/Git/StreamServer.cls | 3 +- cls/SourceControl/Git/Utils.cls | 5 +- cls/SourceControl/Git/WebUIDriver.cls | 61 +++++++++++++++++++ .../share/git-webui/webui/css/git-webui.css | 18 +++++- .../share/git-webui/webui/img/context.svg | 2 +- .../share/git-webui/webui/js/git-webui.js | 3 + .../share/git-webui/webui/css/git-webui.less | 23 ++++++- .../src/share/git-webui/webui/img/context.svg | 2 +- .../src/share/git-webui/webui/js/git-webui.js | 3 + 9 files changed, 108 insertions(+), 12 deletions(-) diff --git a/cls/SourceControl/Git/StreamServer.cls b/cls/SourceControl/Git/StreamServer.cls index daf75a8d..42b2330e 100644 --- a/cls/SourceControl/Git/StreamServer.cls +++ b/cls/SourceControl/Git/StreamServer.cls @@ -7,7 +7,7 @@ Class SourceControl.Git.StreamServer Extends %CSP.StreamServer ClassMethod OnPage() As %Status { if (%stream '= $$$NULLOREF) && $data(%base)#2 { - set sourceControlInclude = ##class(SourceControl.Git.Utils).GetSourceControlInclude() + set sourceControlInclude = ##class(SourceControl.Git.Utils).GetSourceControlInclude(%request.URLPrefix) while '%stream.AtEnd { set text = %stream.Read() set text = $replace(text,"{{baseHref}}",..EscapeHTML(%base)) @@ -19,4 +19,3 @@ ClassMethod OnPage() As %Status } } - diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls index 9f9e159a..1efca933 100644 --- a/cls/SourceControl/Git/Utils.cls +++ b/cls/SourceControl/Git/Utils.cls @@ -2403,10 +2403,10 @@ ClassMethod GetPackageVersion() As %String [ CodeMode = objectgenerator ] quit $$$OK } -ClassMethod GetSourceControlInclude() As %String +ClassMethod GetSourceControlInclude(prefix As %String = "") As %String { quit $select(##class(%Library.EnsembleMgr).IsEnsembleInstalled(): - "", + "", 1: "") } @@ -2622,4 +2622,3 @@ ClassMethod BaselineExport(pCommitMessage = "", pPushToRemote = "") As %Status } } - diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls index 5d8a2b17..1699453c 100644 --- a/cls/SourceControl/Git/WebUIDriver.cls +++ b/cls/SourceControl/Git/WebUIDriver.cls @@ -27,6 +27,67 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out if $isobject($get(responseJSON)) { do responseJSON.%ToJSON(%data) } + } elseif pathStart = "vscode-workspace" { + set handled = 1 + set namespace = $Namespace + set instanceName = $ZConvert(##class(%SYS.System).InstanceGUID(),"L") + set hasCSP = 0 + if (InternalName = "") || context.IsInDefaultPackage { + set hasCSP = ##class(SourceControl.Git.Settings).HasNamespaceWebApp() + set workspaceFilename = namespace_"-"_instanceName_"-.code-workspace" + set filter = "?mapped=0" + } elseif context.IsInGitEnabledPackage { + set workspaceFilename = context.Package.Name_"-"_instanceName_".code-workspace" + // Loading an IPM package in dev mode automatically creates a project for it, so filter to that. + set filter = "?project="_context.Package.Name + } else { + // TODO: Error? But really shouldn't happen. + quit + } + set server = { + "webServer": { + "host": (%request.CgiEnvs("SERVER_NAME")), + "port": (%request.CgiEnvs("SERVER_PORT")), + "scheme": ($Select(%request.Secure:"https",1:"http")) + }, + "username": ($Username) + } + if (%request.URLPrefix '= "") { + set server.webServer.pathPrefix = %request.URLPrefix + } + set workspaceDef = { + "folders": [ + { + "name": ($Namespace), + "uri": ("isfs://"_instanceName_":"_$Namespace_"/"_filter) + } + ], + "settings": { + "intersystems.servers": { + "/default": (instanceName) + }, + "objectscript.conn": { + "active": false + } + } + } + if hasCSP { + do workspaceDef.folders.%Push({ + "name": ($Namespace_" (Filesystem)"), + "uri": ("isfs://"_instanceName_":"_$Namespace_"/git/"_$Namespace_"?csp") + }) + } + set $Property(workspaceDef.settings."intersystems.servers",instanceName) = server + set stream = ##class(%CSP.CharacterStream).%New() + do stream.SetAttribute("ContentDisposition","attachment; filename="_workspaceFilename) + set formatter = ##class(%JSON.Formatter).%New() + do formatter.FormatToStream(workspaceDef,stream) + $$$ThrowOnError(stream.%Save()) + do %request.Set("STREAMOID",##class(%CSP.Page).Encrypt(stream.%Oid())) + set %request.Data("EXPIRES",1,"encrypt") = 1 + do %request.Set("EXPIRES",0) + do ##class(%CSP.StreamServer).OnPreHTTP() // Need to call this to set headers properly + set %stream = 1 // Leak this to webuidriver.csp } elseif $match(pathStart,"git-command|git|dirname|hostname|viewonly|contexts") { if (%request.Method = "GET") { set %data = ##class(%Stream.TmpCharacter).%New() diff --git a/git-webui/release/share/git-webui/webui/css/git-webui.css b/git-webui/release/share/git-webui/webui/css/git-webui.css index 0a0043b7..2eebf585 100644 --- a/git-webui/release/share/git-webui/webui/css/git-webui.css +++ b/git-webui/release/share/git-webui/webui/css/git-webui.css @@ -183,7 +183,7 @@ body { padding-bottom: 100px; } #sidebar #sidebar-content > :first-child, -#sidebar #sidebar-content > :nth-last-child(2) { +#sidebar #sidebar-content > :nth-last-child(3) { border-top: 1px solid #5e5e5e; } #sidebar #sidebar-content h4:before { @@ -216,12 +216,26 @@ body { #sidebar #sidebar-content #sidebar-tags h4:before { content: url(../img/tag.svg); } +#sidebar #sidebar-content #sidebar-vscode a { + color: white; +} +#sidebar #sidebar-content #sidebar-vscode h4:before { + content: url(../img/file.svg); +} +#sidebar #sidebar-content #sidebar-vscode { + position: absolute; + bottom: 80px; + width: 16.7em; + padding-bottom: 0.3rem; + margin-bottom: 0; + background-color: #333333; +} #sidebar #sidebar-content #sidebar-context h4:before { content: url(../img/context.svg); } #sidebar #sidebar-content #sidebar-context { position: absolute; - bottom: 50px; + bottom: 40px; width: 16.7em; padding-bottom: 0.3rem; margin-bottom: 0; diff --git a/git-webui/release/share/git-webui/webui/img/context.svg b/git-webui/release/share/git-webui/webui/img/context.svg index e3732172..f5ef6c98 100644 --- a/git-webui/release/share/git-webui/webui/img/context.svg +++ b/git-webui/release/share/git-webui/webui/img/context.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/git-webui/release/share/git-webui/webui/js/git-webui.js b/git-webui/release/share/git-webui/webui/js/git-webui.js index 9625c506..7161e0d8 100644 --- a/git-webui/release/share/git-webui/webui/js/git-webui.js +++ b/git-webui/release/share/git-webui/webui/js/git-webui.js @@ -973,6 +973,9 @@ webui.SideBarView = function(mainView, noEventHandlers) { '' + + '' + '' + diff --git a/git-webui/src/share/git-webui/webui/css/git-webui.less b/git-webui/src/share/git-webui/webui/css/git-webui.less index 652d5bdb..41b16101 100644 --- a/git-webui/src/share/git-webui/webui/css/git-webui.less +++ b/git-webui/src/share/git-webui/webui/css/git-webui.less @@ -257,7 +257,7 @@ body { color: @gray-lighter; padding-bottom: 100px; - > :first-child, >:nth-last-child(2) { + > :first-child, >:nth-last-child(3) { border-top: 1px solid darken(@separator-line, 50%); } @@ -301,13 +301,30 @@ body { content: url(../img/tag.svg); } + #sidebar-vscode a { + color: white; + } + + #sidebar-vscode h4:before { + content: url(../img/file.svg); + } + + #sidebar-vscode { + position: absolute; + bottom: 80px; + width: 16.7em; + padding-bottom: 0.3rem; + margin-bottom: 0; + background-color: rgba(51, 51, 51, 1); + } + #sidebar-context h4:before { - content: url(../img/context.svg) + content: url(../img/context.svg); } #sidebar-context { position: absolute; - bottom: 50px; + bottom: 40px; width: 16.7em; padding-bottom: 0.3rem; margin-bottom: 0; diff --git a/git-webui/src/share/git-webui/webui/img/context.svg b/git-webui/src/share/git-webui/webui/img/context.svg index e3732172..f5ef6c98 100644 --- a/git-webui/src/share/git-webui/webui/img/context.svg +++ b/git-webui/src/share/git-webui/webui/img/context.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/git-webui/src/share/git-webui/webui/js/git-webui.js b/git-webui/src/share/git-webui/webui/js/git-webui.js index 9625c506..7161e0d8 100644 --- a/git-webui/src/share/git-webui/webui/js/git-webui.js +++ b/git-webui/src/share/git-webui/webui/js/git-webui.js @@ -973,6 +973,9 @@ webui.SideBarView = function(mainView, noEventHandlers) { '' + + '' + '' + From 29516abde0c5720d1c4cea5e57eff020d6e4f3cb Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Thu, 29 Aug 2024 09:55:03 -0400 Subject: [PATCH 03/10] feat: compile files modified via web application --- CHANGELOG.md | 3 +++ cls/SourceControl/Git/Extension.cls | 29 ++++++++++++++++++++--------- cls/SourceControl/Git/Utils.cls | 9 ++++++--- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38d14ff0..05dada90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - New UI for the basic mode Sync (#415) - Allow changing namespaces and IPM package context from web UI (#280) +- Support for editing repo from filesystem perspective via web application (#464) +- Support for downloading a VSCode workspace file from web UI ### Fixed - Instance wide settings are placed in proper global (#444) +- Avoid delay/errors in loading interop JS when there is a URL prefix (e.g., instance name in multi-instance webserver configuration) ## [2.4.1] - 2024-08-02 diff --git a/cls/SourceControl/Git/Extension.cls b/cls/SourceControl/Git/Extension.cls index a55c791e..5e45be73 100644 --- a/cls/SourceControl/Git/Extension.cls +++ b/cls/SourceControl/Git/Extension.cls @@ -74,9 +74,13 @@ Method AfterUserAction(Type As %Integer, Name As %String, InternalName As %Strin if menu '= "%SourceMenu", menu'="%SourceContext" { quit $$$OK } - set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(InternalName) + set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(InternalName, .fromWebApp) set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(InternalName) set ec = ##class(SourceControl.Git.Utils).AfterUserAction(Type, Name, InternalName, .Answer, .Msg, .Reload) + if fromWebApp { + // Force reload and compile of actual item if underlying file has changed + do ..OnBeforeLoad(InternalName,1,1) + } quit ec } @@ -234,12 +238,12 @@ Method OnMenuItem(MenuName As %String, InternalName As %String, SelectedText As /// This is called before the actual load of data to give the chance /// to load the item from an external format. -Method OnBeforeLoad(InternalName As %String, verbose As %Boolean) As %Status +Method OnBeforeLoad(InternalName As %String, verbose As %Boolean, compile As %Boolean = 0) As %Status { set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(InternalName) set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(InternalName) if ##class(SourceControl.Git.Utils).IsInSourceControl(InternalName) { - quit ##class(SourceControl.Git.Utils).ImportItem(InternalName,,0) + quit ##class(SourceControl.Git.Utils).ImportItem(InternalName,,0,compile) } quit $$$OK } @@ -273,14 +277,21 @@ Method OnAfterSave(InternalName As %String, Object As %RegisteredObject = {$$$NU { set sc = $$$OK try { - set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(.InternalName) + set InternalName = ##class(SourceControl.Git.Utils).NormalizeInternalName(.InternalName,.fromWebApp,.fullExternalName) set context = ##class(SourceControl.Git.PackageManagerContext).ForInternalName(InternalName) if ##class(SourceControl.Git.Utils).IsNamespaceInGit() && ..IsInSourceControl(InternalName) { - set filename = ##class(SourceControl.Git.Utils).FullExternalName(InternalName) - $$$ThrowOnError(##class(SourceControl.Git.Utils).RemoveRoutineTSH(InternalName)) - $$$ThrowOnError(##class(SourceControl.Git.Utils).ExportItem(InternalName)) - if '##class(SourceControl.Git.Change).IsUncommitted(filename) { - $$$ThrowOnError(##class(SourceControl.Git.Change).SetUncommitted(filename, "edit", InternalName, $username, "", 1, "", "", 0)) + if fromWebApp { + if fullExternalName = ##class(SourceControl.Git.Utils).FullExternalName(InternalName) { + // Reimport item into database + $$$ThrowOnError(##class(SourceControl.Git.Utils).ImportItem(InternalName,,1,1)) + } + } else { + set filename = ##class(SourceControl.Git.Utils).FullExternalName(InternalName) + $$$ThrowOnError(##class(SourceControl.Git.Utils).RemoveRoutineTSH(InternalName)) + $$$ThrowOnError(##class(SourceControl.Git.Utils).ExportItem(InternalName)) + if '##class(SourceControl.Git.Change).IsUncommitted(filename) { + $$$ThrowOnError(##class(SourceControl.Git.Change).SetUncommitted(filename, "edit", InternalName, $username, "", 1, "", "", 0)) + } } } } catch e { diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls index 1efca933..94290b60 100644 --- a/cls/SourceControl/Git/Utils.cls +++ b/cls/SourceControl/Git/Utils.cls @@ -1116,7 +1116,7 @@ ClassMethod FullExternalName(ByRef InternalName As %String, ByRef MappingExists ..TempFolder()_..ExternalName(.InternalName, .MappingExists) } -ClassMethod NormalizeInternalName(ByRef name As %String) As %String +ClassMethod NormalizeInternalName(ByRef name As %String, Output fromWebApp As %Boolean = 0, Output cspFilename) As %String { //Studio passes name of routine with dots as it is in folders //e.g. Package.SubPackage.Routine.mac has InternalName = /Package/SubPackage/Routine.mac @@ -1137,6 +1137,9 @@ ClassMethod NormalizeInternalName(ByRef name As %String) As %String set cspFilename = $System.CSP.GetFileName(name) if (cspFilename '= "") && (cspFilename [ ..TempFolder()) { set name = ..NameToInternalName(cspFilename) + set fromWebApp = 1 + } else { + kill cspFilename } } @@ -1253,7 +1256,7 @@ ClassMethod FixProjectCspReferences(projectName As %String) As %Status /// imports file if version in system is newer then version on disk. /// if force = 1 then imports in any case. -ClassMethod ImportItem(InternalName As %String, force As %Boolean = 0, verbose As %Boolean = 1) As %Status +ClassMethod ImportItem(InternalName As %String, force As %Boolean = 0, verbose As %Boolean = 1, compile As %Boolean = 0) As %Status { #dim filename as %String = ..FullExternalName(.InternalName) #dim fileTSH = ##class(%File).GetFileDateModified(filename) @@ -1272,7 +1275,7 @@ ClassMethod ImportItem(InternalName As %String, force As %Boolean = 0, verbose A if ($extract(InternalName, 1) = "/"){ set sc = ..ImportCSPFile(InternalName) } else{ - set sc = $system.OBJ.Load(filename,"-l-d") + set sc = $system.OBJ.Load(filename,$Select(compile:"ck-l",1:"-l-d")) } } if sc { From e6ff2eb530badf5ae3b7e2916fa2a277821a3206 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:08:38 -0400 Subject: [PATCH 04/10] fix: tweak InternalName logic --- cls/SourceControl/Git/WebUIDriver.cls | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls index 1699453c..a8331485 100644 --- a/cls/SourceControl/Git/WebUIDriver.cls +++ b/cls/SourceControl/Git/WebUIDriver.cls @@ -32,17 +32,14 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out set namespace = $Namespace set instanceName = $ZConvert(##class(%SYS.System).InstanceGUID(),"L") set hasCSP = 0 - if (InternalName = "") || context.IsInDefaultPackage { - set hasCSP = ##class(SourceControl.Git.Settings).HasNamespaceWebApp() - set workspaceFilename = namespace_"-"_instanceName_"-.code-workspace" - set filter = "?mapped=0" - } elseif context.IsInGitEnabledPackage { + if context.IsInGitEnabledPackage && 'context.IsInDefaultPackage { set workspaceFilename = context.Package.Name_"-"_instanceName_".code-workspace" // Loading an IPM package in dev mode automatically creates a project for it, so filter to that. set filter = "?project="_context.Package.Name } else { - // TODO: Error? But really shouldn't happen. - quit + set hasCSP = ##class(SourceControl.Git.Settings).HasNamespaceWebApp() + set workspaceFilename = namespace_"-"_instanceName_"-.code-workspace" + set filter = "?mapped=0" } set server = { "webServer": { From a6d66a7f2daa738eb1e37e7c8f3948f3221db3f4 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:24:44 -0400 Subject: [PATCH 05/10] fix: remove stray dash --- cls/SourceControl/Git/WebUIDriver.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls index a8331485..5787162b 100644 --- a/cls/SourceControl/Git/WebUIDriver.cls +++ b/cls/SourceControl/Git/WebUIDriver.cls @@ -38,7 +38,7 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out set filter = "?project="_context.Package.Name } else { set hasCSP = ##class(SourceControl.Git.Settings).HasNamespaceWebApp() - set workspaceFilename = namespace_"-"_instanceName_"-.code-workspace" + set workspaceFilename = namespace_"-"_instanceName_".code-workspace" set filter = "?mapped=0" } set server = { From 6008325ecf29e13c84994d0d47963ecfbc630e88 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 30 Aug 2024 09:33:45 -0400 Subject: [PATCH 06/10] fix: always just include one folder --- cls/SourceControl/Git/WebUIDriver.cls | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls index 5787162b..a2888688 100644 --- a/cls/SourceControl/Git/WebUIDriver.cls +++ b/cls/SourceControl/Git/WebUIDriver.cls @@ -54,10 +54,6 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out } set workspaceDef = { "folders": [ - { - "name": ($Namespace), - "uri": ("isfs://"_instanceName_":"_$Namespace_"/"_filter) - } ], "settings": { "intersystems.servers": { @@ -73,6 +69,11 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out "name": ($Namespace_" (Filesystem)"), "uri": ("isfs://"_instanceName_":"_$Namespace_"/git/"_$Namespace_"?csp") }) + } else { + do workspaceDef.folders.%Push({ + "name": ($Namespace), + "uri": ("isfs://"_instanceName_":"_$Namespace_"/"_filter) + }) } set $Property(workspaceDef.settings."intersystems.servers",instanceName) = server set stream = ##class(%CSP.CharacterStream).%New() From 3631c0da97c2d14008b2569ca32c570aee1c0f4f Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:12:34 -0400 Subject: [PATCH 07/10] fix: add JS escaping in sync output --- CHANGELOG.md | 1 + csp/sync.csp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05dada90..417ac339 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Instance wide settings are placed in proper global (#444) - Avoid delay/errors in loading interop JS when there is a URL prefix (e.g., instance name in multi-instance webserver configuration) +- Added proper JS escaping in sync output ## [2.4.1] - 2024-08-02 diff --git a/csp/sync.csp b/csp/sync.csp index 78be9c2c..03404f08 100644 --- a/csp/sync.csp +++ b/csp/sync.csp @@ -146,7 +146,7 @@ &js< var outputContainer = document.getElementById('outputBox'); - var lineText = "#(escapedLine)#"; + var lineText = "#(..QuoteJS(escapedLine))#"; var lineTextNode = document.createTextNode(lineText); outputContainer.innerHTML += lineText + "
"; > From b625fc8fde76f1972e5b9446701a657a1a6c5f42 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:13:47 -0400 Subject: [PATCH 08/10] fix: don't double-quote --- csp/sync.csp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csp/sync.csp b/csp/sync.csp index 03404f08..bab0d58d 100644 --- a/csp/sync.csp +++ b/csp/sync.csp @@ -146,7 +146,7 @@ &js< var outputContainer = document.getElementById('outputBox'); - var lineText = "#(..QuoteJS(escapedLine))#"; + var lineText = #(..QuoteJS(escapedLine))#; var lineTextNode = document.createTextNode(lineText); outputContainer.innerHTML += lineText + "
"; > From ebda553b0059cc23be22fecf2d4f0f74e62bc8eb Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:16:49 -0400 Subject: [PATCH 09/10] fix: tweaks to workspace setup --- cls/SourceControl/Git/WebUIDriver.cls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cls/SourceControl/Git/WebUIDriver.cls b/cls/SourceControl/Git/WebUIDriver.cls index a2888688..d5580448 100644 --- a/cls/SourceControl/Git/WebUIDriver.cls +++ b/cls/SourceControl/Git/WebUIDriver.cls @@ -44,7 +44,7 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out set server = { "webServer": { "host": (%request.CgiEnvs("SERVER_NAME")), - "port": (%request.CgiEnvs("SERVER_PORT")), + "port": (+%request.CgiEnvs("SERVER_PORT")), "scheme": ($Select(%request.Secure:"https",1:"http")) }, "username": ($Username) @@ -66,7 +66,7 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out } if hasCSP { do workspaceDef.folders.%Push({ - "name": ($Namespace_" (Filesystem)"), + "name": ($Namespace), "uri": ("isfs://"_instanceName_":"_$Namespace_"/git/"_$Namespace_"?csp") }) } else { From 9571c57bd9d131ce6a88ddee6ca9b2e88baa9d2c Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:09:17 -0400 Subject: [PATCH 10/10] fix: tweak IE box model Also fixed an issue with regex matching where I couldn't view my local git-source-control repo --- .../share/git-webui/webui/css/git-webui.css | 15 +++++++++------ .../share/git-webui/webui/js/git-webui.js | 3 +++ .../share/git-webui/webui/css/git-webui.less | 18 ++++++++++++------ .../src/share/git-webui/webui/js/git-webui.js | 3 +++ 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/git-webui/release/share/git-webui/webui/css/git-webui.css b/git-webui/release/share/git-webui/webui/css/git-webui.css index 2eebf585..0c75c1f4 100644 --- a/git-webui/release/share/git-webui/webui/css/git-webui.css +++ b/git-webui/release/share/git-webui/webui/css/git-webui.css @@ -219,6 +219,9 @@ body { #sidebar #sidebar-content #sidebar-vscode a { color: white; } +#sidebar #sidebar-content #sidebar-vscode h4 { + padding: 0px; +} #sidebar #sidebar-content #sidebar-vscode h4:before { content: url(../img/file.svg); } @@ -226,10 +229,11 @@ body { position: absolute; bottom: 80px; width: 16.7em; - padding-bottom: 0.3rem; - margin-bottom: 0; background-color: #333333; } +#sidebar #sidebar-content #sidebar-context h4 { + padding: 0px; +} #sidebar #sidebar-content #sidebar-context h4:before { content: url(../img/context.svg); } @@ -237,10 +241,11 @@ body { position: absolute; bottom: 40px; width: 16.7em; - padding-bottom: 0.3rem; - margin-bottom: 0; background-color: #333333; } +#sidebar #sidebar-content #sidebar-settings h4 { + padding: 0px; +} #sidebar #sidebar-content #sidebar-settings h4:before { content: url(../img/gear-fill.svg); } @@ -248,8 +253,6 @@ body { position: absolute; bottom: 0px; width: 16.7em; - padding-bottom: 0.3rem; - margin-bottom: 0px; background-color: #333333; } #sidebar #sidebar-content ul { diff --git a/git-webui/release/share/git-webui/webui/js/git-webui.js b/git-webui/release/share/git-webui/webui/js/git-webui.js index 7161e0d8..632c10f1 100644 --- a/git-webui/release/share/git-webui/webui/js/git-webui.js +++ b/git-webui/release/share/git-webui/webui/js/git-webui.js @@ -421,6 +421,9 @@ webui.SideBarView = function(mainView, noEventHandlers) { if (id.indexOf("local-branches") > -1) { // parses the output of git branch --verbose --verbose var matches = /^\*?\s*([\w-\/]+)\s+([^\s]+)\s+(\[.*\])?.*/.exec(ref); + if (!matches) { + continue; + } var branchInfo = { "branch_name": matches[1], "hash": matches[2], diff --git a/git-webui/src/share/git-webui/webui/css/git-webui.less b/git-webui/src/share/git-webui/webui/css/git-webui.less index 41b16101..8fb86733 100644 --- a/git-webui/src/share/git-webui/webui/css/git-webui.less +++ b/git-webui/src/share/git-webui/webui/css/git-webui.less @@ -305,6 +305,10 @@ body { color: white; } + #sidebar-vscode h4 { + padding: 0px; + } + #sidebar-vscode h4:before { content: url(../img/file.svg); } @@ -313,11 +317,13 @@ body { position: absolute; bottom: 80px; width: 16.7em; - padding-bottom: 0.3rem; - margin-bottom: 0; background-color: rgba(51, 51, 51, 1); } + #sidebar-context h4 { + padding: 0px; + } + #sidebar-context h4:before { content: url(../img/context.svg); } @@ -326,11 +332,13 @@ body { position: absolute; bottom: 40px; width: 16.7em; - padding-bottom: 0.3rem; - margin-bottom: 0; background-color: rgba(51, 51, 51, 1); } + #sidebar-settings h4 { + padding: 0px; + } + #sidebar-settings h4:before { content: url(../img/gear-fill.svg); } @@ -339,8 +347,6 @@ body { position: absolute; bottom: 0px; width: 16.7em; - padding-bottom: 0.3rem; - margin-bottom:0px; background-color: rgba(51, 51, 51, 1); } diff --git a/git-webui/src/share/git-webui/webui/js/git-webui.js b/git-webui/src/share/git-webui/webui/js/git-webui.js index 7161e0d8..632c10f1 100644 --- a/git-webui/src/share/git-webui/webui/js/git-webui.js +++ b/git-webui/src/share/git-webui/webui/js/git-webui.js @@ -421,6 +421,9 @@ webui.SideBarView = function(mainView, noEventHandlers) { if (id.indexOf("local-branches") > -1) { // parses the output of git branch --verbose --verbose var matches = /^\*?\s*([\w-\/]+)\s+([^\s]+)\s+(\[.*\])?.*/.exec(ref); + if (!matches) { + continue; + } var branchInfo = { "branch_name": matches[1], "hash": matches[2],