0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-21 13:39:22 +01:00

Toolbar Date Filter, remove react-hot-loader, fix dashboard date filter URL (#3586)

* dropdown and datepicker z-index

* remove dead code

* pass getPopupContainer to range picker

* make DateFilter's custom time range work in a shadow root

* close after selecting

* show date filter instead of date range

* skip updating url on date filter change in toolbar

* actually filter the dates

* fix flickering (always show map)

* refactor date filter component

* upgrade to webpack 5 and @posthog/react-rrweb-player module

* disconnect dashboardLogic from dateFilterLogic (remove broken url changes, etc)

* add bundle tracker

* remove react-hot-loader

* Revert "add bundle tracker"

This reverts commit e59bcfa8

* remove bundle tracker

* remove updatePath

* fix code quality complaints

* revert @cypress/webpack-preprocessor version

* try different cypress webpack plugin

* add crypto-browserify

* add crypto-browserify

* revert to webpack 4

* revert to webpack 4

* revert to webpack 4

* implement feedback and remove debug stuff

* move insights date filter logic out of lib/

* rename DateFilterComponent to DateFilter

* rename DateFilterCustom to DateFilterRange

* Remove hot from new code
This commit is contained in:
Marius Andra 2021-03-12 14:54:29 +01:00 committed by GitHub
parent 37b11ac20b
commit 8c98e4f61d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 758 additions and 555 deletions

View File

@ -71,18 +71,18 @@ frontend/src/scenes/actions/ActionsTable.tsx(125,29)
frontend/src/scenes/actions/ActionsTable.tsx(136,36)
frontend/src/scenes/actions/ActionsTable.tsx(139,29)
frontend/src/scenes/actions/ActionsTable.tsx(192,35)
frontend/src/scenes/annotations/index.tsx(32,47)
frontend/src/scenes/annotations/index.tsx(51,47)
frontend/src/scenes/annotations/index.tsx(57,48)
frontend/src/scenes/annotations/index.tsx(63,43)
frontend/src/scenes/annotations/index.tsx(69,41)
frontend/src/scenes/annotations/index.tsx(146,44)
frontend/src/scenes/annotations/index.tsx(152,38)
frontend/src/scenes/annotations/index.tsx(156,39)
frontend/src/scenes/annotations/index.tsx(232,50)
frontend/src/scenes/annotations/index.tsx(242,55)
frontend/src/scenes/annotations/index.tsx(280,70)
frontend/src/scenes/annotations/index.tsx(282,59)
frontend/src/scenes/annotations/index.tsx(30,47)
frontend/src/scenes/annotations/index.tsx(49,47)
frontend/src/scenes/annotations/index.tsx(55,48)
frontend/src/scenes/annotations/index.tsx(61,43)
frontend/src/scenes/annotations/index.tsx(67,41)
frontend/src/scenes/annotations/index.tsx(144,44)
frontend/src/scenes/annotations/index.tsx(150,38)
frontend/src/scenes/annotations/index.tsx(154,39)
frontend/src/scenes/annotations/index.tsx(230,50)
frontend/src/scenes/annotations/index.tsx(240,55)
frontend/src/scenes/annotations/index.tsx(278,70)
frontend/src/scenes/annotations/index.tsx(280,59)
frontend/src/scenes/billing/Billing.tsx(6,24)
frontend/src/scenes/billing/Billing.tsx(51,24)
frontend/src/scenes/billing/Billing.tsx(53,61)
@ -129,7 +129,7 @@ frontend/src/scenes/dashboard/DashboardItems.tsx(92,43)
frontend/src/scenes/dashboard/Dashboards.tsx(27,42)
frontend/src/scenes/dashboard/Dashboards.tsx(27,46)
frontend/src/scenes/dashboard/Dashboards.tsx(56,46)
frontend/src/scenes/events/Events.tsx(49,22)
frontend/src/scenes/events/Events.tsx(47,22)
frontend/src/scenes/events/EventsVolumeTable.tsx(53,14)
frontend/src/scenes/events/EventsVolumeTable.tsx(55,22)
frontend/src/scenes/events/EventsVolumeTable.tsx(63,29)
@ -188,7 +188,7 @@ frontend/src/scenes/insights/InsightTabs/TrendTab/TrendTab.tsx(99,32)
frontend/src/scenes/insights/InsightTabs/TrendTab/TrendTab.tsx(99,43)
frontend/src/scenes/insights/InsightTabs/TrendTab/TrendTab.tsx(121,57)
frontend/src/scenes/insights/insightCommandLogic.ts(10,41)
frontend/src/scenes/instance/Licenses/index.tsx(63,31)
frontend/src/scenes/instance/Licenses/index.tsx(61,31)
frontend/src/scenes/instance/Licenses/logic.ts(38,17)
frontend/src/scenes/instance/Licenses/logic.ts(43,5)
frontend/src/scenes/instance/Licenses/logic.ts(47,71)
@ -210,16 +210,12 @@ frontend/src/scenes/persons/Cohort.tsx(80,40)
frontend/src/scenes/persons/Cohort.tsx(166,52)
frontend/src/scenes/persons/Cohort.tsx(168,36)
frontend/src/scenes/persons/CohortGroup.tsx(88,29)
frontend/src/scenes/persons/Cohorts.tsx(28,33)
frontend/src/scenes/persons/Cohorts.tsx(67,83)
frontend/src/scenes/persons/Cohorts.tsx(71,42)
frontend/src/scenes/persons/Cohorts.tsx(74,55)
frontend/src/scenes/persons/Cohorts.tsx(74,65)
frontend/src/scenes/persons/Cohorts.tsx(87,48)
frontend/src/scenes/persons/Cohorts.tsx(109,29)
frontend/src/scenes/persons/Cohorts.tsx(134,39)
frontend/src/scenes/persons/Cohorts.tsx(158,69)
frontend/src/scenes/persons/Cohorts.tsx(167,37)
frontend/src/scenes/persons/Cohorts.tsx(27,33)
frontend/src/scenes/persons/Cohorts.tsx(65,83)
frontend/src/scenes/persons/Cohorts.tsx(69,42)
frontend/src/scenes/persons/Cohorts.tsx(72,55)
frontend/src/scenes/persons/Cohorts.tsx(72,65)
frontend/src/scenes/persons/Cohorts.tsx(85,48)
frontend/src/scenes/persons/MergePerson.tsx(56,56)
frontend/src/scenes/plugins/PluginImage.tsx(4,30)
frontend/src/scenes/plugins/Repository.tsx(22,56)

View File

@ -4,7 +4,6 @@ module.exports = {
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-react-jsx',
'@babel/plugin-proposal-class-properties',
'react-hot-loader/babel',
['babel-plugin-kea', { path: './frontend/src' }],
],
presets: ['@babel/preset-env', '@babel/typescript'],

View File

@ -17,7 +17,6 @@ import { triggerResizeAfterADelay } from 'lib/utils'
import { useEscapeKey } from 'lib/hooks/useEscapeKey'
import lgLogo from 'public/posthog-logo-white.svg'
import smLogo from 'public/icon-white.svg'
import { hot } from 'react-hot-loader/root'
import './Navigation.scss'
import {
IconCohorts,
@ -138,8 +137,7 @@ function PinnedDashboards(): JSX.Element {
)
}
export const MainNavigation = hot(_MainNavigation)
function _MainNavigation(): JSX.Element {
export function MainNavigation(): JSX.Element {
const { user } = useValues(userLogic)
const { currentOrganization } = useValues(organizationLogic)
const { menuCollapsed, toolbarModalOpen, pinnedDashboardsVisible } = useValues(navigationLogic)

View File

@ -22,7 +22,6 @@ import { guardPremiumFeature } from 'scenes/UpgradeModal'
import { sceneLogic } from 'scenes/sceneLogic'
import { CreateProjectModal } from 'scenes/project/CreateProjectModal'
import { CreateOrganizationModal } from 'scenes/organization/CreateOrganizationModal'
import { hot } from 'react-hot-loader/root'
import { isMobile, platformCommandControlKey } from 'lib/utils'
import { commandPaletteLogic } from 'lib/components/CommandPalette/commandPaletteLogic'
import { Link } from 'lib/components/Link'
@ -71,8 +70,7 @@ export function WhoAmI({ user }: { user: UserType }): JSX.Element {
)
}
export const TopNavigation = hot(_TopNavigation)
export function _TopNavigation(): JSX.Element {
export function TopNavigation(): JSX.Element {
const {
setMenuCollapsed,
setChangelogModalOpen,

View File

@ -1,18 +1,23 @@
import React, { useRef, useEffect, useState } from 'react'
import { Select, DatePicker, Button } from 'antd'
import { useValues, useActions } from 'kea'
import moment from 'moment'
import { dateFilterLogic } from './dateFilterLogic'
import React, { useState } from 'react'
import { Select } from 'antd'
import moment, { Moment } from 'moment'
import { dateMapping, isDate, dateFilterToText } from 'lib/utils'
import { DateFilterRange } from 'lib/components/DateFilter/DateFilterRange'
interface Props {
export interface DateFilterProps {
defaultValue: string
showCustom?: boolean
bordered?: boolean
makeLabel?: (key: string) => React.ReactNode
style?: React.CSSProperties
onChange?: () => void
onChange?: (fromDate: string, toDate: string) => void
disabled?: boolean
getPopupContainer?: (props: any) => HTMLElement
}
interface RawDateFilterProps extends DateFilterProps {
dateFrom?: string | Moment
dateTo?: string | Moment
}
export function DateFilter({
@ -23,12 +28,10 @@ export function DateFilter({
disabled,
makeLabel,
onChange,
}: Props): JSX.Element {
const {
dates: { dateFrom, dateTo },
} = useValues(dateFilterLogic)
const { setDates } = useActions(dateFilterLogic)
getPopupContainer,
dateFrom,
dateTo,
}: RawDateFilterProps): JSX.Element {
const [rangeDateFrom, setRangeDateFrom] = useState(
dateFrom && isDate.test(dateFrom as string) ? moment(dateFrom) : undefined
)
@ -42,10 +45,7 @@ export function DateFilter({
}
function setDate(fromDate: string, toDate: string): void {
setDates(fromDate, toDate)
if (onChange) {
onChange()
}
onChange?.(fromDate, toDate)
}
function _onChange(v: string): void {
@ -103,10 +103,12 @@ export function DateFilter({
dropdownMatchSelectWidth={false}
disabled={disabled}
optionLabelProp={makeLabel ? 'label' : undefined}
getPopupContainer={getPopupContainer}
dropdownRender={(menu: React.ReactElement) => {
if (dateRangeOpen) {
return (
<DatePickerDropdown
<DateFilterRange
getPopupContainer={getPopupContainer}
onClick={dropdownOnClick}
onDateFromChange={(date) => setRangeDateFrom(date)}
onDateToChange={(date) => setRangeDateTo(date)}
@ -140,83 +142,3 @@ export function DateFilter({
</Select>
)
}
function DatePickerDropdown(props: {
onClickOutside: () => void
onClick: (e: React.MouseEvent) => void
onDateFromChange: (date: moment.Moment | undefined) => void
onDateToChange: (date: moment.Moment | undefined) => void
onApplyClick: () => void
rangeDateFrom: string | moment.Moment | undefined
rangeDateTo: string | moment.Moment | undefined
}): JSX.Element {
const dropdownRef = useRef<HTMLDivElement | null>(null)
const [calendarOpen, setCalendarOpen] = useState(false)
const onClickOutside = (event: MouseEvent): void => {
if ((!event.target || !dropdownRef.current?.contains(event.target as any)) && !calendarOpen) {
props.onClickOutside()
}
}
useEffect(() => {
document.addEventListener('mousedown', onClickOutside)
return () => {
document.removeEventListener('mousedown', onClickOutside)
}
}, [calendarOpen])
return (
<div ref={dropdownRef}>
<a
style={{
margin: '0 1rem',
color: 'rgba(0, 0, 0, 0.2)',
fontWeight: 700,
}}
href="#"
onClick={props.onClick}
>
&lt;
</a>
<hr style={{ margin: '0.5rem 0' }} />
<div style={{ padding: '0 1rem' }}>
<label className="secondary">From date</label>
<br />
<DatePicker.RangePicker
defaultValue={[
props.rangeDateFrom
? moment.isMoment(props.rangeDateFrom)
? props.rangeDateFrom
: moment(props.rangeDateFrom)
: null,
props.rangeDateTo
? moment.isMoment(props.rangeDateTo)
? props.rangeDateTo
: moment(props.rangeDateTo)
: null,
]}
onOpenChange={(open) => {
setCalendarOpen(open)
}}
onChange={(dates) => {
if (dates && dates.length === 2) {
props.onDateFromChange(dates[0] || undefined)
props.onDateToChange(dates[1] || undefined)
}
}}
popupStyle={{ zIndex: 999999 }}
/>
<br />
<Button
type="default"
disabled={!props.rangeDateTo || !props.rangeDateFrom}
style={{ marginTop: '1rem', marginBottom: '1rem' }}
onClick={props.onApplyClick}
>
Apply filter
</Button>
</div>
</div>
)
}

View File

@ -0,0 +1,110 @@
import React, { useEffect, useRef, useState } from 'react'
import moment from 'moment'
import { Button, DatePicker } from 'antd'
export function DateFilterRange(props: {
onClickOutside: () => void
onClick: (e: React.MouseEvent) => void
onDateFromChange: (date: moment.Moment | undefined) => void
onDateToChange: (date: moment.Moment | undefined) => void
onApplyClick: () => void
rangeDateFrom: string | moment.Moment | undefined
rangeDateTo: string | moment.Moment | undefined
getPopupContainer?: (props: any) => HTMLElement
}): JSX.Element {
const dropdownRef = useRef<HTMLDivElement | null>(null)
const [calendarOpen, setCalendarOpen] = useState(false)
const onClickOutside = (event: MouseEvent): void => {
const target = (event.composedPath?.()?.[0] || event.target) as HTMLElement
if (!target) {
return
}
const clickInPickerContainer = dropdownRef.current?.contains(target)
const clickInDateDropdown = event
.composedPath?.()
?.find((e) => (e as HTMLElement)?.matches?.('.datefilter-datepicker'))
if (clickInPickerContainer && calendarOpen && target.tagName !== 'INPUT') {
setCalendarOpen(false)
return
}
if (!clickInPickerContainer && !clickInDateDropdown) {
if (calendarOpen) {
setCalendarOpen(false)
} else {
props.onClickOutside()
}
}
}
useEffect(() => {
window.addEventListener('mousedown', onClickOutside)
return () => {
window.removeEventListener('mousedown', onClickOutside)
}
}, [calendarOpen])
return (
<div ref={dropdownRef}>
<a
style={{
margin: '0 1rem',
color: 'rgba(0, 0, 0, 0.2)',
fontWeight: 700,
}}
href="#"
onClick={props.onClick}
>
&lt;
</a>
<hr style={{ margin: '0.5rem 0' }} />
<div style={{ padding: '0 1rem' }}>
<label className="secondary">From date</label>
<br />
<DatePicker.RangePicker
dropdownClassName="datefilter-datepicker"
getPopupContainer={props.getPopupContainer}
defaultValue={[
props.rangeDateFrom
? moment.isMoment(props.rangeDateFrom)
? props.rangeDateFrom
: moment(props.rangeDateFrom)
: null,
props.rangeDateTo
? moment.isMoment(props.rangeDateTo)
? props.rangeDateTo
: moment(props.rangeDateTo)
: null,
]}
open={calendarOpen}
onOpenChange={(open) => {
if (open) {
setCalendarOpen(open)
}
}}
onChange={(dates) => {
if (dates && dates.length === 2) {
props.onDateFromChange(dates[0] || undefined)
props.onDateToChange(dates[1] || undefined)
setCalendarOpen(false)
}
}}
popupStyle={{ zIndex: 999999 }}
/>
<br />
<Button
type="default"
disabled={!props.rangeDateTo || !props.rangeDateFrom}
style={{ marginTop: '1rem', marginBottom: '1rem' }}
onClick={props.onApplyClick}
>
Apply filter
</Button>
</div>
</div>
)
}

View File

@ -1 +0,0 @@
export * from './DateFilter'

View File

@ -1,4 +1,3 @@
import { hot } from 'react-hot-loader/root'
import React, { useEffect } from 'react'
import { useActions, useValues } from 'kea'
import { Layout } from 'antd'
@ -23,8 +22,7 @@ function Toast(): JSX.Element {
return <ToastContainer autoClose={8000} transition={Slide} position="top-right" />
}
export const App = hot(_App)
function _App(): JSX.Element | null {
export function App(): JSX.Element | null {
const { user } = useValues(userLogic)
const { currentOrganization, currentOrganizationLoading } = useValues(organizationLogic)
const { currentTeam, currentTeamLoading } = useValues(teamLogic)

View File

@ -7,7 +7,6 @@ import { eventsTableLogic } from 'scenes/events/eventsTableLogic'
import api from 'lib/api'
import { kea } from 'kea'
import { Spin } from 'antd'
import { hot } from 'react-hot-loader/root'
import { EventsTable } from 'scenes/events'
let actionLogic = kea({
@ -64,8 +63,7 @@ let actionLogic = kea({
}),
})
export const Action = hot(_Action)
function _Action({ id }) {
export function Action({ id }) {
const fixedFilters = { action_id: id }
const { push } = useActions(router)

View File

@ -1,4 +1,3 @@
import { hot } from 'react-hot-loader/root'
import React, { useState, useEffect, HTMLAttributes } from 'react'
import { useValues, useActions } from 'kea'
import { Table, Tag, Button, Modal, Input, DatePicker, Row, Spin, Menu, Dropdown } from 'antd'
@ -16,8 +15,7 @@ import { AnnotationType } from '~/types'
const { TextArea } = Input
export const Annotations = hot(_Annotations)
function _Annotations(): JSX.Element {
export function Annotations(): JSX.Element {
const { annotations, annotationsLoading, next, loadingNext } = useValues(annotationsTableLogic)
const { loadAnnotations, updateAnnotation, deleteAnnotation, loadAnnotationsNext, restoreAnnotation } = useActions(
annotationsTableLogic

View File

@ -8,15 +8,13 @@ import { DashboardHeader } from 'scenes/dashboard/DashboardHeader'
import { DashboardItems } from 'scenes/dashboard/DashboardItems'
import { dashboardsModel } from '~/models/dashboardsModel'
import { HedgehogOverlay } from 'lib/components/HedgehogOverlay/HedgehogOverlay'
import { hot } from 'react-hot-loader/root'
interface Props {
id: string
shareToken?: string
}
export const Dashboard = hot(_Dashboard)
function _Dashboard({ id, shareToken }: Props): JSX.Element {
export function Dashboard({ id, shareToken }: Props): JSX.Element {
return (
<BindLogic logic={dashboardLogic} props={{ id: parseInt(id), shareToken }}>
<DashboardView id={id} shareToken={shareToken} />

View File

@ -25,16 +25,16 @@ import { FullScreen } from 'lib/components/FullScreen'
import moment from 'moment'
import { dashboardLogic } from 'scenes/dashboard/dashboardLogic'
import { DashboardType } from '~/types'
import { DateFilter } from 'lib/components/DateFilter'
import { DateFilter } from 'lib/components/DateFilter/DateFilter'
export function DashboardHeader(): JSX.Element {
const { dashboard, draggingEnabled } = useValues(dashboardLogic)
const { dashboard, draggingEnabled, filters: dashboardFilters } = useValues(dashboardLogic)
const {
addNewDashboard,
renameDashboard,
enableDragging,
disableDragging,
updateAndRefreshDashboard,
setDates,
refreshAllDashboardItems,
} = useActions(dashboardLogic)
const { dashboards, dashboardsLoading } = useValues(dashboardsModel)
@ -82,7 +82,9 @@ export function DashboardHeader(): JSX.Element {
<DateFilter
defaultValue="Custom"
showCustom
onChange={updateAndRefreshDashboard}
dateFrom={dashboardFilters?.date_from}
dateTo={dashboardFilters?.date_to}
onChange={setDates}
makeLabel={(key) => (
<>
<CalendarOutlined />

View File

@ -7,14 +7,12 @@ import { Link } from 'lib/components/Link'
import { PlusOutlined } from '@ant-design/icons'
import { Table } from 'antd'
import { PushpinFilled, PushpinOutlined, DeleteOutlined, AppstoreAddOutlined } from '@ant-design/icons'
import { hot } from 'react-hot-loader/root'
import { NewDashboard } from 'scenes/dashboard/NewDashboard'
import { PageHeader } from 'lib/components/PageHeader'
import { createdAtColumn, createdByColumn } from 'lib/components/Table'
import { DashboardType } from '~/types'
export const Dashboards = hot(_Dashboards)
function _Dashboards(): JSX.Element {
export function Dashboards(): JSX.Element {
const { dashboardsLoading } = useValues(dashboardsModel)
const { deleteDashboard, unpinDashboard, pinDashboard, addDashboard } = useActions(dashboardsModel)
const { setNewDashboardDrawer } = useActions(dashboardsLogic)

View File

@ -11,10 +11,9 @@ import { dashboardItemsModel } from '~/models/dashboardItemsModel'
import { PATHS_VIZ, ACTIONS_LINE_GRAPH_LINEAR } from 'lib/constants'
import { ViewType } from 'scenes/insights/insightLogic'
import { eventUsageLogic } from 'lib/utils/eventUsageLogic'
import { dateFilterLogic } from 'lib/components/DateFilter/dateFilterLogic'
export const dashboardLogic = kea({
connect: [dashboardsModel, dashboardItemsModel, eventUsageLogic, dateFilterLogic],
connect: [dashboardsModel, dashboardItemsModel, eventUsageLogic],
key: (props) => props.id,
@ -32,9 +31,10 @@ export const dashboardLogic = kea({
refreshDashboardItem: (id) => ({ id }),
refreshAllDashboardItems: true,
updateAndRefreshDashboard: true,
setDates: (dateFrom, dateTo, reloadDashboard = true) => ({ dateFrom, dateTo, reloadDashboard }),
}),
loaders: ({ props }) => ({
loaders: ({ actions, props }) => ({
allItems: [
{},
{
@ -43,7 +43,7 @@ export const dashboardLogic = kea({
const dashboard = await api.get(
`api/dashboard/${props.id}/?${toParams({ share_token: props.shareToken })}`
)
dateFilterLogic.actions.setDates(dashboard.filters.date_from, dashboard.filters.date_to)
actions.setDates(dashboard.filters.date_from, dashboard.filters.date_to, false)
eventUsageLogic.actions.reportDashboardViewed(dashboard, !!props.shareToken)
return dashboard
} catch (error) {
@ -64,6 +64,12 @@ export const dashboardLogic = kea({
],
}),
reducers: ({ props }) => ({
filters: [
{ date_from: undefined, date_to: undefined },
{
setDates: (state, { dateFrom, dateTo }) => ({ ...state, date_from: dateFrom, date_to: dateTo }),
},
],
allItems: {
[dashboardItemsModel.actions.renameDashboardItemSuccess]: (state, { item }) => {
return { ...state, items: state.items.map((i) => (i.id === item.id ? item : i)) }
@ -335,12 +341,13 @@ export const dashboardLogic = kea({
},
updateAndRefreshDashboard: async (_, breakpoint) => {
await breakpoint(200)
const filters = {
date_from: dateFilterLogic.values.dates.dateFrom,
date_to: dateFilterLogic.values.dates.dateTo,
actions.updateDashboard(values.filters)
dashboardItemsModel.actions.refreshAllDashboardItems(values.filters)
},
setDates: ({ reloadDashboard }) => {
if (reloadDashboard) {
actions.updateAndRefreshDashboard()
}
actions.updateDashboard(filters)
dashboardItemsModel.actions.refreshAllDashboardItems(filters)
},
}),
})

View File

@ -1,7 +1,6 @@
import React from 'react'
import { kea, useActions, useValues } from 'kea'
import { hot } from 'react-hot-loader/root'
import { PageHeader } from 'lib/components/PageHeader'
import { Tabs } from 'antd'
import { ActionsTable } from 'scenes/actions/ActionsTable'
@ -35,8 +34,7 @@ const eventsLogic = kea<eventsLogicType>({
}),
})
export const ManageEvents = hot(_ManageEvents)
function _ManageEvents({}): JSX.Element {
export function ManageEvents(): JSX.Element {
const { tab } = useValues(eventsLogic)
const { setTab } = useActions(eventsLogic)

View File

@ -12,10 +12,8 @@ import { EventName } from 'scenes/actions/EventName'
import { eventToName, toParams } from 'lib/utils'
import './EventsTable.scss'
import { eventsTableLogic } from './eventsTableLogic'
import { hot } from 'react-hot-loader/root'
export const EventsTable = hot(_EventsTable)
function _EventsTable({ fixedFilters, filtersEnabled = true, pageKey }) {
export function EventsTable({ fixedFilters, filtersEnabled = true, pageKey }) {
const logic = eventsTableLogic({ fixedFilters, key: pageKey })
const {
properties,

View File

@ -1,5 +1,4 @@
import React, { Fragment, useState } from 'react'
import { hot } from 'react-hot-loader/root'
import { useValues, useActions } from 'kea'
import { featureFlagLogic } from './featureFlagLogic'
import { Table, Switch, Drawer, Button } from 'antd'
@ -11,8 +10,7 @@ import { PageHeader } from 'lib/components/PageHeader'
import PropertyFiltersDisplay from 'lib/components/PropertyFilters/PropertyFiltersDisplay'
import { createdAtColumn, createdByColumn } from 'lib/components/Table'
export const FeatureFlags = hot(_FeatureFlags)
function _FeatureFlags() {
export function FeatureFlags() {
const [openFeatureFlag, setOpenFeatureFlag] = useState(false)
const logic = featureFlagLogic({ closeDrawer: () => setOpenFeatureFlag(false) })
const { featureFlags, featureFlagsLoading } = useValues(logic)

View File

@ -0,0 +1,23 @@
import React from 'react'
import { useValues, useActions } from 'kea'
import { dateFilterLogic } from './dateFilterLogic'
import { DateFilterProps, DateFilter as DateFilterComponent } from 'lib/components/DateFilter/DateFilter'
export function DateFilter(props: DateFilterProps): JSX.Element {
const {
dates: { dateFrom, dateTo },
} = useValues(dateFilterLogic)
const { setDates } = useActions(dateFilterLogic)
return (
<DateFilterComponent
{...props}
dateFrom={dateFrom}
dateTo={dateTo}
onChange={(dateFrom, dateTo) => {
setDates(dateFrom, dateTo)
props.onChange?.(dateFrom, dateTo)
}}
/>
)
}

View File

@ -1,7 +1,7 @@
import { kea } from 'kea'
import { router } from 'kea-router'
import { Moment } from 'moment'
import { dateFilterLogicType } from 'lib/components/DateFilter/dateFilterLogicType'
import { dateFilterLogicType } from 'scenes/insights/DateFilter/dateFilterLogicType'
import { objectsEqual } from 'lib/utils'
interface UrlParams {
@ -9,7 +9,7 @@ interface UrlParams {
date_to?: string
}
export const dateFilterLogic = kea<dateFilterLogicType<UrlParams, Moment>>({
export const dateFilterLogic = kea<dateFilterLogicType<Moment>>({
actions: () => ({
setDates: (dateFrom: string | Moment | undefined, dateTo: string | Moment | undefined) => ({
dateFrom,

View File

@ -4,7 +4,7 @@ import { useActions, useMountedLogic, useValues, BindLogic } from 'kea'
import { Loading } from 'lib/utils'
import { SaveToDashboard } from 'lib/components/SaveToDashboard/SaveToDashboard'
import moment from 'moment'
import { DateFilter } from 'lib/components/DateFilter'
import { DateFilter } from './DateFilter/DateFilter'
import { IntervalFilter } from 'lib/components/IntervalFilter/IntervalFilter'
import { PageHeader } from 'lib/components/PageHeader'
@ -20,7 +20,6 @@ import {
LIFECYCLE,
FUNNEL_VIZ,
} from 'lib/constants'
import { hot } from 'react-hot-loader/root'
import { annotationsLogic } from '~/lib/components/Annotations'
import { router } from 'kea-router'
@ -101,8 +100,7 @@ const showComparePrevious = {
[`${ViewType.PATHS}`]: false,
}
export const Insights = hot(_Insights)
function _Insights() {
export function Insights() {
useMountedLogic(insightCommandLogic)
const [{ fromItem }] = useState(router.values.hashParams)
const { clearAnnotationsToCreate } = useActions(annotationsLogic({ pageKey: fromItem }))

View File

@ -11,7 +11,7 @@ import { commandPaletteLogicType } from './commandPaletteLogicType'
import { kea } from 'kea'
import { compareFilterLogic } from 'lib/components/CompareFilter/compareFilterLogic'
import { RiseOutlined } from '@ant-design/icons'
import { dateFilterLogic } from 'lib/components/DateFilter/dateFilterLogic'
import { dateFilterLogic } from 'scenes/insights/DateFilter/dateFilterLogic'
import { dateMapping } from 'lib/utils'
const INSIGHT_COMMAND_SCOPE = 'insights'

View File

@ -1,5 +1,4 @@
import React from 'react'
import { hot } from 'react-hot-loader/root'
import { Alert, Form, Button, Table, Input } from 'antd'
import { licenseLogic } from './logic'
import { useValues, useActions } from 'kea'
@ -38,8 +37,7 @@ const columns = [
},
]
export const Licenses = hot(_Licenses)
function _Licenses(): JSX.Element {
export function Licenses(): JSX.Element {
const [form] = Form.useForm()
const { licenses, licensesLoading, error } = useValues(licenseLogic)
const { createLicense } = useActions(licenseLogic)

View File

@ -1,7 +1,6 @@
import './index.scss'
import React from 'react'
import { hot } from 'react-hot-loader/root'
import { Alert, Table, Tag, Card } from 'antd'
import { systemStatusLogic } from './systemStatusLogic'
import { useValues } from 'kea'
@ -28,8 +27,7 @@ const columns = [
},
]
export const SystemStatus = hot(_Status)
function _Status(): JSX.Element {
export function SystemStatus(): JSX.Element {
const { systemStatus, systemStatusLoading, error } = useValues(systemStatusLogic)
return (
<div className="system-status-scene">

View File

@ -3,15 +3,13 @@ import { useValues } from 'kea'
import { Divider, Card } from 'antd'
import { useAnchor } from 'lib/hooks/useAnchor'
import { router } from 'kea-router'
import { hot } from 'react-hot-loader/root'
import { UpdateEmailPreferences } from './UpdateEmailPreferences'
import { ChangePassword } from './ChangePassword'
import { PersonalAPIKeys } from 'lib/components/PersonalAPIKeys'
import { OptOutCapture } from './OptOutCapture'
import { PageHeader } from 'lib/components/PageHeader'
export const MySettings = hot(_MySettings)
function _MySettings(): JSX.Element {
export function MySettings(): JSX.Element {
const { location } = useValues(router)
useAnchor(location.hash)

View File

@ -1,6 +1,5 @@
import { useActions, useValues } from 'kea'
import React from 'react'
import { hot } from 'react-hot-loader/root'
import { inviteSignupLogic, ErrorCodes } from './inviteSignupLogic'
import { SceneLoading } from 'lib/utils'
import './InviteSignup.scss'
@ -178,8 +177,7 @@ function AuthenticatedAcceptInvite({ invite }: { invite: PrevalidatedInvite }):
)
}
export const InviteSignup = hot(_InviteSignup)
function _InviteSignup(): JSX.Element {
export function InviteSignup(): JSX.Element {
const { invite, inviteLoading } = useValues(inviteSignupLogic)
const { user } = useValues(userLogic)

View File

@ -1,6 +1,5 @@
import { PageHeader } from 'lib/components/PageHeader'
import React from 'react'
import { hot } from 'react-hot-loader/root'
import { Button, Col, Collapse, Progress, Row, Switch } from 'antd'
import {
ProjectOutlined,
@ -111,8 +110,7 @@ function OnboardingStep({
)
}
export const OnboardingSetup = hot(_OnboardingSetup)
function _OnboardingSetup(): JSX.Element {
export function OnboardingSetup(): JSX.Element {
const {
stepProjectSetup,
stepInstallation,

View File

@ -1,6 +1,5 @@
import { useActions, useValues } from 'kea'
import React from 'react'
import { hot } from 'react-hot-loader/root'
import { personalizationLogic } from './personalizationLogic'
import { Row, Col, Button } from 'antd'
import { RadioSelect } from 'lib/components/RadioSelect'
@ -8,8 +7,7 @@ import { ROLES, PRODUCTS, IS_TECHNICAL } from './personalizationOptions'
import { Link } from 'lib/components/Link'
import './Personalization.scss'
export const Personalization = hot(_Personalization)
function _Personalization(): JSX.Element {
export function Personalization(): JSX.Element {
const { personalizationData } = useValues(personalizationLogic)
const { appendPersonalizationData, reportPersonalizationSkipped, reportPersonalization } = useActions(
personalizationLogic

View File

@ -4,7 +4,6 @@ import { useValues, useActions } from 'kea'
import { invitesLogic } from './invitesLogic'
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons'
import { humanFriendlyDetailedTime } from 'lib/utils'
import { hot } from 'react-hot-loader/root'
import { OrganizationInviteType, UserNestedType } from '~/types'
import { CopyToClipboardInline } from 'lib/components/CopyToClipboard'
import { CreateInviteModalWithButton } from './CreateInviteModal'
@ -46,8 +45,7 @@ function makeActionsComponent(
)
}
}
export const Invites = hot(_Invites)
function _Invites(): JSX.Element {
export function Invites(): JSX.Element {
const { invites, invitesLoading } = useValues(invitesLogic)
const { deleteInvite } = useActions(invitesLogic)

View File

@ -1,6 +1,5 @@
import React, { useState } from 'react'
import { Button, Card, Input, Divider } from 'antd'
import { hot } from 'react-hot-loader/root'
import { UserType } from '~/types'
import { PageHeader } from 'lib/components/PageHeader'
import { Invites } from './Invites'
@ -45,8 +44,7 @@ function DisplayName({ isRestricted }: RestrictedComponentProps): JSX.Element {
)
}
export const OrganizationSettings = hot(_OrganizationSettings)
function _OrganizationSettings({ user }: { user: UserType }): JSX.Element {
export function OrganizationSettings({ user }: { user: UserType }): JSX.Element {
return (
<>
<PageHeader

View File

@ -5,7 +5,6 @@ import { Tooltip, Table, Spin, Button, Input } from 'antd'
import { ExportOutlined, DeleteOutlined, InfoCircleOutlined } from '@ant-design/icons'
import { cohortsModel } from '../../models/cohortsModel'
import { useValues, useActions, kea } from 'kea'
import { hot } from 'react-hot-loader/root'
import { PageHeader } from 'lib/components/PageHeader'
import { PlusOutlined } from '@ant-design/icons'
import { Cohort } from './Cohort'
@ -51,8 +50,7 @@ const searchCohorts = (sources: CohortType[], search: string): CohortType[] => {
.map((result) => result.item)
}
export const Cohorts = hot(_Cohorts)
function _Cohorts(): JSX.Element {
export function Cohorts(): JSX.Element {
const { cohorts, cohortsLoading } = useValues(cohortsModel)
const { loadCohorts } = useActions(cohortsModel)
const { openCohort } = useValues(cohortsUrlLogic)

View File

@ -1,6 +1,5 @@
import React, { useState } from 'react'
import { Row, Tabs, Col, Card, Skeleton, Tag, Dropdown, Menu, Button, Popconfirm } from 'antd'
import { hot } from 'react-hot-loader/root'
import { SessionsView } from '../sessions/SessionsView'
import { EventsTable } from 'scenes/events'
import { useActions, useValues } from 'kea'
@ -17,8 +16,7 @@ import { NewPropertyComponent } from './NewPropertyComponent'
const { TabPane } = Tabs
export const Person = hot(_Person)
function _Person(): JSX.Element {
export function Person(): JSX.Element {
const [activeTab, setActiveTab] = useState('events')
const [mergeModalOpen, setMergeModalOpen] = useState(false)

View File

@ -1,6 +1,5 @@
import './Plugins.scss'
import React, { useEffect } from 'react'
import { hot } from 'react-hot-loader/root'
import { PluginDrawer } from 'scenes/plugins/edit/PluginDrawer'
import { RepositoryTab } from 'scenes/plugins/tabs/repository/RepositoryTab'
import { InstalledTab } from 'scenes/plugins/tabs/installed/InstalledTab'
@ -13,8 +12,7 @@ import { PageHeader } from 'lib/components/PageHeader'
import { PluginTab } from 'scenes/plugins/types'
import { AdvancedTab } from 'scenes/plugins/tabs/advanced/AdvancedTab'
export const Plugins = hot(_Plugins)
function _Plugins(): JSX.Element {
export function Plugins(): JSX.Element {
const { user } = useValues(userLogic)
const { pluginTab } = useValues(pluginsLogic)
const { setPluginTab } = useActions(pluginsLogic)

View File

@ -10,7 +10,6 @@ import { useAnchor } from 'lib/hooks/useAnchor'
import { router } from 'kea-router'
import { ReloadOutlined } from '@ant-design/icons'
import { red } from '@ant-design/colors'
import { hot } from 'react-hot-loader/root'
import { ToolbarSettings } from './ToolbarSettings'
import { CodeSnippet } from 'scenes/ingestion/frameworks/CodeSnippet'
import { teamLogic } from 'scenes/teamLogic'
@ -62,8 +61,7 @@ function DisplayName(): JSX.Element {
)
}
export const ProjectSettings = hot(_ProjectSettings)
function _ProjectSettings(): JSX.Element {
export function ProjectSettings(): JSX.Element {
const { currentTeam } = useValues(teamLogic)
const { resetToken } = useActions(teamLogic)
const { location } = useValues(router)

View File

@ -1,14 +1,12 @@
import React from 'react'
import { SessionsView } from './SessionsView'
import { hot } from 'react-hot-loader/root'
import { SavedFiltersMenu } from 'scenes/sessions/filters/SavedFiltersMenu'
import { PageHeader } from 'lib/components/PageHeader'
import { Divider } from 'antd'
import { useValues } from 'kea'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
export const Sessions = hot(_Sessions)
function _Sessions(): JSX.Element {
export function Sessions(): JSX.Element {
const { featureFlags } = useValues(featureFlagLogic)
if (featureFlags['filter_by_session_props']) {
return (

View File

@ -1,5 +1,5 @@
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { Player, PlayerRef, findCurrent } from 'posthog-react-rrweb-player'
import { Player, PlayerRef, findCurrent } from '@posthog/react-rrweb-player'
import { Card, Col, Input, Row, Skeleton, Tag } from 'antd'
import {
UserOutlined,
@ -10,7 +10,6 @@ import {
MobileOutlined,
TabletOutlined,
} from '@ant-design/icons'
import { hot } from 'react-hot-loader/root'
import { useActions, useValues } from 'kea'
import { Link } from 'lib/components/Link'
import { colorForString } from 'lib/utils'
@ -45,8 +44,7 @@ function DeviceIcon({ width }: { width: number }): JSX.Element {
return <LaptopOutlined />
}
export const SessionsPlay = hot(_SessionsPlay)
function _SessionsPlay(): JSX.Element {
export function SessionsPlay(): JSX.Element {
const {
session,
sessionPlayerData,

View File

@ -1,3 +1,3 @@
@import 'node_modules/rrweb/dist/rrweb.min';
@import 'node_modules/rc-tooltip/assets/bootstrap';
@import 'node_modules/posthog-react-rrweb-player/dist/index';
@import 'node_modules/@posthog/react-rrweb-player/dist/index';

View File

@ -5,7 +5,7 @@ import { eventToName, toParams } from 'lib/utils'
import { sessionsPlayLogicType } from './sessionsPlayLogicType'
import { PersonType, SessionType } from '~/types'
import moment from 'moment'
import { EventIndex } from 'posthog-react-rrweb-player'
import { EventIndex } from '@posthog/react-rrweb-player'
import { sessionsTableLogic } from 'scenes/sessions/sessionsTableLogic'
import { toast } from 'react-toastify'

View File

@ -2,12 +2,10 @@ import React from 'react'
import { useValues } from 'kea'
import { Elements } from '~/toolbar/elements/Elements'
import { DraggableButton } from '~/toolbar/button/DraggableButton'
import { hot } from 'react-hot-loader/root'
import { toolbarLogic } from '~/toolbar/toolbarLogic'
import { Fade } from 'lib/components/Fade/Fade'
export const ToolbarContainer = hot(_ToolbarContainer)
function _ToolbarContainer(): JSX.Element {
export function ToolbarContainer(): JSX.Element {
const { buttonVisible } = useValues(toolbarLogic)
return (

View File

@ -46,7 +46,7 @@ export function DraggableButton(): JSX.Element {
savePosition={saveHeatmapPosition}
>
<div className="toolbar-block">
<HeatmapStats buttonMode />
<HeatmapStats />
</div>
</ButtonWindow>

View File

@ -16,6 +16,7 @@ export const heatmapLogic = kea<heatmapLogicType<ElementsEventType, CountedHTMLE
enableHeatmap: true,
disableHeatmap: true,
setShowHeatmapTooltip: (showHeatmapTooltip: boolean) => ({ showHeatmapTooltip }),
setHeatmapFilter: (filter: Record<string, any>) => ({ filter }),
},
reducers: {
@ -42,18 +43,26 @@ export const heatmapLogic = kea<heatmapLogicType<ElementsEventType, CountedHTMLE
setShowHeatmapTooltip: (_, { showHeatmapTooltip }) => showHeatmapTooltip,
},
],
heatmapFilter: [
{} as Record<string, any>,
{
setHeatmapFilter: (_, { filter }) => filter,
},
],
},
loaders: {
loaders: ({ values }) => ({
events: [
[] as ElementsEventType[],
{
resetEvents: () => [],
getEvents: async ({ $current_url }: { $current_url: string }, breakpoint) => {
const params = {
const params: Record<string, any> = {
properties: [{ key: '$current_url', value: $current_url }],
temporary_token: toolbarLogic.values.temporaryToken,
...values.heatmapFilter,
}
const url = `${toolbarLogic.values.apiURL}api/element/stats/${encodeParams(params, '?')}`
const response = await fetch(url)
const results = await response.json()
@ -73,7 +82,7 @@ export const heatmapLogic = kea<heatmapLogicType<ElementsEventType, CountedHTMLE
},
},
],
},
}),
selectors: {
elements: [
@ -226,5 +235,8 @@ export const heatmapLogic = kea<heatmapLogicType<ElementsEventType, CountedHTMLE
actions.setShowHeatmapTooltip(false)
}
},
setHeatmapFilter: () => {
actions.getEvents({ $current_url: currentPageLogic.values.href })
},
}),
})

View File

@ -1,37 +1,29 @@
import React from 'react'
import { useActions, useValues } from 'kea'
import { Button, List, Space } from 'antd'
import { List, Space, Spin } from 'antd'
import { heatmapLogic } from '~/toolbar/elements/heatmapLogic'
import { FireFilled, FireOutlined } from '@ant-design/icons'
import { elementsLogic } from '~/toolbar/elements/elementsLogic'
import { getShadowRootPopupContainer } from '~/toolbar/utils'
import { DateFilter } from 'lib/components/DateFilter/DateFilter'
interface HeatmapStatsProps {
buttonMode?: boolean
}
export function HeatmapStats({ buttonMode = false }: HeatmapStatsProps): JSX.Element {
const { countedElements, clickCount, heatmapEnabled, heatmapLoading } = useValues(heatmapLogic)
const { enableHeatmap, disableHeatmap } = useActions(heatmapLogic)
export function HeatmapStats(): JSX.Element {
const { countedElements, clickCount, heatmapEnabled, heatmapLoading, heatmapFilter } = useValues(heatmapLogic)
const { setHeatmapFilter } = useActions(heatmapLogic)
const { setHighlightElement, setSelectedElement } = useActions(elementsLogic)
return (
<div>
{!buttonMode ? (
<div>
<Button
type={heatmapEnabled ? 'primary' : 'default'}
onClick={heatmapEnabled ? disableHeatmap : enableHeatmap}
loading={heatmapLoading}
>
{heatmapEnabled ? <FireFilled /> : <FireOutlined />}
Enable Heatmap
</Button>
</div>
) : null}
{heatmapEnabled && !heatmapLoading ? (
{heatmapEnabled ? (
<>
<div style={{ marginTop: buttonMode ? 0 : 20, marginBottom: 10 }}>
<span style={{ borderBottom: '2px dashed hsla(230, 14%, 78%, 1)' }}>Last 7 days</span>
<div style={{ marginTop: 0, marginBottom: 10 }}>
<DateFilter
defaultValue="Last 7 days"
dateFrom={heatmapFilter.date_from}
dateTo={heatmapFilter.date_to}
onChange={(date_from, date_to) => setHeatmapFilter({ date_from, date_to })}
getPopupContainer={getShadowRootPopupContainer}
/>
{heatmapLoading ? <Spin style={{ marginLeft: 8 }} /> : null}
</div>
<div style={{ marginTop: 20, marginBottom: 10 }}>
Found: {countedElements.length} elements / {clickCount} clicks!

View File

@ -20,9 +20,13 @@
.ant-modal-wrap {
z-index: 2147483030 !important;
}
.ant-tooltip {
.ant-select-dropdown,
.ant-picker-dropdown {
z-index: 2147483031 !important;
}
.ant-tooltip {
z-index: 2147483032 !important;
}
.ant-list-item {
&:hover {
background: #f0f0f0;

View File

@ -19,9 +19,9 @@
"copy-scripts": "cp node_modules/posthog-js/dist/array.js* frontend/dist/; cp node_modules/rrweb/dist/rrweb.min.js frontend/dist/recorder.js",
"test": "jest",
"start": "concurrently -n WEBPACK,TYPEGEN -c blue,green \"yarn run start-http\" \"yarn run typegen:watch\"",
"start-http": "mkdir -p frontend/dist/ && cp -a frontend/public/* frontend/dist/ && npm run copy-scripts && webpack-dev-server --hotOnly",
"start-https": "mkdir -p frontend/dist/ && cp -a frontend/public/* frontend/dist/ && npm run copy-scripts && webpack-dev-server --hotOnly --https",
"start-docker": "mkdir -p frontend/dist/ && cp -a frontend/public/* frontend/dist/ && npm run copy-scripts && webpack-dev-server --hotOnly --host 0.0.0.0",
"start-http": "mkdir -p frontend/dist/ && cp -a frontend/public/* frontend/dist/ && npm run copy-scripts && webpack serve",
"start-https": "mkdir -p frontend/dist/ && cp -a frontend/public/* frontend/dist/ && npm run copy-scripts && webpack serve --https",
"start-docker": "mkdir -p frontend/dist/ && cp -a frontend/public/* frontend/dist/ && npm run copy-scripts && webpack serve --host 0.0.0.0",
"build": "echo \"Building Webpack\" && NODE_ENV=production webpack --config webpack.config.js && cp -a frontend/public/* frontend/dist/ && npm run copy-scripts",
"prettier": "prettier --write \"./frontend/src/**/*.{js,ts,tsx,json,yml,css,scss}\"",
"prettier:check": "prettier --check \"./**/*.{js,ts,tsx,json,yml,css,scss}\"",
@ -40,6 +40,7 @@
"@babel/runtime": "^7.10.4",
"@papercups-io/chat-widget": "^1.1.5",
"@posthog/plugin-scaffold": "0.2.12",
"@posthog/react-rrweb-player": "^1.1.0",
"@posthog/simmerjs": "0.7.2-posthog.2",
"@sentry/browser": "^6.0.4",
"@types/crypto-js": "^4.0.1",
@ -62,14 +63,13 @@
"moment": "^2.24.0",
"posthog-js": "1.9.1",
"posthog-js-lite": "^0.0.3",
"posthog-react-rrweb-player": "^1.0.13",
"prop-types": "^15.7.2",
"query-selector-shadow-dom": "0.8.0",
"react": "^16.13.1",
"react-dom": "^16.12.0",
"react-draggable": "^4.2.0",
"react-grid-layout": "^1.1.1",
"react-markdown": "^5.0.2",
"react-markdown": "^5.0.3",
"react-monaco-editor": "^0.40.0",
"react-redux": "^7.2.0",
"react-shadow": "^18.4.2",
@ -115,8 +115,8 @@
"eslint-plugin-react": "^7.20.3",
"file-loader": "^6.1.0",
"givens": "^1.3.6",
"html-webpack-harddisk-plugin": "^1.0.1",
"html-webpack-plugin": "^4.4.1",
"html-webpack-harddisk-plugin": "^1.0.2",
"html-webpack-plugin": "^4.5.2",
"husky": "^4.3.0",
"jest": "^26.6.3",
"kea-typegen": "^0.5.1",
@ -127,14 +127,13 @@
"monaco-editor-webpack-plugin": "^2.0.0",
"postcss-loader": "^3.0.0",
"prettier": "^2.1.1",
"react-hot-loader": "^4.12.21",
"sass-loader": "^10.0.1",
"style-loader": "^1.2.1",
"ts-node": "^9.1.1",
"typescript": "^3.9.0",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
"webpack": "^4.46.0",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
},
"optionalDependencies": {
"fsevents": "^2.1.2"

View File

@ -85,11 +85,6 @@ function createEntry(entry) {
types: path.resolve(__dirname, 'frontend', 'types'),
public: path.resolve(__dirname, 'frontend', 'public'),
cypress: path.resolve(__dirname, 'cypress'),
...(process.env.NODE_ENV !== 'production'
? {
'react-dom': '@hot-loader/react-dom',
}
: {}),
},
},
module: {
@ -182,19 +177,26 @@ function createEntry(entry) {
},
],
},
devServer: {
contentBase: path.join(__dirname, 'frontend', 'dist'),
hot: true,
host: webpackDevServerHost,
port: 8234,
stats: 'minimal',
disableHostCheck: !!process.env.LOCAL_HTTPS,
public: process.env.JS_URL ? new URL(process.env.JS_URL).host : `${webpackDevServerFrontendAddr}:8234`,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
},
},
// add devServer config only to 'main' entry
...(entry === 'main'
? {
devServer: {
contentBase: path.join(__dirname, 'frontend', 'dist'),
hot: true,
host: webpackDevServerHost,
port: 8234,
stats: 'minimal',
disableHostCheck: !!process.env.LOCAL_HTTPS,
public: process.env.JS_URL
? new URL(process.env.JS_URL).host
: `${webpackDevServerFrontendAddr}:8234`,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
},
},
}
: {}),
plugins: [
new MonacoWebpackPlugin({
languages: ['json', 'javascript'],

738
yarn.lock

File diff suppressed because it is too large Load Diff