Skip to content
This repository has been archived by the owner on Feb 24, 2023. It is now read-only.

Ingest wizard UI #62

Merged
merged 4 commits into from
Apr 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion api/src/enums/IngestSchemaWizard.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export enum IngestSchemaWizard {
EMPTY = 'EMPTY',
USER_TRACKING = 'USER_TRACKING',
ERROR_TRACKING = 'ERROR_TRACKING',
}
33 changes: 33 additions & 0 deletions ui/src/components/atoms/FormWarning.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { FC } from 'react';
import { Box } from '@mui/material';
import WarningIcon from '@mui/icons-material/Warning';

type FormWarningProps = {
warning: string;
};

const FormWarning: FC<FormWarningProps> = ({ warning }) => {
return (
<Box
component="small"
sx={{
display: 'flex',
alignItems: 'center',
color: (theme) => theme.palette.error.main,
width: '100%',
margin: (theme) => theme.spacing(0, 0, 3),
}}
>
<WarningIcon
sx={{
backgroundColor: 'transparent',
color: (theme) => theme.palette.error.main,
margin: '3px',
}}
/>
<Box pt="2px">{warning}</Box>
</Box>
);
};

export default FormWarning;
15 changes: 10 additions & 5 deletions ui/src/components/atoms/IngestEndpointInstallInstructionCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ var fs = require('fs');
var payload = '[payloadJs]';
var reqOptions = {
'method': 'POST',
'hostname': '[domain]',[portOption][pathOption]
'hostname': '[hostname]',[portOption][pathOption]
'headers': {
'Content-Type': 'application/json'
},
Expand Down Expand Up @@ -268,12 +268,17 @@ const IngestEndpointInstallInstructionCode: FC<IngestEndpointInstallInstructionC
const payloadJs = payloadPhp;
const payloadShell = JSON.stringify(props.payload, null, 2).replace(/'/g, "'\\''");

const endpointParsedUrl = new URL(props.endpoint);
const hostname = endpointParsedUrl.hostname;
const port = endpointParsedUrl.port;
const path = endpointParsedUrl.pathname;

const text = props.snippet.snippet
.replace('[endpoint]', props.endpoint)
.replace('[domain]', props.domain)
.replace('[portOption]', props.port === '' ? '' : `\n 'port': ${props.port},`)
.replace('[pathOption]', props.path === '' ? '' : `\n 'path': '${props.path}',`)
.replace('[portParameter]', props.port === '' ? '' : `, ${props.port}`)
.replace('[hostname]', hostname)
.replace('[portOption]', port === '' ? '' : `\n 'port': ${port},`)
.replace('[pathOption]', path === '' ? '' : `\n 'path': '${path}',`)
.replace('[portParameter]', port === '' ? '' : `, ${port}`)
.replace('[payloadRuby]', payloadRuby)
.replace('[payloadPython]', payloadPython)
.replace('[payloadPhp]', payloadPhp)
Expand Down
1 change: 1 addition & 0 deletions ui/src/components/atoms/InputTypes/DateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const DateInput: FC<DateInputProps> = ({
minWidth: '200px',
...(sx ?? {}),
}}
variant="standard"
name={name}
/>
),
Expand Down
35 changes: 5 additions & 30 deletions ui/src/components/molecules/IngestEndpointInstallInstructions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import {
ingestEndpointInstallSnippets,
} from '../atoms/IngestEndpointInstallInstructionCode';
import { Mode } from '../../gql/generated/globalTypes';
import { getNodeEnv } from '../../utils/ConfigUtils';

export type IngestEndpointInstallInstructionsDialogProps = {
installDomain: string;
installEndpoint: string;
cname: string;
payload: DataMapsPayload;
mode: Mode;
Expand All @@ -28,9 +28,6 @@ export type IngestEndpointInstallInstructionsDialogProps = {

export type IngestEndpointInstallInstructionCodeProps = {
endpoint: string;
domain: string;
port: string;
path: string;
payload: DataMapsPayload;
snippet: IngestEndpointInstallSnippet;
};
Expand All @@ -51,27 +48,6 @@ const IngestEndpointInstallInstructions: FC<IngestEndpointInstallInstructionsDia
setSnippetId(event.target.value as string);
};

const domain =
props.mode === Mode.COMMERCIAL
? `https://${props.installDomain}`
: `${window.location.protocol}//${window.location.hostname}`;

const path = props.mode === Mode.COMMERCIAL ? undefined : `/edge/${props.environmentId}`;

const determinePort = () => {
if (props.mode === Mode.COMMERCIAL) {
if (getNodeEnv() === 'development') {
return '8443';
}
return undefined;
}
return window.location.port;
};

const port = determinePort();

const endpoint = `${domain}${port === undefined ? '' : `:${port}`}${path ?? ''}`;

const currentSnippet = ingestEndpointInstallSnippets.find((_) => _.id === snippetId);

return (
Expand Down Expand Up @@ -109,7 +85,9 @@ const IngestEndpointInstallInstructions: FC<IngestEndpointInstallInstructionsDia
{tab === 'pixel' && (
<Box fontSize={12} mt={3} pb={2}>
<CopyBlock
text={`<!-- S8 Pixel -->\n<img width=0 height=0 src="${endpoint}/?d=${encodeURI(
text={`<!-- S8 Pixel -->\n<img width=0 height=0 src="${
props.installEndpoint
}/?d=${encodeURI(
JSON.stringify(props.payload),
)}" alt=""/>\n<!-- / S8 Pixel -->`}
language="html"
Expand Down Expand Up @@ -153,10 +131,7 @@ const IngestEndpointInstallInstructions: FC<IngestEndpointInstallInstructionsDia
</FormControl>
{currentSnippet !== undefined && (
<IngestEndpointInstallInstructionCode
domain={domain}
port={port ?? ''}
path={path ?? ''}
endpoint={endpoint}
endpoint={props.installEndpoint}
payload={props.payload}
snippet={currentSnippet}
/>
Expand Down
10 changes: 2 additions & 8 deletions ui/src/components/molecules/IngestEndpointPayloadInputType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { AppPlatformRevision } from '../../types/TagRulesTypes';
import { Box } from '@mui/material';
import { SelectValueWithSub } from '../../hooks/form/useFormValidation';
import FormWarning from '../atoms/FormWarning';

type SelectIngestEndpointProps = {
ingestEndpointId: string;
Expand Down Expand Up @@ -85,14 +86,7 @@ const SelectIngestEndpointEnvironment: FC<SelectIngestEndpointEnvironmentProps>
}

if (availableEnvironments.length === 0) {
return (
<Box
component="small"
sx={{ width: '100%', margin: (theme) => theme.spacing(0, 0, 3) }}
>
There are no environments defined for this endpoint.
</Box>
);
return <FormWarning warning="There are no environments defined for this endpoint." />;
}

return (
Expand Down
29 changes: 2 additions & 27 deletions ui/src/components/organisms/EnvironmentInstallInstructions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import CheckBoxInput from '../atoms/InputTypes/CheckBoxInput';
import CopyBlock from '../atoms/CopyBlock';
import { buildTagInstallMarkup } from '../../utils/TextUtils';
import { Mode } from '../../gql/generated/globalTypes';
import { getNodeEnv } from '../../utils/ConfigUtils';

export type InstallInstructionsProps = {
installDomain: string;
environmentName: string;
environmentId: string;
installEndpoint: string;
mode: Mode;
cname: string;
tags: { name: string; code: string; type: string }[];
Expand All @@ -24,31 +24,6 @@ const EnvironmentInstallInstructions: FC<InstallInstructionsProps> = (
const [spaSupport, setSpaSupport] = useState(false);
const [hashSupport, setHashSupport] = useState(false);

const domain =
props.mode === Mode.COMMERCIAL
? `https://${props.installDomain}`
: `${window.location.protocol}//${window.location.hostname}`;

const path = props.mode === Mode.COMMERCIAL ? undefined : `/edge/${props.environmentId}`;

const getPort = (): number | undefined => {
if (window.location.port === '80' || window.location.port === '443') {
return undefined;
} else if (props.mode === Mode.COMMERCIAL && getNodeEnv() === 'development') {
return 8443;
} else if (getNodeEnv() === 'development') {
return 6080;
} else if (props.mode === Mode.SELF_HOSTED && getNodeEnv() === 'production') {
return +window.location.port;
} else {
return undefined;
}
};

const port = getPort();

const environmentInstallSrc = `${domain}${port === undefined ? '' : `:${port}`}${path ?? ''}`;

const script = type === 'Tag Manager' ? 'tm.js' : 'analytics.js';

const opts =
Expand All @@ -63,7 +38,7 @@ const EnvironmentInstallInstructions: FC<InstallInstructionsProps> = (
const commentOpen = `<!-- Scale8 Tag Manager${commentAnalytics}${commentEnvironment} -->\n`;
const commentClose = `\n<!-- / Scale8 Tag Manager -->`;

const environmentInstallCode = `${commentOpen}<script src="${environmentInstallSrc}/${script}${opts}" async></script>${commentClose}`;
const environmentInstallCode = `${commentOpen}<script src="${props.installEndpoint}/${script}${opts}" async></script>${commentClose}`;

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,15 @@ import { FC } from 'react';
import { Box, DialogContent, DialogContentText } from '@mui/material';
import { InfoButton, InfoProps } from '../molecules/InfoButton';
import InfoDialogTitle from '../molecules/InfoDialogTitle';
import EnvironmentInstallInstructions from './EnvironmentInstallInstructions';
import { Mode } from '../../gql/generated/globalTypes';
import EnvironmentInstallInstructions, {
InstallInstructionsProps,
} from './EnvironmentInstallInstructions';

export type InstallInstructionsDialogProps = {
export type InstallInstructionsDialogProps = InstallInstructionsProps & {
handleDialogClose: (checkChanges: boolean) => void;
installDomain: string;
title: string;
formInfoProps?: InfoProps;
cname: string;
environmentName: string;
environmentId: string;
mode: Mode;
tags: { name: string; code: string; type: string }[];
};

const EnvironmentInstallInstructionsDialog: FC<InstallInstructionsDialogProps> = (
props: InstallInstructionsDialogProps,
) => {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/organisms/Forms/ConditionRuleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { getDataMapsIcon } from '../../../utils/TypeIconsUtils';
import { platformDataMapsToSubAndDeeper } from '../../../utils/PlatformDataMapsUtils';
import { buildConditionName } from '../../../dialogPages/tagManager/app/trigger/ConditionRuleUpdate';

const platformDataMapsToSelectValues = (
export const platformDataMapsToSelectValues = (
platformDataMaps: PlatformDataMap[],
): SelectValueWithSub[] => {
return platformDataMapsToSubAndDeeper(platformDataMaps).map((subAndDeeper) => {
Expand Down
47 changes: 44 additions & 3 deletions ui/src/components/organisms/Forms/IngestEndpointForm.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import { FC } from 'react';
import { FC, useEffect, useState } from 'react';
import ControlledTextInput from '../../atoms/ControlledInputs/ControlledTextInput';
import DrawerFormLayout from '../../molecules/DrawerFormLayout';
import { IngestEndpointFormProps } from '../../../dialogPages/dataManager/IngestEndpointCreate';
import StorageProviderSelector from '../../molecules/StorageProviderSelector';
import CheckBoxInput from '../../atoms/InputTypes/CheckBoxInput';
import { Mode } from '../../../gql/generated/globalTypes';
import { IngestSchemaWizard, Mode } from '../../../gql/generated/globalTypes';
import { useConfigState } from '../../../context/AppContext';
import { Box } from '@mui/material';
import { Box, Checkbox, FormControlLabel } from '@mui/material';
import ControlledSelect from '../../atoms/ControlledInputs/ControlledSelect';
import { snakeToTitleCase } from '../../../utils/TextUtils';

const IngestEndpointForm: FC<IngestEndpointFormProps> = (props: IngestEndpointFormProps) => {
const { mode } = useConfigState();

const [useWizard, setUseWizard] = useState(false);

const { values, handleChange } = props;

useEffect(() => {
if (values.wizard !== '' && !useWizard) {
handleChange('wizard', '');
}
}, [values, handleChange, useWizard]);

return (
<DrawerFormLayout {...props}>
<ControlledTextInput
Expand All @@ -21,6 +33,35 @@ const IngestEndpointForm: FC<IngestEndpointFormProps> = (props: IngestEndpointFo
required
autoFocus
/>
{props.isCreate && (
<FormControlLabel
sx={{ marginBottom: (theme) => theme.spacing(3) }}
control={
<Checkbox
name="useWizard"
checked={useWizard}
onChange={(event) => {
setUseWizard(event.target.checked);
}}
color="primary"
/>
}
label="Use Wizard"
/>
)}
{useWizard && (
<ControlledSelect
className="DrawerFormField"
label="Wizard"
name="wizard"
values={Object.values(IngestSchemaWizard).map((_) => ({
key: _,
text: snakeToTitleCase(_),
}))}
formProps={props}
required
/>
)}
{mode !== Mode.COMMERCIAL && (
<>
<CheckBoxInput
Expand Down
31 changes: 16 additions & 15 deletions ui/src/dialogPages/dataManager/IngestEndpointCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import IngestEndpointForm from '../../components/organisms/Forms/IngestEndpointF
import { FormProps, FormValidationResult } from '../../hooks/form/useFormValidation';
import CreateIngestEndpointQuery from '../../gql/mutations/CreateIngestEndpointQuery';
import { ApolloError, useMutation } from '@apollo/client';
import { CreateIngestEndpointResult } from '../../gql/generated/CreateIngestEndpointResult';
import {
CreateIngestEndpointResult,
CreateIngestEndpointResultVariables,
} from '../../gql/generated/CreateIngestEndpointResult';
import { DialogPageProps } from '../../types/DialogTypes';
import { buildStandardFormInfo } from '../../utils/InfoLabelsUtils';
import {
Expand Down Expand Up @@ -67,28 +70,26 @@ const IngestEndpointCreate: FC<DialogPageProps> = (props: DialogPageProps) => {
buildInitialState: () => ({
...initialStorageProviderFields,
name: '',
wizard: '',
analyticsEnabled: false,
storageProvider: StorageProvider.MONGODB,
}),
saveQuery: useMutation<CreateIngestEndpointResult>(CreateIngestEndpointQuery),
mapSaveData: (formValues: IngestEndpointValues) => {
if (mode === Mode.COMMERCIAL) {
return {
ingestEndpointCreateInput: {
data_manager_account_id: dataManagerId,
name: formValues.name,
analytics_enabled: true,
},
};
}

mapSaveData: (formValues: IngestEndpointValues): CreateIngestEndpointResultVariables => {
return {
ingestEndpointCreateInput: {
data_manager_account_id: dataManagerId,
ingest_schema_wizard: formValues.wizard === '' ? undefined : formValues.wizard,
name: formValues.name,
analytics_enabled: formValues.analyticsEnabled,
storage_provider: formValues.storageProvider as StorageProvider,
...buildStorageProviderSaveProperties(formValues, true),
...(mode === Mode.COMMERCIAL
? {
analytics_enabled: true,
}
: {
analytics_enabled: formValues.analyticsEnabled,
storage_provider: formValues.storageProvider as StorageProvider,
...buildStorageProviderSaveProperties(formValues, true),
}),
},
};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const IngestEndpointEnvironmentsInstallInstructions: FC<DialogPageProps> = (
>
<IngestEndpointInstallInstructions
installDomain={data.getIngestEndpointEnvironment.install_domain}
installEndpoint={data.getIngestEndpointEnvironment.install_endpoint}
cname={data.getIngestEndpointEnvironment.cname}
mode={mode}
environmentId={data.getIngestEndpointEnvironment.id}
Expand Down
Loading