app.es6 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* eslint-env browser */
  2. const marked = require('marked')
  3. const dragdrop = require('drag-drop')
  4. // Add Robodog JS. It is advisable to install Robodog from npm/yarn.
  5. // But for experimenting, you can use also Transloadit’s CDN, Edgly:
  6. // <script src="https://transloadit.edgly.net/releases/uppy/robodog/v1.9.7/robodog.min.js"></script>
  7. const robodog = require('@uppy/robodog')
  8. const TRANSLOADIT_EXAMPLE_KEY = '35c1aed03f5011e982b6afe82599b6a0'
  9. const TRANSLOADIT_EXAMPLE_TEMPLATE = '0b2ee2bc25dc43619700c2ce0a75164a'
  10. /**
  11. * A textarea for markdown text, with support for file attachments.
  12. *
  13. * ## Usage
  14. *
  15. * ```js
  16. * const element = document.querySelector('textarea')
  17. * const mdtxt = new MarkdownTextarea(element)
  18. * mdtxt.install()
  19. * ```
  20. */
  21. class MarkdownTextarea {
  22. constructor (element) {
  23. this.element = element
  24. this.controls = document.createElement('div')
  25. this.controls.classList.add('mdtxt-controls')
  26. this.uploadLine = document.createElement('button')
  27. this.uploadLine.setAttribute('type', 'button')
  28. this.uploadLine.classList.add('form-upload')
  29. this.uploadLine.appendChild(
  30. document.createTextNode('Tap here to upload an attachment'))
  31. }
  32. install () {
  33. const { element } = this
  34. const wrapper = document.createElement('div')
  35. wrapper.classList.add('mdtxt')
  36. element.parentNode.replaceChild(wrapper, element)
  37. wrapper.appendChild(this.controls)
  38. wrapper.appendChild(element)
  39. wrapper.appendChild(this.uploadLine)
  40. this.setupUploadLine()
  41. this.setupTextareaDrop()
  42. }
  43. setupTextareaDrop () {
  44. dragdrop(this.element, (files) => {
  45. this.uploadFiles(files)
  46. })
  47. }
  48. setupUploadLine () {
  49. this.uploadLine.addEventListener('click', () => {
  50. this.pickFiles()
  51. })
  52. }
  53. reportUploadError (err) {
  54. this.uploadLine.classList.add('error')
  55. const message = document.createElement('span')
  56. message.appendChild(document.createTextNode(err.message))
  57. this.uploadLine.insertChild(message, this.uploadLine.firstChild)
  58. }
  59. unreportUploadError () {
  60. this.uploadLine.classList.remove('error')
  61. const message = this.uploadLine.querySelector('message')
  62. if (message) {
  63. this.uploadLine.removeChild(message)
  64. }
  65. }
  66. insertAttachments (attachments) {
  67. attachments.forEach((attachment) => {
  68. const { file, thumb } = attachment
  69. const link = `\n[LABEL](${file.ssl_url})\n`
  70. const labelText = `View File ${file.basename}`
  71. if (thumb) {
  72. this.element.value += link.replace('LABEL', `![${labelText}](${thumb.ssl_url})`)
  73. } else {
  74. this.element.value += link.replace('LABEL', labelText)
  75. }
  76. })
  77. }
  78. matchFilesAndThumbs (results) {
  79. const filesById = {}
  80. const thumbsById = {}
  81. results.forEach((result) => {
  82. if (result.stepName === 'thumbnails') {
  83. thumbsById[result.original_id] = result
  84. } else {
  85. filesById[result.original_id] = result
  86. }
  87. })
  88. return Object.keys(filesById).reduce((acc, key) => {
  89. const file = filesById[key]
  90. const thumb = thumbsById[key]
  91. acc.push({ file, thumb })
  92. return acc
  93. }, [])
  94. }
  95. uploadFiles (files) {
  96. robodog.upload(files, {
  97. waitForEncoding: true,
  98. params: {
  99. auth: { key: TRANSLOADIT_EXAMPLE_KEY },
  100. template_id: TRANSLOADIT_EXAMPLE_TEMPLATE
  101. }
  102. }).then((result) => {
  103. if (result === null) return
  104. this.insertAttachments(
  105. this.matchFilesAndThumbs(result.results)
  106. )
  107. }).catch((err) => {
  108. console.error(err)
  109. this.reportUploadError(err)
  110. })
  111. }
  112. pickFiles () {
  113. robodog.pick({
  114. waitForEncoding: true,
  115. params: {
  116. auth: { key: TRANSLOADIT_EXAMPLE_KEY },
  117. template_id: TRANSLOADIT_EXAMPLE_TEMPLATE
  118. },
  119. providers: [
  120. 'webcam',
  121. 'url',
  122. 'instagram',
  123. 'google-drive',
  124. 'dropbox'
  125. ]
  126. }).then((result) => {
  127. if (result === null) return
  128. this.insertAttachments(
  129. this.matchFilesAndThumbs(result.results)
  130. )
  131. }).catch((err) => {
  132. console.error(err)
  133. this.reportUploadError(err)
  134. })
  135. }
  136. }
  137. const textarea = new MarkdownTextarea(
  138. document.querySelector('#new textarea'))
  139. textarea.install()
  140. function renderSnippet (title, text) {
  141. const template = document.querySelector('#snippet')
  142. const newSnippet = document.importNode(template.content, true)
  143. const titleEl = newSnippet.querySelector('.snippet-title')
  144. const contentEl = newSnippet.querySelector('.snippet-content')
  145. titleEl.appendChild(document.createTextNode(title))
  146. contentEl.innerHTML = marked(text)
  147. const list = document.querySelector('#snippets')
  148. list.insertBefore(newSnippet, list.firstChild)
  149. }
  150. function saveSnippet (title, text) {
  151. const id = parseInt(localStorage.numSnippets || 0, 10)
  152. localStorage[`snippet_${id}`] = JSON.stringify({ title, text })
  153. localStorage.numSnippets = id + 1
  154. }
  155. function loadSnippets () {
  156. for (let id = 0; localStorage[`snippet_${id}`] != null; id += 1) {
  157. const { title, text } = JSON.parse(localStorage[`snippet_${id}`])
  158. renderSnippet(title, text)
  159. }
  160. }
  161. document.querySelector('#new').addEventListener('submit', (event) => {
  162. event.preventDefault()
  163. const title = event.target.querySelector('input[name="title"]').value ||
  164. 'Unnamed Snippet'
  165. const text = textarea.element.value
  166. saveSnippet(title, text)
  167. renderSnippet(title, text)
  168. event.target.querySelector('input').value = ''
  169. event.target.querySelector('textarea').value = ''
  170. })
  171. window.addEventListener('DOMContentLoaded', () => {
  172. loadSnippets()
  173. })