diff --git a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
new file mode 100644
index 00000000000..e1c837cb09e
--- /dev/null
+++ b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
@@ -0,0 +1,89 @@
+/* global Flash */
+
+import sqljs from 'sql.js';
+
+class BalsamiqViewer {
+ constructor(viewer) {
+ this.viewer = viewer;
+ this.endpoint = this.viewer.dataset.endpoint;
+ }
+
+ loadFile() {
+ const xhr = new XMLHttpRequest();
+
+ xhr.open('GET', this.endpoint, true);
+ xhr.responseType = 'arraybuffer';
+
+ xhr.onload = this.renderFile.bind(this);
+ xhr.onerror = BalsamiqViewer.onError;
+
+ xhr.send();
+ }
+
+ renderFile(loadEvent) {
+ const container = document.createElement('ul');
+
+ this.initDatabase(loadEvent.target.response);
+
+ const previews = this.getPreviews();
+ const renderedPreviews = previews.map(preview => this.renderPreview(preview, container));
+
+ container.innerHTML = renderedPreviews.join('');
+ container.classList.add('list-inline');
+
+ this.viewer.appendChild(container);
+ }
+
+ initDatabase(data) {
+ const previewBinary = new Uint8Array(data);
+
+ this.database = new sqljs.Database(previewBinary);
+ }
+
+ getPreviews() {
+ const thumnails = this.database.exec('SELECT * FROM thumbnails');
+
+ return thumnails[0].values.map(BalsamiqViewer.parsePreview);
+ }
+
+ renderPreview(preview) {
+ const previewElement = document.createElement('li');
+
+ previewElement.innerHTML = this.renderTemplate(preview);
+
+ return previewElement.outerHTML;
+ }
+
+ renderTemplate(preview) {
+ let template = BalsamiqViewer.PREVIEW_TEMPLATE;
+
+ const title = this.database.exec(`SELECT * FROM resources WHERE id = '${preview.resourceID}'`);
+ const name = JSON.parse(title[0].values[0][2]).name;
+ const image = preview.image;
+
+ template = template.replace(/{{name}}/, name).replace(/{{image}}/, image);
+
+ return template;
+ }
+
+ static parsePreview(preview) {
+ return JSON.parse(preview[1]);
+ }
+
+ static onError() {
+ const flash = new Flash('Balsamiq file could not be loaded.');
+
+ return flash;
+ }
+}
+
+BalsamiqViewer.PREVIEW_TEMPLATE = `
+
+
{{name}}
+
+
+
+
+`;
+
+export default BalsamiqViewer;
diff --git a/app/assets/javascripts/blob/balsamiq/index.js b/app/assets/javascripts/blob/balsamiq/index.js
deleted file mode 100644
index 61f4631b423..00000000000
--- a/app/assets/javascripts/blob/balsamiq/index.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import Vue from 'vue';
-import sqljs from 'sql.js';
-
-export default class BalsamiqViewer {
- constructor(el) {
- this.el = el;
- this.loadSqlFile();
- }
-
-
- loadSqlFile() {
- var xhr = new XMLHttpRequest();
- var self = this;
- xhr.open('GET', this.el.dataset.endpoint, true);
- xhr.responseType = 'arraybuffer';
-
- xhr.onload = function(e) {
- var list = document.createElement('ul');
- var uInt8Array = new Uint8Array(this.response);
- var db = new SQL.Database(uInt8Array);
- var contents = db.exec("SELECT * FROM thumbnails");
- var previews = contents[0].values.map((i)=>{return JSON.parse(i[1])});
- previews.forEach((prev) => {
- var li = document.createElement('li');
- var title = db.exec(`select * from resources where id = '${prev.resourceID}'`)
- var template =
- `
-
${JSON.parse(title[0].values[0][2]).name}
-
-
-
-
`;
- li.innerHTML = template;
- list.appendChild(li);
- });
- list.classList += 'list-inline';
- self.el.appendChild(list);
- };
- xhr.send();
- }
-}
\ No newline at end of file
diff --git a/app/assets/javascripts/blob/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq_viewer.js
index b1493398099..1dacf84470f 100644
--- a/app/assets/javascripts/blob/balsamiq_viewer.js
+++ b/app/assets/javascripts/blob/balsamiq_viewer.js
@@ -1,5 +1,6 @@
-import BalsamiqViewer from './balsamiq';
+import BalsamiqViewer from './balsamiq/balsamiq_viewer';
document.addEventListener('DOMContentLoaded', () => {
- new BalsamiqViewer(document.getElementById('js-balsamiq-viewer'));
-});
\ No newline at end of file
+ const balsamiqViewer = new BalsamiqViewer(document.getElementById('js-balsamiq-viewer'));
+ balsamiqViewer.loadFile();
+});
diff --git a/app/views/projects/blob/_bmpr.html.haml b/app/views/projects/blob/_bmpr.html.haml
index 048bdf9dcb5..36ec0cbcce8 100644
--- a/app/views/projects/blob/_bmpr.html.haml
+++ b/app/views/projects/blob/_bmpr.html.haml
@@ -1,5 +1,4 @@
- content_for :page_specific_javascripts do
- = page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('balsamiq_viewer')
-.file-content#js-balsamiq-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
\ No newline at end of file
+.file-content#js-balsamiq-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }