index.html 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset='utf-8' />
  5. <meta name="viewport" content="width=device-width, user-scalable=no">
  6. <title>Tracim</title>
  7. <link rel='shortcut icon' type='image/x-icon' href='/asset/favicon.ico' >
  8. <link rel="stylesheet" type="text/css" href="/font/font-awesome-4.7.0/css/font-awesome.css">
  9. <link href="https://fonts.googleapis.com/css?family=Quicksand:300,400,500,700" rel="stylesheet">
  10. <!--
  11. <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
  12. -->
  13. <link rel="stylesheet" type="text/css" href="/asset/hamburger/hamburgers.min.css">
  14. <link rel="stylesheet" type="text/css" href="/dev/bootstrap-4.0.0-beta.css">
  15. </head>
  16. <body>
  17. <div id='content'></div>
  18. <script src='/tracim.vendor.bundle.js'></script>
  19. <script src='/tracim.app.entry.js'></script>
  20. <script src='/app/html-documents.app.js'></script>
  21. <script src='/app/thread.app.js'></script>
  22. <!-- <script src='/app/file.app.js'></script> -->
  23. <script src="/dev/jquery-3.2.1.js"></script>
  24. <script src="/dev/popper-1.12.3.js"></script>
  25. <script src="/dev/bootstrap-4.0.0-beta.2.js"></script>
  26. <script type="text/javascript" src="/asset/tinymce/js/tinymce/jquery.tinymce.min.js"></script>
  27. <script type="text/javascript" src="/asset/tinymce/js/tinymce/tinymce.min.js"></script>
  28. <script type='text/javascript'>
  29. let prevSelectedApp = {name: ''} // default value
  30. getSelectedApp = name => {
  31. switch (name) {
  32. case 'html-documents':
  33. return appHtmlDocument
  34. case 'thread':
  35. return appThread
  36. case 'file':
  37. return appFile
  38. default:
  39. return null
  40. }
  41. }
  42. GLOBAL_renderApp = app => {
  43. console.log('%cGLOBAL_renderApp', 'color: #5cebeb', app)
  44. const selectedApp = getSelectedApp(app.config.slug)
  45. if (selectedApp.isRendered) {
  46. GLOBAL_dispatchEvent({type: `${app.config.slug}_showApp`, data: app}) // handled by html-documents:src/container/HtmlDocument.jsx
  47. } else {
  48. selectedApp.renderApp(app)
  49. selectedApp.isRendered = true
  50. prevSelectedApp.isRendered = false
  51. prevSelectedApp = selectedApp
  52. }
  53. }
  54. GLOBAL_renderCreateContentApp = app => {
  55. console.log('%cGLOBAL_renderCreateContentApp', 'color: #5cebeb', app)
  56. const selectedApp = getSelectedApp(app.config.slug)
  57. if (!selectedApp) {
  58. console.log('Error in GLOBAL_renderCreateContentApp, selectedApp is undefined', app)
  59. return
  60. }
  61. getSelectedApp(app.config.slug).renderPopupCreation(app)
  62. }
  63. GLOBAL_dispatchEvent = ({ type, data }) => {
  64. console.log('%cGLOBAL_dispatchEvent', 'color: #fff', type, data)
  65. const event = new CustomEvent('appCustomEvent', { detail: { type, data } })
  66. document.dispatchEvent(event)
  67. }
  68. GLOBAL_eventReducer = ({ detail: { type, data } }) => {
  69. switch (type) {
  70. case 'hide_popupCreateContent':
  71. console.log('%cGLOBAL_eventReducer Custom Event', 'color: #28a745', type, data)
  72. getSelectedApp(data.name).unmountApp('popupCreateContentContainer')
  73. break
  74. case 'unmount_app':
  75. console.log('%cGLOBAL_eventReducer Custom Event', 'color: #28a745', type, data)
  76. if (prevSelectedApp.name === '') return
  77. prevSelectedApp.unmountApp('appContainer')
  78. prevSelectedApp.unmountApp('popupCreateContentContainer')
  79. prevSelectedApp.isRendered = false
  80. break
  81. }
  82. }
  83. document.addEventListener('appCustomEvent', GLOBAL_eventReducer)
  84. </script>
  85. <script type='text/javascript'>
  86. (function () {
  87. wysiwyg = function (selector, handleOnChange) {
  88. function base64EncodeAndTinyMceInsert (files) {
  89. for (var i = 0; i < files.length; i++) {
  90. if (files[i].size > 1000000)
  91. files[i].allowed = confirm(files[i].name + " fait plus de 1mo et peut prendre du temps à insérer, voulez-vous continuer ?")
  92. }
  93. for (var i = 0; i < files.length; i++) {
  94. if (files[i].allowed !== false && files[i].type.match('image.*')) {
  95. var img = document.createElement('img')
  96. var fr = new FileReader()
  97. fr.readAsDataURL(files[i])
  98. fr.onloadend = function (e) {
  99. img.src = e.target.result
  100. tinymce.activeEditor.execCommand('mceInsertContent', false, img.outerHTML)
  101. }
  102. }
  103. }
  104. }
  105. // HACK: The tiny mce source code modal contain a textarea, but we
  106. // can't edit it (like it's readonly). The following solution
  107. // solve the bug: https://stackoverflow.com/questions/36952148/tinymce-code-editor-is-readonly-in-jtable-grid
  108. $(document).on('focusin', function(e) {
  109. if ($(e.target).closest(".mce-window").length) {
  110. e.stopImmediatePropagation();
  111. }
  112. });
  113. tinymce.init({
  114. selector: selector,
  115. menubar: false,
  116. resize: false,
  117. skin: "lightgray",
  118. plugins:'advlist autolink lists link image charmap print preview anchor textcolor searchreplace visualblocks code fullscreen insertdatetime media table contextmenu paste code help',
  119. toolbar: 'insert | formatselect | bold italic underline strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | table | code ',
  120. content_style: "div {height: 100%;}",
  121. setup: function ($editor) {
  122. $editor.on('change', function(e) {
  123. handleOnChange({target: {value: $editor.getContent()}}) // target.value to emulate a js event so the react handler can expect one
  124. })
  125. //////////////////////////////////////////////
  126. // add custom btn to handle image by selecting them with system explorer
  127. $editor.addButton('customInsertImage', {
  128. icon: 'mce-ico mce-i-image',
  129. title: 'Image',
  130. onclick: function () {
  131. if ($('#hidden_tinymce_fileinput').length > 0) $('#hidden_tinymce_fileinput').remove()
  132. fileTag = document.createElement('input')
  133. fileTag.id = 'hidden_tinymce_fileinput'
  134. fileTag.type = 'file'
  135. $('body').append(fileTag)
  136. $('#hidden_tinymce_fileinput').on('change', function () {
  137. base64EncodeAndTinyMceInsert($(this)[0].files)
  138. })
  139. $('#hidden_tinymce_fileinput').click()
  140. }
  141. })
  142. //////////////////////////////////////////////
  143. // Handle drag & drop image into TinyMce by encoding them in base64 (to avoid uploading them somewhere and keep saving comment in string format)
  144. $editor
  145. .on('drag dragstart dragend dragover dragenter dragleave drop', function (e) {
  146. e.preventDefault()
  147. e.stopPropagation()
  148. })
  149. .on('drop', function(e) {
  150. base64EncodeAndTinyMceInsert(e.dataTransfer.files)
  151. })
  152. }
  153. })
  154. }
  155. })()
  156. </script>
  157. </body>
  158. </html>