diff --git a/src/i18n/en-US.properties b/src/i18n/en-US.properties index 81eac1016..f4f1ca2c1 100644 --- a/src/i18n/en-US.properties +++ b/src/i18n/en-US.properties @@ -36,6 +36,8 @@ download_file=Download File text_truncated=This file has been truncated due to size limits. Please download to view the whole file. # Button tooltip to toggle Thumbnails Sidebar toggle_thumbnails=Toggle thumbnails +# Message when file has inaccessible xrefs +has_x_refs=This preview has links you cannot view, open in its native application to view # Error messages # Default preview error message diff --git a/src/lib/PreviewUI.js b/src/lib/PreviewUI.js index 7afd36aab..2dffde24b 100644 --- a/src/lib/PreviewUI.js +++ b/src/lib/PreviewUI.js @@ -320,14 +320,15 @@ class PreviewUI { * @public * @param {string} message - Notification message * @param {string} [buttonText] - Optional text to show in button + * @param {boolean} [persist] - Optional boolean to persist the notification * @return {void} */ - showNotification(message, buttonText) { + showNotification(message, buttonText, persist) { if (!this.notification) { return; } - this.notification.show(message, buttonText); + this.notification.show(message, buttonText, persist); } /** diff --git a/src/lib/__tests__/metadataAPI-test.js b/src/lib/__tests__/metadataAPI-test.js index 4a531d87a..c7141e65b 100644 --- a/src/lib/__tests__/metadataAPI-test.js +++ b/src/lib/__tests__/metadataAPI-test.js @@ -36,17 +36,7 @@ describe('metadataAPI', () => { return metadataAPI.getXrefsMetadata('123', 'autocad').then((response) => { expect(stubs.get).to.have.been.called; - expect(response).to.eql(expResponse); - }); - }); - - it('Should return manufactured global template on api 404', () => { - const expResponse = { hasxrefs: 'false' }; - stubs.get.rejects({ response: { status: 404 } }); - - return metadataAPI.getXrefsMetadata('123', 'autocad').then((response) => { - expect(stubs.get).to.have.been.called; - expect(response).to.eql(expResponse); + expect(response).to.eql({ hasxrefs: true }); }); }); diff --git a/src/lib/constants.js b/src/lib/constants.js index 449823a74..12a89d7da 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -129,3 +129,9 @@ export const ANNOTATOR_EVENT = { error: 'annotationerror', scale: 'scaleannotations' }; + +export const METADATA = { + FIELD_HASXREFS: 'hasxrefs', + SCOPE_GLOBAL: 'global', + TEMPLATE_AUTOCAD: 'autocad' +}; diff --git a/src/lib/metadataAPI.js b/src/lib/metadataAPI.js index e30ee14ee..083fe38ef 100644 --- a/src/lib/metadataAPI.js +++ b/src/lib/metadataAPI.js @@ -1,5 +1,8 @@ import api from './api'; import { getHeaders } from './util'; +import { METADATA } from './constants'; + +const { FIELD_HASXREFS, SCOPE_GLOBAL } = METADATA; const metadataAPI = { /** @@ -14,16 +17,11 @@ const metadataAPI = { return Promise.reject(new Error('id and template are required parameters')); } - return metadataAPI.getMetadata(id, 'global', template, options).catch((err) => { - const { response } = err; - // If the http response is 404, this is a valid case because the metadata template - // may not be initialized on the requested file. Resolve the promise with - // a constructed hasxrefs value - if (response && response.status === 404) { - return Promise.resolve({ hasxrefs: 'false' }); - } - - throw err; + return metadataAPI.getMetadata(id, SCOPE_GLOBAL, template, options).then((response) => { + // The hasxrefs value is returned as a string 'false' or 'true' so we want + // to convert this to a boolean + const { [FIELD_HASXREFS]: hasXrefsValue } = response; + return { ...response, [FIELD_HASXREFS]: hasXrefsValue === 'true' }; }); }, @@ -49,7 +47,7 @@ const metadataAPI = { * @param {string} apiHost - API host * @return {string} The metadata url */ - getMetadataURL(fileId, scope = 'global', template, apiHost) { + getMetadataURL(fileId, scope = SCOPE_GLOBAL, template, apiHost) { return `${apiHost}/2.0/files/${fileId}/metadata/${scope}/${template}`; } }; diff --git a/src/lib/viewers/doc/AutoCADViewer.js b/src/lib/viewers/doc/AutoCADViewer.js new file mode 100644 index 000000000..89c26ed7f --- /dev/null +++ b/src/lib/viewers/doc/AutoCADViewer.js @@ -0,0 +1,32 @@ +import DocumentViewer from './DocumentViewer'; +import metadataAPI from '../../metadataAPI'; +import { METADATA } from '../../constants'; + +const { FIELD_HASXREFS, TEMPLATE_AUTOCAD } = METADATA; + +class AutoCADViewer extends DocumentViewer { + /** + * @inheritdoc + */ + load() { + super.load(); + + this.checkForXrefs(); + } + + /** + * Checks for xrefs, depending on file extension + * @return {void} + */ + checkForXrefs() { + const { id } = this.options.file; + + metadataAPI.getXrefsMetadata(id, TEMPLATE_AUTOCAD, this.options).then(({ [FIELD_HASXREFS]: hasxrefsValue }) => { + if (hasxrefsValue) { + this.options.ui.showNotification(__('has_x_refs'), null, true); + } + }); + } +} + +export default AutoCADViewer; diff --git a/src/lib/viewers/doc/DocBaseViewer.js b/src/lib/viewers/doc/DocBaseViewer.js index d6caa4b91..10af1f9e9 100644 --- a/src/lib/viewers/doc/DocBaseViewer.js +++ b/src/lib/viewers/doc/DocBaseViewer.js @@ -10,22 +10,22 @@ import RepStatus from '../../RepStatus'; import PreviewError from '../../PreviewError'; import ThumbnailsSidebar from '../../ThumbnailsSidebar'; import { + ANNOTATOR_EVENT, CLASS_BOX_PREVIEW_FIND_BAR, + CLASS_BOX_PREVIEW_THUMBNAILS_CLOSE_ACTIVE, + CLASS_BOX_PREVIEW_THUMBNAILS_CLOSE, + CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER, + CLASS_BOX_PREVIEW_THUMBNAILS_OPEN_ACTIVE, + CLASS_BOX_PREVIEW_THUMBNAILS_OPEN, CLASS_CRAWLER, CLASS_HIDDEN, CLASS_IS_SCROLLABLE, DOC_STATIC_ASSETS_VERSION, + ENCODING_TYPES, PERMISSION_DOWNLOAD, PRELOAD_REP_NAME, - STATUS_SUCCESS, QUERY_PARAM_ENCODING, - ENCODING_TYPES, - CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER, - ANNOTATOR_EVENT, - CLASS_BOX_PREVIEW_THUMBNAILS_CLOSE, - CLASS_BOX_PREVIEW_THUMBNAILS_CLOSE_ACTIVE, - CLASS_BOX_PREVIEW_THUMBNAILS_OPEN, - CLASS_BOX_PREVIEW_THUMBNAILS_OPEN_ACTIVE + STATUS_SUCCESS } from '../../constants'; import { checkPermission, getRepresentation } from '../../file'; import { appendQueryParams, createAssetUrlCreator, getMidpoint, getDistance, getClosestPageToPinch } from '../../util'; diff --git a/src/lib/viewers/doc/DocLoader.js b/src/lib/viewers/doc/DocLoader.js index abf8a4a21..089b976d9 100644 --- a/src/lib/viewers/doc/DocLoader.js +++ b/src/lib/viewers/doc/DocLoader.js @@ -6,6 +6,7 @@ import SinglePageViewer from './SinglePageViewer'; import RepStatus from '../../RepStatus'; import { ORIGINAL_REP_NAME, STATUS_SUCCESS } from '../../constants'; import { DOCUMENT_EXTENSIONS } from '../../extensions'; +import AutoCADViewer from './AutoCADViewer'; // Order of the viewers matters. For example, a PDF file can be previewed by using the preferred optimized 'pdf' rep // or the original as a fallback. Additionally, we include multiple entries for the presentation viewer so that it can be @@ -17,6 +18,12 @@ const VIEWERS = [ REP: 'pdf', EXT: ['gslide', 'gslides', 'odp', 'ppt', 'pptx', 'key'] }, + { + NAME: 'AutoCAD', + CONSTRUCTOR: AutoCADViewer, + REP: 'pdf', + EXT: ['dwg'] + }, { NAME: 'Document', CONSTRUCTOR: DocumentViewer, diff --git a/src/lib/viewers/doc/__tests__/AutoCADViewer-test.js b/src/lib/viewers/doc/__tests__/AutoCADViewer-test.js new file mode 100644 index 000000000..cdc37c860 --- /dev/null +++ b/src/lib/viewers/doc/__tests__/AutoCADViewer-test.js @@ -0,0 +1,82 @@ +/* eslint-disable no-unused-expressions */ +import DocumentViewer from '../DocumentViewer'; +import AutoCADViewer from '../AutoCADViewer'; +import metadataAPI from '../../../metadataAPI'; +import { METADATA } from '../../../constants'; + +const { FIELD_HASXREFS, TEMPLATE_AUTOCAD } = METADATA; +const sandbox = sinon.sandbox.create(); + +let containerEl; +let autocad; +let stubs = {}; + +describe('lib/viewers/doc/AutoCADViewer', () => { + beforeEach(() => { + containerEl = document.querySelector('.container'); + autocad = new AutoCADViewer({ + container: containerEl, + file: { + id: '0' + } + }); + + stubs.getXrefsMetadata = sandbox.stub(metadataAPI, 'getXrefsMetadata'); + stubs.showNotification = sandbox.stub(); + + autocad.options = { + file: { + id: '123' + }, + ui: { + showNotification: stubs.showNotification + } + }; + }); + + afterEach(() => { + sandbox.verifyAndRestore(); + fixture.cleanup(); + stubs = {}; + }); + + describe('load()', () => { + it('Should call the super.load and checkForXrefs', () => { + stubs.docLoad = sandbox.stub(DocumentViewer.prototype, 'load'); + stubs.checkForXrefs = sandbox.stub(autocad, 'checkForXrefs'); + + autocad.load(); + + expect(stubs.docLoad).to.have.been.called; + expect(stubs.checkForXrefs).to.have.been.called; + }); + }); + + describe('checkForXrefs()', () => { + it('Should show notification if has external refs', () => { + const xrefsPromise = Promise.resolve({ [FIELD_HASXREFS]: true }); + stubs.getXrefsMetadata.resolves(xrefsPromise); + + autocad.checkForXrefs(); + + expect(stubs.getXrefsMetadata).to.have.been.calledWith('123', TEMPLATE_AUTOCAD, autocad.options); + + return xrefsPromise.then(() => { + expect(stubs.showNotification).to.have.been.called; + }); + }); + + it('Should not show notification if does not have external refs', () => { + const xrefsPromise = Promise.resolve({ [FIELD_HASXREFS]: false }); + stubs.getXrefsMetadata.resolves(xrefsPromise); + + autocad.checkForXrefs(); + + expect(stubs.getXrefsMetadata).to.have.been.calledWith('123', TEMPLATE_AUTOCAD, autocad.options); + + return xrefsPromise.then(() => { + expect(stubs.showNotification).not.to.have.been.called; + }); + }); + }); +});