-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit squashed: * Prevent Timeline from updating when changing the description or title. * Remove old shortcode references. * Address feedback from PR review. Encapsulate Timeline node in its own component. * Added debounce for the Sheet URL input. * Add dangerouslySetInnerHTML to the description. * Nicer warning for empty URL * Remove Edit HTML option. Match defaults to PHP. * Address review feedback. * Moving hooks to components folder * Minor improvements to the script and style loader hooks * Add HTMLSidebarHelp component
- Loading branch information
1 parent
1cf1e19
commit 5cf0180
Showing
15 changed files
with
499 additions
and
447 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,247 +1,53 @@ | ||
import {RawHTML, Component, Fragment} from '@wordpress/element'; | ||
import { | ||
CheckboxControl, | ||
TextControl as BaseTextControl, | ||
TextareaControl as BaseTextareaControl, | ||
SelectControl, | ||
ServerSideRender | ||
} from '@wordpress/components'; | ||
import {Preview} from '../../components/Preview'; | ||
import withCharacterCounter from '../../components/withCharacterCounter/withCharacterCounter'; | ||
import {URLInput} from "../../components/URLInput/URLInput"; | ||
|
||
const TextControl = withCharacterCounter( BaseTextControl ); | ||
const TextareaControl = withCharacterCounter( BaseTextareaControl ); | ||
|
||
export class Timeline extends Component { | ||
constructor(props) { | ||
super(props); | ||
} | ||
|
||
componentDidMount() { | ||
this.loadTimeline(this.props); | ||
} | ||
|
||
componentDidUpdate(prevProps) { | ||
this.loadTimeline(prevProps); | ||
} | ||
|
||
loadTimeline(data) { | ||
const timelinejs_version = '3.6.3'; | ||
|
||
let js = 'https://cdn.knightlab.com/libs/timeline3/' + timelinejs_version + '/js/timeline-min.js'; | ||
let scriptLoaded = this.loadScriptAsync(js); | ||
scriptLoaded.then(function () { | ||
new TL.Timeline('timeline-1', data.google_sheets_url, { | ||
"timenav_position": data.timenav_position, | ||
"start_at_end": data.start_at_end, | ||
"language": data.language | ||
}); | ||
}.bind(this)); | ||
} | ||
|
||
loadScriptAsync(uri) { | ||
return new Promise((resolve, reject) => { | ||
let tag = document.createElement('script'); | ||
tag.src = uri; | ||
tag.async = true; | ||
tag.onload = () => { | ||
resolve(); | ||
}; | ||
let body = document.getElementsByTagName('body')[0]; | ||
body.appendChild(tag); | ||
}); | ||
}; | ||
|
||
renderEdit() { | ||
const {__} = wp.i18n; | ||
|
||
const position = [ | ||
{label: 'Bottom', value: 'bottom'}, | ||
{label: 'Top', value: 'top'}, | ||
] | ||
|
||
const languages = [ | ||
{label: 'Afrikaans', value: 'af'}, | ||
{label: 'Arabic', value: 'ar'}, | ||
{label: 'Armenian', value: 'hy'}, | ||
{label: 'Basque', value: 'eu'}, | ||
{label: 'Belarusian', value: 'be'}, | ||
{label: 'Bulgarian', value: 'bg'}, | ||
{label: 'Catalan', value: 'ca'}, | ||
{label: 'Chinese', value: 'zh-cn'}, | ||
{label: 'Croatian / Hrvatski', value: 'hr'}, | ||
{label: 'Czech', value: 'cz'}, | ||
{label: 'Danish', value: 'da'}, | ||
{label: 'Dutch', value: 'nl'}, | ||
{label: 'English', value: 'en'}, | ||
{label: 'English (24-hour time)', value: 'en-24hr'}, | ||
{label: 'Esperanto', value: 'eo'}, | ||
{label: 'Estonian', value: 'et'}, | ||
{label: 'Faroese', value: 'fo'}, | ||
{label: 'Farsi', value: 'fa'}, | ||
{label: 'Finnish', value: 'fi'}, | ||
{label: 'French', value: 'fr'}, | ||
{label: 'Frisian', value: 'fy'}, | ||
{label: 'Galician', value: 'gl'}, | ||
{label: 'Georgian', value: 'ka'}, | ||
{label: 'German / Deutsch', value: 'de'}, | ||
{label: 'Greek', value: 'el'}, | ||
{label: 'Hebrew', value: 'he'}, | ||
{label: 'Hindi', value: 'hi'}, | ||
{label: 'Hungarian', value: 'hu'}, | ||
{label: 'Icelandic', value: 'is'}, | ||
{label: 'Indonesian', value: 'id'}, | ||
{label: 'Irish', value: 'ga'}, | ||
{label: 'Italian', value: 'it'}, | ||
{label: 'Japanese', value: 'ja'}, | ||
{label: 'Korean', value: 'ko'}, | ||
{label: 'Latvian', value: 'lv'}, | ||
{label: 'Lithuanian', value: 'lt'}, | ||
{label: 'Luxembourgish', value: 'lb'}, | ||
{label: 'Malay', value: 'ms'}, | ||
{label: 'Myanmar', value: 'my'}, | ||
{label: 'Nepali', value: 'ne'}, | ||
{label: 'Norwegian', value: 'no'}, | ||
{label: 'Polish', value: 'pl'}, | ||
{label: 'Portuguese', value: 'pt'}, | ||
{label: 'pt-br', value: 'Portuguese (Brazilian)'}, | ||
{label: 'Romanian', value: 'ro'}, | ||
{label: 'Romansh', value: 'rm'}, | ||
{label: 'Russian', value: 'ru'}, | ||
{label: 'Serbian - Cyrillic', value: 'sr-cy'}, | ||
{label: 'Serbian - Latin', value: 'sr'}, | ||
{label: 'Sinhalese', value: 'si'}, | ||
{label: 'Slovak', value: 'sk'}, | ||
{label: 'Slovenian', value: 'sl'}, | ||
{label: 'Spanish', value: 'es'}, | ||
{label: 'Swedish', value: 'sv'}, | ||
{label: 'Tagalog', value: 'tl'}, | ||
{label: 'Tamil', value: 'ta'}, | ||
{label: 'Taiwanese', value: 'zh-tw'}, | ||
{label: 'Telugu', value: 'te'}, | ||
{label: 'Thai', value: 'th'}, | ||
{label: 'Turkish', value: 'tr'}, | ||
{label: 'Ukrainian', value: 'uk'}, | ||
{label: 'Urdu', value: 'ur'}, | ||
] | ||
|
||
let url_desc = __( | ||
'Enter the URL of the Google Sheets spreadsheet containing your timeline data.', | ||
'p4ge' | ||
); | ||
url_desc += '<br><a href="https://timeline.knightlab.com/#make" target="_blank" rel="noopener noreferrer">'; | ||
url_desc += __( | ||
'See the TimelineJS website for a template GSheet.', | ||
'p4ge' | ||
); | ||
url_desc += '</a><br>'; | ||
url_desc += __( | ||
'Copy this, add your own timeline data, and publish to the web.', | ||
'p4ge' | ||
); | ||
url_desc += '<br>'; | ||
url_desc += __( | ||
"Once you have done so, use the URL from your address bar (not the one provided in Google's 'publish to web' dialog).", | ||
'p4ge' | ||
); | ||
|
||
return ( | ||
<Fragment> | ||
<div> | ||
<h2>{__('Timeline options', 'p4ge')}</h2> | ||
<p><i>{__( | ||
'Display a timeline from a Google Sheet', | ||
'p4ge' | ||
)}</i></p> | ||
|
||
<div> | ||
<TextControl | ||
label={__('Timeline Title', 'p4ge')} | ||
placeholder={__('Enter title', 'p4ge')} | ||
value={this.props.timeline_title} | ||
onChange={this.props.onTimelineTitleChange} | ||
characterLimit={60} | ||
/> | ||
</div> | ||
|
||
<div> | ||
<TextareaControl | ||
label={__('Description', 'p4ge')} | ||
placeholder={__('Enter description', 'p4ge')} | ||
value={this.props.description} | ||
onChange={this.props.onDescriptionChange} | ||
characterLimit={400} | ||
/> | ||
</div> | ||
|
||
<div> | ||
<URLInput | ||
label={__('Google Sheets URL', 'p4ge')} | ||
placeholder={__('Enter URL', 'p4ge')} | ||
help=<RawHTML>{url_desc}</RawHTML> | ||
value={this.props.google_sheets_url} | ||
onChange={this.props.onGoogleSheetsUrlChange} | ||
/> | ||
</div> | ||
|
||
<div> | ||
<SelectControl | ||
label={__('Language', 'p4ge')} | ||
value={this.props.language} | ||
options={languages} | ||
onChange={(e) => this.props.onLanguageChange(e)} | ||
/> | ||
</div> | ||
|
||
<div> | ||
<SelectControl | ||
label={__('Timeline navigation position', 'p4ge')} | ||
value={this.props.timenav_position} | ||
options={position} | ||
onChange={(e) => this.props.onTimenavPositionChange(e)} | ||
/> | ||
</div> | ||
|
||
<div> | ||
<CheckboxControl | ||
label={__('Start at end', 'p4ge')} | ||
help={__('Begin at the end of the timeline', 'p4ge')} | ||
value={this.props.start_at_end} | ||
checked={this.props.start_at_end} | ||
onChange={(e) => this.props.onStartAtEndChange(e)} | ||
/> | ||
</div> | ||
|
||
</div> | ||
</Fragment> | ||
); | ||
} | ||
|
||
render() { | ||
return ( | ||
<div> | ||
{ | ||
this.props.isSelected | ||
? this.renderEdit() | ||
: null | ||
} | ||
<Preview showBar={this.props.isSelected}> | ||
<ServerSideRender | ||
block={'planet4-blocks/timeline'} | ||
attributes={{ | ||
timeline_title: this.props.timeline_title, | ||
description: this.props.description, | ||
google_sheets_url: this.props.google_sheets_url, | ||
language: this.props.language, | ||
timenav_position: this.props.timenav_position, | ||
start_at_end: this.props.start_at_end, | ||
}} | ||
urlQueryArgs={{post_id: document.querySelector('#post_ID').value}} | ||
> | ||
</ServerSideRender> | ||
</Preview> | ||
</div> | ||
); | ||
}; | ||
import { useScript } from '../../components/useScript/useScript'; | ||
import { useStyleSheet } from '../../components/useStyleSheet/useStyleSheet'; | ||
import { useRef, useEffect } from 'react'; | ||
import { uniqueId } from 'lodash'; | ||
|
||
const TIMELINE_JS_VERSION = '3.6.6'; | ||
|
||
export const Timeline = (props) => { | ||
const { | ||
google_sheets_url, | ||
timenav_position, | ||
start_at_end, | ||
language | ||
} = props; | ||
|
||
const timelineNode = useRef(null); | ||
|
||
const [stylesLoaded, stylesError] = useStyleSheet( | ||
`https://cdnjs.cloudflare.com/ajax/libs/timelinejs/${TIMELINE_JS_VERSION}/css/timeline.css` | ||
); | ||
|
||
const setupTimeline = function() { | ||
timelineNode.current.id = uniqueId('timeline'); | ||
|
||
new TL.Timeline(timelineNode.current.id, google_sheets_url, { | ||
'timenav_position': timenav_position, | ||
'start_at_end': start_at_end, | ||
'language': language | ||
}); | ||
} | ||
|
||
const [scriptLoaded, scriptError] = useScript( | ||
`https://cdnjs.cloudflare.com/ajax/libs/timelinejs/${TIMELINE_JS_VERSION}/js/timeline-min.js` | ||
); | ||
|
||
useEffect( | ||
() => { | ||
if (stylesLoaded && scriptLoaded) { | ||
setupTimeline(); | ||
} | ||
}, | ||
[ | ||
stylesLoaded, | ||
scriptLoaded, | ||
start_at_end, | ||
google_sheets_url, | ||
timenav_position, | ||
language, | ||
], | ||
); | ||
|
||
return <div ref={ timelineNode }></div> | ||
} |
Oops, something went wrong.