PageRenderTime 35ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/config/js/backend-scripts.js

https://gitlab.com/glancr/system
JavaScript | 326 lines | 258 code | 38 blank | 30 comment | 17 complexity | 2b4ccf60af7bb6780a377f7ab3df7c5b MD5 | raw file
  1. /**
  2. * Scripts for dynamic backend management tasks in the config screen.
  3. */
  4. $(document).ready(function () {
  5. $.each(modulesInUse, function (index, value) {
  6. $('.module-' + value).hide()
  7. })
  8. })
  9. // Remove red border on input fields when they have focus, since the user might input missing data now.
  10. $('input[type="text"]').focus(function () {
  11. $(this).removeClass('error')
  12. })
  13. $('.block__actions--edit').click(function () {
  14. $('#size-row').val($(this).prev().val())
  15. $('#layout').val(modules[$(this).prev().val()].length)
  16. })
  17. // Reorder active modules when user changes a row layout.
  18. $('#layout').change(function () {
  19. var row = $('#size-row').val()
  20. var cols = $(this).val()
  21. if (cols == 1) {
  22. if (modules[row][1].length > 0) {
  23. modulesInUse = $.grep(modulesInUse, function (value) {
  24. return value != modules[row][1]
  25. })
  26. $('.module-' + modules[row][1]).show()
  27. }
  28. modules[row].splice(1, 1)
  29. $('.module-row:eq(' + row + ')').find('.small-6:eq(1)').remove()
  30. $('.module-row:eq(' + row + ')').find('.small-6:eq(0)').removeClass('small-6').addClass('small-12')
  31. } else {
  32. modules[row][1] = ''
  33. $('.module-row:eq(' + row + ') > .small-12:eq(0)').find('.small-12:eq(0)').removeClass('small-12').addClass('small-6')
  34. $('.module-row:eq(' + row + ') > .small-12:eq(0) > .row > .small-6:eq(0)').after('<div class="small-6 columns"><div class="block__add">'
  35. + '<button class="block__add--button" href="#" aria-label="plus button" data-open="gr-modal-add">'
  36. + '<span class="fi-plus"></span></button></div></div>')
  37. }
  38. $.post('writeLayout.php', {'row': row, 'modules[]': modules[row]})
  39. .done(function () {
  40. $('#gr-modal-size').foundation('close')
  41. $('#ok').show(30, function () {
  42. $(this).hide('slow')
  43. })
  44. })
  45. })
  46. $('body').delegate('.block__add--button', 'click', function () {
  47. var col
  48. if ($(this).parent().parent().hasClass('small-12') || $(this).parent().parent().next().hasClass('small-6')) {
  49. col = 0
  50. } else {
  51. col = 1
  52. }
  53. var row = $(this).parent().parent().parent().parent().children().eq(0).children().eq(0).val()
  54. $('#newModulCol').val(col)
  55. $('#newModulRow').val(row)
  56. })
  57. $('body').delegate('.module__delete', 'click', function () {
  58. var col
  59. if ($(this).parent().parent().parent().hasClass('small-12') || $(this).parent().parent().parent().next().hasClass('small-6')) {
  60. col = 0
  61. } else {
  62. col = 1
  63. }
  64. var row = $(this).parent().parent().parent().parent().parent().children().eq(0).children().eq(0).val()
  65. var moduleId = modules[row][col]
  66. modules[row][col] = ''
  67. $.post('writeLayout.php', {'row': row, 'modules[]': modules[row]})
  68. .done(function () {
  69. $('#ok').show(30, function () {
  70. $(this).hide('slow')
  71. })
  72. })
  73. $(this).parent().parent().html('<button class="block__add--button" href="#" aria-label="plus button" data-open="gr-modal-add">'
  74. + '<span class="fi-plus"></span></button>')
  75. modulesInUse = $.grep(modulesInUse, function (value) {
  76. return value != moduleId
  77. })
  78. $('.module-' + moduleId).show()
  79. })
  80. // Adds a chosen module to the selected slot.
  81. $('.chooseModule').click(function () {
  82. var row = $('#newModulRow').val()
  83. var col = $('#newModulCol').val()
  84. var moduleId = $(this).children('.newModulId').val()
  85. modules[row][col] = moduleId
  86. $('.module-row').eq(row).children().eq(0).children().eq(1).children().eq(col).children().eq(0).html(
  87. '<div class="module">' +
  88. ' <button class="module__edit" data-open="gr-modal-' + moduleId + '">' +
  89. ' <span class="fi-pencil"></span>' +
  90. ' </button>' +
  91. ' <span class="module__title">' + moduleNames[moduleId] + '</span>' +
  92. ' <button class="module__delete" href="#">' +
  93. ' <span class="fi-trash"></span>' +
  94. ' </button>' +
  95. '</div>')
  96. modulesInUse.push(moduleId)
  97. $('.module-' + moduleId).hide()
  98. $.post('writeLayout.php', {'row': row, 'modules[]': modules[row]})
  99. .done(function () {
  100. $('#gr-modal-add').foundation('close')
  101. $('#ok').show(30, function () {
  102. $(this).hide('slow')
  103. })
  104. return false
  105. })
  106. })
  107. // Respond to a module deletion intent: user taps trash icon in module library.
  108. $('[data-deleteModule]').click(function (e) {
  109. e.preventDefault()
  110. moduleName = $(this).attr('data-deleteModule')
  111. console.log('user wants to delete ' + moduleName)
  112. $('[data-deleteModule-confirmbox=' + moduleName + ']').show()
  113. })
  114. $('[data-deleteModule-confirm]').click(function () {
  115. moduleName = $(this).attr('data-deleteModule-confirm')
  116. var row = $('section.module-' + moduleName)
  117. $.ajax({
  118. url: 'deleteModule.php',
  119. type: 'POST',
  120. data: {module: moduleName, action: 'delete'},
  121. success: function (response) {
  122. row.html('<p>' + LOCALE.deleteSuccess + '</p>')
  123. row.fadeOut(3000)
  124. },
  125. error: function (jqXHR, textStatus, errorMessage) {
  126. console.log(jqXHR.responseText)
  127. $('#fileError').text(LOCALE.internalError + jqXHR.responseText).animate({
  128. opacity: 0
  129. }, 6000, function () {
  130. $('#fileError').text('')
  131. $('#fileError').css('opacity', 1)
  132. })
  133. }
  134. })
  135. })
  136. $('[data-deleteModule-cancel]').click(function () {
  137. moduleName = $(this).attr('data-deleteModule-cancel')
  138. console.log('user has canceled deletion of ' + moduleName)
  139. $('[data-deleteModule-confirmbox=' + moduleName + ']').hide()
  140. })
  141. //@TODO: Closes the deletion confirmation box if user closes the modal before.
  142. $('#gr-modal-add').on('closed.zf.reveal', function () {
  143. $('[data-deleteModule-confirmbox]').hide()
  144. })
  145. /**
  146. * Installs a new module from a given ZIP file.
  147. * @param formData A valid module ZIP file, @see https://gitlab.com/glancr/modules for documentation.
  148. */
  149. function installModule (formData) {
  150. var col = $('#newModulCol').val()
  151. var row = $('#newModulRow').val()
  152. $.ajax({
  153. url: 'installModule.php?col=' + col + '&row=' + row,
  154. type: 'POST',
  155. data: formData,
  156. processData: false,
  157. contentType: false,
  158. success: function (response) {
  159. console.log(response)
  160. location.reload()
  161. }
  162. })
  163. }
  164. /**
  165. * Checks an uploaded module for code integrity, i.e. if all necessary files are present.
  166. * @param formData A FormData object {@see https://developer.mozilla.org/en-US/docs/Web/API/FormData} containing a glancr module in ZIP format.
  167. */
  168. function checkModuleIntegrity (formData) {
  169. $.ajax({
  170. url: 'checkModuleZip.php',
  171. type: 'POST',
  172. data: formData,
  173. processData: false,
  174. contentType: false,
  175. success: function (response) {
  176. console.log(response)
  177. if (response == 'valid') {
  178. $('#ok').show(30, function () {
  179. $(this).hide('slow')
  180. })
  181. installModule(formData)
  182. } else {
  183. $('#fileError').text(response).animate({
  184. opacity: 0
  185. }, 3000, function () {
  186. $('#fileError').text('')
  187. $('#fileError').css('opacity', 1)
  188. })
  189. }
  190. },
  191. error: function (jqXHR, textStatus, errorMessage) {
  192. console.log(errorMessage) // Optional
  193. $('#fileError').text(LOCALE.errorModule).animate({
  194. opacity: 0
  195. }, 3000, function () {
  196. $('#fileError').text('')
  197. $('#fileError').css('opacity', 1)
  198. })
  199. }
  200. })
  201. }
  202. function openZipUpload () {
  203. $('#moduleZip').click()
  204. }
  205. var zipInput = $('#moduleZip'),
  206. uploadButton = $('#uploadModule')
  207. zipInput.change(function () {
  208. uploadButton.attr('disabled', true)
  209. uploadButton.addClass('loading__button')
  210. var initialText = uploadButton.text()
  211. uploadButton.html('<div class="loading__button--inner"></div>')
  212. var file = zipInput[0].files[0]
  213. // if(!(file.type === 'application/zip' || file.type === 'application/x-zip-compressed')) {
  214. // zipInput.val('');
  215. // $('#fileError').text(LOCALE.notZip).animate({
  216. // opacity: 0
  217. // }, 3000, function() {
  218. // $('#fileError').text('');
  219. // $('#fileError').css('opacity',1);
  220. // });
  221. //
  222. // } else {
  223. var fd = new FormData()
  224. fd.append('moduleZip', file)
  225. checkModuleIntegrity(fd)
  226. // }
  227. window.setTimeout(
  228. function () {
  229. uploadButton.attr('disabled', false)
  230. uploadButton.html(initialText)
  231. uploadButton.removeClass('loading__button')
  232. },
  233. 3000
  234. )
  235. // location.reload();
  236. })
  237. function updateModules (updates) {
  238. if (window.confirm(LOCALE.confirmModuleUpdates)) {
  239. var updateModulesDiv = $('#update-notification')
  240. updateModulesDiv.addClass('loading')
  241. updateModulesDiv.html('<button class="button">' + LOCALE.updatingModulesMessage + '<span class="loading__button--inline"><span class="loading__button--inner"></div></span></button>')
  242. updates.forEach(function (module) {
  243. $.ajax({
  244. url: 'runUpdate.php',
  245. type: 'POST',
  246. data: {type: 'module', name: module.name, version: module.newVersion},
  247. success: function (response) {
  248. $.post('setConfigValueAjax.php', {'key': 'module_updates', 'value': ''})
  249. $('#update-notification').html(LOCALE.updatesSuccess).animate({
  250. opacity: 0
  251. }, 6000, function () {
  252. $(this).text('')
  253. $(this).css('opacity', 1)
  254. })
  255. },
  256. error: function (response) {
  257. $('#update-notification').html(LOCALE.internalError + response.responseText)
  258. //@TODO: improve error handling: At least show button to retry update or contact devs
  259. }
  260. })
  261. })
  262. }
  263. }
  264. function updateSystem () {
  265. if (window.confirm(LOCALE.confirmSystemUpdate)) {
  266. var updateSystemDiv = $('#system-update-notification')
  267. updateSystemDiv.addClass('loading')
  268. updateSystemDiv.html('<button class="button">' + LOCALE.updatingSystemMessage + '<div class="loading__button--inline"><div class="loading__button--inner"></div></div></button>')
  269. $.ajax({
  270. url: 'runUpdate.php',
  271. type: 'POST',
  272. data: {type: 'system'},
  273. success: function (response) {
  274. $('#system-update-notification').html(LOCALE.updatesSuccess).animate({
  275. opacity: 0
  276. }, 6000, function () {
  277. $(this).text('')
  278. $(this).css('opacity', 1)
  279. })
  280. location.reload()
  281. },
  282. error: function (response) {
  283. $('#system-update-notification').html(LOCALE.internalError + response.responseText)
  284. //@TODO: improve error handling: At least show button to retry update or contact devs
  285. }
  286. })
  287. }
  288. }