mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-03 19:36:20 +00:00 
			
		
		
		
	Merge pull request #5610 from strapi/features/media-lib-fix-bugs
ML fix front-end bugs
This commit is contained in:
		
						commit
						6cdf0a7891
					
				@ -1,4 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "kind": "collectionType",
 | 
			
		||||
  "connection": "default",
 | 
			
		||||
  "collectionName": "addresses",
 | 
			
		||||
  "info": {
 | 
			
		||||
@ -7,14 +8,13 @@
 | 
			
		||||
  },
 | 
			
		||||
  "options": {
 | 
			
		||||
    "increments": true,
 | 
			
		||||
    "timestamps": ["created_at", "updated_at"],
 | 
			
		||||
    "timestamps": [
 | 
			
		||||
      "created_at",
 | 
			
		||||
      "updated_at"
 | 
			
		||||
    ],
 | 
			
		||||
    "comment": ""
 | 
			
		||||
  },
 | 
			
		||||
  "attributes": {
 | 
			
		||||
    "geolocation": {
 | 
			
		||||
      "type": "json",
 | 
			
		||||
      "required": true
 | 
			
		||||
    },
 | 
			
		||||
    "city": {
 | 
			
		||||
      "type": "string",
 | 
			
		||||
      "required": true
 | 
			
		||||
@ -30,16 +30,22 @@
 | 
			
		||||
    "cover": {
 | 
			
		||||
      "model": "file",
 | 
			
		||||
      "via": "related",
 | 
			
		||||
      "allowedTypes": [
 | 
			
		||||
        "files",
 | 
			
		||||
        "images",
 | 
			
		||||
        "videos"
 | 
			
		||||
      ],
 | 
			
		||||
      "plugin": "upload",
 | 
			
		||||
      "required": false,
 | 
			
		||||
      "allowedTypes": ["images", "cover"]
 | 
			
		||||
      "required": false
 | 
			
		||||
    },
 | 
			
		||||
    "images": {
 | 
			
		||||
      "collection": "file",
 | 
			
		||||
      "via": "related",
 | 
			
		||||
      "allowedTypes": [
 | 
			
		||||
        "images"
 | 
			
		||||
      ],
 | 
			
		||||
      "plugin": "upload",
 | 
			
		||||
      "required": false,
 | 
			
		||||
      "allowedTypes": []
 | 
			
		||||
      "required": false
 | 
			
		||||
    },
 | 
			
		||||
    "full_name": {
 | 
			
		||||
      "type": "string",
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "kind": "collectionType",
 | 
			
		||||
  "connection": "default",
 | 
			
		||||
  "collectionName": "categories",
 | 
			
		||||
  "info": {
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
module.exports = {
 | 
			
		||||
  // provider: 'aws-s3',
 | 
			
		||||
  // provider: 'cloudinary',
 | 
			
		||||
  // providerOptions: {
 | 
			
		||||
  //   cloud_name: '',
 | 
			
		||||
  //   api_key: '',
 | 
			
		||||
  //   api_secret: '',
 | 
			
		||||
  //   cloud_name: 'cloud-name',
 | 
			
		||||
  //   api_key: 'api-key',
 | 
			
		||||
  //   api_secret: 'api-secret',
 | 
			
		||||
  // },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,7 @@
 | 
			
		||||
    "strapi-plugin-users-permissions": "3.0.0-beta.19.3",
 | 
			
		||||
    "strapi-provider-email-mailgun": "3.0.0-beta.19.3",
 | 
			
		||||
    "strapi-provider-upload-aws-s3": "3.0.0-beta.19.3",
 | 
			
		||||
    "strapi-provider-upload-cloudinary": "3.0.0-beta.19.3",
 | 
			
		||||
    "strapi-utils": "3.0.0-beta.19.3"
 | 
			
		||||
  },
 | 
			
		||||
  "strapi": {
 | 
			
		||||
 | 
			
		||||
@ -273,5 +273,6 @@
 | 
			
		||||
  "notification.contentType.relations.conflict": "Content type has conflicting relations",
 | 
			
		||||
  "notification.form.error.fields": "The form contains some errors",
 | 
			
		||||
  "notification.form.success.fields": "Changes saved",
 | 
			
		||||
  "notification.success.delete": "The item has been deleted",
 | 
			
		||||
  "global.prompt.unsaved": "Are you sure you want to leave this page? All your modifications will be lost"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,14 @@ const Overlay = styled.div`
 | 
			
		||||
    right: 0;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    background: linear-gradient(rgba(0, 0, 0, 15) 0%, rgba(0, 0, 0, 0) 100%);
 | 
			
		||||
    ${({ noGradient }) => {
 | 
			
		||||
      if (noGradient) {
 | 
			
		||||
        return '';
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return `background: linear-gradient(rgba(0, 0, 0, 15) 0%, rgba(0, 0, 0, 0) 100%)`;
 | 
			
		||||
    }};
 | 
			
		||||
 | 
			
		||||
    opacity: 0.5;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -25,7 +32,13 @@ const Overlay = styled.div`
 | 
			
		||||
    right: 0;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    left: 24rem;
 | 
			
		||||
    background: linear-gradient(#fbfbfb 20%, rgba(0, 0, 100, 0) 100%);
 | 
			
		||||
    ${({ noGradient }) => {
 | 
			
		||||
      if (noGradient) {
 | 
			
		||||
        return '';
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return `background: linear-gradient(#fbfbfb 20%, rgba(0, 0, 100, 0) 100%)`;
 | 
			
		||||
    }};
 | 
			
		||||
    box-shadow: inset 0px 2px 4px rgba(0, 0, 0, 0.1);
 | 
			
		||||
    box-shadow: inset 0 1px 2px 0 rgba(40, 42, 49, 0.16);
 | 
			
		||||
  }
 | 
			
		||||
@ -38,4 +51,9 @@ const Overlay = styled.div`
 | 
			
		||||
    z-index: 1100;
 | 
			
		||||
  }
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
Overlay.defaultProps = {
 | 
			
		||||
  noGradient: false,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Overlay;
 | 
			
		||||
 | 
			
		||||
@ -110,7 +110,7 @@ class OverlayBlocker extends React.Component {
 | 
			
		||||
 | 
			
		||||
    if (this.props.isOpen) {
 | 
			
		||||
      return ReactDOM.createPortal(
 | 
			
		||||
        <Overlay>
 | 
			
		||||
        <Overlay noGradient={this.props.noGradient}>
 | 
			
		||||
          <div>{content}</div>
 | 
			
		||||
        </Overlay>,
 | 
			
		||||
        this.overlayContainer
 | 
			
		||||
@ -126,6 +126,7 @@ OverlayBlocker.defaultProps = {
 | 
			
		||||
  description: 'components.OverlayBlocker.description',
 | 
			
		||||
  icon: 'sync-alt',
 | 
			
		||||
  isOpen: false,
 | 
			
		||||
  noGradient: false,
 | 
			
		||||
  title: 'components.OverlayBlocker.title',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -134,6 +135,7 @@ OverlayBlocker.propTypes = {
 | 
			
		||||
  description: PropTypes.string,
 | 
			
		||||
  icon: PropTypes.string,
 | 
			
		||||
  isOpen: PropTypes.bool,
 | 
			
		||||
  noGradient: PropTypes.bool,
 | 
			
		||||
  title: PropTypes.string,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,8 @@ import Text from './Text';
 | 
			
		||||
const MenuList = ({ selectProps: { changeMediaAllowedTypes, value }, ...rest }) => {
 | 
			
		||||
  const { formatMessage } = useGlobalContext();
 | 
			
		||||
  const Component = components.MenuList;
 | 
			
		||||
  const areAllAllowedTypesSelected = value.value.length === 3;
 | 
			
		||||
  const someChecked = !areAllAllowedTypesSelected && value.value.length > 0;
 | 
			
		||||
  const areAllAllowedTypesSelected = value.value && value.value.length === 3;
 | 
			
		||||
  const someChecked = value.value && !areAllAllowedTypesSelected && value.value.length > 0;
 | 
			
		||||
  const options = [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'images',
 | 
			
		||||
@ -58,7 +58,7 @@ const MenuList = ({ selectProps: { changeMediaAllowedTypes, value }, ...rest })
 | 
			
		||||
          </div>
 | 
			
		||||
          <SubUl tad="ul" isOpen>
 | 
			
		||||
            {options.map(({ name, infos }) => {
 | 
			
		||||
              const isChecked = value.value.includes(name);
 | 
			
		||||
              const isChecked = value.value && value.value.includes(name);
 | 
			
		||||
              const target = { name, value: !isChecked };
 | 
			
		||||
 | 
			
		||||
              return (
 | 
			
		||||
 | 
			
		||||
@ -15,8 +15,9 @@ const AllowedTypesSelect = ({ name, changeMediaAllowedTypes, styles, value }) =>
 | 
			
		||||
  const ref = useRef();
 | 
			
		||||
 | 
			
		||||
  /* eslint-disable indent */
 | 
			
		||||
 | 
			
		||||
  const displayedValue =
 | 
			
		||||
    value.length === 0
 | 
			
		||||
    value === null || value.length === 0
 | 
			
		||||
      ? formatMessage({ id: getTrad('form.attribute.media.allowed-types.none') })
 | 
			
		||||
      : value
 | 
			
		||||
          .sort()
 | 
			
		||||
@ -35,16 +36,20 @@ const AllowedTypesSelect = ({ name, changeMediaAllowedTypes, styles, value }) =>
 | 
			
		||||
      ref={ref}
 | 
			
		||||
      refState={ref}
 | 
			
		||||
      styles={styles}
 | 
			
		||||
      value={{ label: displayedValue, value }}
 | 
			
		||||
      value={{ label: displayedValue, value: value || '' }}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
AllowedTypesSelect.defaultProps = {
 | 
			
		||||
  value: null,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
AllowedTypesSelect.propTypes = {
 | 
			
		||||
  changeMediaAllowedTypes: PropTypes.func.isRequired,
 | 
			
		||||
  name: PropTypes.string.isRequired,
 | 
			
		||||
  styles: PropTypes.object.isRequired,
 | 
			
		||||
  value: PropTypes.array.isRequired,
 | 
			
		||||
  value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default AllowedTypesSelect;
 | 
			
		||||
 | 
			
		||||
@ -419,8 +419,8 @@ const DataManagerProvider = ({ allIcons, children }) => {
 | 
			
		||||
      if (!isInContentTypeView) {
 | 
			
		||||
        emitEvent('didNotSaveComponent');
 | 
			
		||||
      }
 | 
			
		||||
      console.error({ err });
 | 
			
		||||
      strapi.notification.error(err.response.payload.error || 'notification.error');
 | 
			
		||||
      console.error({ err: err.response });
 | 
			
		||||
      strapi.notification.error('notification.error');
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -53,6 +53,7 @@ const FormModal = () => {
 | 
			
		||||
  const { emitEvent, formatMessage } = useGlobalContext();
 | 
			
		||||
  const query = useQuery();
 | 
			
		||||
  const attributeOptionRef = useRef();
 | 
			
		||||
 | 
			
		||||
  const {
 | 
			
		||||
    addAttribute,
 | 
			
		||||
    addCreatedComponentToDynamicZone,
 | 
			
		||||
@ -1197,6 +1198,8 @@ const FormModal = () => {
 | 
			
		||||
                            value = retrievedValue.join('\n');
 | 
			
		||||
                          } else if (input.name === 'uid') {
 | 
			
		||||
                            value = input.value;
 | 
			
		||||
                          } else if (input.name === 'allowedTypes' && retrievedValue === '') {
 | 
			
		||||
                            value = null;
 | 
			
		||||
                          } else {
 | 
			
		||||
                            value = retrievedValue;
 | 
			
		||||
                          }
 | 
			
		||||
 | 
			
		||||
@ -103,13 +103,21 @@ const reducer = (state, action) => {
 | 
			
		||||
            return fromJS(['images', 'videos', 'files']);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          return fromJS([]);
 | 
			
		||||
          return null;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return state.updateIn(['modifiedData', 'allowedTypes'], list => {
 | 
			
		||||
      return state.updateIn(['modifiedData', 'allowedTypes'], currentList => {
 | 
			
		||||
        let list = currentList || fromJS([]);
 | 
			
		||||
 | 
			
		||||
        if (list.includes(action.name)) {
 | 
			
		||||
          return list.filter(v => v !== action.name);
 | 
			
		||||
          list = list.filter(v => v !== action.name);
 | 
			
		||||
 | 
			
		||||
          if (list.size === 0) {
 | 
			
		||||
            return null;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          return list;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return list.push(action.name);
 | 
			
		||||
 | 
			
		||||
@ -248,7 +248,7 @@ describe('CTB | containers | FormModal | reducer | actions', () => {
 | 
			
		||||
        value: false,
 | 
			
		||||
        type: 'ON_CHANGE_ALLOWED_TYPE',
 | 
			
		||||
      };
 | 
			
		||||
      const expected = state.setIn(['modifiedData', 'allowedTypes'], fromJS([]));
 | 
			
		||||
      const expected = state.setIn(['modifiedData', 'allowedTypes'], null);
 | 
			
		||||
 | 
			
		||||
      expect(reducer(state, action)).toEqual(expected);
 | 
			
		||||
    });
 | 
			
		||||
@ -271,7 +271,7 @@ describe('CTB | containers | FormModal | reducer | actions', () => {
 | 
			
		||||
      expect(reducer(state, action)).toEqual(expected);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Shoul remove the type', () => {
 | 
			
		||||
    it('Should remove the type', () => {
 | 
			
		||||
      const state = initialState.setIn(
 | 
			
		||||
        ['modifiedData', 'allowedTypes'],
 | 
			
		||||
        fromJS(['videos', 'images', 'files'])
 | 
			
		||||
@ -285,6 +285,18 @@ describe('CTB | containers | FormModal | reducer | actions', () => {
 | 
			
		||||
 | 
			
		||||
      expect(reducer(state, action)).toEqual(expected);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Should remove set the allowedTypes to null if removing the last type', () => {
 | 
			
		||||
      const state = initialState.setIn(['modifiedData', 'allowedTypes'], fromJS(['videos']));
 | 
			
		||||
      const action = {
 | 
			
		||||
        name: 'videos',
 | 
			
		||||
        value: null,
 | 
			
		||||
        type: 'ON_CHANGE_ALLOWED_TYPE',
 | 
			
		||||
      };
 | 
			
		||||
      const expected = state.setIn(['modifiedData', 'allowedTypes'], null);
 | 
			
		||||
 | 
			
		||||
      expect(reducer(state, action)).toEqual(expected);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('RESET_PROPS', () => {
 | 
			
		||||
 | 
			
		||||
@ -16,12 +16,7 @@ import { Inputs } from '@buffetjs/custom';
 | 
			
		||||
import { useGlobalContext } from 'strapi-helper-plugin';
 | 
			
		||||
import Cropper from 'cropperjs';
 | 
			
		||||
import 'cropperjs/dist/cropper.css';
 | 
			
		||||
import {
 | 
			
		||||
  canDownloadFile,
 | 
			
		||||
  createFileToDownloadName,
 | 
			
		||||
  getTrad,
 | 
			
		||||
  prefixFileUrlWithBackendUrl,
 | 
			
		||||
} from '../../utils';
 | 
			
		||||
import { createFileToDownloadName, getTrad, prefixFileUrlWithBackendUrl } from '../../utils';
 | 
			
		||||
import CardControl from '../CardControl';
 | 
			
		||||
import CardControlsWrapper from '../CardControlsWrapper';
 | 
			
		||||
import CardPreview from '../CardPreview';
 | 
			
		||||
@ -60,9 +55,9 @@ const EditForm = forwardRef(
 | 
			
		||||
    const [src, setSrc] = useState(null);
 | 
			
		||||
 | 
			
		||||
    const fileURL = get(fileToEdit, ['file', 'url'], null);
 | 
			
		||||
    const isFileDownloadable = canDownloadFile(fileURL);
 | 
			
		||||
 | 
			
		||||
    const prefixedFileURL = fileURL ? prefixFileUrlWithBackendUrl(fileURL) : null;
 | 
			
		||||
    const downloadFileName = isFileDownloadable ? createFileToDownloadName(fileToEdit) : null;
 | 
			
		||||
    const downloadFileName = createFileToDownloadName(fileToEdit);
 | 
			
		||||
    const mimeType =
 | 
			
		||||
      get(fileToEdit, ['file', 'type'], null) || get(fileToEdit, ['file', 'mime'], '');
 | 
			
		||||
    const isImg = isImageType(mimeType);
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import { Checkbox } from '@buffetjs/core';
 | 
			
		||||
import { get } from 'lodash';
 | 
			
		||||
import { createMatrix } from '../../utils';
 | 
			
		||||
import Card from '../Card';
 | 
			
		||||
import CardControlsWrapper from '../CardControlsWrapper';
 | 
			
		||||
@ -19,7 +20,8 @@ const List = ({ data, onChange, onClickEditFile, selectedItems, canSelect }) =>
 | 
			
		||||
        return (
 | 
			
		||||
          <div className="row" key={key}>
 | 
			
		||||
            {rowContent.map(item => {
 | 
			
		||||
              const { id, url } = item;
 | 
			
		||||
              const { id } = item;
 | 
			
		||||
              const url = get(item, ['formats', 'thumbnail', 'url'], '');
 | 
			
		||||
 | 
			
		||||
              const checked = selectedItems.findIndex(file => file.id === id) !== -1;
 | 
			
		||||
              const fileUrl = url.startsWith('/') ? `${strapi.backendURL}${url}` : url;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import { Checkbox } from '@buffetjs/core';
 | 
			
		||||
import { get } from 'lodash';
 | 
			
		||||
import DraggableCard from './DraggableCard';
 | 
			
		||||
import CardControlsWrapper from '../CardControlsWrapper';
 | 
			
		||||
import ListWrapper from '../ListWrapper';
 | 
			
		||||
@ -14,7 +15,8 @@ const SortableList = ({ data, moveAsset, onChange, onClickEditFile, selectedItem
 | 
			
		||||
    <ListWrapper>
 | 
			
		||||
      <div className="row">
 | 
			
		||||
        {data.map((item, index) => {
 | 
			
		||||
          const { id, url } = item;
 | 
			
		||||
          const { id } = item;
 | 
			
		||||
          const url = get(item, ['formats', 'thumbnail', 'url'], '');
 | 
			
		||||
          const checked = selectedItems.findIndex(file => file.id === id) !== -1;
 | 
			
		||||
          const fileUrl = url.startsWith('/') ? `${strapi.backendURL}${url}` : url;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -71,6 +71,7 @@ const HomePage = () => {
 | 
			
		||||
      await request(requestURL, {
 | 
			
		||||
        method: 'DELETE',
 | 
			
		||||
      });
 | 
			
		||||
      strapi.notification.success('notification.success.delete');
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      if (isMounted) {
 | 
			
		||||
        strapi.notification.error('notification.error');
 | 
			
		||||
@ -79,6 +80,8 @@ const HomePage = () => {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const fetchListData = async () => {
 | 
			
		||||
    dispatch({ type: 'GET_DATA' });
 | 
			
		||||
 | 
			
		||||
    const [data, count] = await Promise.all([fetchData(), fetchDataCount()]);
 | 
			
		||||
 | 
			
		||||
    if (isMounted) {
 | 
			
		||||
@ -101,7 +104,10 @@ const HomePage = () => {
 | 
			
		||||
 | 
			
		||||
      return Promise.resolve(data);
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      strapi.notification.error('notification.error');
 | 
			
		||||
      if (isMounted) {
 | 
			
		||||
        dispatch({ type: 'GET_DATA_ERROR' });
 | 
			
		||||
        strapi.notification.error('notification.error');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return [];
 | 
			
		||||
@ -118,6 +124,7 @@ const HomePage = () => {
 | 
			
		||||
      return Promise.resolve(count);
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      if (isMounted) {
 | 
			
		||||
        dispatch({ type: 'GET_DATA_ERROR' });
 | 
			
		||||
        strapi.notification.error('notification.error');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@ -204,6 +211,28 @@ const HomePage = () => {
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleDeleteMediaFromModal = async id => {
 | 
			
		||||
    handleClickToggleModal();
 | 
			
		||||
    const overlayblockerParams = {
 | 
			
		||||
      children: <div />,
 | 
			
		||||
      noGradient: true,
 | 
			
		||||
    };
 | 
			
		||||
    strapi.lockApp(overlayblockerParams);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      await deleteMedia(id);
 | 
			
		||||
 | 
			
		||||
      dispatch({
 | 
			
		||||
        type: 'ON_DELETE_MEDIA_SUCCEEDED',
 | 
			
		||||
        mediaId: id,
 | 
			
		||||
      });
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      // Silent
 | 
			
		||||
    } finally {
 | 
			
		||||
      strapi.unlockApp();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleDeleteMedias = async () => {
 | 
			
		||||
    await Promise.all(dataToDelete.map(item => deleteMedia(item.id)));
 | 
			
		||||
 | 
			
		||||
@ -333,7 +362,9 @@ const HomePage = () => {
 | 
			
		||||
        initialStep={modalInitialStep}
 | 
			
		||||
        isOpen={isModalOpen}
 | 
			
		||||
        onClosed={handleModalClose}
 | 
			
		||||
        onDeleteMedia={handleDeleteMediaFromModal}
 | 
			
		||||
        onToggle={handleClickToggleModal}
 | 
			
		||||
        refetchData={fetchListData}
 | 
			
		||||
      />
 | 
			
		||||
      <PopUpWarning
 | 
			
		||||
        isOpen={isPopupOpen}
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,10 @@ const reducer = (state, action) => {
 | 
			
		||||
  switch (action.type) {
 | 
			
		||||
    case 'CLEAR_DATA_TO_DELETE':
 | 
			
		||||
      return state.update('dataToDelete', () => fromJS([]));
 | 
			
		||||
    case 'GET_DATA':
 | 
			
		||||
      return state.update('isLoading', () => true);
 | 
			
		||||
    case 'GET_DATA_ERROR':
 | 
			
		||||
      return state.update('isLoading', () => false);
 | 
			
		||||
    case 'GET_DATA_SUCCEEDED':
 | 
			
		||||
      return state
 | 
			
		||||
        .update('data', () => fromJS(action.data))
 | 
			
		||||
@ -48,6 +52,10 @@ const reducer = (state, action) => {
 | 
			
		||||
        return dataToDelete.concat(newItems);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    case 'ON_DELETE_MEDIA_SUCCEEDED':
 | 
			
		||||
      return state
 | 
			
		||||
        .update('data', list => list.filter(item => item.get('id') !== action.mediaId))
 | 
			
		||||
        .update('dataCount', count => count - 1);
 | 
			
		||||
    default:
 | 
			
		||||
      return state;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,44 @@ import { fromJS } from 'immutable';
 | 
			
		||||
import reducer, { initialState } from '../reducer';
 | 
			
		||||
 | 
			
		||||
describe('Upload | containers | HomePage | reducer', () => {
 | 
			
		||||
  describe('GET_DATA', () => {
 | 
			
		||||
    it('should set isLoading to true', () => {
 | 
			
		||||
      const state = fromJS({
 | 
			
		||||
        isLoading: false,
 | 
			
		||||
        test: true,
 | 
			
		||||
      });
 | 
			
		||||
      const action = {
 | 
			
		||||
        type: 'GET_DATA',
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const expected = fromJS({
 | 
			
		||||
        isLoading: true,
 | 
			
		||||
        test: true,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(reducer(state, action)).toEqual(expected);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('GET_DATA_ERROR', () => {
 | 
			
		||||
    it('should set isLoading to false', () => {
 | 
			
		||||
      const state = fromJS({
 | 
			
		||||
        isLoading: true,
 | 
			
		||||
        test: true,
 | 
			
		||||
      });
 | 
			
		||||
      const action = {
 | 
			
		||||
        type: 'GET_DATA_ERROR',
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const expected = fromJS({
 | 
			
		||||
        isLoading: false,
 | 
			
		||||
        test: true,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(reducer(state, action)).toEqual(expected);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should update data with received data', () => {
 | 
			
		||||
    const state = initialState;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,20 @@ import { get } from 'lodash';
 | 
			
		||||
import { Modal, ModalFooter, PopUpWarning, useGlobalContext, request } from 'strapi-helper-plugin';
 | 
			
		||||
import { Button } from '@buffetjs/core';
 | 
			
		||||
import pluginId from '../../pluginId';
 | 
			
		||||
import { getRequestUrl, getTrad } from '../../utils';
 | 
			
		||||
import { getTrad } from '../../utils';
 | 
			
		||||
import ModalHeader from '../../components/ModalHeader';
 | 
			
		||||
import stepper from './stepper';
 | 
			
		||||
import init from './init';
 | 
			
		||||
import reducer, { initialState } from './reducer';
 | 
			
		||||
 | 
			
		||||
const ModalStepper = ({ initialFileToEdit, initialStep, isOpen, onClosed, onToggle }) => {
 | 
			
		||||
const ModalStepper = ({
 | 
			
		||||
  initialFileToEdit,
 | 
			
		||||
  initialStep,
 | 
			
		||||
  isOpen,
 | 
			
		||||
  onClosed,
 | 
			
		||||
  onDeleteMedia,
 | 
			
		||||
  onToggle,
 | 
			
		||||
}) => {
 | 
			
		||||
  const { formatMessage } = useGlobalContext();
 | 
			
		||||
  const [isWarningDeleteOpen, setIsWarningDeleteOpen] = useState(false);
 | 
			
		||||
  const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
 | 
			
		||||
@ -66,15 +73,15 @@ const ModalStepper = ({ initialFileToEdit, initialStep, isOpen, onClosed, onTogg
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleCancelFileToUpload = fileIndex => {
 | 
			
		||||
    const fileToCancel = get(filesToUpload, fileIndex, {});
 | 
			
		||||
  const handleCancelFileToUpload = fileOriginalIndex => {
 | 
			
		||||
    const fileToCancel = filesToUpload.find(file => file.originalIndex === fileOriginalIndex);
 | 
			
		||||
 | 
			
		||||
    // Cancel upload
 | 
			
		||||
    fileToCancel.abortController.abort();
 | 
			
		||||
 | 
			
		||||
    dispatch({
 | 
			
		||||
      type: 'REMOVE_FILE_TO_UPLOAD',
 | 
			
		||||
      fileIndex,
 | 
			
		||||
      fileIndex: fileOriginalIndex,
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -123,16 +130,7 @@ const ModalStepper = ({ initialFileToEdit, initialStep, isOpen, onClosed, onTogg
 | 
			
		||||
    if (shouldDeleteFile) {
 | 
			
		||||
      const { id } = fileToEdit;
 | 
			
		||||
 | 
			
		||||
      try {
 | 
			
		||||
        const requestURL = getRequestUrl(`files/${id}`);
 | 
			
		||||
 | 
			
		||||
        await request(requestURL, { method: 'DELETE' });
 | 
			
		||||
 | 
			
		||||
        setShouldDeleteFile(false);
 | 
			
		||||
        toggleRef.current(true);
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        console.log(err);
 | 
			
		||||
      }
 | 
			
		||||
      onDeleteMedia(id);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -268,11 +266,13 @@ const ModalStepper = ({ initialFileToEdit, initialStep, isOpen, onClosed, onTogg
 | 
			
		||||
            null
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
          dispatch({
 | 
			
		||||
            type: 'SET_FILE_ERROR',
 | 
			
		||||
            fileIndex: originalIndex,
 | 
			
		||||
            errorMessage,
 | 
			
		||||
          });
 | 
			
		||||
          if (errorMessage) {
 | 
			
		||||
            dispatch({
 | 
			
		||||
              type: 'SET_FILE_ERROR',
 | 
			
		||||
              fileIndex: originalIndex,
 | 
			
		||||
              errorMessage,
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
@ -330,12 +330,12 @@ const ModalStepper = ({ initialFileToEdit, initialStep, isOpen, onClosed, onTogg
 | 
			
		||||
            onChange={handleChange}
 | 
			
		||||
            onClickCancelUpload={handleCancelFileToUpload}
 | 
			
		||||
            onClickDeleteFileToUpload={
 | 
			
		||||
              currentStep === 'edit-new' ? handleClickDeleteFileToUpload : handleClickDeleteFile
 | 
			
		||||
              currentStep === 'edit' ? handleClickDeleteFile : handleClickDeleteFileToUpload
 | 
			
		||||
            }
 | 
			
		||||
            onClickEditNewFile={handleGoToEditNewFile}
 | 
			
		||||
            onGoToAddBrowseFiles={handleGoToAddBrowseFiles}
 | 
			
		||||
            onSubmitEdit={
 | 
			
		||||
              currentStep === 'edit-new' ? handleSubmitEditNewFile : handleSubmitEditExistingFile
 | 
			
		||||
              currentStep === 'edit' ? handleSubmitEditExistingFile : handleSubmitEditNewFile
 | 
			
		||||
            }
 | 
			
		||||
            onToggle={handleToggle}
 | 
			
		||||
            toggleDisableForm={setIsFormDisabled}
 | 
			
		||||
@ -408,6 +408,7 @@ ModalStepper.defaultProps = {
 | 
			
		||||
  initialFileToEdit: null,
 | 
			
		||||
  initialStep: 'browse',
 | 
			
		||||
  onClosed: () => {},
 | 
			
		||||
  onDeleteMedia: () => {},
 | 
			
		||||
  onToggle: () => {},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -416,6 +417,7 @@ ModalStepper.propTypes = {
 | 
			
		||||
  initialStep: PropTypes.string,
 | 
			
		||||
  isOpen: PropTypes.bool.isRequired,
 | 
			
		||||
  onClosed: PropTypes.func,
 | 
			
		||||
  onDeleteMedia: PropTypes.func,
 | 
			
		||||
  onToggle: PropTypes.func,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ const formatFileForEditing = file => {
 | 
			
		||||
    abortController,
 | 
			
		||||
    id: file.id,
 | 
			
		||||
    file: {
 | 
			
		||||
      ...pick(file, ['size', 'ext', 'width', 'height', 'url', 'mime', 'name']),
 | 
			
		||||
      ...pick(file, ['size', 'ext', 'width', 'height', 'mime', 'name', 'url']),
 | 
			
		||||
      created_at: file.created_at || file.createdAt,
 | 
			
		||||
    },
 | 
			
		||||
    fileInfo: pick(file, ['alternativeText', 'caption', 'name']),
 | 
			
		||||
 | 
			
		||||
@ -19,8 +19,18 @@ describe('UPLOAD | utils | formatFileForEditing', () => {
 | 
			
		||||
      updated_at: '2020-03-23T11:43:46.729Z',
 | 
			
		||||
      alternativeText: 'test',
 | 
			
		||||
      id: 12,
 | 
			
		||||
      formats: null,
 | 
			
		||||
      provider_metadata: null,
 | 
			
		||||
      formats: {
 | 
			
		||||
        thumbnail: {
 | 
			
		||||
          hash: 'thumbnail_Screenshot_2020-03-26_at_13.09.24.png_df7f56f901',
 | 
			
		||||
          ext: '.png',
 | 
			
		||||
          mime: 'image/png',
 | 
			
		||||
          width: 245,
 | 
			
		||||
          height: 23,
 | 
			
		||||
          size: 4.09,
 | 
			
		||||
          url: '/uploads/thumbnail_Screenshot_2020-03-26_at_13.09.24.png_df7f56f901.png',
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
    const abortController = new AbortController();
 | 
			
		||||
 | 
			
		||||
@ -68,7 +78,17 @@ describe('UPLOAD | utils | formatFileForEditing', () => {
 | 
			
		||||
      updated_at: '2020-03-23T11:43:46.729Z',
 | 
			
		||||
      alternativeText: 'test',
 | 
			
		||||
      id: 12,
 | 
			
		||||
      formats: null,
 | 
			
		||||
      formats: {
 | 
			
		||||
        thumbnail: {
 | 
			
		||||
          hash: 'thumbnail_Screenshot_2020-03-26_at_13.09.24.png_df7f56f901',
 | 
			
		||||
          ext: '.png',
 | 
			
		||||
          mime: 'image/png',
 | 
			
		||||
          width: 245,
 | 
			
		||||
          height: 23,
 | 
			
		||||
          size: 4.09,
 | 
			
		||||
          url: '/uploads/thumbnail_Screenshot_2020-03-26_at_13.09.24.png_df7f56f901.png',
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      provider_metadata: null,
 | 
			
		||||
    };
 | 
			
		||||
    const abortController = new AbortController();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user