Skip to content

Commit

Permalink
Merge pull request #203 from swishjam/misc-improvements
Browse files Browse the repository at this point in the history
misc improvments
  • Loading branch information
CollinSchneider committed Apr 23, 2024
2 parents 893920e + a4bd5bb commit 3bab56a
Show file tree
Hide file tree
Showing 29 changed files with 237 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ class UserPropertiesAugmentor < Ingestion::EventPreparers::Base
AnalyticsUserProfile::ReservedMetadataProperties.INITIAL_LANDING_PAGE_URL_QUERY_PARAMS => [Analytics::Event::ReservedPropertyNames.SESSION_LANDING_PAGE_URL_QUERY_PARAMS, Analytics::Event::ReservedPropertyNames.URL_QUERY_PARAMS],
AnalyticsUserProfile::ReservedMetadataProperties.INITIAL_LANDING_PAGE_BASE_URL => [Analytics::Event::ReservedPropertyNames.SESSION_LANDING_PAGE_BASE_URL, Analytics::Event::ReservedPropertyNames.BASE_URL],

# .INITIAL_REFERRER semantically makes the most sense becaues the referrer can be 'direct' or a URL
# the _URL suffixes (besides .INITIAL_REFERRER_URL) will only be populated if the referrer is a URL
AnalyticsUserProfile::ReservedMetadataProperties.INITIAL_REFERRER => [Analytics::Event::ReservedPropertyNames.SESSION_REFERRER_URL, Analytics::Event::ReservedPropertyNames.REFERRER]
AnalyticsUserProfile::ReservedMetadataProperties.INITIAL_REFERRER_URL => [Analytics::Event::ReservedPropertyNames.SESSION_REFERRER_URL, Analytics::Event::ReservedPropertyNames.REFERRER],
AnalyticsUserProfile::ReservedMetadataProperties.INITIAL_REFERRER_URL_HOST => [Analytics::Event::ReservedPropertyNames.SESSION_REFERRER_URL_HOST, Analytics::Event::ReservedPropertyNames.REFERRER_URL_HOST],
AnalyticsUserProfile::ReservedMetadataProperties.INITIAL_REFERRER_URL_PATH => [Analytics::Event::ReservedPropertyNames.SESSION_REFERRER_URL_PATH, Analytics::Event::ReservedPropertyNames.REFERRER_URL_PATH],
Expand Down
1 change: 1 addition & 0 deletions backend/app/models/analytics/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class << self
SESSION_LANDING_PAGE_URL_PATH
SESSION_LANDING_PAGE_URL_QUERY_PARAMS
SESSION_LANDING_PAGE_BASE_URL
SESSION_REFERRER
SESSION_REFERRER_URL
SESSION_REFERRER_URL_HOST
SESSION_REFERRER_URL_PATH
Expand Down
1 change: 1 addition & 0 deletions backend/app/models/analytics_user_profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class << self
INITIAL_LANDING_PAGE_URL_QUERY_PARAMS
INITIAL_LANDING_PAGE_BASE_URL

INITIAL_REFERRER
INITIAL_REFERRER_URL
INITIAL_REFERRER_URL_HOST
INITIAL_REFERRER_URL_PATH
Expand Down
8 changes: 5 additions & 3 deletions dashboard/src/app/(authenticated)/dashboards/[id]/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Timefilter from "@/components/Timefilter";
import { useEffect, useState, useRef } from "react";
import ValueCardConfiguration from "@/components/Dashboards/Builder/Configurations/ValueCard";
import { swishjam } from "@swishjam/react";
import { Dialog, DialogModal } from "@/components/ui/dialog";

const AUTO_SAVE_CHECK_INTERVAL = 2_500;
const DEFAULT_GRID_CONFIGURATIONS = {
Expand All @@ -36,9 +37,10 @@ const ConfigureDashboardComponentModal = ({ componentType, eventOptions, onSave,
ValueCard: ValueCardConfiguration,
}[componentType];
return (
<Modal onClose={onClose} isOpen={true} closeOnBackdropClick={false} size="x-large">

<DialogModal open={true} onOpenChange={onClose} fullWidth={true} title={`Configure ${componentType}`}>
<ConfigurationComponent eventOptions={eventOptions} onConfigurationSave={onSave} />
</Modal>
</DialogModal>
)
}

Expand Down Expand Up @@ -168,7 +170,7 @@ export default function Dashboard({ params }) {
}}
/>
)}
<div className='grid grid-cols-2 mt-8 flex items-center'>
<div className='grid grid-cols-2 mt-8 items-center'>
<div>
{dashboardName === undefined
? <Skeleton className='h-12 w-40' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ export default function BarChartConfiguration({ onConfigurationSave = () => { }
includeUserProperties={true}
onConfigurationChange={onConfigurationChange}
onSave={onConfigurationSave}
previewDashboardComponent={title => (
previewDashboardComponent={(title, subTitle) => (
<BarChartComponent
title={title}
subTitle={subTitle}
data={barChartResults?.data}
groupedBy={barChartResults?.groupedBy}
includeSettingsDropdown={false}
includeCard={true}
/>
)}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import AdvancedSettingsSection from '@/components/Dashboards/Builder/Configurations/AdvancedSettingsSection';
import EventAndPropertySelector from './EventAndPropertySelector';
import { useState } from 'react'
import { Input } from '@/components/ui/input';

export default function ConfigurationModal({
AdditionalSettings = <></>,
Expand All @@ -9,17 +10,18 @@ export default function ConfigurationModal({
description,
includeCalculationsDropdown,
includePropertiesDropdown = true,
includeSubtitleInput = true,
includeUserProperties = false,
onConfigurationChange,
onSave = () => { },
previewDashboardComponent,
type,
}) {
const [dataSourceToPullFrom, setDataSourceToPullFrom] = useState(defaultDataSource)
const [errorMessage, setErrorMessage] = useState();
const [selectedPropertyName, setSelectedPropertyName] = useState();
const [selectedEventName, setSelectedEventName] = useState();
const [selectedCalculation, setSelectedCalculation] = useState(includeCalculationsDropdown ? null : 'count');
const [subtitle, setSubtitle] = useState();
const [title, setTitle] = useState();

const onFormSubmit = e => {
Expand All @@ -31,73 +33,73 @@ export default function ConfigurationModal({
} else if (selectedCalculation !== 'count' && !selectedPropertyName) {
setErrorMessage('Please select a property to use from the property dropdown.')
} else {
onSave({ title: title, event: selectedEventName, property: selectedPropertyName, calculation: selectedCalculation, dataSource: dataSourceToPullFrom });
onSave({ title, subtitle, event: selectedEventName, property: selectedPropertyName, calculation: selectedCalculation, dataSource: dataSourceToPullFrom });
}
}

return (
<form onSubmit={onFormSubmit}>
<h1 className='text-lg font-medium text-gray-700'>Configure {type}</h1>
<h2 className='text-sm text-gray-500 mb-4'>{description}</h2>
<div className='grid grid-cols-2 gap-4 items-center'>
<div>
<input className='input' placeholder={`${type} Title`} value={title} onChange={e => setTitle(e.target.value)} />
<div className='max-h-[75vh] overflow-y-scroll pb-4 px-1'>
<h2 className='text-sm text-gray-500 mb-4'>{description}</h2>
<Input id='title' className='w-1/2' placeholder='Title *' value={title} onChange={e => setTitle(e.target.value)} />
{includeSubtitleInput && (
<Input id='subtitle' className='w-3/4 mt-1' placeholder='Subtitle' value={subtitle} onChange={e => setSubtitle(e.target.value)} />
)}
<EventAndPropertySelector
calculationOptions={includeCalculationsDropdown ? calculationOptions : []}
dataSource={dataSourceToPullFrom}
includePropertiesDropdown={includePropertiesDropdown}
includeUserProperties={includeUserProperties}
onCalculationSelected={calculation => {
setSelectedCalculation(calculation);
onConfigurationChange({
calculation,
eventName: selectedEventName,
propertyName: selectedPropertyName,
dataSource: dataSourceToPullFrom
});
}}
onEventSelected={event => {
setSelectedEventName(event)
onConfigurationChange({
calculation: selectedCalculation,
eventName: event,
propertyName: selectedPropertyName,
dataSource: dataSourceToPullFrom
});
}}
onPropertySelected={property => {
setSelectedPropertyName(property);
onConfigurationChange({
calculation: selectedCalculation,
eventName: selectedEventName,
propertyName: property,
dataSource: dataSourceToPullFrom
});
}}
/>
<AdvancedSettingsSection
selectedDataSource={dataSourceToPullFrom}
onDataSourceSelected={dataSource => {
setDataSourceToPullFrom(dataSource)
onConfigurationChange({
calculation: selectedCalculation,
eventName: selectedEventName,
propertyName: selectedPropertyName,
dataSource
})
}}
>
{AdditionalSettings}
</AdvancedSettingsSection>
<div className='mt-4'>
{previewDashboardComponent(title, subtitle)}
</div>
</div>
<EventAndPropertySelector
calculationOptions={includeCalculationsDropdown ? calculationOptions : []}
dataSource={dataSourceToPullFrom}
includePropertiesDropdown={includePropertiesDropdown}
includeUserProperties={includeUserProperties}
onCalculationSelected={calculation => {
setSelectedCalculation(calculation);
onConfigurationChange({
calculation,
eventName: selectedEventName,
propertyName: selectedPropertyName,
dataSource: dataSourceToPullFrom
});
}}
onEventSelected={event => {
setSelectedEventName(event)
onConfigurationChange({
calculation: selectedCalculation,
eventName: event,
propertyName: selectedPropertyName,
dataSource: dataSourceToPullFrom
});
}}
onPropertySelected={property => {
setSelectedPropertyName(property);
onConfigurationChange({
calculation: selectedCalculation,
eventName: selectedEventName,
propertyName: property,
dataSource: dataSourceToPullFrom
});
}}
/>
<AdvancedSettingsSection
selectedDataSource={dataSourceToPullFrom}
onDataSourceSelected={dataSource => {
setDataSourceToPullFrom(dataSource)
onConfigurationChange({
calculation: selectedCalculation,
eventName: selectedEventName,
propertyName: selectedPropertyName,
dataSource
})
}}
>
{AdditionalSettings}
</AdvancedSettingsSection>
<div className='mt-4'>
{previewDashboardComponent(title)}
</div>
<div className='flex items-center justify-center text-red-500 mt-2 text-sm'>
{errorMessage}
</div>
<div className='flex justify-end mt-4'>
<div className='flex justify-end mt-4 border-t border-gray-200 pt-4'>
<button
className='ml-2 flex justify-center items-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white focus:outline-none focus:ring-2 bg-swishjam hover:bg-swishjam-dark'
type='submit'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ import { Skeleton } from '@/components/ui/skeleton';
import SwishjamAPI from '@/lib/api-client/swishjam-api';
import { useEffect, useState } from 'react'
import ComboboxEvents from '@/components/utils/ComboboxEvents';
import Combobox from '@/components/utils/Combobox';
import { CalculatorIcon, ChevronLeftIcon, ChevronRightIcon, HashIcon, PlusIcon } from 'lucide-react';

const CALCULATION_ICONS = {
count: <HashIcon className='h-3 w-3' />,
sum: <PlusIcon className='h-3 w-3' />,
min: <ChevronLeftIcon className='h-3 w-3' />,
max: <ChevronRightIcon className='h-3 w-3' />,
avg: <CalculatorIcon className='h-3 w-3' />,
}

export default function EventAndPropertySelector({
calculationOptions = [],
Expand Down Expand Up @@ -33,20 +43,26 @@ export default function EventAndPropertySelector({
}
}, [includeUserProperties])

const formattedCalculationOptions = calculationOptions.map(option => ({
label: <span className='flex items-center space-x-2'>{CALCULATION_ICONS[option]} <span>{option}</span></span>,
value: option,
}))

return (
<div className='flex text-sm text-gray-700 items-center mt-2 break-keep'>
<div className='flex text-sm text-gray-700 items-center mt-2 break-keep' >
<div className='inline-flex items-center mx-1'>
Chart the
{calculationOptions.length > 0
? (
<div className='mx-1'>
<Dropdown
label={<span className='italic'>calculation</span>}
options={calculationOptions}
onSelect={calculation => {
<Combobox
placeholder='calculation'
selectedValue={selectedCalculation}
onSelectionChange={calculation => {
setSelectedCalculation(calculation);
onCalculationSelected(calculation)
}}
options={formattedCalculationOptions}
/>
</div>
) : <>{' '}occurrences</>
Expand All @@ -72,31 +88,32 @@ export default function EventAndPropertySelector({
) : <Skeleton className='h-8 w-12' />
}

{selectedCalculation === 'count' || !includePropertiesDropdown
? <span className='mx-1'>event over time.</span>
: selectedCalculation === 'users'
? <span className='mx-1'>the most.</span>
: (
<>
<span className='mx-1'>by the {selectedEventProperty && selectedEventProperty.startsWith('user.') ? 'user' : 'event'}'s</span>
<ComboboxEvents
selectedValue={selectedEventProperty}
onSelectionChange={selection => {
setSelectedEventProperty(selection)
onPropertySelected(selection)
}}
options={[
...(uniquePropertiesForEvent || []),
...(includeUserProperties ? uniqueUserProperties || [] : [])
]}
placeholder="Select a property"
swishjamEventsHeading="Event Properties"
/>
<span className='mx-1'>property over time.</span>
</>
)
{
selectedCalculation === 'count' || !includePropertiesDropdown
? <span className='mx-1'>event over time.</span>
: selectedCalculation === 'users'
? <span className='mx-1'>the most.</span>
: (
<>
<span className='mx-1'>by the {selectedEventProperty && selectedEventProperty.startsWith('user.') ? 'user' : 'event'}'s</span>
<ComboboxEvents
selectedValue={selectedEventProperty}
onSelectionChange={selection => {
setSelectedEventProperty(selection)
onPropertySelected(selection)
}}
options={[
...(uniquePropertiesForEvent || []),
...(includeUserProperties ? uniqueUserProperties || [] : [])
]}
placeholder="Select a property"
swishjamEventsHeading="Event Properties"
/>
<span className='mx-1'>property over time.</span>
</>
)
}
</div>
</div >
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default function LineChartConfiguration({ onConfigurationSave = () => { }
includeCalculationsDropdown={true}
includePropertiesDropdown={true}
onSave={onSave}
previewDashboardComponent={title => (
previewDashboardComponent={(title, subtitle) => (
<LineChartWithValue
includeSettingsDropdown={includeSettingsDropdownConfig}
includeComparisonData={includeComparisonDataConfig}
Expand All @@ -134,6 +134,7 @@ export default function LineChartConfiguration({ onConfigurationSave = () => { }
showAxis={!hideAxisConfig}
timeseries={timeseriesData?.timeseries}
title={title}
subtitle={subtitle}
value={timeseriesData?.value}
valueFormatter={val => {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ export default function PieChartConfiguration({ onConfigurationSave = () => { }
includeCalculationsDropdown={true}
includePropertiesDropdown={true}
onSave={configuration => onConfigurationSave({ ...configuration, value_formatter: valueFormatterConfig })}
previewDashboardComponent={title => (
previewDashboardComponent={(title, subtitle) => (
<ValueCard
title={title}
subtitle={subtitle}
value={valueCardValue}
previousValue={valueCardPreviousValue}
valueFormatter={value => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useEffect, useState } from "react";

export default function BarListDashboardComponent({ configuration, timeframe }) {
const [barChartResults, setBarChartResults] = useState();
const { title, event, property, dataSource } = configuration;
const { title, subtitle, event, property, dataSource } = configuration;

useEffect(() => {
setBarChartResults();
Expand All @@ -18,6 +18,7 @@ export default function BarListDashboardComponent({ configuration, timeframe })
return (
<BarChart
title={title}
subtitle={subtitle}
data={barChartResults?.data}
groupedBy={barChartResults?.groupedBy}
includeCard={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SwishjamAPI from '@/lib/api-client/swishjam-api';

export default function BarListDashboardComponent({ configuration, timeframe }) {
const [barListData, setBarListData] = useState();
const { title, event, property, dataSource } = configuration;
const { title, subtitle, event, property, dataSource } = configuration;

useEffect(() => {
setBarListData();
Expand Down Expand Up @@ -32,6 +32,7 @@ export default function BarListDashboardComponent({ configuration, timeframe })
includeCard={false}
items={barListData}
title={title}
subtitle={subtitle}
/>
)
}

0 comments on commit 3bab56a

Please sign in to comment.