SU-SWS/react_paragraphs

View on GitHub
js/src/Components/Widgets/Media/MediaList.js

Summary

Maintainability
A
0 mins
Test Coverage
import React, {useEffect, useState} from "react";
import {FlexDiv} from "../../Atoms/FlexDiv";
import {XButton} from "../../Atoms/XButton";
import {Loader} from "../../Atoms/Loader";
import {ErrorBoundary} from "../../Atoms/ErrorBoundary";
import {SortableContainer, SortableElement} from "react-sortable-hoc";
import {UrlFix} from "../../../utils/UrlFix";

const {arrayMoveImmutable} = require('array-move');

const SortableItem = SortableElement(({item, delta, onRemove}) => (
  <MediaItem
    mid={item.target_id}
    onRemove={onRemove}
    delta={delta}
  />
));

const SortableList = SortableContainer(({items, onRemoveItem}) => {
  return (
    <FlexDiv style={{flexWrap: 'wrap'}}>
      {items.map((item, delta) => (
        <SortableItem
          key={item.target_uuid}
          index={delta}
          item={item}
          delta={delta}
          onRemove={onRemoveItem}
        />
      ))}
    </FlexDiv>
  );
});

/**
 * List of media items for media widget.
 */
export const MediaList = ({selectedItems, onRemove, updateOrder}) => {

  const onSortEnd = ({oldIndex, newIndex}) => {
    updateOrder(arrayMoveImmutable(selectedItems, oldIndex, newIndex));
  }

  return (
    <SortableList
      axis="xy"
      transitionDuration={250}
      items={selectedItems}
      onSortEnd={onSortEnd}
      onRemoveItem={onRemove}
    />
  )
}

/**
 * Individual media item.
 */
const MediaItem = ({mid, delta, onRemove}) => {
  const [mediaData, setMediaData] = useState(false);

  useEffect(() => {
    if (!mediaData) {
      // Fetch the media data. If the content is not json or the page fails, it
      // will just bail.
      fetch(UrlFix(`/media/${mid}/edit?_format=json`))
        .then(response => response.json())
        .then(jsonData => {
          if (typeof jsonData.message !== 'undefined') {
            console.error(jsonData.message);
          }
          // Always set the media data so that it will remove the loader tag.
          setMediaData(jsonData);
        });
    }
  }, []);

  if (!mediaData) {
    return (
      <div
        className="relative max-w-[200px] mr-2.5 mb-2.5 min-h-[100px] min-w-[100px] z-[999] cursor-move">
        <Loader/>
      </div>
    )
  }

  return (
    <div
      className="relative max-w-[200px] mr-2.5 mb-2.5 min-h-[100px] min-w-[100px] z-[999] cursor-move">
      <XButton
        title="Remove Media Item"
        onClick={() => onRemove(delta)}
        greyIcon
        style={{zIndex: 1000}}
      />
      {/* Wrap the preview image in an error handler. */}
      <ErrorBoundary
        errorMessage={
          <div className="p-5">
            Unable to provide a preview of media.
          </div>
        }
      >
        <PreviewImage mediaData={mediaData}/>
      </ErrorBoundary>
    </div>
  )
}

/**
 * The preview image tag and name.
 */
const PreviewImage = ({mediaData}) => {
  return (
    <>
      <div className="bg-[#ebebeb] px-5">
        <img
          src={mediaData.thumbnail[0].url}
          alt=""
          role="presentation"
          className="h-44 object-contain object-center max-w-full"
        />
      </div>
      <div className="p-1">
        {mediaData.name[0].value}
      </div>
    </>
  )
}