@craftercms/studio-ui
Version:
Services, components, models & utils to build CrafterCMS authoring extensions.
172 lines (170 loc) • 6.4 kB
JavaScript
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { PREVIEW_URL_PATH, UNDEFINED } from '../../utils/constants';
import { useMemo } from 'react';
import useSpreadState from '../../hooks/useSpreadState';
import { changeCurrentUrl } from '../../state/actions/preview';
import { getSystemLink } from '../../utils/system';
import { generateMultipleItemOptions, generateSingleItemOptions } from '../../utils/itemActions';
import { actionsToBeShown } from '../DashletCard/dashletCommons';
import { isImage, isPdfDocument, isPreviewable, isVideo } from '../PathNavigator/utils';
export function parseDashletContentHeight(contentHeight) {
return contentHeight ? parseInt(`${contentHeight}`.replace('px', '')) : UNDEFINED;
}
export function getPersonFullName(person) {
return `${person.firstName} ${person.lastName}`;
}
export function useSpreadStateWithSelected(initialState) {
// @ts-ignore - Unsure how to make the compiler happy. Probably due to the generic ItemType of WithSelectedState.
const [state, setState] = useSpreadState({
items: null,
isAllSelected: false,
hasSelected: false,
selected: {},
selectedCount: 0,
...initialState
});
const { items, selected } = state;
const onSelectAll = (e) => {
if (items.length > 0) {
const nextState = {};
if (e.target.checked) {
// Check all
nextState.hasSelected = true;
nextState.selectedCount = items.length;
nextState.selected = items.reduce((state, item) => {
state[item.id] = true;
return state;
}, {});
nextState.isAllSelected = true;
} else {
// Uncheck all
nextState.selected = {};
nextState.hasSelected = false;
nextState.isAllSelected = false;
nextState.selectedCount = 0;
}
setState(nextState);
}
};
const onSelectItem = (e, item) => {
let isChecked = !isSelected(item);
let nextState = {};
nextState.selected = { ...selected, [item.id]: isChecked };
let checkedOnly = Object.values(nextState.selected).filter(Boolean);
nextState.hasSelected = checkedOnly.length > 0;
nextState.isAllSelected = items.length && checkedOnly.length === items.length;
nextState.selectedCount = isChecked ? state.selectedCount + 1 : state.selectedCount - 1;
setState(nextState);
};
const isSelected = (item) => {
return selected[item.id] ?? false;
};
return [state, setState, onSelectItem, onSelectAll, isSelected];
}
export function isPage(systemType) {
return systemType === 'page';
}
export function previewPage(site, authoringBase, item, dispatch, onWidgetModeAction) {
const previewUrl = item.previewUrl;
const pathname = window.location.pathname;
if (pathname.includes(PREVIEW_URL_PATH)) {
dispatch(changeCurrentUrl(previewUrl));
onWidgetModeAction?.();
} else {
window.location.href = getSystemLink({
page: previewUrl,
systemLinkId: 'preview',
site,
authoringBase
});
}
}
export function useSelectionOptions(items, formatMessage, selectedCount) {
return useMemo(() => {
return selectedCount
? selectedCount === 1
? generateSingleItemOptions(items[0], formatMessage, {
includeOnly: actionsToBeShown
}).flat()
: generateMultipleItemOptions(items, formatMessage, { includeOnly: actionsToBeShown })
: [];
}, [items, formatMessage, selectedCount]);
}
export function getItemViewOption(item) {
const type = item.systemType;
let option;
if (['page', 'component', 'taxonomy', 'levelDescriptor'].includes(type)) {
option = 'view';
} else if (isPreviewable(item)) {
if (isImage(item) || isVideo(item) || isPdfDocument(item.mimeType)) {
option = 'viewMedia';
} else {
option = 'viewCode';
}
}
return option;
}
export function getCurrentPage(offset, limit) {
return Math.ceil(offset / limit);
}
export function getValidatedSelectionState(items, selected, limit) {
let newItemsById = {};
// Verify if the number of pages changed
const lastPageWithItems = items.length ? Math.ceil(items.length / limit) - 1 : 0;
// Update the itemsById lookup.
items.forEach((item) => {
newItemsById[item.id] = item;
});
// Update selected items (remove items that no longer exist in the dashlet
const newSelected = {};
Object.keys(selected).forEach((selectedKey) => {
if (newItemsById[selectedKey]) {
newSelected[selectedKey] = true;
}
});
const newSelectedArray = Object.keys(newSelected);
// Get the items that belong to the current page
const currentPageItems = items.slice(lastPageWithItems * limit, lastPageWithItems * limit + limit);
return {
itemsById: newItemsById,
state: {
items: currentPageItems,
offset: limit * lastPageWithItems,
total: items.total,
loading: false,
selected: newSelected,
hasSelected: Boolean(newSelectedArray.length),
selectedCount: newSelectedArray.length,
isAllSelected: Boolean(newSelectedArray.length) && newSelectedArray.length === items.total
}
};
}