Skip to content

Commit

Permalink
feat(loading): Add options for loading icon and progress bar (#1344)
Browse files Browse the repository at this point in the history
  • Loading branch information
jstoffan authored Mar 29, 2021
1 parent 4ca9819 commit 99e3f92
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 56 deletions.
6 changes: 6 additions & 0 deletions src/lib/Preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,12 @@ class Preview extends EventEmitter {
// Whether annotations v2 should be shown
this.options.showAnnotations = !!options.showAnnotations;

// Whether the loading indicator should be shown
this.options.showLoading = options.showLoading !== false;

// Whether the progress indicator should be shown
this.options.showProgress = options.showProgress !== false;

// Whether annotations v4 buttons should be shown in toolbar
this.options.showAnnotationsControls = !!options.showAnnotationsControls;

Expand Down
76 changes: 69 additions & 7 deletions src/lib/PreviewUI.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ProgressBar from './ProgressBar';
import shellTemplate from './shell.html';
import Notification from './Notification';
import { insertTemplate } from './util';
import {
CLASS_BOX_PREVIEW_BASE_HEADER,
CLASS_BOX_PREVIEW_HAS_HEADER,
Expand All @@ -25,7 +24,10 @@ import {
SELECTOR_NAVIGATION_LEFT,
SELECTOR_NAVIGATION_RIGHT,
SELECTOR_BOX_PREVIEW_CONTENT,
SELECTOR_BOX_PREVIEW_ICON,
} from './constants';
import { getIconFromName, getIconFromExtension } from './icons/icons';
import { insertTemplate } from './util';

class PreviewUI {
/** @property {HTMLElement} - Container element */
Expand Down Expand Up @@ -122,10 +124,16 @@ class PreviewUI {
}

// Setup progress bar
this.progressBar = new ProgressBar(this.container);
if (options.showProgress) {
this.progressBar = new ProgressBar(this.container);
}

// Setup loading indicator
this.setupLoading();
if (options.showLoading) {
this.setupLoading();
} else {
this.destroyLoading();
}

// Attach keyboard events
document.addEventListener('keydown', this.keydownHandler);
Expand Down Expand Up @@ -258,7 +266,7 @@ class PreviewUI {
}

/**
* Shows the loading indicator
* Shows the loading indicator.
*
* @public
* @return {void}
Expand All @@ -281,22 +289,59 @@ class PreviewUI {
}

this.previewContainer.classList.add(CLASS_PREVIEW_LOADED);
this.showCrawler();
}

/**
* Hides the loading crawler.
*
* @public
* @return {void}
*/
hideCrawler() {
const crawler = this.previewContainer.querySelector(SELECTOR_BOX_PREVIEW_CRAWLER_WRAPPER);
if (crawler) {
crawler.classList.add(CLASS_HIDDEN);
}
}

// Re-show the cralwer for the next preview since it is hidden in finishLoadingSetup() in BaseViewer.js
/**
* Shows the loading crawler.
*
* @public
* @return {void}
*/
showCrawler() {
const crawler = this.previewContainer.querySelector(SELECTOR_BOX_PREVIEW_CRAWLER_WRAPPER);
if (crawler) {
crawler.classList.remove(CLASS_HIDDEN);
}
}

/**
* Set the icon for the loading indicator based on the file extension.
*
* @public
* @param {string} extension - File extension
* @return {void}
*/
setLoadingIcon(extension) {
const iconWrapperEl = this.container.querySelector(SELECTOR_BOX_PREVIEW_ICON);
if (iconWrapperEl) {
iconWrapperEl.innerHTML = getIconFromExtension(extension) || getIconFromName('FILE_DEFAULT');
}
}

/**
* Shows and starts a progress bar at the top of the preview.
*
* @public
* @return {void}
*/
startProgressBar() {
this.progressBar.start();
if (this.progressBar) {
this.progressBar.start();
}
}

/**
Expand All @@ -306,7 +351,9 @@ class PreviewUI {
* @return {void}
*/
finishProgressBar() {
this.progressBar.finish();
if (this.progressBar) {
this.progressBar.finish();
}
}

/**
Expand Down Expand Up @@ -376,6 +423,21 @@ class PreviewUI {
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Remove global loading indicators from the shell
*
* @private
* @return {void}
*/
destroyLoading() {
const loadingWrapperEl = this.container.querySelector(SELECTOR_BOX_PREVIEW_LOADING_WRAPPER);
if (!loadingWrapperEl) {
return;
}

loadingWrapperEl.parentElement.removeChild(loadingWrapperEl);
}

/**
* Sets up the preview header.
*
Expand Down
18 changes: 18 additions & 0 deletions src/lib/__tests__/Preview-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,24 @@ describe('lib/Preview', () => {
expect(preview.options.showAnnotations).toBe(true);
});

test('should set whether to show loading indicators', () => {
preview.parseOptions(preview.previewOptions);
expect(preview.options.showLoading).toBe(true);

preview.previewOptions.showLoading = false;
preview.parseOptions(preview.previewOptions);
expect(preview.options.showLoading).toBe(false);
});

test('should set whether to show progress indicators', () => {
preview.parseOptions(preview.previewOptions);
expect(preview.options.showProgress).toBe(true);

preview.previewOptions.showProgress = false;
preview.parseOptions(preview.previewOptions);
expect(preview.options.showProgress).toBe(false);
});

test('should set whether to skip load from the server and any server updates', () => {
preview.parseOptions(preview.previewOptions);
expect(preview.options.skipServerUpdate).toBe(false);
Expand Down
47 changes: 46 additions & 1 deletion src/lib/__tests__/PreviewUI-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable no-unused-expressions */
import * as constants from '../constants';
import PreviewUI from '../PreviewUI';
import { getIconFromExtension } from '../icons/icons';

const sandbox = sinon.createSandbox();
let ui;
Expand All @@ -19,6 +20,8 @@ describe('lib/PreviewUI', () => {
containerEl = document.querySelector('.ui');
options = {
container: containerEl,
showLoading: true,
showProgress: true,
};
});

Expand Down Expand Up @@ -64,6 +67,17 @@ describe('lib/PreviewUI', () => {
expect(loadingWrapperEl).toContainHTML('Download File');
});

test('should not setup the progress bar or loading state if their respective option is false', () => {
const resultEl = ui.setup({ container: containerEl, showLoading: false, showProgress: false });
expect(resultEl).not.toContainSelector(constants.SELECTOR_BOX_PREVIEW_PROGRESS_BAR);

// Check loading state
expect(resultEl).not.toContainSelector(constants.SELECTOR_BOX_PREVIEW_LOADING_WRAPPER);
expect(resultEl).not.toContainSelector(constants.SELECTOR_BOX_PREVIEW_ICON);
expect(resultEl).not.toContainHTML('Loading Preview...');
expect(resultEl).not.toContainHTML('Download File');
});

test('should setup logo if option specifies', () => {
const url = 'http://someurl.com/';
options.logoUrl = url;
Expand Down Expand Up @@ -231,19 +245,38 @@ describe('lib/PreviewUI', () => {
});

describe('hideLoadingIndicator()', () => {
beforeEach(() => {
jest.spyOn(ui, 'showCrawler');
});

test('should hide loading indicator', () => {
const contentContainerEl = containerEl.querySelector(constants.SELECTOR_BOX_PREVIEW);
ui.hideLoadingIndicator();
expect(contentContainerEl).toHaveClass(constants.CLASS_PREVIEW_LOADED);
});

test('should show the crawler', () => {
ui.hideLoadingIndicator();
expect(ui.showCrawler).toBeCalled();
});
});

describe('showCrawler()', () => {
test('should remove the hidden class from the crawler', () => {
const crawlerEl = containerEl.querySelector(constants.SELECTOR_BOX_PREVIEW_CRAWLER_WRAPPER);
ui.hideLoadingIndicator();
ui.showCrawler();
expect(crawlerEl).not.toHaveClass(constants.CLASS_HIDDEN);
});
});

describe('hideCrawler()', () => {
test('should add the hidden class to the crawler', () => {
const crawlerEl = containerEl.querySelector(constants.SELECTOR_BOX_PREVIEW_CRAWLER_WRAPPER);
ui.hideCrawler();
expect(crawlerEl).toHaveClass(constants.CLASS_HIDDEN);
});
});

describe('setupNotification()', () => {
test('should set up the notification', () => {
ui.setupNotification();
Expand All @@ -252,6 +285,18 @@ describe('lib/PreviewUI', () => {
});
});

describe('setLoadingIcon()', () => {
test('should hide the crawler and set the file icon into the icon element', () => {
const iconEl = document.createElement('div');
iconEl.innerHTML = getIconFromExtension('pdf');

ui.setup(options);
ui.setLoadingIcon('pdf');

expect(containerEl.querySelector(constants.SELECTOR_BOX_PREVIEW_ICON).innerHTML).toEqual(iconEl.innerHTML);
});
});

describe('startProgressBar()', () => {
test('should start the progress bar', () => {
ui.progressBar = {
Expand Down
27 changes: 8 additions & 19 deletions src/lib/viewers/BaseViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,15 @@ import {
CLASS_ANNOTATIONS_CREATE_REGION,
CLASS_ANNOTATIONS_DISCOVERABLE,
CLASS_BOX_PREVIEW_MOBILE,
CLASS_HIDDEN,
FILE_OPTION_START,
SELECTOR_BOX_PREVIEW_BTN_ANNOTATE_DRAW,
SELECTOR_BOX_PREVIEW_BTN_ANNOTATE_POINT,
SELECTOR_BOX_PREVIEW_CONTENT,
SELECTOR_BOX_PREVIEW_CRAWLER_WRAPPER,
SELECTOR_BOX_PREVIEW_ICON,
SELECTOR_BOX_PREVIEW,
STATUS_SUCCESS,
STATUS_VIEWABLE,
} from '../constants';
import { EXCLUDED_EXTENSIONS } from '../extensions';
import { getIconFromExtension, getIconFromName } from '../icons/icons';
import { VIEWER_EVENT, ERROR_CODE, LOAD_METRIC, DOWNLOAD_REACHABILITY_METRICS } from '../events';
import AnnotationControlsFSM, { AnnotationInput, AnnotationMode } from '../AnnotationControlsFSM';
import AnnotationModule from '../AnnotationModule';
Expand Down Expand Up @@ -73,8 +69,6 @@ const ANNOTATION_BUTTONS = {
},
};

const DEFAULT_FILE_ICON_NAME = 'FILE_DEFAULT';

class BaseViewer extends EventEmitter {
/** @property {Api} - Api instance used for XHR calls */
api;
Expand Down Expand Up @@ -186,13 +180,9 @@ class BaseViewer extends EventEmitter {
}

if (this.options.file) {
const fileExt = this.options.file.extension;
this.fileLoadingIcon = getIconFromExtension(fileExt);
this.startAt = getProp(this.options, `fileOptions.${this.options.file.id}.${FILE_OPTION_START}`, {});
}

this.finishLoadingSetup();

// Get the container dom element if selector was passed, in tests
let { container } = this.options;
if (typeof container === 'string') {
Expand All @@ -204,6 +194,9 @@ class BaseViewer extends EventEmitter {
// From the perspective of viewers bp-content holds everything
this.containerEl = container.querySelector(SELECTOR_BOX_PREVIEW_CONTENT);

// Update the loading indicators
this.setupLoading();

// Attach event listeners
this.addCommonListeners();

Expand Down Expand Up @@ -235,16 +228,12 @@ class BaseViewer extends EventEmitter {
*
* @return {void}
*/
finishLoadingSetup() {
const { container } = this.options;
const crawler = container.querySelector(SELECTOR_BOX_PREVIEW_CRAWLER_WRAPPER);
if (crawler) {
crawler.classList.add(CLASS_HIDDEN);
}
setupLoading() {
const { file = {} } = this.options;

const iconWrapperEl = container.querySelector(SELECTOR_BOX_PREVIEW_ICON);
if (iconWrapperEl) {
iconWrapperEl.innerHTML = this.fileLoadingIcon || getIconFromName(DEFAULT_FILE_ICON_NAME);
if (this.previewUI) {
this.previewUI.hideCrawler();
this.previewUI.setLoadingIcon(file.extension);
}
}

Expand Down
Loading

0 comments on commit 99e3f92

Please sign in to comment.