editfile.html 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <!--
  2. Copyright (C) 2023 Nicola Murino
  3. This WebUI uses the KeenThemes Mega Bundle, a proprietary theme:
  4. https://keenthemes.com/products/templates-mega-bundle
  5. KeenThemes HTML/CSS/JS components are allowed for use only within the
  6. SFTPGo product and restricted to be used in a resealable HTML template
  7. that can compete with KeenThemes products anyhow.
  8. This WebUI is allowed for use only within the SFTPGo product and
  9. therefore cannot be used in derivative works/products without an
  10. explicit grant from the SFTPGo Team ([email protected]).
  11. -->
  12. {{template "base" .}}
  13. {{define "title"}}{{.Title}}{{end}}
  14. {{- define "extra_css"}}
  15. <style {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
  16. .shortcut {font-family: monospace; color: #666;}
  17. .cm-editor {
  18. height: 100%;
  19. width: 100%;
  20. }
  21. </style>
  22. {{- end}}
  23. {{- define "additionalnavitems"}}
  24. <div class="d-flex align-items-center ms-2 ms-lg-3" id="kt_header_user_menu_toggle">
  25. <div class="btn btn-icon btn-active-light-primary w-35px h-35px w-md-40px h-md-40px" data-bs-toggle="modal" data-bs-target="#info_modal">
  26. <i class="ki-duotone ki-information-2 fs-2">
  27. <i class="path1"></i>
  28. <i class="path2"></i>
  29. <i class="path3"></i>
  30. </i>
  31. </div>
  32. </div>
  33. {{- end}}
  34. {{- define "page_body"}}
  35. {{- template "errmsg" ""}}
  36. <div class="card shadow-sm">
  37. <div class="card-header">
  38. {{- if .ReadOnly}}
  39. <h6 class="card-title">View file "{{.Path}}"</h6>
  40. {{- else}}
  41. <h6 class="card-title">Edit file "{{.Path}}"</h6>
  42. {{- end}}
  43. <div class="card-toolbar">
  44. <a class="btn btn-light-primary px-10 me-5" href='{{.FilesURL}}?path={{.CurrentDir}}' role="button">Back</a>
  45. {{- if not .ReadOnly}}
  46. <a id="save_button" type="button" class="btn btn-primary px-10" href="#" role="button">
  47. <span class="indicator-label">Save</span>
  48. <span class="indicator-progress">Please wait...
  49. <span class="spinner-border spinner-border-sm align-middle ms-2"></span>
  50. </span>
  51. </a>
  52. {{- end}}
  53. </div>
  54. </div>
  55. <div class="card-body">
  56. <div id="editor" class="col-sm-12 border border-light-primary"></div>
  57. </div>
  58. </div>
  59. {{- end}}
  60. {{- define "modals"}}
  61. <div class="modal fade" id="info_modal" tabindex="-1">
  62. <div class="modal-dialog">
  63. <div class="modal-content">
  64. <div class="modal-header">
  65. <h3 class="modal-title">Editor keybindings</h3>
  66. <div class="btn btn-icon btn-sm btn-active-light-primary ms-2" data-bs-dismiss="modal" aria-label="Close">
  67. <i class="ki-duotone ki-cross fs-1"><span class="path1"></span><span class="path2"></span></i>
  68. </div>
  69. </div>
  70. <div class="modal-body">
  71. <p>
  72. <span class="shortcut">Ctrl-F / Cmd-F</span> => Open search panel
  73. </p>
  74. <p>
  75. <span class="shortcut">Alt-G</span> => Jump to line
  76. </p>
  77. <p>
  78. <span class="shortcut">Tab</span> => Indent more
  79. </p>
  80. <p>
  81. <span class="shortcut">Shift-Tab</span> => Indent less
  82. </p>
  83. </div>
  84. <div class="modal-footer">
  85. <button class="btn btn-primary" type="button" data-bs-dismiss="modal">OK</button>
  86. </div>
  87. </div>
  88. </div>
  89. </div>
  90. {{- end}}
  91. {{- define "extra_js"}}
  92. <script src="{{.StaticURL}}/vendor/codemirror/cm6.bundle.min.js"></script>
  93. <script type="text/javascript" {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
  94. var cmView;
  95. function keepAlive() {
  96. axios.get('{{.PingURL}}',{
  97. timeout: 15000,
  98. responseType: 'text'
  99. }).catch(function (error){});
  100. }
  101. //{{- if not .ReadOnly}}
  102. function saveFile() {
  103. $('#errorMsg').addClass("d-none");
  104. let saveButton = document.querySelector('#save_button');
  105. saveButton.setAttribute('data-kt-indicator', 'on');
  106. saveButton.disabled = true;
  107. let uploadPath = '{{.FileURL}}?path='+encodeURIComponent('{{.CurrentDir}}/{{.Name}}');
  108. let blob = new Blob([cmView.state.doc.toString()]);
  109. axios.post(uploadPath, blob, {
  110. headers: {
  111. 'X-CSRF-TOKEN': '{{.CSRFToken}}'
  112. },
  113. timeout: 600000,
  114. validateStatus: function (status) {
  115. return status == 201;
  116. }
  117. }).then(function (response) {
  118. window.location.replace('{{.FilesURL}}?path='+encodeURIComponent('{{.CurrentDir}}'));
  119. }).catch(function (error) {
  120. saveButton.removeAttribute('data-kt-indicator');
  121. saveButton.disabled = false;
  122. let errorMessage = "Error saving file";
  123. if (error && error.response) {
  124. if (error.response.data.message) {
  125. errorMessage = error.response.data.message;
  126. }
  127. if (error.response.data.error) {
  128. errorMessage += ": " + error.response.data.error;
  129. }
  130. }
  131. $('#errorTxt').text(errorMessage);
  132. $('#errorMsg').removeClass("d-none");
  133. });
  134. }
  135. //{{- end}}
  136. KTUtil.onDOMContentLoaded(function () {
  137. let filename = "{{.Name}}";
  138. let extension = filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
  139. let options = {
  140. oneDark: KTThemeMode.getMode() == "dark",
  141. fileExt: extension
  142. };
  143. //{{- if .ReadOnly}}
  144. options.readOnly = true;
  145. //{{- end}}
  146. //{{- if .CSPNonce}}
  147. options.cspNonce = "{{.CSPNonce}}";
  148. //{{- end}}
  149. let editorState = cm6.createEditorState("{{.Data}}", options);
  150. cmView = cm6.createEditorView(editorState, document.getElementById("editor"));
  151. var saveBtn = $('#save_button');
  152. if (saveBtn){
  153. saveBtn.on("click", function(){
  154. saveFile();
  155. });
  156. }
  157. setInterval(keepAlive, 300000);
  158. });
  159. </script>
  160. {{- end}}