Skip to content

Commit

Permalink
Merge pull request #16 from kuno1/feature/multiple-auhor-selector
Browse files Browse the repository at this point in the history
Feature/multiple auhor selector
  • Loading branch information
fumikito authored Oct 30, 2024
2 parents 39f362e + 2b0d36c commit f3eb49e
Show file tree
Hide file tree
Showing 28 changed files with 23,540 additions and 254 deletions.
25 changes: 4 additions & 21 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
{
"parser": "babel-eslint",
"env": {
"browser": true,
"jquery": true
},
"globals": {
"wp": false,
"jQuery": false,
"angular": false,
"Hametuha": true,
"wpApiSettings": false,
"ga": false,
"Hashboard": true,
"Vue": false
},
"extends": [
"plugin:@wordpress/eslint-plugin/recommended"
"plugin:@wordpress/eslint-plugin/recommended-with-formatting"
],
"globals": {
"kvm": "readonly"
},
"rules": {
"no-alert": "off",
"prettier/prettier": "off",
Expand All @@ -33,10 +21,5 @@
"yoda": "off",
"strict": "off",
"@wordpress/valid-sprintf": "off"
},
"settings": {
"react": {
"version": "16.9.0"
}
}
}
39 changes: 18 additions & 21 deletions .github/workflows/wordpress.yml → .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
name: Deploy Plugin
name: Test Plugin

on:
push:
branches:
- master
tags:
- '*'
pull_request:
branches:
- master

jobs:
phpcs:
name: PHP Syntax Check
uses: tarosky/workflows/.github/workflows/phpcs.yml@main
with:
version: 8.0

assets:
name: Stylelint & ESLint
uses: tarosky/workflows/.github/workflows/npm.yml@main

release:
name: Deploy WordPress.org
needs: [ phpcs, assets ]
name: Create Release
if: contains(github.ref, 'tags/')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: master

- name: Check tagged branch
run: |
BRANCHS=$(git branch --contains ${{ github.ref_name }})
set -- $BRANCHS
for BRANCH in $BRANCHS ; do
if [[ "$BRANCH" == "main" ]]; then
exit 0
fi
done
exit 1
- name: Setup PHP with composer v2
uses: shivammathur/setup-php@v2
Expand All @@ -37,9 +34,9 @@ jobs:
tools: composer

- name: Install Node
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: '14'
node-version: '20'

- name: Build Plugin
run: bash bin/build.sh ${{ github.ref }}
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Test Plugin

on:
pull_request:
branches:
- master

jobs:
phpcs:
name: PHP Syntax Check
uses: tarosky/workflows/.github/workflows/phpcs.yml@main
with:
version: 7.4

assets:
name: Stylelint & ESLint
uses: tarosky/workflows/.github/workflows/npm.yml@main
with:
node-version: 20

status-check:
name: Status Check
runs-on: ubuntu-latest
if: always()
needs: [ phpcs, assets ]
steps:
- uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/vendor/
/node_modules/
composer.lock
package-lock.json
/wordpress/
/dist/
4 changes: 1 addition & 3 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
{
"extends": [
"stylelint-config-wordpress/scss"
"@wordpress/stylelint-config/scss"
],
"rules": {
"value-keyword-case": [ "lower", {
"ignoreProperties": [ "font-family" ]
} ],
"number-leading-zero": null,
"rule-empty-line-before": null,
"declaration-property-unit-whitelist": null,
"selector-class-pattern": null,
"at-rule-empty-line-before": null,
"no-descending-specificity": null
Expand Down
2 changes: 2 additions & 0 deletions .wp-env.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"plugins": [
".",
"https://downloads.wordpress.org/plugin/classic-editor.latest-stable.zip",
"https://downloads.wordpress.org/plugin/plugin-check.latest-stable.zip",
"https://downloads.wordpress.org/plugin/query-monitor.latest-stable.zip"
],
"themes": [
Expand Down
35 changes: 35 additions & 0 deletions assets/js/user-selector-classic-editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*!
* User selector for classic editor
*
* @handle kvm-user-selector-classic-editor
* @deps kvm-user-selector, wp-i18n, wp-components, wp-element
*/

const { createRoot, render, useState } = wp.element;
const { UserSelectorComponent } = kvm;

// virtual-author-id[]

const UserSelectorClassic = ( props ) => {
const [ currentUsers, setUsers ] = useState( [] );
return (
<div className="kvm-user-selector-classic">
<UserSelectorComponent post={ props.post } onUserChange={ ( users ) => setUsers( users ) } />
{ currentUsers.map( ( user ) => {
return (
<input type="hidden" name="virtual-author-id[]" value={ user.id } key={ user.id } />
);
} ) }
</div>
);
};

document.addEventListener( 'DOMContentLoaded', () => {
const container = document.getElementById( 'kvm-user-selector-classic' );
const id = container.dataset.postId;
if ( createRoot ) {
createRoot( container ).render( <UserSelectorClassic post={ id } /> );
} else {
render( <UserSelectorClassic post={ id } />, container );
}
} );
147 changes: 147 additions & 0 deletions assets/js/user-selector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*!
* User Selector
*
* @handle kvm-user-selector
*
* @deps wp-element, wp-api-fetch, wp-components, wp-i18n
*/

/* global KvmUserSelector:false */

const { useState, useEffect } = wp.element;
const { Button, Icon, ComboboxControl } = wp.components;
const { apiFetch } = wp;

const UserToken = ( { user, onUserDelete } ) => {
return (
<Button className="kvm-user-token" onClick={ () => onUserDelete( user ) }
iconPosition="right" variant="secondary">
{ user.name }
<small>({ user.group.length > 0 ? user.group.map( ( g ) => g.name ).join( ', ' ) : '---' })</small>
<Icon icon="no-alt" />
</Button>
);
};

const UserComboBox = ( { onUserSelected } ) => {
const [ query, setQuery ] = useState( '' );
const [ users, setUsers ] = useState( [] );
const [ selectedOption, setSelectedOption ] = useState( null );
const [ timer, setTimer ] = useState( null );

// Do incremental search
useEffect( () => {
if ( timer ) {
clearTimeout( timer );
}
setTimer( setTimeout( () => {
if ( query ) {
// Search authros via API
const fetchOptions = async () => {
const response = await apiFetch( { path: `/kvm/v1/authors/search?s=${ query }` } );
setUsers( response );
};
try {
fetchOptions();
} catch ( error ) {
setUsers( [] );
}
} else {
setUsers( [] );
}
}, 300 ) );
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ query ] );

return (
<ComboboxControl
label={ KvmUserSelector.slabel }
placeholder={ KvmUserSelector.search }
value={ selectedOption }
options={ users.map( ( user ) => {
return { label: user.name, value: user.id };
} ) }
onChange={ ( value ) => {
// User is selected.
users.forEach( ( user ) => {
if ( user.id === value ) {
onUserSelected( user );
}
} );
setSelectedOption( '' );
} }
onFilterValueChange={ ( newQuery ) => setQuery( newQuery ) }
/>
);
};

/**
* User Select components.
*/

const UserSelectorComponent = ( { post, onUserChange } ) => {
const [ users, setUsers ] = useState( [] );

useEffect( () => {
const fetchUsers = async () => {
try {
const response = await apiFetch( {
path: `/kvm/v1/authors/of/${ post }`,
} );
setUsers( response );
} catch ( error ) {
// eslint-disable-next-line no-undef
alert( error.message || 'Error' );
}
};
fetchUsers();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );

useEffect( () => {
onUserChange( users );
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ users ] );

const removeUser = ( user ) => {
const newUsers = [];
users.map( ( u ) => {
if ( u.id !== user.id ) {
newUsers.push( u );
}
return u;
} );
setUsers( newUsers );
};

return (
<>
{ users.length > 0 ? (
<div className="kvm-user-token-wrapper">
{
users.map( ( user ) => {
return <UserToken key={ user.id } user={ user }
onUserDelete={ ( u ) => removeUser( u ) } />;
} )
}
</div>
) : (
<div className="notice notice-error notice-alt">
<p>{ KvmUserSelector.nouser }</p>
</div>
) }
<UserComboBox onUserSelected={ ( user ) => {
const userIds = users.map( ( u ) => u.id );
if ( userIds.includes( user.id ) ) {
return;
}
setUsers( users.concat( [ user ] ) );
} } />
</>
);
};

// Export components.
const kvm = window.kvm || {};
kvm.UserSelectorComponent = UserSelectorComponent;
window.kvm = kvm;
19 changes: 19 additions & 0 deletions assets/scss/user-selector.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*!
* User selector
*
* @handle kvm-user-selector
* @deps wp-components
*/

.kvm-user-token {
display: inline-block;
}

.kvm-user-token-wrapper {
margin: 1rem 0;
display: flex;
flex-wrap: wrap;
gap: 1em;
justify-content: flex-start;
align-items: flex-start;
}
Loading

0 comments on commit f3eb49e

Please sign in to comment.