3
votes

I've written a custom field for KeystoneJS's AdminUI which uses TinyMCE's editor.

KeystoneJS runs an Apollo GraphQL Server underneath and auto-generates mutations and queries based on your CMS schema. TinyMCE has the capability to enter custom hooks to upload images.

I'd like to be able to connect the two -- upload images from TinyMCE to KeystoneJS's server using GraphQL mutations.

For instance, in my setup I have an Image field in the CMS. KeystoneJS has a GraphQL mutation that will allow me to upload an image

createImage(data: ImageCreateInput): Image

where imageCreateInputis

type ImageCreateInput {file: Upload}

This tutorial has an explanation of how to upload images from Apollo Client to an Apollo Server (which KeystoneJS is running).

const UPLOAD_MUTATION = gql`
  mutation submit($file: Upload!) {
    submitAFile(file: $file) {
      filename
      mimetype
      filesize
    }
  }
`;

 return (
    <form>
      <Mutation mutation={UPLOAD_MUTATION} update={mutationComplete}>
        {mutation => (
          <input
            type="file"
            onChange={e => {
              const [file] = e.target.files;
              mutation({
                variables: {
                  file
                }
              });
            }}
          />
        )}
      </Mutation>
    </form>
  );

I'm a bit confused as to how to integrate this into TinyMCE, particularly since the example is based on using a form, and TinyMCE sends me the data encoded in -- as far as I can see -- Base64.

TinyMCE provides me the opportunity to specify a custom upload handler :

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  images_upload_handler: function (blobInfo, success, failure) {
    var xhr, formData;

    xhr = new XMLHttpRequest();
    xhr.withCredentials = false;
    xhr.open('POST', 'postAcceptor.php');

    xhr.onload = function() {
      var json;

      if (xhr.status != 200) {
        failure('HTTP Error: ' + xhr.status);
        return;
      }

      json = JSON.parse(xhr.responseText);

      if (!json || typeof json.location != 'string') {
        failure('Invalid JSON: ' + xhr.responseText);
        return;
      }

      success(json.location);
    };

    formData = new FormData();
    formData.append('file', blobInfo.blob(), blobInfo.filename());

    xhr.send(formData);
  }
});

It seems that TinyMCE provides me with a blob, when, as far as I see, Apollo Client expects a file name. Do I just use blobInfo.filename ? Is there a better way to upload TinyMCE images to a GraphQL Apollo Server?

I've never done any image uploading with TinyMCE before.

1

1 Answers

1
votes

I've never used this, too ... but I would try to use file_picker_callback.

In this demo you can see files[0] - I'm pretty sure you can insert here a upload mutation call with file as an argument. Result (url) pass to cb() (as in example).

Also adjust configuration as in this answer