Browse Source

Fixes #4091 - Preview of *.ics files in ticket zoom attachments.

Bola Ahmed Buari 2 years ago
parent
commit
b5fac9a19c

+ 11 - 1
LICENSE-ICONS-3RD-PARTY.json

@@ -164,6 +164,11 @@
         "url": "",
         "license": "MIT"
     },
+    "file-calendar.svg": {
+        "author": "Felix Niklas",
+        "url": "",
+        "license": "MIT"
+    },
     "file-code.svg": {
         "author": "Felix Niklas",
         "url": "",
@@ -234,6 +239,11 @@
         "url": "",
         "license": ""
     },
+    "gitlab-logo.svg": {
+        "author": "",
+        "url": "",
+        "license": ""
+    },
     "google-button.svg": {
         "author": "Google",
         "url": "",
@@ -704,4 +714,4 @@
         "url": "",
         "license": "MIT"
     }
-}
+}

+ 19 - 0
app/assets/javascripts/app/controllers/knowledge_base/reader_controller.coffee

@@ -142,6 +142,25 @@ class App.KnowledgeBaseReaderController extends App.Controller
       attachments: attachments
     )
 
+    @answerAttachments.on('click', '.file-image .js-preview', (e) =>
+      @imageView(e)
+    )
+
+    @answerAttachments.on('click', '.file-calendar .js-preview', (e) =>
+      @calendarView(e)
+    )
+
+  imageView: (e) ->
+    e.preventDefault()
+    e.stopPropagation()
+    new App.TicketZoomArticleImageView(image: $(e.target).get(0).outerHTML)
+
+  calendarView: (e) ->
+    e.preventDefault()
+    e.stopPropagation()
+    parentElement = $(e.target).closest('.attachment.file-calendar')
+    new App.TicketZoomArticleCalendarView(calendar: parentElement.get(0).outerHTML)
+
   renderTags: (tags) ->
     @answerTags.html App.view('knowledge_base/_reader_tags')(
       tags: tags

+ 59 - 0
app/assets/javascripts/app/controllers/ticket_zoom/article_calendar_view.coffee

@@ -0,0 +1,59 @@
+class App.TicketZoomArticleCalendarView extends App.ControllerModal
+  shown: false
+  buttonClose: true
+  buttonCancel: true
+  buttonSubmit: 'Download'
+  buttonClass: 'btn--success'
+  head: ''
+  calendarPreview: ''
+
+  events:
+    'submit form':      'submit'
+    'click .js-cancel': 'cancel'
+    'click .js-close':  'cancel'
+
+  constructor: ->
+    super
+    @fetch()
+
+  fetch: =>
+    attachment_preview_url = $(@calendar).data('preview-url')
+    attachment_id = $(@calendar).data('id')
+    @ajax(
+      id:    "calendar_preview_#{attachment_id}"
+      type:  'GET'
+      url:   "#{attachment_preview_url}&type=calendar"
+      processData: true
+      success: (data, status, xhr) =>
+        @calendarPreview = App.view('generic/calender_preview')(
+          events: data.events
+        )
+        @render()
+
+      error: (xhr) ->
+        statusText = xhr.statusText
+        rawResponseText     = xhr.responseText
+
+        # ignore if request is aborted
+        return if statusText is 'abort'
+
+        try
+          json = JSON.parse(rawResponseText)
+          text = json.error_human || json.error
+
+        text = rawResponseText if !text
+        errorMessage = App.i18n.translateContent(text || 'Could not process your request')
+
+        # show error message
+        new App.ControllerTechnicalErrorModal(
+          contentCode: errorMessage
+          head:        App.i18n.translateContent('An error has occurred')
+        )
+      )
+
+  content: =>
+    "<div class=\"justified vertical calendar-preview\">#{@calendarPreview}</div>"
+
+  onSubmit: =>
+    url = "#{$(@calendar).attr('href')}"
+    window.open(url, '_blank')

+ 7 - 0
app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee

@@ -89,6 +89,7 @@ class ArticleViewItem extends App.ControllerObserver
     'click .js-toggleFold':           'toggleFold'
     'click .richtext-content img':    'imageView'
     'click .attachments img':         'imageView'
+    'click .file-calendar .js-preview':  'calendarView'
     'click .js-securityRetryProcess': 'retrySecurityProcess'
 
   constructor: ->
@@ -491,5 +492,11 @@ class ArticleViewItem extends App.ControllerObserver
     e.stopPropagation()
     new App.TicketZoomArticleImageView(image: $(e.target).get(0).outerHTML, parentElement: $(e.currentTarget))
 
+  calendarView: (e) ->
+    e.preventDefault()
+    e.stopPropagation()
+    parentElement = $(e.target).closest('.attachment.file-calendar')
+    new App.TicketZoomArticleCalendarView(calendar: parentElement.get(0).outerHTML)
+
   updateFormId: (newFormId) ->
     @articleActions?.form_id = newFormId

+ 9 - 3
app/assets/javascripts/app/controllers/ticket_zoom/sidebar_article_attachments.coffee

@@ -48,13 +48,19 @@ class SidebarArticleAttachments extends App.Controller
     )
 
     @el.html(html)
-    @el.on('click', '.js-attachments img', (e) =>
-      @imageView(e)
-    )
+    @el.find('.js-attachments img').click(@imageView)
+    @el.find('.file-calendar .js-preview').click(@calendarView)
 
   imageView: (e) ->
     e.preventDefault()
     e.stopPropagation()
     new App.TicketZoomArticleImageView(image: $(e.target).get(0).outerHTML)
 
+  calendarView: (e) ->
+    e.preventDefault()
+    e.stopPropagation()
+    parentElement = $(e.target).closest('.attachment.file-calendar')
+    console.log({ parentElement })
+    new App.TicketZoomArticleCalendarView(calendar: parentElement.get(0).outerHTML)
+
 App.Config.set('900-ArticleAttachments', SidebarArticleAttachments, 'TicketZoomSidebar')

+ 1 - 0
app/assets/javascripts/app/lib/mixins/view_helpers.coffee

@@ -216,6 +216,7 @@ App.ViewHelpers =
       # text
       'text/plain': 'file-text'
       'text/rtf': 'file-text'
+      'text/calendar': 'file-calendar'
       # archives
       'application/gzip': 'file-archive'
       'application/zip': 'file-archive'

+ 9 - 4
app/assets/javascripts/app/views/generic/attachments.jst.eco

@@ -10,8 +10,8 @@
         </div>
       <% else: %>
         <% content_type = @ContentOrMimeType(attachment) %>
-        <a class="attachment attachment--preview" href="<%= attachment.url %>" data-type="attachment"<% if @canDownload(content_type): %> download<% else: %>target="_blank"<% end %>>
-          <div class="attachment-icon">
+        <a class="attachment attachment--preview <%- @ContentTypeIcon(content_type) if @ContentTypeIcon(content_type) %>" href="<%= attachment.url %>" data-type="attachment" data-preview-url="<%= attachment.preview_url %>" data-id="<%= attachment.id %>" <% if @canDownload(content_type): %> download<% else: %>target="_blank"<% end %>>
+          <div class="attachment-icon js-preview">
           <% if attachment.preferences && content_type && @ContentTypeIcon(content_type): %>
             <% if @canPreview(content_type): %>
               <img src="<%= attachment.preview_url %>">
@@ -22,8 +22,13 @@
             <%- @Icon('file-unknown') %>
           <% end %>
           </div>
-          <span class="attachment-name u-highlight"><%= attachment.filename %></span>
-          <div class="attachment-size"><%- @humanFileSize(attachment.size) %></div>
+          <div class="attachment-text">
+            <span class="attachment-name u-highlight"><%= attachment.filename %></span>
+            <div class="attachment-size"><%- @humanFileSize(attachment.size) %></div>
+          </div>
+          <% if @ContentTypeIcon(content_type) is 'file-calendar': %>
+            <button class="btn js-preview" type="button"><%- @T('PREVIEW') %></button>
+          <% end %>
         </a>
       <% end %>
     <% end %>

+ 50 - 0
app/assets/javascripts/app/views/generic/calender_preview.jst.eco

@@ -0,0 +1,50 @@
+<% if !_.isEmpty(@events): %>
+  <% for event in @events: %>
+    <article class="calendar-events">
+      <h2 class="title"><%= event.title %></h2>
+      <% if !_.isEmpty(event.location): %>
+        <h4><%- @T('Location') %></h4>
+        <p><%- App.Utils.linkify(event.location) %></p>
+      <% end %>
+      <div class="event-row">
+        <div>
+          <h4><%- @T('From') %></h4>
+          <p><%- @datetime(event.start_date) %></p>
+        </div>
+        <div>
+          <h4><%- @T('Till') %></h4>
+          <p><%- @datetime(event.end_date) %></p>
+        </div>
+      </div>
+      <div class="event-row">
+        <% if !_.isEmpty(event.organizer): %>
+          <div>
+          <h4><%- @T('Organizer') %></h4>
+          <p><%= event.organizer %></p>
+          </div>
+        <% end %>
+        <% if !_.isEmpty(event.attendees): %>
+          <div>
+          <h4><%- @T('Attendees') %></h4>
+          <ul>
+            <% for attendee in event.attendees: %>
+              <li><%- attendee %></li>
+            <% end %>
+          </ul>
+          </div>
+        <% end %>
+      </div>
+      <% if !_.isEmpty(event.description): %>
+        <section class="description">
+          <h4>Description</h4>
+          <%- App.Utils.text2html(event.description) %>
+        </section>
+      <% end %>
+    </article>
+    <% if @events.length > 1: %>
+      <div class="divider"></div>
+    <% end %>
+  <% end %>
+<% else: %>
+  <div><%- @T('No Entries') %></div>
+<% end %>

+ 8 - 3
app/assets/javascripts/app/views/ticket_zoom/sidebar_article_attachment.jst.eco

@@ -1,7 +1,7 @@
 <div class="attachments-block js-attachments">
   <% for data in @ticketAttachments: %>
     <% content_type = @ContentOrMimeType(data.attachment) %>
-    <a class="attachment attachment--preview" target="_blank" href="<%= App.Config.get('api_path') %>/ticket_attachment/<%= data.article.ticket_id %>/<%= data.article.id %>/<%= data.attachment.id %>?disposition=attachment" data-type="attachment"<% if @canDownload(content_type): %> download<% end %>>
+    <a class="attachment attachment--preview  <%- @ContentTypeIcon(content_type) if @ContentTypeIcon(content_type) %>" data-preview-url="<%= data.attachment.preview_url %>" data-id="<%= data.attachment.id %>" target="_blank" href="<%= App.Config.get('api_path') %>/ticket_attachment/<%= data.article.ticket_id %>/<%= data.article.id %>/<%= data.attachment.id %>?disposition=attachment" data-type="attachment"<% if @canDownload(content_type): %> download<% end %>>
       <div class="attachment-icon">
       <% if content_type && @ContentTypeIcon(content_type): %>
         <% if @canPreview(content_type): %>
@@ -13,8 +13,13 @@
         <%- @Icon('file-unknown') %>
       <% end %>
       </div>
-      <span class="attachment-name u-highlight"><%= data.attachment.filename %></span>
-      <div class="attachment-size"><%- @humanTime(data.article.created_at) %> (<%- @humanFileSize(data.attachment.size) %>)</div>
+      <div class="attachment-text">
+        <span class="attachment-name u-highlight"><%= data.attachment.filename %></span>
+        <div class="attachment-size"><%- @humanTime(data.article.created_at) %> (<%- @humanFileSize(data.attachment.size) %>)</div>
+      </div>
+      <% if @ContentTypeIcon(content_type) is 'file-calendar': %>
+        <button class="btn js-preview" type="button">PREVIEW</button>
+      <% end %>
     </a>
   <% end %>
 </div>

+ 20 - 2
app/assets/stylesheets/svg-dimensions.css

@@ -4,14 +4,23 @@
 .icon-arrow-right { width: 7px; height: 13px; }
 .icon-arrow-up { width: 13px; height: 7px; }
 .icon-bold { width: 12px; height: 12px; }
+.icon-caret-down { width: 24px; height: 24px; }
 .icon-chain { width: 16px; height: 16px; }
 .icon-chat { width: 24px; height: 24px; }
+.icon-check { width: 24px; height: 24px; }
 .icon-checkbox-checked { width: 11px; height: 11px; }
 .icon-checkbox-indeterminate { width: 11px; height: 11px; }
 .icon-checkbox { width: 11px; height: 11px; }
+.icon-checked-no { width: 24px; height: 24px; }
+.icon-checked-yes { width: 24px; height: 24px; }
 .icon-checkmark { width: 16px; height: 14px; }
+.icon-chevron-down { width: 24px; height: 24px; }
+.icon-chevron-left { width: 24px; height: 24px; }
+.icon-chevron-right { width: 24px; height: 24px; }
+.icon-chevron-up { width: 24px; height: 24px; }
 .icon-clipboard { width: 16px; height: 16px; }
 .icon-clock { width: 16px; height: 16px; }
+.icon-close-small { width: 24px; height: 24px; }
 .icon-cloud { width: 16px; height: 16px; }
 .icon-cog { width: 20px; height: 20px; }
 .icon-crown { width: 62px; height: 27px; }
@@ -26,11 +35,13 @@
 .icon-email-button { width: 29px; height: 24px; }
 .icon-email { width: 17px; height: 17px; }
 .icon-external { width: 16px; height: 16px; }
-.icon-eye { width: 16px; height: 16px; }
+.icon-eye-off { width: 24px; height: 24px; }
+.icon-eye { width: 24px; height: 24px; }
 .icon-eyedropper { width: 17px; height: 17px; }
 .icon-facebook-button { width: 29px; height: 24px; }
 .icon-facebook { width: 17px; height: 17px; }
 .icon-file-archive { width: 24px; height: 31px; }
+.icon-file-calendar { width: 24px; height: 31px; }
 .icon-file-code { width: 24px; height: 31px; }
 .icon-file-email { width: 24px; height: 31px; }
 .icon-file-excel { width: 24px; height: 31px; }
@@ -64,6 +75,7 @@
 .icon-line-right-arrow { width: 34px; height: 7px; }
 .icon-linkedin-button { width: 29px; height: 24px; }
 .icon-list { width: 16px; height: 16px; }
+.icon-loader { width: 24px; height: 24px; }
 .icon-loading { width: 16px; height: 16px; }
 .icon-lock-open { width: 16px; height: 17px; }
 .icon-lock { width: 16px; height: 17px; }
@@ -110,6 +122,7 @@
 .icon-reply-all { width: 16px; height: 17px; }
 .icon-reply { width: 16px; height: 17px; }
 .icon-report { width: 20px; height: 20px; }
+.icon-search { width: 24px; height: 24px; }
 .icon-searchdetail { width: 18px; height: 14px; }
 .icon-signed { width: 14px; height: 14px; }
 .icon-signout { width: 15px; height: 19px; }
@@ -117,7 +130,12 @@
 .icon-sms { width: 17px; height: 17px; }
 .icon-spinner-small { width: 15px; height: 15px; }
 .icon-split { width: 16px; height: 17px; }
-.icon-sso-button { width: 96.57px; height: 79.92px; }
+.icon-sso-button { width: 29px; height: 24px; }
+.icon-state-closed { width: 24px; height: 24px; }
+.icon-state-escalated { width: 24px; height: 24px; }
+.icon-state-open { width: 24px; height: 24px; }
+.icon-state-waiting-for-closure { width: 24px; height: 24px; }
+.icon-state-waiting-for-reminder { width: 24px; height: 24px; }
 .icon-status-modified-outer-circle { width: 16px; height: 16px; }
 .icon-status { width: 16px; height: 16px; }
 .icon-stopwatch { width: 77px; height: 83px; }

Some files were not shown because too many files changed in this diff