Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selectively disable annotations #322

Merged
42 changes: 36 additions & 6 deletions src/lib/annotations/BoxAnnotations.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,47 @@ class BoxAnnotations {
}

/**
* Chooses a annotator based on viewer.
* Get all annotators for a given viewer.
*
* @param {Object} viewer - Current preview viewer
* @param {string} viewerName - Name of the viewer to get annotators for
* @param {Array} [disabledAnnotators] - List of disabled annotators
* @return {Object} The annotator to use
* @return {Object} Annotator for the viewer
*/
determineAnnotator(viewer, disabledAnnotators = []) {
return this.annotators.find(
(annotator) => !disabledAnnotators.includes(annotator.NAME) && annotator.VIEWER.includes(viewer)
getAnnotatorsForViewer(viewerName, disabledAnnotators = []) {
const annotators = this.getAnnotators();

return annotators.find(
(annotator) => !disabledAnnotators.includes(annotator.NAME) && annotator.VIEWER.includes(viewerName)
);
}

/**
* Chooses a annotator based on viewer.
*
* @param {Object} viewerName - Current preview viewer name
* @param {Object} [viewerConfig] - Annotation configuration for a specific viewer
* @param {Array} [disabledAnnotators] - List of disabled annotators
* @return {Object|null} A copy of the annotator to use, if available
*/
determineAnnotator(viewerName, viewerConfig = {}, disabledAnnotators = []) {
const annotator = this.getAnnotatorsForViewer(viewerName, disabledAnnotators);
let modifiedAnnotator = null;

if (!annotator || viewerConfig.enabled === false) {
return modifiedAnnotator;
}

modifiedAnnotator = Object.assign({}, annotator);

// Filter out disabled annotation types
if (Array.isArray(viewerConfig.disabledTypes)) {
modifiedAnnotator.TYPE = modifiedAnnotator.TYPE.filter((type) => {
return !viewerConfig.disabledTypes.includes(type);
});
}

return modifiedAnnotator;
}
}

global.BoxAnnotations = BoxAnnotations;
Expand Down
61 changes: 58 additions & 3 deletions src/lib/annotations/__tests__/BoxAnnotations-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ describe('lib/annotators/BoxAnnotations', () => {
});
});

describe('getAnnotatorsForViewer()', () => {
it('should return undefined if the annotator does not exist', () => {
const annotator = loader.getAnnotatorsForViewer('not_supported_type');
expect(annotator).to.be.undefined;
});

it('should return the correct annotator for the viewer name', () => {
const name = 'Document';
const annotator = loader.getAnnotatorsForViewer(name);
expect(annotator.NAME).to.equal(name); // First entry is Document annotator
});

it('should return nothing if the viewer requested is disabled', () => {
const annotator = loader.getAnnotatorsForViewer('Document', ['Document']);
expect(annotator).to.be.undefined;
});
});

describe('determineAnnotator()', () => {
it('should choose the first annotator that matches the viewer', () => {
const viewer = 'Document';
Expand All @@ -38,13 +56,50 @@ describe('lib/annotators/BoxAnnotations', () => {
});

it('should not choose a disabled annotator', () => {
const annotator = loader.determineAnnotator('Image', ['Image']);
expect(annotator).to.be.undefined;
const annotator = loader.determineAnnotator('Image', {}, ['Image']);
expect(annotator).to.be.null;
});

it('should not return a annotator if no matching annotator is found', () => {
const annotator = loader.determineAnnotator('Swf');
expect(annotator).to.be.undefined;
expect(annotator).to.be.null;
});

it('should return a copy of the annotator that matches', () => {
const viewer = 'Document';
const docAnnotator = {
NAME: viewer,
VIEWER: ['Document']
};
loader.annotators = [docAnnotator];
const annotator = loader.determineAnnotator(viewer);
docAnnotator.NAME = 'another_name';
expect(annotator.NAME).to.equal(viewer);
expect(annotator.NAME).to.not.equal(docAnnotator.NAME);
});

it('should return null if the config for the viewer disables annotations', () => {
const config = {
enabled: false
};
const annotator = loader.determineAnnotator('Document', config);
expect(annotator).to.be.null;
});

it('should filter disabled annotation types from the annotator.TYPE', () => {
const config = {
enabled: true,
disabledTypes: ['point']
};
const docAnnotator = {
NAME: 'Document',
VIEWER: ['Document'],
TYPE: ['point', 'highlight']
};
loader.annotators = [docAnnotator];
const annotator = loader.determineAnnotator('Document', config);
expect(annotator.TYPE.includes('point')).to.be.false;
expect(annotator.TYPE.includes('highlight')).to.be.true;
});
});
});
48 changes: 37 additions & 11 deletions src/lib/viewers/BaseViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,28 +622,53 @@ class BaseViewer extends EventEmitter {
// Annotations
//--------------------------------------------------------------------------

/**
* Get the configuration for viewer annotations and transform if legacy format.
*
* @return {Object} An object containing configuration properties.
*/
getViewerAnnotationsConfig() {
const option = this.getViewerOption('annotations');
const config = option !== null && option !== undefined ? option : {};

// Backwards compatability for old boolean flag usage
if (typeof config === 'boolean') {
return {
enabled: config
};
}

return config;
}

/**
* Loads the appropriate annotator and loads the file's annotations
*
* @protected
* @return {void}
*/
loadAnnotator() {
// Do nothing if annotations are disabled for the viewer
if (!this.areAnnotationsEnabled()) {
return;
}

/* global BoxAnnotations */
const boxAnnotations = new BoxAnnotations();
// #TODO(@spramod|@jholdstock): remove this after we have annotation instancing
const viewerName = this.options.viewer.NAME;
const annotationsConfig = this.getViewerAnnotationsConfig();

this.annotatorConf = boxAnnotations.determineAnnotator(this.options.viewer.NAME);
this.annotatorConf = boxAnnotations.determineAnnotator(viewerName, annotationsConfig);
if (!this.annotatorConf) {
return;
}

if (this.areAnnotationsEnabled()) {
const { file } = this.options;
this.canAnnotate = checkPermission(file, PERMISSION_ANNOTATE);
const { file } = this.options;
this.canAnnotate = checkPermission(file, PERMISSION_ANNOTATE);

if (this.canAnnotate) {
this.initAnnotations();
}
if (this.canAnnotate) {
this.initAnnotations();
}
}

Expand Down Expand Up @@ -696,13 +721,14 @@ class BaseViewer extends EventEmitter {
*/
areAnnotationsEnabled() {
// Respect viewer-specific annotation option if it is set
const viewerAnnotations = this.getViewerOption('annotations');
if (typeof viewerAnnotations === 'boolean') {
return viewerAnnotations;
const viewerAnnotations = this.getViewerAnnotationsConfig();

if (viewerAnnotations && viewerAnnotations.enabled !== undefined) {
return viewerAnnotations.enabled;
}

// Otherwise, use global preview annotation option
return this.options.showAnnotations;
return !!this.options.showAnnotations;
}

/**
Expand Down
26 changes: 26 additions & 0 deletions src/lib/viewers/__tests__/BaseViewer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,32 @@ describe('lib/viewers/BaseViewer', () => {
});
});

describe('getViewerAnnotationsConfig()', () => {
it('should return an empty object if none options available', () => {
sandbox.stub(base, 'getViewerOption').returns(undefined);
const config = base.getViewerAnnotationsConfig();
expect(config).to.deep.equal({});
});

it('should create an object with an "enabled" flag if using legacy boolean value', () => {
sandbox.stub(base, 'getViewerOption').returns(false);
const config = base.getViewerAnnotationsConfig();
expect(config).to.deep.equal({ enabled: false });

});

it('should pass through the annotations object if an object', () => {
const annConfig = {
enabled: true,
disabledTypes: ['drawing']
};
sandbox.stub(base, 'getViewerOption').returns(annConfig);
const config = base.getViewerAnnotationsConfig();
expect(config).to.deep.equal(annConfig);

});
});

describe('loadAnnotator()', () => {
beforeEach(() => {
base.options.viewer = {
Expand Down