/* globals gettext */ import 'whatwg-fetch'; import PropTypes from 'prop-types'; import React from 'react'; import _ from 'underscore'; import styles from './style.css'; class LibrarySourcedBlockPicker extends React.Component { constructor(props) { super(props); this.state = { libraries: [], xblocks: [], searchedLibrary: '', libraryLoading: false, xblocksLoading: false, selectedLibrary: undefined, selectedXblocks: new Set(this.props.selectedXblocks), }; this.onLibrarySearchInput = this.onLibrarySearchInput.bind(this); this.onXBlockSearchInput = this.onXBlockSearchInput.bind(this); this.onLibrarySelected = this.onLibrarySelected.bind(this); this.onXblockSelected = this.onXblockSelected.bind(this); this.onDeleteClick = this.onDeleteClick.bind(this); } componentDidMount() { this.fetchLibraries(); } fetchLibraries(textSearch='', page=1, append=false) { this.setState({ libraries: append ? this.state.libraries : [], libraryLoading: true, }, async function() { try { let res = await fetch(`/api/libraries/v2/?pagination=true&page=${page}&text_search=${textSearch}`); res = await res.json(); this.setState({ libraries: this.state.libraries.concat(res.results), libraryLoading: false, }, () => { if (res.next) { this.fetchLibraries(textSearch, page+1, true); } }); } catch (error) { $('#library-sourced-block-picker').trigger('error', { title: 'Could not fetch library', message: error, }); this.setState({ libraries: [], libraryLoading: false, }); } }); } fetchXblocks(library, textSearch='', page=1, append=false) { this.setState({ xblocks: append ? this.state.xblocks : [], xblocksLoading: true, }, async function() { try { let res = await fetch(`/api/libraries/v2/${library}/blocks/?pagination=true&page=${page}&text_search=${textSearch}`); res = await res.json(); this.setState({ xblocks: this.state.xblocks.concat(res.results), xblocksLoading: false, }, () => { if (res.next) { this.fetchXblocks(library, textSearch, page+1, true); } }); } catch (error) { $('#library-sourced-block-picker').trigger('error', { title: 'Could not fetch xblocks', message: error, }); this.setState({ xblocks: [], xblocksLoading: false, }); } }); } onLibrarySearchInput(event) { event.persist() this.setState({ searchedLibrary: event.target.value, }); if (!this.debouncedFetchLibraries) { this.debouncedFetchLibraries = _.debounce(value => { this.fetchLibraries(value); }, 300); } this.debouncedFetchLibraries(event.target.value); } onXBlockSearchInput(event) { event.persist() if (!this.debouncedFetchXblocks) { this.debouncedFetchXblocks = _.debounce(value => { this.fetchXblocks(this.state.selectedLibrary, value); }, 300); } this.debouncedFetchXblocks(event.target.value); } onLibrarySelected(event) { this.setState({ selectedLibrary: event.target.value, }); this.fetchXblocks(event.target.value); } onXblockSelected(event) { let state = new Set(this.state.selectedXblocks); if (event.target.checked) { state.add(event.target.value); } else { state.delete(event.target.value); } this.setState({ selectedXblocks: state, }, this.updateList); } onDeleteClick(event) { let value; if (event.target.tagName == 'SPAN') { value = event.target.parentElement.dataset.value; } else { value = event.target.dataset.value; } let state = new Set(this.state.selectedXblocks); state.delete(value); this.setState({ selectedXblocks: state, }, this.updateList); } updateList(list) { $('#library-sourced-block-picker').trigger('selected-xblocks', { sourceBlockIds: Array.from(this.state.selectedXblocks), }); } render() { return (

Hitting 'Save and Import' will import the latest versions of the selected blocks, overwriting any changes done to this block post-import.

{ this.state.libraries.map(lib => (
)) } { this.state.libraryLoading && {gettext('Loading...')} }
{ this.state.xblocks.map(block => (
)) } { this.state.xblocksLoading && {gettext('Loading...')} }

{gettext('Selected blocks')}

    { Array.from(this.state.selectedXblocks).map(block => (
  • )) }
); } } LibrarySourcedBlockPicker.propTypes = { selectedXblocks: PropTypes.array, }; LibrarySourcedBlockPicker.defaultProps = { selectedXblocks: [], }; export { LibrarySourcedBlockPicker }; // eslint-disable-line import/prefer-default-export