Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core: Resizer): 13601 - increase length of analytical panel #290

Merged
merged 9 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/core/localization/gettext/template/common.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2022-12-08T12:34:57.903Z\n"
"PO-Revision-Date: 2022-12-08T12:34:57.903Z\n"
"POT-Creation-Date: 2022-12-12T16:48:08.625Z\n"
"PO-Revision-Date: 2022-12-12T16:48:08.625Z\n"

#: km
msgid "km"
Expand Down
50 changes: 33 additions & 17 deletions src/core/store/columnContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ export type PanelMeta = {
closeCb: () => void;
minHeight: number;
getOpenState: () => boolean;
panelId?: string;
};

class PanelsRepository {
export class PanelsRepository {
panels = new Set<PanelMeta>();

add(panel: PanelMeta) {
Expand All @@ -38,15 +39,20 @@ class PanelsRepository {
panel.resizableNode.style.height = newHeight + 'px';
}

/* Returns array with [panel, panelHeight] entries */
getPanelsWithExtraSpace() {
return Array.from(this.panels).reduce((acc: [PanelMeta, number][], c) => {
const height = c.resizableNode.getBoundingClientRect().height;
if (height > c.minHeight) {
acc.push([c, height]);
getPanelsWithExtraSpace(): [[PanelMeta, number, number][], number] {
let totalExtraSpace = 0;
const panelsWithSizes: [PanelMeta, number, number][] = [];

this.panels.forEach((panel) => {
const height = panel.resizableNode.getBoundingClientRect().height;
if (height > panel.minHeight) {
const extraSpace = height - panel.minHeight;
panelsWithSizes.push([panel, height, extraSpace]);
totalExtraSpace += extraSpace;
}
return acc;
}, []);
});

return [panelsWithSizes, totalExtraSpace];
}

getPanelsWithOpenState() {
Expand Down Expand Up @@ -104,7 +110,7 @@ export class Resizer {
);
}

/* 1. Adjust size when column size changed (window resize) */
/* 2. Adjust size when column size changed (window resize) */
const containerEl = this.limiter.current;
if (containerEl !== null) {
const containerObserver = new ResizeObserver((containerElements) => {
Expand All @@ -131,16 +137,26 @@ export class Resizer {
}
}

// why not resize first and close only after?
// then we have scenario when we shrinked all the panels and still have to close some
// after closing free space left but the panels are already shrinked
IlyaIzr marked this conversation as resolved.
Show resolved Hide resolved
_adjustPanelsHeight(diff: number) {
// Get all children with height more than minimal
const cardsWithExtraSpace = this.panels.getPanelsWithExtraSpace();
if (cardsWithExtraSpace.length > 0) {
// Reduce cards height
const reduceSize = Math.ceil(diff / cardsWithExtraSpace.length);
cardsWithExtraSpace.forEach(([card, currentHeight]) => {
this.panels.adjustToHeight(card, currentHeight - reduceSize);
const [cardsWithExtraSpace, totalExtraSpace] = this.panels.getPanelsWithExtraSpace();
// If it's possible to free all the space needed by resizing - start resizing
if (totalExtraSpace > diff) {
// store the amount left to reduce
let leftToReduce = diff;

cardsWithExtraSpace.forEach(([card, currentHeight, availableExtraSpace]) => {
// Reduce first card as much as needed
if (leftToReduce) {
const reduceAmount =
availableExtraSpace > leftToReduce ? leftToReduce : availableExtraSpace;
this.panels.adjustToHeight(card, currentHeight - reduceAmount);
leftToReduce = leftToReduce - reduceAmount;
}
});
// In case no children with extra space
} else {
// Close first opened card
const openedPanels = this.panels.getPanelsWithOpenState();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Panel, PanelIcon } from '@konturio/ui-kit';
import { lazy, useCallback, useState } from 'react';
import { lazy, useCallback, useLayoutEffect, useRef, useState } from 'react';
import clsx from 'clsx';
import { Analytics24 } from '@konturio/default-icons';
import { useAtom } from '@reatom/react';
import { i18n } from '~core/localization';
import { panelClasses } from '~components/Panel';
import { IS_MOBILE_QUERY, useMediaQuery } from '~utils/hooks/useMediaQuery';
import { useAutoCollapsePanel } from '~utils/hooks/useAutoCollapsePanel';
import { useHeightResizer } from '~utils/hooks/useResizer';
import { MIN_HEIGHT } from '../../constants';
import { analyticsResourceAtom } from '../../atoms/analyticsResource';
import styles from './AnalyticsPanel.module.css';

const LazyLoadedAnalyticsContainer = lazy(
Expand All @@ -17,7 +19,15 @@ const LazyLoadedAnalyticsContainer = lazy(
export function AnalyticsPanel() {
const [isOpen, setIsOpen] = useState<boolean>(true);
const isMobile = useMediaQuery(IS_MOBILE_QUERY);
const handleRefChange = useHeightResizer(setIsOpen, isOpen, MIN_HEIGHT);
const [analyticsResourceState] = useAtom(analyticsResourceAtom);
const contentRef = useRef<null | HTMLDivElement>(null);
const [contentHeight, setContentHeight] = useState(MIN_HEIGHT);

const handleRefChange = useHeightResizer(setIsOpen, isOpen, contentHeight, 'analytics');

useLayoutEffect(() => {
contentRef.current && setContentHeight(contentRef.current.scrollHeight);
}, [contentRef, analyticsResourceState]);

const togglePanel = useCallback(() => {
setIsOpen((prevState) => !prevState);
Expand Down Expand Up @@ -54,7 +64,7 @@ export function AnalyticsPanel() {
contentClassName={styles.contentWrap}
contentContainerRef={handleRefChange}
>
<div className={styles.panelBody}>
<div className={styles.panelBody} ref={contentRef}>
<LazyLoadedAnalyticsContainer />
</div>
</Panel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useAutoCollapsePanel } from '~utils/hooks/useAutoCollapsePanel';
import { panelClasses } from '~components/Panel';
import { useHeightResizer } from '~utils/hooks/useResizer';
import { useShortPanelState } from '~utils/hooks/useShortPanelState';
import { MIN_HEIGHT, MIN_SHORT_STATE_HEIGHT } from '../../constants';
import { MIN_HEIGHT } from '../../constants';
import { FullState } from '../FullState/FullState';
import { ShortState } from '../ShortState/ShortState';
import s from './EventsPanel.module.css';
Expand All @@ -32,7 +32,8 @@ export function EventsPanel({
const handleRefChange = useHeightResizer(
(isOpen) => !isOpen && setPanelState('closed'),
isOpen,
isShort ? MIN_SHORT_STATE_HEIGHT : MIN_HEIGHT,
MIN_HEIGHT,
'event_list',
);

const openFullState = useCallback(() => {
Expand Down
27 changes: 2 additions & 25 deletions src/features/events_list/components/ShortState/ShortState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,12 @@ import { useAtom } from '@reatom/react';
import { useEffect, useState } from 'react';
import { i18n } from '~core/localization';
import { currentEventResourceAtom } from '~core/shared_state/currentEventResource';
import { eventListResourceAtom } from '~features/events_list/atoms/eventListResource';
import { EpisodeTimelineToggle } from '../EpisodeTimelineToggle/EpisodeTimelineToggle';
import { EventCard } from '../EventCard/EventCard';
import { eventListResourceAtom } from '../../atoms/eventListResource';
import { CurrentEvent } from '../CurrentEvent/CurrentEvent';
import s from './ShortState.module.css';
import type { MouseEventHandler } from 'react';
import type { Event } from '~core/types';

const SingleEventCard = ({
event,
hasTimeline,
}: {
event: Event;
hasTimeline?: boolean;
}) => (
<EventCard
event={event}
isActive={true}
alternativeActionControl={
hasTimeline ? <EpisodeTimelineToggle isActive={true} /> : null
}
externalUrls={event.externalUrls}
/>
);

export function ShortState({
hasTimeline,
openFullState,
Expand All @@ -54,11 +35,7 @@ export function ShortState({
if (!event && currentEvent) setEvent(currentEvent);
}, [currentEvent, event, setEvent]);

const eventInfo = event ? (
<SingleEventCard event={event} hasTimeline={hasTimeline} />
) : (
<CurrentEvent hasTimeline={hasTimeline} />
);
const eventInfo = event ? <CurrentEvent hasTimeline={hasTimeline} /> : null;

const panelContent = eventInfo || (
<div className={s.noDisasters}>
Expand Down
4 changes: 3 additions & 1 deletion src/utils/hooks/useResizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const useHeightResizer = (
setIsOpen: (value: SetStateAction<boolean>) => void,
isOpen: boolean,
minHeight: number,
panelId?: string,
) => {
const columnContext = useColumnContext();
const openStateRef = useRef(isOpen);
Expand Down Expand Up @@ -44,12 +45,13 @@ export const useHeightResizer = (
closeCb: () => setIsOpen(false),
minHeight,
getOpenState: () => openStateRef.current,
panelId,
};
// UseCallback not have cleanup like useEffect, this is workaround
cleanup.current = columnContext.addPanel(panel);
}
},
[columnContext, setIsOpen, minHeight],
[columnContext, setIsOpen, minHeight, panelId],
);

return handleRefChange;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export function LayersAndLegendsWidget({ layersProps, legendProps }: PanelProps)
(isOpen) => !isOpen && setPanelState('closed'),
isOpen,
minHeight,
'legend_and_layers',
);

const onPanelIconClick = useCallback(() => {
Expand Down