如何在编辑器外使用MediaUpload

时间:2019-07-01 作者:OpensaurusRex

我正在尝试创建一个界面,允许用户管理与他们相关的帖子中存储的数据,而不允许他们访问存储该数据的自定义帖子类型。

其他一切都很好,但我想添加一种方法,让他们从这个页面上传一张在React应用程序中显示的个人资料图片。所有其他元素的加载都很好,比如TextControl和SelectControl等。然而,我很难让MediaUpload在块编辑器之外激活。

有没有什么方法可以让我在我的react应用程序中使用它,以便他们可以上传个人资料图片?

下面是一些代码:

import React, { Component } from \'react\'
import ReactDOM from \'react-dom\'
import ReactPhoneInput from \'react-phone-input-2\'

let { Button, SelectControl, TextControl, ToggleControl } = window.wp.components
let { MediaUpload, RichText } = window.wp.editor

class ClassmateProfile extends Component {
  constructor (props) {
    super(props)
    this.state = {
      pageID: USNA1978.pageID,
      aboutDetails: USNA1978.aboutDetails,
      aboutImage1: USNA1978.aboutImage1,
      aboutImage2: USNA1978.aboutImage2,
      firstName: USNA1978.firstName,
      middleName: USNA1978.middleName,
      lastName: USNA1978.lastName,
      //...
    }
  }

  render () {
    if (this.state.pageID) {
      return (
        <div className=\'profile-layout\'>
          <div className=\'left-side\'>
            <div className=\'panel panel-default\'>
              <div className=\'panel-heading\'>
                <strong>About</strong>
              </div>
              <div className=\'panel-body\'>
                <div className=\'image-grid\'>
                  <div>
                    {(() => {
                      if (this.state.aboutImage1) {
                        return <img alt=\'Current Photo\' src={this.state.aboutImage1} />
                      } else {
                        return <span>Graduation Photo</span>
                      }
                    })()}
                  </div>
                  <div>
                    {(() => {
                      if (this.state.aboutImage2) {
                        return <img alt=\'Current Photo\' src={this.state.aboutImage2} />
                      } else {
                        return <span>Graduation Photo</span>
                      }
                    })()}
                    <MediaUpload
                      value={this.state.aboutImage2}
                      onSelect={media => this.setState({ aboutImage2: media.url })}
                      render={({ open }) => (
                        <Button className=\'button button-large sidebar-detail-icon-button\' onClick={open}>
                          {!this.state.aboutImage2 ? \'Upload/Select Photo\' : \'Change Photo\'}
                        </Button>
                      )}
                    />
                  </div>
                </div>
                <RichText
                  tag=\'p\'
                  value={this.state.aboutDetails}
                  onChange={value => this.setState({ aboutDetails: value })}
                  placeholder=\'Click here to add details about this classmate...\'
                />
              </div>
            </div>
            <!-- ... -->
          </div>

          <div className=\'right-side\'>
            <div className=\'panel panel-default\'>
              <div className=\'panel-heading\'>
                <strong>Contact Info</strong>
              </div>
              <div className=\'panel-body\'>
                <table className=\'borderless\'>
                  <tr>
                    <th colSpan=\'2\'>Name &amp; Company</th>
                  </tr>
                  <tr>
                    <td>
                      <label htmlFor=\'firstName\'>First Name</label>
                    </td>
                    <td>
                      <TextControl
                        value={this.state.firstName}
                        onChange={value => this.setState({ firstName: value })}
                      />
                    </td>
                  </tr>
                  <tr>
                    <td>
                      <label htmlFor=\'middleName\'>Middle Name</label>
                    </td>
                    <td>
                      <TextControl
                        value={this.state.middleName}
                        onChange={value => this.setState({ middleName: value })}
                      />
                    </td>
                  </tr>
                  <tr>
                    <td>
                      <label htmlFor=\'lastName\'>Last Name</label>
                    </td>
                    <td>
                      <TextControl
                        value={this.state.lastName}
                        onChange={value => this.setState({ lastName: value })}
                      />
                    </td>
                  </tr>
                  <!-- ... -->
                </table>
              </div>
            </div>
          </div>
        </div>
      )
    }
  }
}

if (document.getElementById(\'edit_classmate_profile\')) {
  ReactDOM.render(<ClassmateProfile />, document.getElementById(\'edit_classmate_profile\'))
}

1 个回复
最合适的回答,由SO网友:OpensaurusRex 整理而成

答案实际上是几个步骤,我做了很多实验,但归根结底是以下代码,您需要使用webpack之类的工具进行编译并提取库,等等:

// MediaUploadFilter.js
import { MediaUpload } from \'@wordpress/media-utils\'
 
const { addFilter } = window.wp.hooks
const replaceMediaUpload = () => MediaUpload

addFilter(
  \'editor.MediaUpload\',
  \'core/edit-post/components/media-upload/replace-media-upload\',
  replaceMediaUpload
)
本质上,我已经剥离了这个类,让您看到它在init hook期间被调用:

<?php
public function __construct()
{
    add_action(\'admin_menu\', [$this, \'setAdminMenus\']);
    // ...
}
public function setAdminMenus(): void
{
    $pageMenuObject = add_menu_page(
        \'Classmate Profile\',
        \'Classmate Profile\',
        \'edit_classmates_profile\',
        \'classmate-profile\',
        [$this->displayHandler, \'displayPage\'], // a function loading a view
        \'dashicons-admin-users\',
        21
    );

    add_action(\'admin_enqueue_scripts\', static function ($hook) use ($pageMenuObject) {
       /**
         * Make sure that we load the scripts specific to the add to release page
         */
        if ($hook === $pageMenuObject) {
            $pageMenuData = ClassmateProfileData::getInstance(); // Grabs data for user
            $allPageData = [];
            if ($pageMenuData) {
                $allPageData = $pageMenuData->getPageData() ?: [];
            }

            static::enqueueLibraryAssets(); // See below abstract function I pasted below

            wp_enqueue_script(
                \'plugin-classmate-profile\',
                mix_plugin_uri(\'/assets/js/ClassmateProfile.js\'),
                [\'plugin-media-upload-filter\', \'wp-editor\', \'wp-block-editor\'],
                PLUGIN_VERSION,
                true
            );
            wp_localize_script(
                \'plugin-classmate-profile\',
                \'ClassmateProfileData\',
                $allPageData
            );
        }
    });
}
// This is from the parent abstract class for the class I am calling it in
public static function enqueueLibraryAssets(): void
{
    wp_enqueue_style(
        \'plugin-application\',
        mix_plugin_uri(\'assets/css/app.css\'),
        [\'wp-edit-blocks\'],
        PLUGIN_VERSION
    );
    wp_enqueue_media(); // MUST HAVE THIS! Loads the files you need...
    wp_enqueue_script(
        \'plugin-library-manifest\',
        mix_plugin_uri(\'assets/js/manifest.js\'),
        [\'lodash\', \'react\', \'react-dom\', \'wp-components\', \'wp-i18n\', \'wp-element\', \'wp-editor\'],
        PLUGIN_VERSION,
        true
    );
    wp_enqueue_script(
        \'plugin-library-vendor\',
        mix_plugin_uri(\'assets/js/vendor.js\'),
        [\'plugin-library-manifest\'],
        PLUGIN_VERSION,
        true
    );
    wp_enqueue_script(
        \'plugin-media-upload-filter\',
        mix_plugin_uri(\'assets/js/MediaUploadFilter.js\'),
        [\'plugin-library-manifest\', \'plugin-library-vendor\'],
        PLUGIN_VERSION,
        true
    );
}

相关推荐

Custom CSS In Uploads Folder

我想知道上传文件夹中是否有自定义CSS文件。我从以前的开发人员那里继承了一个自定义主题,前端的大量样式都是从这个样式表派生出来的,它同样不在主题或插件文件夹中,而是wp-content/uploads 文件夹我正在努力找出它是如何推导出来的,但它确实存在。这是否被视为不良做法,或者是否有这样的用例?我相信之前的开发人员提到了Visual Composer或JS Composer以及编译更少的文件。。。但我对此不确定,他已经失去了联系,我想知道为什么我们要以这种方式使用样式表,因此这个问题是关于最佳实践的,