"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = PostList;
var _components = require("@wordpress/components");
var _coreData = require("@wordpress/core-data");
var _element = require("@wordpress/element");
var _router = require("@wordpress/router");
var _data = require("@wordpress/data");
var _dataviews = require("@wordpress/dataviews");
var _editor = require("@wordpress/editor");
var _i18n = require("@wordpress/i18n");
var _icons = require("@wordpress/icons");
var _compose = require("@wordpress/compose");
var _url = require("@wordpress/url");
var _page = _interopRequireDefault(require("../page"));
var _defaultViews = require("../sidebar-dataviews/default-views");
var _constants = require("../../utils/constants");
var _addNewPost = _interopRequireDefault(require("../add-new-post"));
var _lockUnlock = require("../../lock-unlock");
var _dataviewsActions = require("../dataviews-actions");
var _jsxRuntime = require("react/jsx-runtime");
/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

const {
  usePostActions,
  usePostFields
} = (0, _lockUnlock.unlock)(_editor.privateApis);
const {
  useLocation,
  useHistory
} = (0, _lockUnlock.unlock)(_router.privateApis);
const {
  useEntityRecordsWithPermissions
} = (0, _lockUnlock.unlock)(_coreData.privateApis);
const EMPTY_ARRAY = [];
const getDefaultView = (defaultViews, activeView) => {
  return defaultViews.find(({
    slug
  }) => slug === activeView)?.view;
};
const getCustomView = editedEntityRecord => {
  if (!editedEntityRecord?.content) {
    return undefined;
  }
  const content = JSON.parse(editedEntityRecord.content);
  if (!content) {
    return undefined;
  }
  return {
    ...content,
    ..._defaultViews.defaultLayouts[content.type]
  };
};

/**
 * This function abstracts working with default & custom views by
 * providing a [ state, setState ] tuple based on the URL parameters.
 *
 * Consumers use the provided tuple to work with state
 * and don't have to deal with the specifics of default & custom views.
 *
 * @param {string} postType Post type to retrieve default views for.
 * @return {Array} The [ state, setState ] tuple.
 */
function useView(postType) {
  const {
    path,
    query: {
      activeView = 'all',
      isCustom = 'false',
      layout
    }
  } = useLocation();
  const history = useHistory();
  const defaultViews = (0, _defaultViews.useDefaultViews)({
    postType
  });
  const {
    editEntityRecord
  } = (0, _data.useDispatch)(_coreData.store);
  const editedEntityRecord = (0, _data.useSelect)(select => {
    if (isCustom !== 'true') {
      return undefined;
    }
    const {
      getEditedEntityRecord
    } = select(_coreData.store);
    return getEditedEntityRecord('postType', 'wp_dataviews', Number(activeView));
  }, [activeView, isCustom]);
  const [view, setView] = (0, _element.useState)(() => {
    let initialView;
    if (isCustom === 'true') {
      var _getCustomView;
      initialView = (_getCustomView = getCustomView(editedEntityRecord)) !== null && _getCustomView !== void 0 ? _getCustomView : {
        type: layout !== null && layout !== void 0 ? layout : _constants.LAYOUT_LIST
      };
    } else {
      var _getDefaultView;
      initialView = (_getDefaultView = getDefaultView(defaultViews, activeView)) !== null && _getDefaultView !== void 0 ? _getDefaultView : {
        type: layout !== null && layout !== void 0 ? layout : _constants.LAYOUT_LIST
      };
    }
    const type = layout !== null && layout !== void 0 ? layout : initialView.type;
    return {
      ...initialView,
      type,
      ..._defaultViews.defaultLayouts[type]
    };
  });
  const setViewWithUrlUpdate = (0, _compose.useEvent)(newView => {
    setView(newView);
    if (isCustom === 'true' && editedEntityRecord?.id) {
      editEntityRecord('postType', 'wp_dataviews', editedEntityRecord?.id, {
        content: JSON.stringify(newView)
      });
    }
    const currentUrlLayout = layout !== null && layout !== void 0 ? layout : _constants.LAYOUT_LIST;
    if (newView.type !== currentUrlLayout) {
      history.navigate((0, _url.addQueryArgs)(path, {
        layout: newView.type
      }));
    }
  });

  // When layout URL param changes, update the view type
  // without affecting any other config.
  const onUrlLayoutChange = (0, _compose.useEvent)(() => {
    setView(prevView => {
      const newType = layout !== null && layout !== void 0 ? layout : _constants.LAYOUT_LIST;
      if (newType === prevView.type) {
        return prevView;
      }
      return {
        ...prevView,
        type: newType,
        ..._defaultViews.defaultLayouts[newType]
      };
    });
  });
  (0, _element.useEffect)(() => {
    onUrlLayoutChange();
  }, [onUrlLayoutChange, layout]);

  // When activeView or isCustom URL parameters change, reset the view.
  const onUrlActiveViewChange = (0, _compose.useEvent)(() => {
    let newView;
    if (isCustom === 'true') {
      newView = getCustomView(editedEntityRecord);
    } else {
      newView = getDefaultView(defaultViews, activeView);
    }
    if (newView) {
      const type = layout !== null && layout !== void 0 ? layout : newView.type;
      setView({
        ...newView,
        type,
        ..._defaultViews.defaultLayouts[type]
      });
    }
  });
  (0, _element.useEffect)(() => {
    onUrlActiveViewChange();
  }, [onUrlActiveViewChange, activeView, isCustom, defaultViews, editedEntityRecord]);
  return [view, setViewWithUrlUpdate];
}
const DEFAULT_STATUSES = 'draft,future,pending,private,publish'; // All but 'trash'.

function getItemId(item) {
  return item.id.toString();
}
function getItemLevel(item) {
  return item.level;
}
function PostList({
  postType
}) {
  var _postId$split, _data$map, _usePrevious;
  const [view, setView] = useView(postType);
  const defaultViews = (0, _defaultViews.useDefaultViews)({
    postType
  });
  const history = useHistory();
  const location = useLocation();
  const {
    postId,
    quickEdit = false,
    isCustom,
    activeView = 'all'
  } = location.query;
  const [selection, setSelection] = (0, _element.useState)((_postId$split = postId?.split(',')) !== null && _postId$split !== void 0 ? _postId$split : []);
  const onChangeSelection = (0, _element.useCallback)(items => {
    var _location$query$isCus;
    setSelection(items);
    if (((_location$query$isCus = location.query.isCustom) !== null && _location$query$isCus !== void 0 ? _location$query$isCus : 'false') === 'false') {
      history.navigate((0, _url.addQueryArgs)(location.path, {
        postId: items.join(',')
      }));
    }
  }, [location.path, location.query.isCustom, history]);
  const getActiveViewFilters = (views, match) => {
    var _found$filters;
    const found = views.find(({
      slug
    }) => slug === match);
    return (_found$filters = found?.filters) !== null && _found$filters !== void 0 ? _found$filters : [];
  };
  const {
    isLoading: isLoadingFields,
    fields: _fields
  } = usePostFields({
    postType
  });
  const fields = (0, _element.useMemo)(() => {
    const activeViewFilters = getActiveViewFilters(defaultViews, activeView).map(({
      field
    }) => field);
    return _fields.map(field => ({
      ...field,
      elements: activeViewFilters.includes(field.id) ? [] : field.elements
    }));
  }, [_fields, defaultViews, activeView]);
  const queryArgs = (0, _element.useMemo)(() => {
    const filters = {};
    view.filters?.forEach(filter => {
      if (filter.field === 'status' && filter.operator === _constants.OPERATOR_IS_ANY) {
        filters.status = filter.value;
      }
      if (filter.field === 'author' && filter.operator === _constants.OPERATOR_IS_ANY) {
        filters.author = filter.value;
      } else if (filter.field === 'author' && filter.operator === _constants.OPERATOR_IS_NONE) {
        filters.author_exclude = filter.value;
      }
    });

    // The bundled views want data filtered without displaying the filter.
    const activeViewFilters = getActiveViewFilters(defaultViews, activeView);
    activeViewFilters.forEach(filter => {
      if (filter.field === 'status' && filter.operator === _constants.OPERATOR_IS_ANY) {
        filters.status = filter.value;
      }
      if (filter.field === 'author' && filter.operator === _constants.OPERATOR_IS_ANY) {
        filters.author = filter.value;
      } else if (filter.field === 'author' && filter.operator === _constants.OPERATOR_IS_NONE) {
        filters.author_exclude = filter.value;
      }
    });

    // We want to provide a different default item for the status filter
    // than the REST API provides.
    if (!filters.status || filters.status === '') {
      filters.status = DEFAULT_STATUSES;
    }
    return {
      per_page: view.perPage,
      page: view.page,
      _embed: 'author',
      order: view.sort?.direction,
      orderby: view.sort?.field,
      orderby_hierarchy: !!view.showLevels,
      search: view.search,
      ...filters
    };
  }, [view, activeView, defaultViews]);
  const {
    records,
    isResolving: isLoadingData,
    totalItems,
    totalPages
  } = useEntityRecordsWithPermissions('postType', postType, queryArgs);

  // The REST API sort the authors by ID, but we want to sort them by name.
  const data = (0, _element.useMemo)(() => {
    if (!isLoadingFields && view?.sort?.field === 'author') {
      return (0, _dataviews.filterSortAndPaginate)(records, {
        sort: {
          ...view.sort
        }
      }, fields).data;
    }
    return records;
  }, [records, fields, isLoadingFields, view?.sort]);
  const ids = (_data$map = data?.map(record => getItemId(record))) !== null && _data$map !== void 0 ? _data$map : [];
  const prevIds = (_usePrevious = (0, _compose.usePrevious)(ids)) !== null && _usePrevious !== void 0 ? _usePrevious : [];
  const deletedIds = prevIds.filter(id => !ids.includes(id));
  const postIdWasDeleted = deletedIds.includes(postId);
  (0, _element.useEffect)(() => {
    if (postIdWasDeleted) {
      history.navigate((0, _url.addQueryArgs)(location.path, {
        postId: undefined
      }));
    }
  }, [history, postIdWasDeleted, location.path]);
  const paginationInfo = (0, _element.useMemo)(() => ({
    totalItems,
    totalPages
  }), [totalItems, totalPages]);
  const {
    labels,
    canCreateRecord
  } = (0, _data.useSelect)(select => {
    const {
      getPostType,
      canUser
    } = select(_coreData.store);
    return {
      labels: getPostType(postType)?.labels,
      canCreateRecord: canUser('create', {
        kind: 'postType',
        name: postType
      })
    };
  }, [postType]);
  const postTypeActions = usePostActions({
    postType,
    context: 'list'
  });
  const editAction = (0, _dataviewsActions.useEditPostAction)();
  const actions = (0, _element.useMemo)(() => [editAction, ...postTypeActions], [postTypeActions, editAction]);
  const [showAddPostModal, setShowAddPostModal] = (0, _element.useState)(false);
  const openModal = () => setShowAddPostModal(true);
  const closeModal = () => setShowAddPostModal(false);
  const handleNewPage = ({
    type,
    id
  }) => {
    history.navigate(`/${type}/${id}?canvas=edit`);
    closeModal();
  };
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_page.default, {
    title: labels?.name,
    actions: labels?.add_new_item && canCreateRecord && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
        variant: "primary",
        onClick: openModal,
        __next40pxDefaultSize: true,
        children: labels.add_new_item
      }), showAddPostModal && /*#__PURE__*/(0, _jsxRuntime.jsx)(_addNewPost.default, {
        postType: postType,
        onSave: handleNewPage,
        onClose: closeModal
      })]
    }),
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataviews.DataViews, {
      paginationInfo: paginationInfo,
      fields: fields,
      actions: actions,
      data: data || EMPTY_ARRAY,
      isLoading: isLoadingData || isLoadingFields,
      view: view,
      onChangeView: setView,
      selection: selection,
      onChangeSelection: onChangeSelection,
      isItemClickable: item => item.status !== 'trash',
      onClickItem: ({
        id
      }) => {
        history.navigate(`/${postType}/${id}?canvas=edit`);
      },
      getItemId: getItemId,
      getItemLevel: getItemLevel,
      defaultLayouts: _defaultViews.defaultLayouts,
      header: window.__experimentalQuickEditDataViews && view.type !== _constants.LAYOUT_LIST && postType === 'page' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
        size: "compact",
        isPressed: quickEdit,
        icon: _icons.drawerRight,
        label: (0, _i18n.__)('Details'),
        onClick: () => {
          history.navigate((0, _url.addQueryArgs)(location.path, {
            quickEdit: quickEdit ? undefined : true
          }));
        }
      })
    }, activeView + isCustom)
  });
}
//# sourceMappingURL=index.js.map