diff --git a/assets/css/admin-distributed-post.css b/assets/css/admin-distributed-post.css
index a07aa4a7f..cb2d083a2 100644
--- a/assets/css/admin-distributed-post.css
+++ b/assets/css/admin-distributed-post.css
@@ -12,15 +12,3 @@
.open-distributor-help {
cursor: pointer;
}
-
-#distributed-to:before {
- content: ' ';
- display: inline-block;
- top: 5px;
- padding-right: 25px;
- width: 20px;
- height: 20px;
- background: url(../../assets/img/icon.svg) no-repeat top left;
- background-size: contain;
- position: relative;
-}
diff --git a/assets/css/admin.css b/assets/css/admin.css
index abe4d4ca6..981f8155f 100644
--- a/assets/css/admin.css
+++ b/assets/css/admin.css
@@ -11,3 +11,22 @@
font-weight: bold;
font-size: 14px;
}
+
+@media (min-width: 783px) {
+ body.is-showing-distributor.is-fullscreen-mode #wpadminbar {
+ display: block;
+ }
+
+ body.is-showing-distributor.is-fullscreen-mode .interface-interface-skeleton {
+ top: 32px;
+ }
+}
+
+.distributor-panel .components-panel__body-title svg {
+ height: 20px;
+ width: 20px;
+}
+
+.distributor-toggle {
+ margin-bottom: 8px;
+}
diff --git a/assets/css/gutenberg-syndicated-post.css b/assets/css/gutenberg-syndicated-post.css
index 645dd0d2b..121d1b338 100644
--- a/assets/css/gutenberg-syndicated-post.css
+++ b/assets/css/gutenberg-syndicated-post.css
@@ -59,15 +59,3 @@ body.dt-linked-post {
#distributed-from a {
vertical-align: top;
}
-
-#distributed-from:before {
- content: ' ';
- display: inline-block;
- top: -1px;
- padding-right: 2px;
- width: 20px;
- height: 20px;
- background: url(../../assets/img/icon.svg) no-repeat top left;
- background-size: contain;
- position: relative;
-}
diff --git a/assets/css/push.css b/assets/css/push.css
index 5e182b819..a880e5ae7 100644
--- a/assets/css/push.css
+++ b/assets/css/push.css
@@ -9,6 +9,7 @@
@custom-media --small-screen (min-width: 480px);
@custom-media --medium-screen (min-width: 768px);
+@custom-media --gutenberg-small-screen (max-width: 782px);
#distributor-push-wrapper,
#wpadminbar #wp-admin-bar-distributor-placeholder > .ab-item {
@@ -47,17 +48,20 @@
display: block;
}
-#wp-admin-bar-distributor.hover::before,
-#wp-admin-bar-distributor.syncing::before {
+#distributor-overlay {
+ display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
- background: rgba(0,0,0,0.6);
- z-index: -1;
- content: '';
- pointer-events: none;
+ background: rgba(0, 0, 0, 0.6);
+ z-index: 10000;
+
+ &.show,
+ &.syncing {
+ display: block;
+ }
}
#wpadminbar #distributor-push-wrapper .inner {
@@ -432,6 +436,12 @@
}
}
+.distributor-panel {
+ @media (--gutenberg-small-screen) {
+ display: none;
+ }
+}
+
#distributor-push-wrapper .loader-item,
#distributor-push-wrapper .loader-item *,
#distributor-push-wrapper .loader-item ::after,
diff --git a/assets/js/gutenberg-plugin.js b/assets/js/gutenberg-plugin.js
new file mode 100644
index 000000000..0421c98aa
--- /dev/null
+++ b/assets/js/gutenberg-plugin.js
@@ -0,0 +1,163 @@
+import { wp, dtGutenberg } from 'window';
+import PluginIcon from '../img/icon.svg'; // eslint-disable-line no-unused-vars
+
+const { Icon } = wp.components; // eslint-disable-line no-unused-vars
+const { select, useSelect } = wp.data;
+const { PluginDocumentSettingPanel } = wp.editPost; // eslint-disable-line no-unused-vars
+const { __, sprintf } = wp.i18n;
+const { registerPlugin } = wp.plugins;
+
+/**
+ * Add ability to show the admin bar, if needed
+ */
+const RenderShowAdminBar = () => { // eslint-disable-line no-unused-vars
+ const bodyClasses = document.body.classList;
+ const isFullScreenMode = select( 'core/edit-post' ).isFeatureActive( 'fullscreenMode' );
+ const distributorTopMenu = document.querySelector( '#wp-admin-bar-distributor' );
+ const distributorAdminItem = document.querySelector( '#wp-admin-bar-distributor > a' );
+
+ // Don't show anything if this is a distributed item
+ if ( 0 !== parseInt( dtGutenberg.syndicationTime ) ) {
+ return null;
+ }
+
+ if ( ! distributorTopMenu || ! distributorAdminItem ) {
+ return (
+
+ { __( 'Refresh page to see distribution options', 'distributor' ) }
+
+ );
+ }
+
+ return (
+
+
+
+ );
+};
+
+/**
+ * Render the draft message
+ */
+const RenderDraftMessage = () => { // eslint-disable-line no-unused-vars
+ if ( 0 !== parseInt( dtGutenberg.syndicationTime ) ) {
+ return null;
+ }
+
+ return (
+
+ { __( 'Distribution options available once published', 'distributor' ) }
+
+ );
+};
+
+/**
+ * Render the distribution information, if needed
+ */
+const RenderDistributionInfo = () => { // eslint-disable-line no-unused-vars
+ if ( 0 < parseInt( dtGutenberg.syndicationCount ) ) {
+ return ;
+ } else if ( 0 !== parseInt( dtGutenberg.syndicationTime ) ) {
+ return ;
+ }
+
+ return null;
+};
+
+/**
+ * Render the distributed to component
+ */
+const RenderDistributedTo = () => { // eslint-disable-line no-unused-vars
+ return(
+
+ { sprintf( __( 'Distributed to %1$s connection%2$s.', 'distributor' ),
+ dtGutenberg.syndicationCount,
+ '1' === dtGutenberg.syndicationCount ? '' : 's' ) }
+
+ );
+};
+
+/**
+ * Render the distributed from component
+ */
+const RenderDistributedFrom = () => { // eslint-disable-line no-unused-vars
+ return(
+
+ { __( 'Distributed on: ', 'distributor' ) }
+ { dtGutenberg.syndicationTime }
+
+ );
+};
+
+/**
+ * Create the Distributor icon
+ */
+const DistributorIcon = () => (
+ }
+ size={ 20 }
+ />
+);
+
+/**
+ * Add the Distributor panel to Gutenberg
+ */
+const DistributorPlugin = () => {
+ // Ensure the user has proper permissions
+ if ( dtGutenberg.noPermissions && 1 === parseInt( dtGutenberg.noPermissions ) ) {
+ return null;
+ }
+
+ const postType = useSelect( select => select( 'core/editor' ).getCurrentPostType() );
+ const postStatus = useSelect( select => select( 'core/editor' ).getCurrentPostAttribute( 'status' ) );
+
+ // Ensure we are on a supported post type
+ if ( dtGutenberg.supportedPostTypes && dtGutenberg.supportedPostTypes[ postType ] === undefined ) {
+ return null;
+ }
+
+ // If we are on a non-supported post status, change what we show
+ if ( dtGutenberg.supportedPostStati && ! dtGutenberg.supportedPostStati.includes( postStatus ) ) {
+ return (
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+ );
+};
+
+registerPlugin( 'distributor-plugin', { render: DistributorPlugin } );
diff --git a/assets/js/gutenberg-status-plugin.js b/assets/js/gutenberg-status-plugin.js
deleted file mode 100644
index c13faf40e..000000000
--- a/assets/js/gutenberg-status-plugin.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { wp, dtGutenberg } from 'window';
-
-if ( 'undefined' !== typeof wp.editPost.PluginPostStatusInfo ) {
- const { registerPlugin } = wp.plugins;
- const { __ } = wp.i18n;
- const { PluginPostStatusInfo } = wp.editPost; // eslint-disable-line no-unused-vars
-
- /**
- * Render the distributed from component.
- */
- const renderDistributedFrom = () => {
- return(
-
-
- { __( 'Distributed on: ' ) }
- { dtGutenberg.syndicationTime }
-
-
- );
- };
-
- /**
- * Render the distributed to component.
- */
- const renderDistributedTo = () => {
- return(
-
-
- { wp.i18n.sprintf( wp.i18n.__( 'Distributed to %1$s connection%2$s.', 'distributor' ),
- dtGutenberg.syndicationCount,
- '1' === dtGutenberg.syndicationCount ? '' : 's' ) }
-
-
- );
- };
-
- if ( 0 < parseInt( dtGutenberg.syndicationCount ) ) {
- registerPlugin( 'distributor-status-panel', { render: renderDistributedTo } );
- } else if ( 0 !== parseInt( dtGutenberg.syndicationTime ) ) {
- registerPlugin( 'distributor-status-panel', { render: renderDistributedFrom } );
- }
-}
diff --git a/assets/js/push.js b/assets/js/push.js
index 93341c444..c16e5e8f8 100755
--- a/assets/js/push.js
+++ b/assets/js/push.js
@@ -51,6 +51,12 @@ jQuery( window ).on( 'load', () => {
distributorMenuItem.appendChild( distributorPushWrapper );
+ // Add our overlay div
+ const overlayDiv = document.createElement( 'div' );
+ overlayDiv.id = 'distributor-overlay';
+ const contentNode = document.getElementById( 'wpadminbar' );
+ contentNode.parentNode.insertBefore( overlayDiv, contentNode );
+
/**
* Set variables after connections have been rendered
*/
@@ -273,12 +279,42 @@ jQuery( window ).on( 'load', () => {
}
}
+ /**
+ * If the menu isn't showing yet, wait to see if it does.
+ *
+ * This is an attempt to deal with the delay on the
+ * hoverintent function core uses on the adminbar.
+ */
+ function waitForDistributorMenuToShow() {
+ if ( distributorTopMenu.classList.contains( 'hover' ) ) {
+ distributorMenuEntered();
+ } else {
+ setTimeout( () => {
+ if ( distributorTopMenu.classList.contains( 'hover' ) ) {
+ distributorMenuEntered();
+ }
+ }, 210 );
+ }
+ }
+
/**
* Handle distributor push dropdown menu.
*/
function distributorMenuEntered() {
distributorMenuItem.focus();
+ // Show or hide the overlay
+ if (
+ overlayDiv.classList.contains( 'show' ) &&
+ ! overlayDiv.classList.contains( 'syncing' ) &&
+ ! distributorTopMenu.classList.contains( 'hover' )
+ ) {
+ overlayDiv.classList.remove( 'show' );
+ document.body.classList.remove( 'is-showing-distributor' );
+ } else {
+ overlayDiv.classList.add( 'show' );
+ }
+
if ( distributorPushWrapper.classList.contains( 'loaded' ) ) {
return;
}
@@ -340,16 +376,82 @@ jQuery( window ).on( 'load', () => {
} );
}
- // Event listerners when to fetch distributor data.
+ /**
+ * Close distributor menu when a click occurs outside of it
+ */
+ function maybeCloseDistributorMenu() {
+ // If a distribution is in progress, don't close things
+ if ( overlayDiv.classList.contains( 'syncing' ) ) {
+ return;
+ }
+
+ // If the Distributor menu is showing, hide everything
+ if ( distributorTopMenu.classList.contains( 'hover' ) ) {
+ overlayDiv.classList.remove( 'show' );
+ distributorTopMenu.classList.remove( 'hover' );
+ document.body.classList.remove( 'is-showing-distributor' );
+ }
+
+ // If the Distributor menu isn't showing but the overlay is, remove the overlay
+ if (
+ ! distributorTopMenu.classList.contains( 'hover' ) &&
+ overlayDiv.classList.contains( 'show' )
+ ) {
+ overlayDiv.classList.remove( 'show' );
+ document.body.classList.remove( 'is-showing-distributor' );
+ }
+ }
+
+ // Event listeners when to fetch distributor data.
distributorAdminItem.addEventListener( 'keydown', function( e ) {
// Pressing Enter.
if ( ( 13 === e.keyCode ) ) {
distributorMenuEntered();
}
+
+ // Pressing Escape.
+ if ( 27 === e.keyCode ) {
+ overlayDiv.classList.remove( 'show' );
+ }
}, false );
- distributorAdminItem.addEventListener( 'touchstart', distributorMenuEntered, false );
- distributorAdminItem.addEventListener( 'mouseenter', distributorMenuEntered, false );
+ // Listen for hover events to remove overlay div
+ window.hoverintent(
+ distributorTopMenu,
+ hoverIn,
+ hoverOut
+ ).options( {
+ timeout: 190
+ } );
+
+ /**
+ * Distributor menu hovered on
+ *
+ * Not currently using as this is handled in the
+ * distributorMenuEntered function.
+ */
+ function hoverIn() {
+ return null;
+ }
+
+ /**
+ * Distributor menu hovered out
+ *
+ * Used to remove the overlay.
+ */
+ function hoverOut() {
+ if (
+ ! distributorTopMenu.classList.contains( 'hover' ) &&
+ ! overlayDiv.classList.contains( 'syncing' )
+ ) {
+ overlayDiv.classList.remove( 'show' );
+ document.body.classList.remove( 'is-showing-distributor' );
+ }
+ }
+
+ distributorAdminItem.addEventListener( 'touchstart', waitForDistributorMenuToShow, false );
+ distributorAdminItem.addEventListener( 'mouseenter', waitForDistributorMenuToShow, false );
+ overlayDiv.addEventListener( 'click', maybeCloseDistributorMenu, true );
/**
* Do syndication ajax
@@ -360,6 +462,7 @@ jQuery( window ).on( 'load', () => {
}
distributorTopMenu.classList.add( 'syncing' );
+ overlayDiv.classList.add( 'syncing' );
const data = {
action: 'dt_push',
@@ -380,6 +483,10 @@ jQuery( window ).on( 'load', () => {
} ).done( ( response ) => {
setTimeout( () => {
distributorTopMenu.classList.remove( 'syncing' );
+ overlayDiv.classList.remove( 'syncing' );
+
+ // Hide the overlay if a user moved out of the Distributor menu
+ hoverOut();
if ( ! response.success ) {
doError( response.data );
@@ -396,6 +503,7 @@ jQuery( window ).on( 'load', () => {
} ).error( ( xhr, textStatus, errorThrown ) => {
setTimeout( () => {
distributorTopMenu.classList.remove( 'syncing' );
+ overlayDiv.classList.remove( 'syncing' );
doError( `${dt.messages.ajax_error} ${errorThrown}` );
}, 500 );
diff --git a/includes/syndicated-post-ui.php b/includes/syndicated-post-ui.php
index 0083e607f..26e06aafa 100644
--- a/includes/syndicated-post-ui.php
+++ b/includes/syndicated-post-ui.php
@@ -564,7 +564,7 @@ function enqueue_gutenberg_edit_scripts() {
}
wp_enqueue_script( 'dt-gutenberg-syndicated-post', plugins_url( '/dist/js/gutenberg-syndicated-post.min.js', __DIR__ ), [ 'wp-blocks' ], DT_VERSION, true );
- wp_enqueue_script( 'dt-gutenberg-syndicated-status-plugin', plugins_url( '/dist/js/gutenberg-status-plugin.min.js', __DIR__ ), [ 'wp-blocks', 'wp-edit-post' ], DT_VERSION, true );
+ wp_enqueue_script( 'dt-gutenberg-plugin', plugins_url( '/dist/js/gutenberg-plugin.min.js', __DIR__ ), [ 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-edit-post', 'wp-i18n', 'wp-plugins' ], DT_VERSION, true );
wp_localize_script(
'dt-gutenberg-syndicated-post',
@@ -584,6 +584,9 @@ function enqueue_gutenberg_edit_scripts() {
'originalLocationName' => sanitize_text_field( $original_location_name ),
'unlinkNonceUrl' => wp_nonce_url( add_query_arg( 'action', 'unlink', admin_url( sprintf( $post_type_object->_edit_link, $post->ID ) ) ), "unlink-post_{$post->ID}" ),
'linkNonceUrl' => wp_nonce_url( add_query_arg( 'action', 'link', admin_url( sprintf( $post_type_object->_edit_link, $post->ID ) ) ), "link-post_{$post->ID}" ),
+ 'supportedPostTypes' => \Distributor\Utils\distributable_post_types(),
+ 'supportedPostStati' => \Distributor\Utils\distributable_post_statuses(),
+ 'noPermissions' => ! is_user_logged_in() || ! current_user_can( apply_filters( 'dt_syndicatable_capabilities', 'edit_posts' ) ),
]
);
}
diff --git a/package-lock.json b/package-lock.json
index 6ba485949..3bad17e9c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9941,6 +9941,12 @@
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
"dev": true
},
+ "ramda": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz",
+ "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=",
+ "dev": true
+ },
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -10554,6 +10560,12 @@
}
}
},
+ "rx": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
+ "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=",
+ "dev": true
+ },
"rxjs": {
"version": "6.5.5",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
@@ -11221,6 +11233,45 @@
"es6-symbol": "^3.1.1"
}
},
+ "svg-react-loader": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/svg-react-loader/-/svg-react-loader-0.4.6.tgz",
+ "integrity": "sha512-HVEypjWQsQuJdBIPzXGxpmQsQts7QwfQuYgK1rah6BVCMoLNSCh/ESKVNd7/tHq8DkWYHHTyaUMDA1FjqZYrgA==",
+ "dev": true,
+ "requires": {
+ "css": "2.2.4",
+ "loader-utils": "1.1.0",
+ "ramda": "0.21.0",
+ "rx": "4.1.0",
+ "traverse": "0.6.6",
+ "xml2js": "0.4.17"
+ },
+ "dependencies": {
+ "big.js": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
+ "dev": true
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "dev": true,
+ "requires": {
+ "big.js": "^3.1.3",
+ "emojis-list": "^2.0.0",
+ "json5": "^0.5.0"
+ }
+ }
+ }
+ },
"svgo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
@@ -11571,6 +11622,12 @@
"through2": "^2.0.3"
}
},
+ "traverse": {
+ "version": "0.6.6",
+ "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
+ "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=",
+ "dev": true
+ },
"tslib": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
@@ -12384,6 +12441,25 @@
"mkdirp": "^0.5.1"
}
},
+ "xml2js": {
+ "version": "0.4.17",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz",
+ "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=",
+ "dev": true,
+ "requires": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "^4.1.0"
+ }
+ },
+ "xmlbuilder": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz",
+ "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.0.0"
+ }
+ },
"xmlcreate": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz",
diff --git a/package.json b/package.json
index 89867e5ac..6e03424ff 100644
--- a/package.json
+++ b/package.json
@@ -55,6 +55,7 @@
"pump": "^3.0.0",
"require-dir": "^1.2.0",
"run-sequence": "^2.2.1",
+ "svg-react-loader": "^0.4.6",
"webpack": "^4.43.0",
"webpack-stream": "^5.2.1",
"wp-hookdoc": "^0.2.0"
diff --git a/webpack.config.babel.js b/webpack.config.babel.js
index 8bd1c99b3..c4c68c2ed 100644
--- a/webpack.config.babel.js
+++ b/webpack.config.babel.js
@@ -1,6 +1,6 @@
import path from 'path';
-const DIST_PATH = path.resolve('./dist/js');
+const DIST_PATH = path.resolve( './dist/js' );
module.exports = {
cache: true,
@@ -11,7 +11,7 @@ module.exports = {
'admin-distributed-post': './assets/js/admin-distributed-post.js',
push: './assets/js/push.js',
'gutenberg-syndicated-post': './assets/js/gutenberg-syndicated-post.js',
- 'gutenberg-status-plugin': './assets/js/gutenberg-status-plugin.js',
+ 'gutenberg-plugin': './assets/js/gutenberg-plugin.js',
},
output: {
path: DIST_PATH,
@@ -34,16 +34,22 @@ module.exports = {
query: {
configFile: './.eslintrc.json'
}
- }
+ },
+ {
+ test: /\.svg$/,
+ use: [{
+ loader: 'svg-react-loader'
+ }]
+ },
]
},
mode: 'production',
-
externals: {
jquery: 'jQuery',
+ react: 'React',
underscores: '_',
window: 'window',
wp: 'wp'
},
stats: { colors: true },
-}
+};