PluginProbe
codoc / 0.9.59
codoc v0.9.59
0.9.8.8 0.9.8.9 0.9.9 0.9.9.1 trunk 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.8.1 0.8.2 0.8.3 0.8.4 0.8.6 0.8.7 0.8.8 0.8.9 0.9 0.9.1 0.9.10 0.9.11 All 114 releases
← All changes | src/block/block.js +204 -87 0.30.9.59 View file →
@@ -10,9 +10,8 @@
10 10 import './editor.scss';
11 11 import icon from './icon';
12 12 //import { ENTER } from '@wordpress/keycodes';
13 13 const { ENTER } = wp.keycodes;
14 -
15 14 const { __ } = wp.i18n; // Import __() from wp.i18n
16 15 const { Component } = wp.element;
17 16
18 17 const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks
@@ -26,8 +25,9 @@
26 25 PanelBody,
27 26 ToggleControl,
28 27 CheckboxControl,
29 28 RangeControl,
29 + TextControl,
30 30 } = wp.components;
31 31
32 32 const {
33 33 getDefaultBlockName,
@@ -35,24 +35,33 @@
35 35 } = wp.blocks;
36 36
37 37 const { withState } = wp.compose;
38 38
39 -const codocURL = OPTIONS.codoc_url;
40 -const codocUserCode = OPTIONS.codoc_usercode;
41 -const codocEntriesClass = 'codoc-entries';
39 +const CODOC_URL = OPTIONS.codoc_url;
40 +const CODOC_USER_CODE = OPTIONS.codoc_usercode;
41 +const CODOC_PLUGIN_VERSION = OPTIONS.codoc_plugin_version;
42 +const CODOC_ENTRIES_CLASS = 'codoc-entries';
43 +const CODOC_ACCOUNT_IS_PRO = OPTIONS.codoc_account_is_pro;
44 +const CODOC_CURRENCY_CODE = OPTIONS.codoc_currency_code;
45 +const CODOC_CURRENCY_DECIMAL_PLACES = OPTIONS.codoc_currency_decimal_places;
42 46
43 -import Cookies from 'universal-cookie';
44 -const cookies = new Cookies();
47 +//import Cookies from 'universal-cookie';
48 +//const cookies = new Cookies();
45 49
46 50 class CodocControls extends Component {
47 51 constructor( props ) {
48 52 super( ...arguments );
49 -
50 53 this.subscriptionsFetched = [];
54 + this.subscriptionSearchTerm = '';
55 + this.state = {
56 + searchTerm: '',
57 + filteredSubscriptions: []
58 + };
51 59 this.fetchSubscriptions();
60 + this.handleSearchChange = this.handleSearchChange.bind(this);
52 61 }
53 62
54 - fetchSubscriptions() {
63 + fetchSubscriptions(searchTitle = '') {
55 64 const {
56 65 setAttributes,
57 66 attributes: {
58 67 fetching,
@@ -63,10 +72,15 @@
63 72 return
64 73 }
65 74
66 75 setAttributes( { fetching: true } )
67 - let url = codocURL + '/api/v1/cms/' + codocUserCode + '/subscriptions?without_token=1';
76 + let url = CODOC_URL + '/api/v1/cms/' + CODOC_USER_CODE + '/subscriptions?without_token=1';
68 77
78 + // Add title parameter if search term exists
79 + if (searchTitle) {
80 + url += '&title=' + encodeURIComponent(searchTitle);
81 + }
82 +
69 83 fetch(url)
70 84 .then( res => res.json() )
71 85 .then( res => {
72 86 let list = [];
@@ -74,30 +88,54 @@
74 88 for ( var i = 0; i < res.subscriptions.length; i++ ) {
75 89 let info = {
76 90 value: res.subscriptions[i].code,
77 91 label: res.subscriptions[i].title,
92 + term: res.subscriptions[i].term,
93 + price: res.subscriptions[i].price,
94 + currency: res.subscriptions[i].currency
78 95 }
79 96 list[i] = info
80 97 }
81 98 }
82 - if (list.length) {
99 + if (list.length || searchTitle) {
83 100 this.subscriptionsFetched = list;
101 + this.setState({ filteredSubscriptions: list });
84 102 }
85 103 setAttributes( { fetching: false } )
86 104 })
87 105 }
88 -
106 +
107 + handleSearchChange(value) {
108 + this.setState({ searchTerm: value });
109 +
110 + // Debounce the API call
111 + clearTimeout(this.searchTimeout);
112 + this.searchTimeout = setTimeout(() => {
113 + this.fetchSubscriptions(value);
114 + }, 500);
115 + }
116 +
89 117 getShowPriceHelp( checked ) {
90 118 return checked ?
91 - __( 'する' ) :
92 - __( 'しない' );
119 + __( 'Enable','codoc' ) :
120 + __( 'Disable','codoc' );
93 121 }
94 122 getShowSupportHelp( checked ) {
95 123 return checked ?
96 - __( '受け付ける' ) :
97 - __( '受け付けない' );
124 + __( 'Accept' ,'codoc') :
125 + __( 'Do not accept' ,'codoc');
98 126 }
99 -
127 + getShowPaywalledSupportHelp( checked ) {
128 + return checked ?
129 + __( 'The paid part will be hidden upon access, but will be displayed after tapping "Pay to Read". Viewers can freely specify the amount to purchase based on the content. Please note that there may be cases where it is not purchased.' ,'codoc') :
130 + __( ' ' );
131 + }
132 + getStatusLimitedHelp( checked ) {
133 + return checked ?
134 + __( 'Unlisted' ,'codoc') :
135 + __( 'Published' ,'codoc');
136 + }
137 +
100 138 render() {
101 139 const {
102 140 setAttributes,
103 141 attributes: {
@@ -104,57 +142,87 @@
104 142 showPrice,
105 143 price,
106 144 limited,
107 145 limitedCount,
108 -
146 +
109 147 affiliateMode,
110 148 affiliateRate,
111 149
112 150 showSupport,
113 -
151 + showPaywalledSupport,
152 + statusLimited,
114 153 subscriptions,
115 154 }
116 155 } = this.props;
117 156
118 -
119 -
120 157 const toggleShowPrice = () => setAttributes( { showPrice: ! showPrice } );
121 158 const toggleLimited = () => setAttributes( { limited: ! limited } );
159 + const toggleShowPaywalledSupport = () => setAttributes( { showPaywalledSupport: ! showPaywalledSupport } );
160 + const toggleStatusLimited = () => setAttributes( { statusLimited: ! statusLimited } );
122 161 const toggleAffiliateMode = () => setAttributes( { affiliateMode: ! affiliateMode } );
123 162 const toggleShowSupport = () => setAttributes( { showSupport: ! showSupport } );
124 -
163 +
125 164 const SubscriptionCheckBoxes = withState({
126 - checked_obj: Object.assign(new Object, subscriptions)
127 - })( ( { checked_obj , setState } ) => (
165 + checked_obj: Object.assign({}, subscriptions)
166 + })( ({ checked_obj, setState }) => (
167 + <div>
168 + {this.state.filteredSubscriptions.length === 0 ? (
169 + <p style={{ fontStyle: 'italic', color: '#666' }}>
170 + { this.state.searchTerm
171 + ? __('No plans found matching your search.','codoc')
172 + : __('No reader plans available.','codoc')
173 + }
174 + </p>
175 + ) : (
128 176 <ul>
129 - {
130 - this.subscriptionsFetched.map((v) => (
131 - <li><CheckboxControl
132 - className="check_items"
133 - label={v.label}
134 - checked={checked_obj[v.value]}
177 + {
178 + this.state.filteredSubscriptions.map((v) => {
179 + const isChecked = !!checked_obj[v.value];
180 + const checkedCount = Object.keys(checked_obj).length;
135 181
136 - onChange={ ( check ) => {
137 - check ? checked_obj[v.value] = true : delete checked_obj[v.value]
138 - setAttributes({subscriptions : checked_obj})
139 - setState({checked_obj})
140 - } }
141 - /></li>
142 - ) )
182 + return (
183 + <li key={v.value}>
184 + <CheckboxControl
185 + className="check_items"
186 + label={v.label}
187 + checked={isChecked}
188 + onChange={(check) => {
189 + // 追加する場合、5個以上は無効
190 + if (check && checkedCount >= 5) {
191 + return; // これ以上チェックできない
192 + }
193 +
194 + const newChecked = { ...checked_obj };
195 +
196 + if (check) {
197 + newChecked[v.value] = true;
198 + } else {
199 + delete newChecked[v.value];
200 + }
201 +
202 + setAttributes({ subscriptions: newChecked });
203 + setState({ checked_obj: newChecked });
204 + }}
205 + />
206 + </li>
207 + );
208 + })
143 209 }
144 210 </ul>
211 + )}
212 + </div>
145 213 ) )
146 214 const affiliateRateOptions = [
147 - { value: '0.0500', label:'販売価格の5%' },
148 - { value: '0.1000', label:'販売価格の10%' },
149 - { value: '0.1500', label:'販売価格の15%' },
150 - { value: '0.2000', label:'販売価格の20%' },
151 - { value: '0.2500', label:'販売価格の25%' },
152 - { value: '0.3000', label:'販売価格の30%' },
153 - { value: '0.3500', label:'販売価格の35%' },
154 - { value: '0.4000', label:'販売価格の40%' },
155 - { value: '0.4500', label:'販売価格の45%' },
156 - { value: '0.5000', label:'販売価格の50%' },
215 + { value: '0.0500', label:'5%' },
216 + { value: '0.1000', label:'10%' },
217 + { value: '0.1500', label:'15%' },
218 + { value: '0.2000', label:'20%' },
219 + { value: '0.2500', label:'25%' },
220 + { value: '0.3000', label:'30%' },
221 + { value: '0.3500', label:'35%' },
222 + { value: '0.4000', label:'40%' },
223 + { value: '0.4500', label:'45%' },
224 + { value: '0.5000', label:'50%' },
157 225 ];
158 226
159 227 return(
160 228 <InspectorControls key="CodocControls">
@@ -161,19 +229,18 @@
161 229
162 230 <PanelBody>
163 231
164 232 <ToggleControl
165 - label={ __( '単体販売' ) }
233 + label={ __( 'individual sale','codoc' ) }
166 234 checked={ !! showPrice }
167 235 help={ this.getShowPriceHelp }
168 236 ref="showPrice"
169 237 onChange={ toggleShowPrice }
170 238 />
171 -
239 +
172 240 <div style={{ display: showPrice ? 'initial' : 'none' }}>
173 -
174 241 <RangeControl
175 - label={ __( '価格(円)' ) }
242 + label={ __('price','codoc') + ' ' + (CODOC_CURRENCY_DECIMAL_PLACES > 0 ? (price / 100).toFixed(CODOC_CURRENCY_DECIMAL_PLACES) : price) + ' ' + __(CODOC_CURRENCY_CODE) + __(showPaywalledSupport ? '【' + __('Displayed as the your suggested price','codoc') + '】' : '' ) }
176 243 value={ price }
177 244 initialPosition={ price }
178 245 onChange={ ( value ) => {
179 246 // do validate this
@@ -179,13 +246,21 @@
179 246 // do validate this
180 247 setAttributes({ price: value });
181 248 }}
182 249 min="100"
183 - max="50000"
250 + max={ CODOC_ACCOUNT_IS_PRO == 1 ? 100000 : 50000 }
184 251 /><br />
185 -
252 +
186 253 <ToggleControl
187 - label={ __( '数量限定販売' ) }
254 + label={ __( 'Pay-what-you-want','codoc' ) }
255 + checked={ !! showPaywalledSupport }
256 + help={ this.getShowPaywalledSupportHelp }
257 + onChange={ toggleShowPaywalledSupport }
258 + />
259 +
260 + <div style={{ display: showPaywalledSupport ? 'none' : 'initial' }}>
261 + <ToggleControl
262 + label={ __( 'Limited quantity sale','codoc' ) }
188 263 checked={ !! limited }
189 264 onChange={ toggleLimited }
190 265 />
191 266
@@ -190,9 +265,9 @@
190 265 />
191 266
192 267 <div style={{ display: limited ? 'initial' : 'none' }}>
193 268 <RangeControl
194 - label={ __( '限定数' ) }
269 + label={ __( 'Limited quantity','codoc' ) }
195 270 value={ limitedCount }
196 271 onChange={ ( value ) => {
197 272 // do validate this
198 273 setAttributes({ limitedCount: value });
@@ -197,15 +272,15 @@
197 272 // do validate this
198 273 setAttributes({ limitedCount: value });
199 274 }}
200 275 initialPosition={ limitedCount }
201 - min="1"
276 + min="0"
202 277 max="100"
203 278 /><br />
204 279 </div>
205 -
280 +
206 281 <ToggleControl
207 - label={ __( 'アフィリエイト' ) }
282 + label={ __( 'Affiliate','codoc' ) }
208 283 checked={ !! affiliateMode }
209 284 onChange={ toggleAffiliateMode }
210 285 />
211 286
@@ -210,30 +285,62 @@
210 285 />
211 286
212 287 <div style={{ display: affiliateMode ? 'initial' : 'none' }}>
213 288 <SelectControl
214 - label={ __( '料率' ) }
215 - description={ __( '購入者を対象に指定した料率でアフィリエイトをオファーできます') }
289 + label={ __( 'Rate' , 'codoc') }
290 + description={ __( 'You can offer affiliate marketing at a specified rate for purchasers.', 'codoc') }
216 291 options={ affiliateRateOptions }
217 292 value={ affiliateRate }
218 293 onChange={ ( value ) => {
219 294 setAttributes( { affiliateRate: value } );
220 - }}/><br />
295 + }}/><br />
221 296 </div>
222 -
297 +
223 298 </div>
224 -
299 + </div>
300 +
301 + <div style={{ display: showPaywalledSupport ? 'none' : 'initial' }}>
225 302 <ToggleControl
226 - label={ __( 'サポート' ) }
303 + label={ __( 'Tipping', 'codoc') }
227 304 checked={ !! showSupport }
228 305 value="1"
229 306 onChange={ toggleShowSupport }
230 307 help={ this.getShowSupportHelp }
231 308 />
309 + </div>
310 +
311 + <div style={{ display: 'initial' }}>
312 + <ToggleControl
313 + label={ __( 'Unlisted','codoc' ) }
314 + checked={ !! statusLimited }
315 + value="1"
316 + onChange={ toggleStatusLimited }
317 + help={ this.getStatusLimitedHelp }
318 + />
319 + </div>
320 +
321 + <div class="codoc-subscription-title">
322 + <label>
323 + { __('Reader Plans','codoc') }
324 + </label>
325 + <a
326 + href={ CODOC_URL + '/me/subscriptions'}
327 + target="_blank" class="codoc-subscription-add"
328 + >
329 + { __('Add','codoc') }
330 + </a>
331 + </div>
232 332
233 - <label>サブスクリプション</label>
333 + <TextControl
334 + label={ __('Search Plans','codoc') }
335 + value={ this.state.searchTerm }
336 + onChange={ this.handleSearchChange }
337 + placeholder={ __('Enter title to search...','codoc') }
338 + />
339 +
234 340 <SubscriptionCheckBoxes />
235 341
342 +
236 343 </PanelBody>
237 344 </InspectorControls>
238 345 );
239 346 }
@@ -242,22 +349,26 @@
242 349 class EditBlockContent extends Component {
243 350 constructor() {
244 351 super( ...arguments );
245 352 // デフォルト値
246 - this.props.setAttributes({ wpPluginVer: '0.3' });
247 - this.props.setAttributes({ showPrice: this.props.attributes.showPrice == null ? true : this.props.attributes.showPrice });
248 - this.props.setAttributes({ price: this.props.attributes.price == null ? 100 : this.props.attributes.price });
249 - this.props.setAttributes({ limited: this.props.attributes.limited == null ? false : this.props.attributes.limited });
250 - this.props.setAttributes({ limitedCount: this.props.attributes.limitedCount == null ? 10 : this.props.attributes.limitedCount });
251 - this.props.setAttributes({ affiliateMode: this.props.attributes.affiliateMode == null ? false : this.props.attributes.affiliateMode });
252 - this.props.setAttributes({ affiliateRate: this.props.attributes.affiliateRate == null ? '0.0500' : this.props.attributes.affiliateRate });
253 - this.props.setAttributes({ showSupport: this.props.attributes.showSupport == null ? false : this.props.attributes.showSupport });
254 - this.props.setAttributes({ subscriptions: this.props.attributes.subscriptions == null ? {} : this.props.attributes.subscriptions });
353 + const bd = OPTIONS.codoc_block_defaults || {};
354 + const d = (key, fallback) => bd.hasOwnProperty(key) ? bd[key] : fallback;
355 + this.props.setAttributes({ version: CODOC_PLUGIN_VERSION });
356 + this.props.setAttributes({ showPrice: this.props.attributes.showPrice == null ? d('showPrice', true) : this.props.attributes.showPrice });
357 + this.props.setAttributes({ price: this.props.attributes.price == null ? d('price', 500) : this.props.attributes.price });
358 + this.props.setAttributes({ limited: this.props.attributes.limited == null ? d('limited', false) : this.props.attributes.limited });
359 + this.props.setAttributes({ limitedCount: this.props.attributes.limitedCount == null ? d('limitedCount', 10) : this.props.attributes.limitedCount });
360 + this.props.setAttributes({ affiliateMode: this.props.attributes.affiliateMode == null ? d('affiliateMode', false) : this.props.attributes.affiliateMode });
361 + this.props.setAttributes({ affiliateRate: this.props.attributes.affiliateRate == null ? d('affiliateRate', '0.0500') : this.props.attributes.affiliateRate });
362 + this.props.setAttributes({ showSupport: this.props.attributes.showSupport == null ? d('showSupport', false) : this.props.attributes.showSupport });
363 + this.props.setAttributes({ showPaywalledSupport: this.props.attributes.showPaywalledSupport == null ? d('showPaywalledSupport', false) : this.props.attributes.showPaywalledSupport });
364 + this.props.setAttributes({ statusLimited: this.props.attributes.statusLimited == null ? d('statusLimited', false) : this.props.attributes.statusLimited });
365 + this.props.setAttributes({ subscriptions: this.props.attributes.subscriptions == null ? d('subscriptions', {}) : this.props.attributes.subscriptions });
255 366
256 367 this.onChangeInput = this.onChangeInput.bind( this );
257 368 this.onKeyDown = this.onKeyDown.bind( this );
258 369 this.state = {
259 - defaultText: __( 'この続きをみるには' ),
370 + defaultText: __( 'To continue reading, ...','codoc' ),
260 371 };
261 372 }
262 373 onChangeInput( event ) {
263 374 this.setState( {
@@ -273,9 +384,9 @@
273 384 if ( keyCode === ENTER ) {
274 385 insertBlocksAfter( [ createBlock( getDefaultBlockName() ) ] );
275 386 }
276 387 }
277 -
388 +
278 389 render() {
279 390 const {
280 391 attributes: {
281 392 customText,
@@ -307,10 +418,10 @@
307 418 };
308 419
309 420
310 421 registerBlockType( 'codoc/codoc-block', {
311 - title: __( 'codoc' ),
312 - description: __( 'このブロックから下のブロックは認証されたcodocユーザーのみが閲覧できる有料エリアとなります。' ),
422 + title: __( 'codoc' ,'codoc'),
423 + description: __( 'The area from this block down is a paid area that only authenticated codoc users can view.','codoc' ),
313 424 icon,
314 425 category: 'layout',
315 426 supports: {
316 427 customClassName: false,
@@ -318,11 +429,11 @@
318 429 html: false,
319 430 multiple: false,
320 431 },
321 432 keywords: [
322 - __( 'codoc Block' ),
323 - __( 'plugin for codoc' ),
324 - __( 'codoc-block' ),
433 + __( 'codoc Block' ,'codoc'),
434 + __( 'plugin for codoc' ,'codoc'),
435 + __( 'codoc-block' ,'codoc'),
325 436 ],
326 437 attributes: {
327 438 showPrice: {
328 439 type: 'boolean',
@@ -351,8 +462,16 @@
351 462 showSupport: {
352 463 type: 'boolean',
353 464 default: null,
354 465 },
466 + showPaywalledSupport: {
467 + type: 'boolean',
468 + default: null,
469 + },
470 + statusLimited: {
471 + type: 'boolean',
472 + default: null,
473 + },
355 474 subscriptions: {
356 475 type: 'object',
357 476 default: null,
358 477 },
@@ -359,16 +478,16 @@
359 478 customText: {
360 479 type: 'string',
361 480 default: '',
362 481 },
363 - wpPluginVer: {
482 + version: {
364 483 type: 'string',
365 484 default: null,
366 485 },
367 486 },
368 -
487 +
369 488 edit: EditBlockContent,
370 -
489 +
371 490 save: function( props ) {
372 491 const {
373 492 setAttributes,
374 493 attributes: {
@@ -375,12 +494,11 @@
375 494 customText,
376 495 }
377 496 } = props;
378 497 return ( // return if link behavior normal
379 - <div>
380 - <span
498 + <div
381 499 data-id='codoc-tag'
382 - className={ codocEntriesClass }
500 + className={ CODOC_ENTRIES_CLASS }
383 501 >
384 502 { customText && !! customText.length && (
385 503 <RichText.Content
386 504 value={ customText }
@@ -385,9 +503,8 @@
385 503 <RichText.Content
386 504 value={ customText }
387 505 />
388 506 )}
389 - </span>
390 507 </div>
391 508 )
392 509 },
393 510 } );