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

New: Add _enableFilters property (fixes #115) #116

Merged
merged 11 commits into from
May 21, 2024
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ With the [Adapt CLI](https://github.com/adaptlearning/adapt-cli) installed, run
<div float align=right><a href="#top">Back to Top</a></div>

## Settings
The attributes listed below are used in *course.json* to configure **Resources**, and are properly formatted as JSON in [*example.json*](https://github.com/adaptlearning/adapt-contrib-resources/blob/master/example.json). Visit the [**Resources** wiki](https://github.com/adaptlearning/adapt-contrib-resources/wiki) for more information about how they appear in the [authoring tool](https://github.com/adaptlearning/adapt_authoring/wiki).

The attributes listed below are used in *course.json* to configure **Resources**, and are properly formatted as JSON in [*example.json*](https://github.com/adaptlearning/adapt-contrib-resources/blob/master/example.json). Some attributes can also be overridden for each content object in *contentObjects.json* (see [*example.json*](https://github.com/adaptlearning/adapt-contrib-resources/blob/master/example.json)).

Visit the [**Resources** wiki](https://github.com/adaptlearning/adapt-contrib-resources/wiki) for more information about how they appear in the [authoring tool](https://github.com/adaptlearning/adapt_authoring/wiki).

**\_resources** (object): The Resources object that contains values for **title**, **description**, **\_filterButtons**, **\_filterAria**, and **\_resourcesItems**.

Expand All @@ -44,6 +47,8 @@ The attributes listed below are used in *course.json* to configure **Resources**

>**instruction** (string): The instruction text for the resources which displays at the top of the resources drawer.

>**\_enableFilters** (boolean): Turns the filter buttons on and off. Acceptable values are `true` and `false`. Defaults to `true`. Note that the filter buttons will be automatically disabled if all `_resourcesItems` items have the same `_type` value.

>**\_filterButtons** (object): This attribute group maintains the labels for the four buttons that filter resources by type. It contains values for **all**, **document**, **media**, and **link**.

>>**all** (string): This text appears on the button that returns all **\_resourcesItems**.
Expand Down Expand Up @@ -91,4 +96,4 @@ No known limitations.
**Author / maintainer:** Adapt Core Team with [contributors](https://github.com/adaptlearning/adapt-contrib-resources/graphs/contributors)<br>
**Accessibility support:** WAI AA<br>
**RTL support:** Yes<br>
**Cross-platform coverage:** Chrome, Chrome for Android, Firefox (ESR + latest version), Edge, IE11, Safari 12+13 for macOS/iOS/iPadOS, Opera<br>
**Cross-platform coverage:** Chrome, Chrome for Android, Firefox (ESR + latest version), Edge, Safari for macOS/iOS/iPadOS, Opera<br>
1 change: 1 addition & 0 deletions example.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"displayTitle": "",
"body": "",
"instruction": "",
"_enableFilters": true,
"_filterButtons": {
"all": "All",
"document": "PDF",
Expand Down
5 changes: 4 additions & 1 deletion js/ResourcesView.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ export default class ResourcesView extends Backbone.View {
...this,
model: this.model.toJSON(),
resources: this.model.get('_resources'),
resourceTypes: this.model.get('_resourceTypes')
resourceTypes: this.model.get('_resourceTypes'),
_showFilters: this.model.get('_showFilters'),
_filterColumnCount: this.model.get('_filterColumnCount'),
_canDownload: this.model.get('_canDownload')
};
ReactDOM.render(<templates.resources {...data} />, this.el);

Expand Down
33 changes: 31 additions & 2 deletions js/adapt-contrib-resources.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Adapt from 'core/js/adapt';
import drawer from 'core/js/drawer';
import device from 'core/js/device';
import ResourcesView from './ResourcesView';

class Resources extends Backbone.Controller {
Expand Down Expand Up @@ -48,15 +49,43 @@ class Resources extends Backbone.Controller {
model.set('_resources', resources);

this.setupTypes(model, resourcesData);
this.setupFilters(model, resources);
this.setupCanDownload(model);

drawer.triggerCustomView(new ResourcesView({ model }).$el);
});
}

setupTypes(model, resourcesData) {
const configuredTypes = Object.keys(resourcesData._filterButtons).filter(type => type !== 'all');
const allTypes = [ 'all', ...configuredTypes ];
model.set('_resourceTypes', allTypes);
const typesWithItems = configuredTypes.filter(type => {
return resourcesData._resourcesItems.some(_.matcher({ _type: type }));
});

model.set('_resourceTypes', [ 'all', ...typesWithItems ]);
}

setupFilters(model, resources) {
const hasMultipleResources = resources.length > 1;
const hasMultipleTypes = !resources.every(_.matcher({ _type: resources[0]._type }));
const enableFilters = model.get('_enableFilters') ?? true;

const showFilters = hasMultipleResources && hasMultipleTypes && enableFilters;
model.set('_showFilters', showFilters);

const filterColumnCount = _.uniq(_.pluck(resources, '_type')).length + 1;
model.set('_filterColumnCount', filterColumnCount);
}
oliverfoster marked this conversation as resolved.
Show resolved Hide resolved

/**
* IE doesn't support the 'download' attribute
* https://github.com/adaptlearning/adapt_framework/issues/1559
* and iOS just opens links with that attribute in the same window
* https://github.com/adaptlearning/adapt_framework/issues/1852
*/
setupCanDownload(model) {
const canEnableDownloads = device.browser !== 'internet explorer' && device.OS !== 'ios';
model.set('_canDownload', canEnableDownloads);
}

}
Expand Down
9 changes: 9 additions & 0 deletions properties.schema
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@
"help": "The instruction text for the resources which displays at the top of the resources drawer.",
"translatable": true
},
"_enableFilters": {
"type": "boolean",
"required":true,
"default": true,
"title": "Enable filter buttons",
"inputType": "Checkbox",
"validators": [],
"help": "Turns the filter buttons on and off. Note that the filter buttons will be automatically disabled if all resource items have the same Type value."
},
"_filterButtons": {
"type": "object",
"title": "Filter Buttons",
Expand Down
6 changes: 6 additions & 0 deletions schema/course.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@
"translatable": true
}
},
"_enableFilters": {
"type": "boolean",
"title": "Enable filter buttons",
"default": true,
"description": "Turns the filter buttons on and off. Note that the filter buttons will be automatically disabled if all resource items have the same Type value."
},
"_filterButtons": {
"type": "object",
"title": "Filter buttons",
Expand Down
23 changes: 6 additions & 17 deletions templates/resources.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,12 @@ import { classes, templates } from 'core/js/reactHelpers';
export default function Resources (props) {
const {
resources,
resourceTypes
resourceTypes,
_showFilters,
_filterColumnCount
} = props;

const _globals = Adapt.course.get('_globals');

function resourcesHasMultipleTypes(resources) {
if (resources.length < 2) return false;

const allSameType = resources.every(_.matcher({ _type: resources[0]._type }));
return !allSameType;
}

function resourcesGetColumnCount(resources) {
return _.uniq(_.pluck(resources, '_type')).length + 1; // add 1 for the 'All' button column
}

const [selectedFilter, setSelectedFilter] = useState('all');
const [selectedId, setSelectedId] = useState('resources__show-all');
const [focusFlag, setFocusFlag] = useState(false);
Expand Down Expand Up @@ -59,13 +49,12 @@ export default function Resources (props) {
<div className="resources__inner">

<templates.header {...props.model} />

{resourcesHasMultipleTypes(resources) &&
{_showFilters &&
<div
className={classes([
'resources__filter',
`has-${resourcesGetColumnCount(resources)}-columns`,
(resourcesGetColumnCount(resources) > 4) && 'has-extra-types'
`has-${_filterColumnCount}-columns`,
(_filterColumnCount > 4) && 'has-extra-types'
])}
>
<div className="resources__filter-inner" role="tablist">
Expand Down
7 changes: 0 additions & 7 deletions templates/resourcesFilterButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,13 @@ export default function ResourcesFilterButton (props) {
const {
model,
onClick,
resources,
selected,
_filter
} = props;

const buttonText = model._filterButtons[_filter];
const ariaLabel = model._filterAria[`${_filter}Aria`];

function resourcesHasType(resources, type) {
return resources.some(_.matcher({ _type: type }));
}

if (!resourcesHasType(resources, _filter) && _filter !== 'all') return null;

return (
<button
id={`resources__show-${_filter}`}
Expand Down
18 changes: 2 additions & 16 deletions templates/resourcesItem.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import device from 'core/js/device';
import { classes } from 'core/js/reactHelpers';

export default function ResourcesItem (props) {
const {
_forceDownload,
_canDownload,
_isGlobal,
_link,
_type,
Expand All @@ -16,20 +16,6 @@ export default function ResourcesItem (props) {
onResourceItemClicked
} = props;

/**
* IE doesn't support the 'download' attribute
* https://github.com/adaptlearning/adapt_framework/issues/1559
* and iOS just opens links with that attribute in the same window
* https://github.com/adaptlearning/adapt_framework/issues/1852
*/
function resourcesForceDownload(filename, _forceDownload) {
if (device.browser === 'internet explorer' || device.OS === 'ios') {
return false;
}

return (_forceDownload || filename);
}

return (
<div
className={classes([
Expand All @@ -43,7 +29,7 @@ export default function ResourcesItem (props) {
<a href={_link} className="resources__item-btn drawer__item-btn"
data-type={_type}
data-index={_index}
download={resourcesForceDownload(filename, _forceDownload) && filename }
download={(_canDownload && _forceDownload) && filename }
onClick={onResourceItemClicked}
target="_blank"
rel="noreferrer"
Expand Down