chore: upgrade react 18 (#17731)
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 51 KiB |
@ -1,6 +1,6 @@
|
||||
import '~/styles'
|
||||
import './Exporter.scss'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { loadPostHogJS } from '~/loadPostHogJS'
|
||||
import { initKea } from '~/initKea'
|
||||
import { Exporter } from '~/exporter/Exporter'
|
||||
@ -20,11 +20,10 @@ const exportedData: ExportedData = window.POSTHOG_EXPORTED_DATA
|
||||
function renderApp(): void {
|
||||
const root = document.getElementById('root')
|
||||
if (root) {
|
||||
ReactDOM.render(
|
||||
createRoot(root).render(
|
||||
<ErrorBoundary>
|
||||
<Exporter {...exportedData} />
|
||||
</ErrorBoundary>,
|
||||
root
|
||||
</ErrorBoundary>
|
||||
)
|
||||
} else {
|
||||
console.error('Attempted, but could not render PostHog app because <div id="root" /> is not found.')
|
||||
|
@ -1,6 +1,6 @@
|
||||
import '~/styles'
|
||||
|
||||
import ReactDOM from 'react-dom'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { getContext } from 'kea'
|
||||
|
||||
import { App } from 'scenes/App'
|
||||
@ -28,13 +28,12 @@ if (typeof window !== 'undefined') {
|
||||
function renderApp(): void {
|
||||
const root = document.getElementById('root')
|
||||
if (root) {
|
||||
ReactDOM.render(
|
||||
createRoot(root).render(
|
||||
<ErrorBoundary>
|
||||
<PostHogProvider client={posthog}>
|
||||
<App />
|
||||
</PostHogProvider>
|
||||
</ErrorBoundary>,
|
||||
root
|
||||
</ErrorBoundary>
|
||||
)
|
||||
} else {
|
||||
console.error('Attempted, but could not render PostHog app because <div id="root" /> is not found.')
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ReactNode, useEffect, useRef, useState } from 'react'
|
||||
import { LemonButton, LemonButtonProps } from 'lib/lemon-ui/LemonButton'
|
||||
import { LemonModal, LemonModalProps } from 'lib/lemon-ui/LemonModal'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { useValues } from 'kea'
|
||||
import { router } from 'kea-router'
|
||||
|
||||
@ -86,14 +86,15 @@ export function LemonDialog({
|
||||
|
||||
LemonDialog.open = (props: LemonDialogProps) => {
|
||||
const div = document.createElement('div')
|
||||
const root = createRoot(div)
|
||||
function destroy(): void {
|
||||
const unmountResult = ReactDOM.unmountComponentAtNode(div)
|
||||
if (unmountResult && div.parentNode) {
|
||||
root.unmount()
|
||||
if (div.parentNode) {
|
||||
div.parentNode.removeChild(div)
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(div)
|
||||
ReactDOM.render(<LemonDialog {...props} onAfterClose={destroy} />, div)
|
||||
root.render(<LemonDialog {...props} onAfterClose={destroy} />)
|
||||
return
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { FunctionComponent, useCallback, useMemo } from 'react'
|
||||
import React, { FunctionComponent, ReactNode, useCallback, useMemo } from 'react'
|
||||
import { LemonButton, LemonButtonProps } from '../LemonButton'
|
||||
import { TooltipProps } from '../Tooltip'
|
||||
import { TooltipPlacement } from 'antd/lib/tooltip'
|
||||
@ -256,7 +256,7 @@ const LemonMenuItemButton: FunctionComponent<LemonMenuItemButtonProps & React.Re
|
||||
size={size}
|
||||
{...buttonProps}
|
||||
>
|
||||
{label as string | JSX.Element}
|
||||
{label as ReactNode}
|
||||
{keyboardShortcut && (
|
||||
<div className="-mr-0.5 inline-flex grow justify-end">
|
||||
{/* Show the keyboard shortcut on the right */}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import ReactDOM from 'react-dom'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { Placement } from '@floating-ui/react'
|
||||
import { kea, path, actions, reducers, listeners, selectors, connect, afterMount, beforeUnmount } from 'kea'
|
||||
import type { inAppPromptLogicType } from './inAppPromptLogicType'
|
||||
@ -125,9 +125,10 @@ function cancellableTooltipWithRetries(
|
||||
const close = (): number => window.setTimeout(trigger, 1)
|
||||
const show = new Promise((resolve, reject) => {
|
||||
const div = document.createElement('div')
|
||||
const root = createRoot(div)
|
||||
function destroy(): void {
|
||||
const unmountResult = ReactDOM.unmountComponentAtNode(div)
|
||||
if (unmountResult && div.parentNode) {
|
||||
root.unmount()
|
||||
if (div.parentNode) {
|
||||
div.parentNode.removeChild(div)
|
||||
}
|
||||
}
|
||||
@ -182,7 +183,7 @@ function cancellableTooltipWithRetries(
|
||||
props = { ...props, element }
|
||||
}
|
||||
|
||||
ReactDOM.render(<LemonActionableTooltip {...props} />, div)
|
||||
root.render(<LemonActionableTooltip {...props} />)
|
||||
|
||||
resolve(true)
|
||||
} catch (e) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import ReactDOM from 'react-dom'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { kea, props, path, key, actions, events, listeners } from 'kea'
|
||||
import { Modal, ModalProps, Input, InputProps, Form, FormItemProps } from 'antd'
|
||||
|
||||
@ -118,12 +118,13 @@ export function cancellablePrompt(config: Pick<PromptProps, 'title' | 'placehold
|
||||
}
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const div = document.createElement('div')
|
||||
const root = createRoot(div)
|
||||
document.body.appendChild(div)
|
||||
let currentConfig: PromptProps = { ...config, close, visible: true } as any
|
||||
|
||||
function destroy(value: unknown): void {
|
||||
const unmountResult = ReactDOM.unmountComponentAtNode(div)
|
||||
if (unmountResult && div.parentNode) {
|
||||
root.unmount()
|
||||
if (div.parentNode) {
|
||||
div.parentNode.removeChild(div)
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
@ -134,7 +135,7 @@ export function cancellablePrompt(config: Pick<PromptProps, 'title' | 'placehold
|
||||
}
|
||||
|
||||
function render(props: PromptProps): void {
|
||||
ReactDOM.render(<Prompt {...props} />, div)
|
||||
root.render(<Prompt {...props} />)
|
||||
}
|
||||
|
||||
function close(this: PromptProps, value: string): void {
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { useValues } from 'kea'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { FunnelStepWithConversionMetrics } from '~/types'
|
||||
import { LemonRow } from 'lib/lemon-ui/LemonRow'
|
||||
import { Lettermark, LettermarkColor } from 'lib/lemon-ui/Lettermark'
|
||||
import { EntityFilterInfo } from 'lib/components/EntityFilterInfo'
|
||||
import { getActionFilterFromFunnelStep } from 'scenes/insights/views/Funnels/funnelStepTableUtils'
|
||||
import { humanFriendlyDuration, humanFriendlyNumber, percentage } from 'lib/utils'
|
||||
import { ensureTooltipElement } from 'scenes/insights/views/LineGraph/LineGraph'
|
||||
import { ensureTooltip } from 'scenes/insights/views/LineGraph/LineGraph'
|
||||
import { LemonDivider } from 'lib/lemon-ui/LemonDivider'
|
||||
import { cohortsModel } from '~/models/cohortsModel'
|
||||
import { ClickToInspectActors } from 'scenes/insights/InsightTooltip/InsightTooltip'
|
||||
@ -109,14 +108,14 @@ export function useFunnelTooltip(showPersonsModal: boolean): React.RefObject<HTM
|
||||
|
||||
useEffect(() => {
|
||||
const svgRect = vizRef.current?.getBoundingClientRect()
|
||||
const tooltipEl = ensureTooltipElement()
|
||||
const [tooltipRoot, tooltipEl] = ensureTooltip()
|
||||
tooltipEl.style.opacity = isTooltipShown ? '1' : '0'
|
||||
if (isTooltipShown) {
|
||||
tooltipEl.style.display = 'initial'
|
||||
}
|
||||
const tooltipRect = tooltipEl.getBoundingClientRect()
|
||||
if (tooltipOrigin) {
|
||||
ReactDOM.render(
|
||||
tooltipRoot.render(
|
||||
<>
|
||||
{currentTooltip && (
|
||||
<FunnelTooltip
|
||||
@ -127,8 +126,7 @@ export function useFunnelTooltip(showPersonsModal: boolean): React.RefObject<HTM
|
||||
breakdownFilter={breakdown}
|
||||
/>
|
||||
)}
|
||||
</>,
|
||||
tooltipEl
|
||||
</>
|
||||
)
|
||||
// Put the tooltip to the bottom right of the cursor, but flip to left if tooltip doesn't fit
|
||||
let xOffset: number
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { useValues } from 'kea'
|
||||
import { useLayoutEffect, useRef, useState } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import Textfit from './Textfit'
|
||||
import clsx from 'clsx'
|
||||
|
||||
import { insightLogic } from '../../insightLogic'
|
||||
@ -9,7 +7,7 @@ import { insightVizDataLogic } from 'scenes/insights/insightVizDataLogic'
|
||||
|
||||
import { ChartParams, TrendResult } from '~/types'
|
||||
import { formatAggregationAxisValue } from 'scenes/insights/aggregationAxisFormat'
|
||||
import { ensureTooltipElement } from '../LineGraph/LineGraph'
|
||||
import { ensureTooltip } from '../LineGraph/LineGraph'
|
||||
import { groupsModel } from '~/models/groupsModel'
|
||||
import { InsightTooltip } from 'scenes/insights/InsightTooltip/InsightTooltip'
|
||||
import { IconFlare, IconTrendingDown, IconTrendingFlat, IconTrendingUp } from 'lib/lemon-ui/icons'
|
||||
@ -20,6 +18,8 @@ import { openPersonsModal } from 'scenes/trends/persons-modal/PersonsModal'
|
||||
import { PropertyKeyInfo } from 'lib/components/PropertyKeyInfo'
|
||||
|
||||
import './BoldNumber.scss'
|
||||
import { useEffect } from 'react'
|
||||
import Textfit from './Textfit'
|
||||
|
||||
/** The tooltip is offset by a few pixels from the cursor to give it some breathing room. */
|
||||
const BOLD_NUMBER_TOOLTIP_OFFSET_PX = 8
|
||||
@ -37,9 +37,10 @@ function useBoldNumberTooltip({
|
||||
|
||||
const divRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const divRect = divRef.current?.getBoundingClientRect()
|
||||
const [tooltipRoot, tooltipEl] = ensureTooltip()
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const divRect = divRef.current?.getBoundingClientRect()
|
||||
const tooltipEl = ensureTooltipElement()
|
||||
tooltipEl.style.opacity = isTooltipShown ? '1' : '0'
|
||||
if (isTooltipShown) {
|
||||
tooltipEl.style.display = 'initial'
|
||||
@ -47,7 +48,7 @@ function useBoldNumberTooltip({
|
||||
|
||||
const seriesResult = insightData?.result?.[0]
|
||||
|
||||
ReactDOM.render(
|
||||
tooltipRoot.render(
|
||||
<InsightTooltip
|
||||
renderCount={(value: number) => <>{formatAggregationAxisValue(trendsFilter, value)}</>}
|
||||
seriesData={[
|
||||
@ -64,20 +65,20 @@ function useBoldNumberTooltip({
|
||||
hideColorCol
|
||||
hideInspectActorsSection={!showPersonsModal}
|
||||
groupTypeLabel={aggregationLabel(series?.[0].math_group_type_index).plural}
|
||||
/>,
|
||||
tooltipEl,
|
||||
() => {
|
||||
const tooltipRect = tooltipEl.getBoundingClientRect()
|
||||
if (divRect) {
|
||||
const desiredTop = window.scrollY + divRect.top - tooltipRect.height - BOLD_NUMBER_TOOLTIP_OFFSET_PX
|
||||
const desiredLeft = divRect.left + divRect.width / 2 - tooltipRect.width / 2
|
||||
tooltipEl.style.top = `${Math.min(desiredTop, window.innerHeight)}px`
|
||||
tooltipEl.style.left = `${Math.min(desiredLeft, window.innerWidth)}px`
|
||||
}
|
||||
}
|
||||
/>
|
||||
)
|
||||
}, [isTooltipShown])
|
||||
|
||||
useEffect(() => {
|
||||
const tooltipRect = tooltipEl.getBoundingClientRect()
|
||||
if (divRect) {
|
||||
const desiredTop = window.scrollY + divRect.top - tooltipRect.height - BOLD_NUMBER_TOOLTIP_OFFSET_PX
|
||||
const desiredLeft = divRect.left + divRect.width / 2 - tooltipRect.width / 2
|
||||
tooltipEl.style.top = `${Math.min(desiredTop, window.innerHeight)}px`
|
||||
tooltipEl.style.left = `${Math.min(desiredLeft, window.innerWidth)}px`
|
||||
}
|
||||
})
|
||||
|
||||
return divRef
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Root, createRoot } from 'react-dom/client'
|
||||
import { useValues } from 'kea'
|
||||
import {
|
||||
ActiveElement,
|
||||
@ -38,16 +38,23 @@ import { TrendsFilter } from '~/queries/schema'
|
||||
import { insightVizDataLogic } from 'scenes/insights/insightVizDataLogic'
|
||||
import ChartjsPluginStacked100, { ExtendedChartData } from 'chartjs-plugin-stacked100'
|
||||
|
||||
export function ensureTooltipElement(): HTMLElement {
|
||||
let tooltipRoot: Root
|
||||
|
||||
export function ensureTooltip(): [Root, HTMLElement] {
|
||||
let tooltipEl = document.getElementById('InsightTooltipWrapper')
|
||||
if (!tooltipEl) {
|
||||
tooltipEl = document.createElement('div')
|
||||
tooltipEl.id = 'InsightTooltipWrapper'
|
||||
tooltipEl.classList.add('InsightTooltipWrapper')
|
||||
tooltipEl.style.display = 'none'
|
||||
document.body.appendChild(tooltipEl)
|
||||
|
||||
if (!tooltipEl || !tooltipRoot) {
|
||||
if (!tooltipEl) {
|
||||
tooltipEl = document.createElement('div')
|
||||
tooltipEl.id = 'InsightTooltipWrapper'
|
||||
tooltipEl.classList.add('InsightTooltipWrapper')
|
||||
tooltipEl.style.display = 'none'
|
||||
document.body.appendChild(tooltipEl)
|
||||
}
|
||||
|
||||
tooltipRoot = createRoot(tooltipEl)
|
||||
}
|
||||
return tooltipEl
|
||||
return [tooltipRoot, tooltipEl]
|
||||
}
|
||||
|
||||
function truncateString(str: string, num: number): string {
|
||||
@ -441,7 +448,7 @@ export function LineGraph_({
|
||||
return
|
||||
}
|
||||
|
||||
const tooltipEl = ensureTooltipElement()
|
||||
const [tooltipRoot, tooltipEl] = ensureTooltip()
|
||||
if (tooltip.opacity === 0) {
|
||||
tooltipEl.style.opacity = '0'
|
||||
return
|
||||
@ -468,7 +475,7 @@ export function LineGraph_({
|
||||
)
|
||||
})
|
||||
|
||||
ReactDOM.render(
|
||||
tooltipRoot.render(
|
||||
<InsightTooltip
|
||||
date={dataset?.days?.[tooltip.dataPoints?.[0]?.dataIndex]}
|
||||
timezone={timezone}
|
||||
@ -524,8 +531,7 @@ export function LineGraph_({
|
||||
: aggregationLabel(labelGroupType).plural
|
||||
}
|
||||
{...tooltipConfig}
|
||||
/>,
|
||||
tooltipEl
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -15,13 +15,12 @@ import { areObjectValuesEmpty } from '~/lib/utils'
|
||||
import { GraphType } from '~/types'
|
||||
import { formatAggregationAxisValue } from 'scenes/insights/aggregationAxisFormat'
|
||||
import {
|
||||
ensureTooltipElement,
|
||||
ensureTooltip,
|
||||
filterNestedDataset,
|
||||
LineGraphProps,
|
||||
onChartClick,
|
||||
onChartHover,
|
||||
} from 'scenes/insights/views/LineGraph/LineGraph'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { InsightTooltip } from 'scenes/insights/InsightTooltip/InsightTooltip'
|
||||
import { useActions, useValues } from 'kea'
|
||||
import { groupsModel } from '~/models/groupsModel'
|
||||
@ -177,7 +176,7 @@ export function PieChart({
|
||||
return
|
||||
}
|
||||
|
||||
const tooltipEl = ensureTooltipElement()
|
||||
const [tooltipRoot, tooltipEl] = ensureTooltip()
|
||||
if (tooltip.opacity === 0) {
|
||||
// remove highlight from the legend
|
||||
if (trendsFilter?.show_legend) {
|
||||
@ -204,7 +203,7 @@ export function PieChart({
|
||||
|
||||
highlightSeries(seriesData[0].dataIndex)
|
||||
|
||||
ReactDOM.render(
|
||||
tooltipRoot.render(
|
||||
<InsightTooltip
|
||||
seriesData={seriesData}
|
||||
hideColorCol={!!tooltipConfig?.hideColorCol}
|
||||
@ -250,8 +249,7 @@ export function PieChart({
|
||||
: aggregationLabel(labelGroupType).plural
|
||||
}
|
||||
{...tooltipConfig}
|
||||
/>,
|
||||
tooltipEl
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { useValues, useActions } from 'kea'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { insightLogic } from 'scenes/insights/insightLogic'
|
||||
import { ChartParams, TrendResult } from '~/types'
|
||||
import './WorldMap.scss'
|
||||
import { InsightTooltip } from 'scenes/insights/InsightTooltip/InsightTooltip'
|
||||
import { SeriesDatum } from '../../InsightTooltip/insightTooltipUtils'
|
||||
import { ensureTooltipElement } from '../LineGraph/LineGraph'
|
||||
import { ensureTooltip } from '../LineGraph/LineGraph'
|
||||
import { worldMapLogic } from './worldMapLogic'
|
||||
import { countryCodeToFlag, countryCodeToName } from './countryCodes'
|
||||
import { countryVectors } from './countryVectors'
|
||||
@ -29,16 +28,17 @@ function useWorldMapTooltip(showPersonsModal: boolean): React.RefObject<SVGSVGEl
|
||||
|
||||
const svgRef = useRef<SVGSVGElement>(null)
|
||||
|
||||
const svgRect = svgRef.current?.getBoundingClientRect()
|
||||
const [tooltipRoot, tooltipEl] = ensureTooltip()
|
||||
|
||||
useEffect(() => {
|
||||
const svgRect = svgRef.current?.getBoundingClientRect()
|
||||
const tooltipEl = ensureTooltipElement()
|
||||
tooltipEl.style.opacity = isTooltipShown ? '1' : '0'
|
||||
if (isTooltipShown) {
|
||||
tooltipEl.style.display = 'initial'
|
||||
}
|
||||
|
||||
if (tooltipCoordinates) {
|
||||
ReactDOM.render(
|
||||
tooltipRoot.render(
|
||||
<>
|
||||
{currentTooltip && (
|
||||
<InsightTooltip
|
||||
@ -68,27 +68,7 @@ function useWorldMapTooltip(showPersonsModal: boolean): React.RefObject<SVGSVGEl
|
||||
groupTypeLabel={aggregationLabel(series?.[0].math_group_type_index).plural}
|
||||
/>
|
||||
)}
|
||||
</>,
|
||||
tooltipEl,
|
||||
() => {
|
||||
const tooltipRect = tooltipEl.getBoundingClientRect()
|
||||
// Put the tooltip to the bottom right of the cursor, but flip to left if tooltip doesn't fit
|
||||
let xOffset: number
|
||||
if (
|
||||
svgRect &&
|
||||
tooltipRect &&
|
||||
tooltipCoordinates[0] + tooltipRect.width + WORLD_MAP_TOOLTIP_OFFSET_PX >
|
||||
svgRect.x + svgRect.width
|
||||
) {
|
||||
xOffset = -(tooltipRect.width + WORLD_MAP_TOOLTIP_OFFSET_PX)
|
||||
} else {
|
||||
xOffset = WORLD_MAP_TOOLTIP_OFFSET_PX
|
||||
}
|
||||
tooltipEl.style.left = `${window.pageXOffset + tooltipCoordinates[0] + xOffset}px`
|
||||
tooltipEl.style.top = `${
|
||||
window.pageYOffset + tooltipCoordinates[1] + WORLD_MAP_TOOLTIP_OFFSET_PX
|
||||
}px`
|
||||
}
|
||||
</>
|
||||
)
|
||||
} else {
|
||||
tooltipEl.style.left = 'revert'
|
||||
@ -96,6 +76,25 @@ function useWorldMapTooltip(showPersonsModal: boolean): React.RefObject<SVGSVGEl
|
||||
}
|
||||
}, [isTooltipShown, tooltipCoordinates, currentTooltip])
|
||||
|
||||
useEffect(() => {
|
||||
if (tooltipCoordinates) {
|
||||
const tooltipRect = tooltipEl.getBoundingClientRect()
|
||||
// Put the tooltip to the bottom right of the cursor, but flip to left if tooltip doesn't fit
|
||||
let xOffset: number
|
||||
if (
|
||||
svgRect &&
|
||||
tooltipRect &&
|
||||
tooltipCoordinates[0] + tooltipRect.width + WORLD_MAP_TOOLTIP_OFFSET_PX > svgRect.x + svgRect.width
|
||||
) {
|
||||
xOffset = -(tooltipRect.width + WORLD_MAP_TOOLTIP_OFFSET_PX)
|
||||
} else {
|
||||
xOffset = WORLD_MAP_TOOLTIP_OFFSET_PX
|
||||
}
|
||||
tooltipEl.style.left = `${window.pageXOffset + tooltipCoordinates[0] + xOffset}px`
|
||||
tooltipEl.style.top = `${window.pageYOffset + tooltipCoordinates[1] + WORLD_MAP_TOOLTIP_OFFSET_PX}px`
|
||||
}
|
||||
}, [currentTooltip, tooltipEl])
|
||||
|
||||
return svgRef
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,27 @@ import { ContainsTypeFilters } from 'scenes/notebooks/NotebooksTable/ContainsTyp
|
||||
import { DEFAULT_FILTERS, notebooksTableLogic } from 'scenes/notebooks/NotebooksTable/notebooksTableLogic'
|
||||
import { notebookPanelLogic } from '../NotebookPanel/notebookPanelLogic'
|
||||
|
||||
function titleColumn(): LemonTableColumn<NotebookListItemType, 'title'> {
|
||||
return {
|
||||
title: 'Title',
|
||||
dataIndex: 'title',
|
||||
width: '100%',
|
||||
render: function Render(title, { short_id, is_template }) {
|
||||
return (
|
||||
<Link
|
||||
data-attr="notebook-title"
|
||||
to={urls.notebook(short_id)}
|
||||
className="font-semibold flex items-center gap-2"
|
||||
>
|
||||
{title || 'Untitled'}
|
||||
{is_template && <LemonTag type="highlight">TEMPLATE</LemonTag>}
|
||||
</Link>
|
||||
)
|
||||
},
|
||||
sorter: (a, b) => (a.title ?? 'Untitled').localeCompare(b.title ?? 'Untitled'),
|
||||
}
|
||||
}
|
||||
|
||||
export function NotebooksTable(): JSX.Element {
|
||||
const { notebooksAndTemplates, filters, notebooksLoading, notebookTemplates } = useValues(notebooksTableLogic)
|
||||
const { loadNotebooks, setFilters } = useActions(notebooksTableLogic)
|
||||
@ -26,24 +47,7 @@ export function NotebooksTable(): JSX.Element {
|
||||
}, [])
|
||||
|
||||
const columns: LemonTableColumns<NotebookListItemType> = [
|
||||
{
|
||||
title: 'Title',
|
||||
dataIndex: 'title',
|
||||
width: '100%',
|
||||
render: function Render(title, { short_id, is_template }) {
|
||||
return (
|
||||
<Link
|
||||
data-attr="notebook-title"
|
||||
to={urls.notebook(short_id)}
|
||||
className="font-semibold flex items-center gap-2"
|
||||
>
|
||||
{title || 'Untitled'}
|
||||
{is_template && <LemonTag type="highlight">TEMPLATE</LemonTag>}
|
||||
</Link>
|
||||
)
|
||||
},
|
||||
sorter: (a, b) => (a.title ?? 'Untitled').localeCompare(b.title ?? 'Untitled'),
|
||||
},
|
||||
titleColumn() as LemonTableColumn<NotebookListItemType, keyof NotebookListItemType | undefined>,
|
||||
createdByColumn<NotebookListItemType>() as LemonTableColumn<
|
||||
NotebookListItemType,
|
||||
keyof NotebookListItemType | undefined
|
||||
|
@ -17,6 +17,23 @@ export type SavedSessionRecordingPlaylistsProps = {
|
||||
tab: ReplayTabs.Playlists
|
||||
}
|
||||
|
||||
function nameColumn(): LemonTableColumn<SessionRecordingPlaylistType, 'name'> {
|
||||
return {
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
render: function Render(name, { short_id, derived_name, description }) {
|
||||
return (
|
||||
<>
|
||||
<Link className={clsx('font-semibold', !name && 'italic')} to={urls.replayPlaylist(short_id)}>
|
||||
{name || derived_name || '(Untitled)'}
|
||||
</Link>
|
||||
{description ? <div className="truncate">{description}</div> : null}
|
||||
</>
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function SavedSessionRecordingPlaylists({ tab }: SavedSessionRecordingPlaylistsProps): JSX.Element {
|
||||
const logic = savedSessionRecordingPlaylistsLogic({ tab })
|
||||
const { playlists, playlistsLoading, filters, sorting, pagination } = useValues(logic)
|
||||
@ -38,20 +55,7 @@ export function SavedSessionRecordingPlaylists({ tab }: SavedSessionRecordingPla
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
render: function Render(name, { short_id, derived_name, description }) {
|
||||
return (
|
||||
<>
|
||||
<Link className={clsx('font-semibold', !name && 'italic')} to={urls.replayPlaylist(short_id)}>
|
||||
{name || derived_name || '(Untitled)'}
|
||||
</Link>
|
||||
{description ? <div className="truncate">{description}</div> : null}
|
||||
</>
|
||||
)
|
||||
},
|
||||
},
|
||||
nameColumn() as LemonTableColumn<SessionRecordingPlaylistType, keyof SessionRecordingPlaylistType | undefined>,
|
||||
{
|
||||
...(createdByColumn<SessionRecordingPlaylistType>() as LemonTableColumn<
|
||||
SessionRecordingPlaylistType,
|
||||
|
@ -15,7 +15,7 @@ import { IconPlayCircle, IconUnfoldLess, IconUnfoldMore } from 'lib/lemon-ui/ico
|
||||
import { triggerExport } from 'lib/components/ExportButton/exporter'
|
||||
import { LemonButton, LemonBadge, LemonDivider, LemonInput, LemonModal, LemonSelect, Link } from '@posthog/lemon-ui'
|
||||
import { PersonDisplay } from 'scenes/persons/PersonDisplay'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { Spinner } from 'lib/lemon-ui/Spinner/Spinner'
|
||||
import { SaveCohortModal } from './SaveCohortModal'
|
||||
import { ProfilePicture } from 'lib/lemon-ui/ProfilePicture'
|
||||
@ -403,13 +403,14 @@ export type OpenPersonsModalProps = Omit<PersonsModalProps, 'onClose' | 'onAfter
|
||||
|
||||
export const openPersonsModal = (props: OpenPersonsModalProps): void => {
|
||||
const div = document.createElement('div')
|
||||
const root = createRoot(div)
|
||||
function destroy(): void {
|
||||
const unmountResult = ReactDOM.unmountComponentAtNode(div)
|
||||
if (unmountResult && div.parentNode) {
|
||||
root.unmount()
|
||||
if (div.parentNode) {
|
||||
div.parentNode.removeChild(div)
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(div)
|
||||
ReactDOM.render(<PersonsModal {...props} onAfterClose={destroy} />, div)
|
||||
root.render(<PersonsModal {...props} onAfterClose={destroy} />)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import '~/styles'
|
||||
import './styles.scss'
|
||||
|
||||
import ReactDOM from 'react-dom'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { initKea } from '~/initKea'
|
||||
import { ToolbarApp } from '~/toolbar/ToolbarApp'
|
||||
import { ToolbarParams } from '~/types'
|
||||
@ -9,6 +9,8 @@ import { PostHog } from 'posthog-js'
|
||||
;(window as any)['ph_load_toolbar'] = function (toolbarParams: ToolbarParams, posthog: PostHog) {
|
||||
initKea()
|
||||
const container = document.createElement('div')
|
||||
const root = createRoot(container)
|
||||
|
||||
document.body.appendChild(container)
|
||||
|
||||
if (!posthog) {
|
||||
@ -17,14 +19,13 @@ import { PostHog } from 'posthog-js'
|
||||
)
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
root.render(
|
||||
<ToolbarApp
|
||||
{...toolbarParams}
|
||||
actionId={parseInt(String(toolbarParams.actionId))}
|
||||
jsURL={toolbarParams.jsURL || toolbarParams.apiURL}
|
||||
posthog={posthog}
|
||||
/>,
|
||||
container
|
||||
/>
|
||||
)
|
||||
}
|
||||
/** @deprecated, use "ph_load_toolbar" instead */
|
||||
|
20
package.json
@ -91,9 +91,8 @@
|
||||
"@tiptap/starter-kit": "^2.1.0-rc.12",
|
||||
"@tiptap/suggestion": "^2.1.0-rc.12",
|
||||
"@types/md5": "^2.3.0",
|
||||
"@types/react-textfit": "^1.1.0",
|
||||
"@types/react-transition-group": "^4.4.5",
|
||||
"@types/react-virtualized": "^9.21.14",
|
||||
"@types/react-virtualized": "^9.21.23",
|
||||
"antd": "^4.17.1",
|
||||
"antd-dayjs-webpack-plugin": "^1.0.6",
|
||||
"babel-preset-nano-react-app": "^0.1.0",
|
||||
@ -146,18 +145,17 @@
|
||||
"rc-select": "~13.1.0-alpha.0",
|
||||
"rc-table": "~7.19.0",
|
||||
"rc-trigger": "^5.2.5",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-draggable": "^4.2.0",
|
||||
"react-grid-layout": "^1.3.0",
|
||||
"react-intersection-observer": "^9.4.3",
|
||||
"react-markdown": "^5.0.3",
|
||||
"react-modal": "^3.15.1",
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-shadow": "^18.4.2",
|
||||
"react-shadow": "^20.3.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react-textarea-autosize": "^8.3.3",
|
||||
"react-textfit": "^1.1.1",
|
||||
"react-toastify": "^8.2.0",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"react-virtualized": "^9.22.5",
|
||||
@ -182,7 +180,6 @@
|
||||
"@babel/preset-typescript": "^7.22.5",
|
||||
"@babel/runtime": "^7.22.10",
|
||||
"@cypress/webpack-preprocessor": "^5.17.1",
|
||||
"@hot-loader/react-dom": "^16.14.0",
|
||||
"@playwright/test": "1.29.2",
|
||||
"@sentry/types": "7.22.0",
|
||||
"@storybook/addon-a11y": "^7.5.1",
|
||||
@ -204,7 +201,7 @@
|
||||
"@sucrase/jest-plugin": "^3.0.0",
|
||||
"@testing-library/dom": ">=7.21.4",
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react": "^12.1.2",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/chartjs-plugin-crosshair": "^1.1.1",
|
||||
@ -221,14 +218,13 @@
|
||||
"@types/pixelmatch": "^5.2.4",
|
||||
"@types/pngjs": "^6.0.1",
|
||||
"@types/query-selector-shadow-dom": "^1.0.0",
|
||||
"@types/react": "^16.14.2",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"@types/react": "^17.0.39",
|
||||
"@types/react-dom": "^18.2.8",
|
||||
"@types/react-grid-layout": "^1.1.2",
|
||||
"@types/react-modal": "^3.13.1",
|
||||
"@types/react-resizable": "^3.0.4",
|
||||
"@types/react-syntax-highlighter": "^15.5.7",
|
||||
"@types/react-textfit": "^1.1.0",
|
||||
"@types/react-virtualized": "^9.21.14",
|
||||
"@types/react-virtualized": "^9.21.23",
|
||||
"@types/testing-library__jest-dom": "^5.14.5",
|
||||
"@types/zxcvbn": "^4.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
||||
|