mirror of
https://github.com/BillyOutlast/posthog.git
synced 2026-02-04 03:01:23 +01:00
feat(embeds): various changes (#10597)
* upgrade storybook * flip the "legend" option, enable by default on png exports * noHeader sharing mode for insights * fix storybook 6.5 issue * split exporter component and rendering * remove `fitScreen` from options - it was not used anywhere from what I can tell * storybook with no data * get an actual iframe into storybook * export insight * dashboard mock * load dashboard directly, not via window * add dashboard story * tweaks * code fixes * fix type
This commit is contained in:
@@ -34,7 +34,7 @@ await buildInParallel(
|
||||
},
|
||||
{
|
||||
name: 'Exporter',
|
||||
entryPoints: ['src/exporter/Exporter.tsx'],
|
||||
entryPoints: ['src/exporter/index.tsx'],
|
||||
format: 'iife',
|
||||
outfile: path.resolve(__dirname, 'dist', 'exporter.js'),
|
||||
...common,
|
||||
@@ -76,5 +76,5 @@ export function writeIndexHtml(chunks = {}, entrypoints = []) {
|
||||
}
|
||||
|
||||
export function writeExporterHtml(chunks = {}, entrypoints = []) {
|
||||
copyIndexHtml(__dirname, 'src/exporter/exporter.html', 'dist/exporter.html', 'exporter', chunks, entrypoints)
|
||||
copyIndexHtml(__dirname, 'src/exporter/index.html', 'dist/exporter.html', 'exporter', chunks, entrypoints)
|
||||
}
|
||||
|
||||
@@ -9,21 +9,22 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.ExportedInsight-header {
|
||||
.ExportedInsight__header {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.ExportedInsight-header-title {
|
||||
.ExportedInsight__header__title {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.ExportedInsight-content {
|
||||
.ExportedInsight__content {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
.FunnelBarChart {
|
||||
min-height: 50vw;
|
||||
}
|
||||
@@ -39,11 +40,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
.ExportedInsight__watermark {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
svg {
|
||||
font-size: 0.75rem;
|
||||
margin: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.ExportedInsight--fit-screen {
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
|
||||
.ExportedInsight-content {
|
||||
.ExportedInsight__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -59,6 +71,10 @@
|
||||
min-height: 100px;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
&.ExportedInsight__content--with-watermark {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,17 @@ import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
|
||||
import { dateFilterToText } from 'lib/utils'
|
||||
import { FriendlyLogo } from '~/toolbar/assets/FriendlyLogo'
|
||||
import { InsightLegend } from 'lib/components/InsightLegend/InsightLegend'
|
||||
import { ExportOptions } from '~/exporter/types'
|
||||
import { ExportOptions, ExportType } from '~/exporter/types'
|
||||
import clsx from 'clsx'
|
||||
|
||||
export function ExportedInsight({
|
||||
insight,
|
||||
exportOptions: { whitelabel, noLegend, fitScreen },
|
||||
exportOptions: { whitelabel, noHeader, legend },
|
||||
type,
|
||||
}: {
|
||||
insight: InsightModel
|
||||
exportOptions: ExportOptions
|
||||
type: ExportType
|
||||
}): JSX.Element {
|
||||
const insightLogicProps: InsightLogicProps = {
|
||||
dashboardItemId: insight.short_id,
|
||||
@@ -27,36 +29,51 @@ export function ExportedInsight({
|
||||
const { filters, name, derived_name, description } = insight
|
||||
|
||||
const showLegend =
|
||||
!noLegend &&
|
||||
legend &&
|
||||
filters.insight === InsightType.TRENDS &&
|
||||
filters.display !== ChartDisplayType.WorldMap &&
|
||||
filters.display !== ChartDisplayType.ActionsTable
|
||||
const showWatermark = noHeader && !whitelabel
|
||||
|
||||
return (
|
||||
<BindLogic logic={insightLogic} props={insightLogicProps}>
|
||||
<div
|
||||
className={clsx('ExportedInsight', {
|
||||
'ExportedInsight--fit-screen': fitScreen,
|
||||
'ExportedInsight--fit-screen': type === ExportType.Embed,
|
||||
})}
|
||||
>
|
||||
<div className="ExportedInsight-header">
|
||||
<div>
|
||||
<h5>
|
||||
<span title={INSIGHT_TYPES_METADATA[filters.insight || InsightType.TRENDS]?.description}>
|
||||
{INSIGHT_TYPES_METADATA[filters.insight || InsightType.TRENDS]?.name}
|
||||
</span>{' '}
|
||||
• {dateFilterToText(filters.date_from, filters.date_to, 'Last 7 days')}
|
||||
</h5>
|
||||
<h4 title={name} className="ExportedInsight-header-title">
|
||||
{name || derived_name}
|
||||
</h4>
|
||||
{description && <div className="ExportedInsight-header-description">{description}</div>}
|
||||
{!noHeader && (
|
||||
<div className="ExportedInsight__header">
|
||||
<div>
|
||||
<h5>
|
||||
<span
|
||||
title={INSIGHT_TYPES_METADATA[filters.insight || InsightType.TRENDS]?.description}
|
||||
>
|
||||
{INSIGHT_TYPES_METADATA[filters.insight || InsightType.TRENDS]?.name}
|
||||
</span>{' '}
|
||||
• {dateFilterToText(filters.date_from, filters.date_to, 'Last 7 days')}
|
||||
</h5>
|
||||
<h4 title={name} className="ExportedInsight__header__title">
|
||||
{name || derived_name}
|
||||
</h4>
|
||||
{description && <div className="ExportedInsight__header-description">{description}</div>}
|
||||
</div>
|
||||
|
||||
{!whitelabel && <FriendlyLogo style={{ fontSize: '1rem' }} />}
|
||||
</div>
|
||||
)}
|
||||
{showWatermark && (
|
||||
<div className="ExportedInsight__watermark">
|
||||
<FriendlyLogo />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!whitelabel && <FriendlyLogo style={{ fontSize: '1rem' }} />}
|
||||
</div>
|
||||
|
||||
<div className="ExportedInsight-content">
|
||||
<div
|
||||
className={clsx({
|
||||
ExportedInsight__content: true,
|
||||
'ExportedInsight__content--with-watermark': showWatermark,
|
||||
})}
|
||||
>
|
||||
<InsightViz insight={insight as any} style={{ top: 0, left: 0, position: 'relative' }} />
|
||||
{showLegend ? (
|
||||
<div className="pa">
|
||||
|
||||
41
frontend/src/exporter/Exporter.stories.tsx
Normal file
41
frontend/src/exporter/Exporter.stories.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { ComponentMeta, ComponentStory } from '@storybook/react'
|
||||
import { Exporter } from './Exporter'
|
||||
import { insight, dashboard } from '~/exporter/__mocks__/Exporter.mocks'
|
||||
|
||||
export default {
|
||||
title: 'Exporter/Exporter',
|
||||
component: Exporter,
|
||||
args: {
|
||||
type: 'embed',
|
||||
whitelabel: false,
|
||||
noHeader: false,
|
||||
legend: false,
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
inlineStories: false,
|
||||
iframeHeight: 400,
|
||||
source: { state: 'close' },
|
||||
},
|
||||
viewMode: 'story',
|
||||
},
|
||||
} as ComponentMeta<typeof Exporter>
|
||||
|
||||
const Template: ComponentStory<typeof Exporter> = (props) => {
|
||||
useEffect(() => {
|
||||
document.body.className = ''
|
||||
document.documentElement.className = `export-type-${props.type}`
|
||||
}, [props.type])
|
||||
return (
|
||||
<div className={`storybook-export-type-${props.type}`}>
|
||||
<Exporter {...props} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const Insight = Template.bind({})
|
||||
Insight.args = { insight }
|
||||
|
||||
export const Dashboard = Template.bind({})
|
||||
Dashboard.args = { dashboard }
|
||||
@@ -1,31 +1,16 @@
|
||||
import '~/styles'
|
||||
import './Exporter.scss'
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { loadPostHogJS } from '~/loadPostHogJS'
|
||||
import { initKea } from '~/initKea'
|
||||
import { ExportedData, ExportType } from '~/exporter/types'
|
||||
import { DashboardPlacement } from '~/types'
|
||||
import { ExportedInsight } from '~/exporter/ExportedInsight/ExportedInsight'
|
||||
import { FriendlyLogo } from '~/toolbar/assets/FriendlyLogo'
|
||||
import { Dashboard } from 'scenes/dashboard/Dashboard'
|
||||
|
||||
const exportedData: ExportedData = window.POSTHOG_EXPORTED_DATA
|
||||
|
||||
// Disable tracking for all exports and embeds.
|
||||
// This is explicitly set as to not track our customers' customers data.
|
||||
// Without it, embeds of self-hosted iframes will log metrics to app.posthog.com.
|
||||
window.JS_POSTHOG_API_KEY = null
|
||||
|
||||
loadPostHogJS()
|
||||
initKea()
|
||||
|
||||
function Exporter(): JSX.Element {
|
||||
const { type, dashboard, insight, team, ...exportOptions } = exportedData
|
||||
export function Exporter(props: ExportedData): JSX.Element {
|
||||
const { type, dashboard, insight, team, ...exportOptions } = props
|
||||
const { whitelabel } = exportOptions
|
||||
|
||||
exportOptions.fitScreen = exportOptions.fitScreen ?? type == ExportType.Embed
|
||||
|
||||
return (
|
||||
<div className="Exporter">
|
||||
{!whitelabel && dashboard ? (
|
||||
@@ -60,10 +45,11 @@ function Exporter(): JSX.Element {
|
||||
) : null}
|
||||
|
||||
{insight ? (
|
||||
<ExportedInsight insight={insight} exportOptions={exportOptions} />
|
||||
<ExportedInsight type={type} insight={insight} exportOptions={exportOptions} />
|
||||
) : dashboard ? (
|
||||
<Dashboard
|
||||
id={String(dashboard.id)}
|
||||
dashboard={dashboard}
|
||||
placement={type === ExportType.Image ? DashboardPlacement.Export : DashboardPlacement.Public}
|
||||
/>
|
||||
) : (
|
||||
@@ -88,5 +74,3 @@ function Exporter(): JSX.Element {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ReactDOM.render(<Exporter />, document.getElementById('root'))
|
||||
|
||||
1421
frontend/src/exporter/__mocks__/Exporter.mocks.tsx
Normal file
1421
frontend/src/exporter/__mocks__/Exporter.mocks.tsx
Normal file
File diff suppressed because it is too large
Load Diff
20
frontend/src/exporter/index.tsx
Normal file
20
frontend/src/exporter/index.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import '~/styles'
|
||||
import './Exporter.scss'
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { loadPostHogJS } from '~/loadPostHogJS'
|
||||
import { initKea } from '~/initKea'
|
||||
import { Exporter } from '~/exporter/Exporter'
|
||||
import { ExportedData } from '~/exporter/types'
|
||||
|
||||
// Disable tracking for all exports and embeds.
|
||||
// This is explicitly set as to not track our customers' customers data.
|
||||
// Without it, embeds of self-hosted iframes will log metrics to app.posthog.com.
|
||||
window.JS_POSTHOG_API_KEY = null
|
||||
|
||||
loadPostHogJS()
|
||||
initKea()
|
||||
|
||||
const exportedData: ExportedData = window.POSTHOG_EXPORTED_DATA
|
||||
|
||||
ReactDOM.render(<Exporter {...exportedData} />, document.getElementById('root'))
|
||||
@@ -8,13 +8,13 @@ export enum ExportType {
|
||||
|
||||
export interface ExportOptions {
|
||||
whitelabel?: boolean
|
||||
noLegend?: boolean
|
||||
fitScreen?: boolean
|
||||
noHeader?: boolean
|
||||
legend?: boolean
|
||||
}
|
||||
|
||||
export interface ExportedData extends ExportOptions {
|
||||
type: ExportType
|
||||
dashboard?: Partial<DashboardType>
|
||||
dashboard?: DashboardType
|
||||
insight?: InsightModel
|
||||
team?: Partial<TeamType>
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { SideBar } from './SideBar/SideBar'
|
||||
|
||||
export default {
|
||||
title: 'Layout/Navigation',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export function Navigation_(): JSX.Element {
|
||||
|
||||
@@ -15,7 +15,7 @@ const fakeInsight: Partial<InsightModel> = {
|
||||
export default {
|
||||
title: 'Components/Sharing',
|
||||
component: Sharing,
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as ComponentMeta<typeof Sharing>
|
||||
|
||||
const Template = (args: Partial<SharingModalProps> & { licensed?: boolean }): JSX.Element => {
|
||||
|
||||
@@ -42,7 +42,7 @@ export function Sharing({ dashboardId, insightShortId, insight, closeModal }: Sh
|
||||
|
||||
const [iframeLoaded, setIframeLoaded] = useState(false)
|
||||
|
||||
const showNoLegendCheckbox = insight?.filters?.insight === InsightType.TRENDS
|
||||
const showLegendCheckbox = insight?.filters?.insight === InsightType.TRENDS
|
||||
const resource = dashboardId ? 'dashboard' : 'insight'
|
||||
|
||||
useEffect(() => {
|
||||
@@ -152,15 +152,28 @@ export function Sharing({ dashboardId, insightShortId, insight, closeModal }: Sh
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
{showNoLegendCheckbox && (
|
||||
<Field name="noLegend" noStyle>
|
||||
{insight && (
|
||||
<Field name="noHeader" noStyle>
|
||||
{({ value, onChange }) => (
|
||||
<LemonSwitch
|
||||
fullWidth
|
||||
type="primary"
|
||||
label={<div>Show title and description</div>}
|
||||
onChange={() => onChange(!value)}
|
||||
checked={!value}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
)}
|
||||
{showLegendCheckbox && (
|
||||
<Field name="legend" noStyle>
|
||||
{({ value, onChange }) => (
|
||||
<LemonSwitch
|
||||
fullWidth
|
||||
type="primary"
|
||||
label={<div>Show legend</div>}
|
||||
onChange={() => onChange(!value)}
|
||||
checked={!value}
|
||||
checked={value}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
||||
@@ -28,7 +28,8 @@ const defaultEmbedConfig: EmbedConfig = {
|
||||
width: '100%',
|
||||
height: '400',
|
||||
whitelabel: false,
|
||||
noLegend: false,
|
||||
legend: false,
|
||||
noHeader: false,
|
||||
}
|
||||
|
||||
const propsToApiParams = async (props: SharingLogicProps): Promise<{ dashboardId?: number; insightId?: number }> => {
|
||||
@@ -87,16 +88,16 @@ export const sharingLogic = kea<sharingLogicType>([
|
||||
],
|
||||
shareLink: [
|
||||
(s) => [s.siteUrl, s.sharingConfiguration, s.embedConfig],
|
||||
(siteUrl, sharingConfiguration, { whitelabel, noLegend }) =>
|
||||
(siteUrl, sharingConfiguration, { whitelabel, legend, noHeader }) =>
|
||||
sharingConfiguration
|
||||
? siteUrl + urls.shared(sharingConfiguration.access_token, { whitelabel, noLegend })
|
||||
? siteUrl + urls.shared(sharingConfiguration.access_token, { whitelabel, legend, noHeader })
|
||||
: '',
|
||||
],
|
||||
embedLink: [
|
||||
(s) => [s.siteUrl, s.sharingConfiguration, s.embedConfig],
|
||||
(siteUrl, sharingConfiguration, { whitelabel, noLegend }) =>
|
||||
(siteUrl, sharingConfiguration, { whitelabel, legend, noHeader }) =>
|
||||
sharingConfiguration
|
||||
? siteUrl + urls.embedded(sharingConfiguration.access_token, { whitelabel, noLegend })
|
||||
? siteUrl + urls.embedded(sharingConfiguration.access_token, { whitelabel, legend, noHeader })
|
||||
: '',
|
||||
],
|
||||
iframeProperties: [
|
||||
|
||||
@@ -13,7 +13,7 @@ import { createMockSubscription, mockIntegration, mockSlackChannels } from '~/te
|
||||
export default {
|
||||
title: 'Components/Subscriptions',
|
||||
component: Subscriptions,
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as ComponentMeta<typeof Subscriptions>
|
||||
|
||||
const Template = (
|
||||
|
||||
@@ -1088,7 +1088,7 @@ export function endWithPunctation(text?: string | null): string {
|
||||
return trimmedText
|
||||
}
|
||||
|
||||
export function shortTimeZone(timeZone?: string, atDate?: Date): string | null {
|
||||
export function shortTimeZone(timeZone?: string | null, atDate?: Date): string | null {
|
||||
/**
|
||||
* Return the short timezone identifier for a specific timezone (e.g. BST, EST, PDT, UTC+2).
|
||||
* @param timeZone E.g. 'America/New_York'
|
||||
|
||||
@@ -5,7 +5,7 @@ import React from 'react'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-Other/Onboarding',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export const Preflight = (): JSX.Element => <PreflightCheck />
|
||||
|
||||
@@ -5,7 +5,7 @@ import React from 'react'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-Other/Unsubscribe',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export const UnsubscribeScene = (): JSX.Element => <Unsubscribe />
|
||||
|
||||
@@ -9,7 +9,7 @@ import { urls } from 'scenes/urls'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-Other/Login',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
// export more stories with different state
|
||||
|
||||
@@ -9,7 +9,7 @@ import { passwordResetLogic } from 'scenes/authentication/passwordResetLogic'
|
||||
// some metadata and optional parameters
|
||||
export default {
|
||||
title: 'Scenes-Other/Password Reset',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
// export more stories with different state
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useStorybookMocks } from '~/mocks/browser'
|
||||
// some metadata and optional parameters
|
||||
export default {
|
||||
title: 'Scenes-Other/Password Reset Complete',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
// export more stories with different state
|
||||
|
||||
@@ -8,7 +8,7 @@ import preflightJson from '~/mocks/fixtures/_preflight.json'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-Other/Signup',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
decorators: [
|
||||
mswDecorator({
|
||||
get: { '/api/users/@me': () => [500, null] },
|
||||
|
||||
@@ -8,7 +8,7 @@ import { urls } from 'scenes/urls'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-Other/Billing',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
decorators: [
|
||||
mswDecorator({
|
||||
get: {
|
||||
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
},
|
||||
}),
|
||||
],
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export const List = (): JSX.Element => {
|
||||
|
||||
@@ -541,11 +541,7 @@ export const dashboardLogic = kea<dashboardLogicType>({
|
||||
events: ({ actions, cache, props }) => ({
|
||||
afterMount: () => {
|
||||
if (props.id) {
|
||||
const exportedDashboard = window.POSTHOG_EXPORTED_DATA?.dashboard
|
||||
if (exportedDashboard && exportedDashboard.id === props.id && exportedDashboard.items) {
|
||||
actions.loadExportedDashboard(exportedDashboard as DashboardType)
|
||||
} else if (props.dashboard) {
|
||||
// When the scene is initially loaded, the dashboard ID is undefined
|
||||
if (props.dashboard) {
|
||||
actions.loadExportedDashboard(props.dashboard)
|
||||
} else {
|
||||
actions.loadDashboardItems({
|
||||
|
||||
@@ -14,7 +14,7 @@ export default {
|
||||
get: { '/api/projects/:projectId/events': { next: null, results: eventList } },
|
||||
}),
|
||||
],
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export const LiveEvents = (): JSX.Element => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { AvailableFeature } from '~/types'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-App/Feature Flags',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' }, // scene mode
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' }, // scene mode
|
||||
decorators: [
|
||||
mswDecorator({
|
||||
get: {
|
||||
|
||||
@@ -6,7 +6,7 @@ import React from 'react'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-Other/Onboarding',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export const Ingestion = (): JSX.Element => <IngestionWizard />
|
||||
|
||||
@@ -12,7 +12,7 @@ import { App } from 'scenes/App'
|
||||
// some metadata and optional parameters
|
||||
export default {
|
||||
title: 'Scenes-App/Insights/Error states',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export function EmptyState(): JSX.Element {
|
||||
|
||||
@@ -45,7 +45,7 @@ export interface InsightTooltipProps extends TooltipConfig {
|
||||
seriesData?: SeriesDatum[]
|
||||
forceEntitiesAsColumns?: boolean
|
||||
groupTypeLabel?: string
|
||||
timezone?: string
|
||||
timezone?: string | null
|
||||
}
|
||||
|
||||
export const COL_CUTOFF = 4
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createInsightScene } from 'scenes/insights/__mocks__/createInsightScene
|
||||
|
||||
export default {
|
||||
title: 'Scenes-App/Insights',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
decorators: [
|
||||
mswDecorator({
|
||||
get: {
|
||||
|
||||
@@ -59,7 +59,7 @@ interface LineGraphProps {
|
||||
isCompare?: boolean
|
||||
incompletenessOffsetFromEnd?: number // Number of data points at end of dataset to replace with a dotted line. Only used in line graphs.
|
||||
labelGroupType: number | 'people' | 'none'
|
||||
timezone?: string
|
||||
timezone?: string | null
|
||||
}
|
||||
|
||||
const noop = (): void => {}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { urls } from 'scenes/urls'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-App/Licenses',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export const Licenses = (): JSX.Element => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { PerfBlock } from 'scenes/performance/WebPerformanceWaterfallChart'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-App/Web Performance',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
decorators: [
|
||||
mswDecorator({
|
||||
get: {
|
||||
|
||||
@@ -16,7 +16,7 @@ export default {
|
||||
},
|
||||
}),
|
||||
],
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
export const ProjectHomepage = (): JSX.Element => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { SlackIntegration } from './SlackIntegration'
|
||||
export default {
|
||||
title: 'Components/Integrations/Slack',
|
||||
component: SlackIntegration,
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as ComponentMeta<typeof SlackIntegration>
|
||||
|
||||
const Template = (args: { instanceConfigured?: boolean; integrated?: boolean }): JSX.Element => {
|
||||
|
||||
@@ -15,7 +15,7 @@ const insights = [trendsBarBreakdown, trendsPieBreakdown, funnelTopToBottom]
|
||||
|
||||
export default {
|
||||
title: 'Scenes-App/Saved Insights',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
decorators: [
|
||||
mswDecorator({
|
||||
get: {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { App } from 'scenes/App'
|
||||
|
||||
export default {
|
||||
title: 'Scenes-App/Recordings',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
decorators: [
|
||||
mswDecorator({
|
||||
get: {
|
||||
|
||||
@@ -92,11 +92,13 @@ export const urls = {
|
||||
shared: (token: string, exportOptions?: ExportOptions): string =>
|
||||
combineUrl(`/shared/${token}`, {
|
||||
...(exportOptions?.whitelabel ? { whitelabel: null } : {}),
|
||||
...(exportOptions?.noLegend ? { noLegend: null } : {}),
|
||||
...(exportOptions?.legend ? { legend: null } : {}),
|
||||
...(exportOptions?.noHeader ? { legend: null } : {}),
|
||||
}).url,
|
||||
embedded: (token: string, exportOptions?: ExportOptions): string =>
|
||||
combineUrl(`/embedded/${token}`, {
|
||||
...(exportOptions?.whitelabel ? { whitelabel: null } : {}),
|
||||
...(exportOptions?.noLegend ? { noLegend: null } : {}),
|
||||
...(exportOptions?.legend ? { legend: null } : {}),
|
||||
...(exportOptions?.noHeader ? { noHeader: null } : {}),
|
||||
}).url,
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ export default {
|
||||
}),
|
||||
],
|
||||
// NB! These `parameters` only apply for Scene stories.
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' }, // scene mode
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' }, // scene mode
|
||||
} as Meta
|
||||
|
||||
export function NewDashboard (): JSX.Element {
|
||||
|
||||
@@ -21,7 +21,7 @@ const editorParams: EditorProps = {
|
||||
|
||||
export default {
|
||||
title: 'Scenes-Other/Toolbar',
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'canvas' },
|
||||
parameters: { layout: 'fullscreen', options: { showPanel: false }, viewMode: 'story' },
|
||||
} as Meta
|
||||
|
||||
function useToolbarStyles(): void {
|
||||
|
||||
@@ -797,7 +797,7 @@ export interface InsightModel extends DashboardTile {
|
||||
/** The primary key in the database, used as well in API endpoints */
|
||||
id: number
|
||||
name: string
|
||||
derived_name?: string
|
||||
derived_name?: string | null
|
||||
description?: string
|
||||
favorited?: boolean
|
||||
order: number | null
|
||||
@@ -814,7 +814,7 @@ export interface InsightModel extends DashboardTile {
|
||||
last_modified_by: UserBasicType | null
|
||||
effective_restriction_level: DashboardRestrictionLevel
|
||||
effective_privilege_level: DashboardPrivilegeLevel
|
||||
timezone?: string
|
||||
timezone?: string | null
|
||||
/** Only used in the frontend to store the next breakdown url */
|
||||
next?: string
|
||||
}
|
||||
|
||||
12
package.json
12
package.json
@@ -123,11 +123,11 @@
|
||||
"@babel/preset-typescript": "^7.16.7",
|
||||
"@cypress/webpack-preprocessor": "5.12.0",
|
||||
"@hot-loader/react-dom": "^16.13.0",
|
||||
"@storybook/addon-actions": "^6.4.19",
|
||||
"@storybook/addon-essentials": "^6.4.19",
|
||||
"@storybook/addon-links": "^6.4.19",
|
||||
"@storybook/addon-storysource": "^6.4.19",
|
||||
"@storybook/react": "^6.4.19",
|
||||
"@storybook/addon-actions": "^6.5.9",
|
||||
"@storybook/addon-essentials": "^6.5.9",
|
||||
"@storybook/addon-links": "^6.5.9",
|
||||
"@storybook/addon-storysource": "^6.5.9",
|
||||
"@storybook/react": "^6.5.9",
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react": "^12.1.2",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@@ -191,7 +191,7 @@
|
||||
"prettier": "^2.3.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"sass-loader": "^10.0.1",
|
||||
"storybook-addon-turbo-build": "^1.0.1",
|
||||
"storybook-addon-turbo-build": "^1.1.0",
|
||||
"style-loader": "^2.0.0",
|
||||
"timekeeper": "^2.2.0",
|
||||
"ts-node": "^9.1.1",
|
||||
|
||||
@@ -185,8 +185,10 @@ class SharingViewerPageViewSet(mixins.RetrieveModelMixin, StructuredViewSetMixin
|
||||
|
||||
if "whitelabel" in request.GET and "white_labelling" in resource.team.organization.available_features:
|
||||
exported_data.update({"whitelabel": True})
|
||||
if "noLegend" in request.GET:
|
||||
exported_data.update({"noLegend": True})
|
||||
if "noHeader" in request.GET:
|
||||
exported_data.update({"noHeader": True})
|
||||
if "legend" in request.GET:
|
||||
exported_data.update({"legend": True})
|
||||
|
||||
if request.path.endswith(f".json"):
|
||||
return response.Response(exported_data)
|
||||
|
||||
@@ -77,7 +77,7 @@ def _export_to_png(exported_asset: ExportedAsset) -> None:
|
||||
access_token = get_public_access_token(exported_asset, timedelta(minutes=15))
|
||||
|
||||
if exported_asset.insight is not None:
|
||||
url_to_render = absolute_uri(f"/exporter?token={access_token}")
|
||||
url_to_render = absolute_uri(f"/exporter?token={access_token}&legend")
|
||||
wait_for_css_selector = ".ExportedInsight"
|
||||
screenshot_width = 800
|
||||
elif exported_asset.dashboard is not None:
|
||||
|
||||
Reference in New Issue
Block a user