Skip to content
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 ui/public/vite.svg

This file was deleted.

7 changes: 7 additions & 0 deletions ui/src/api/services/analyticsService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
/**
* AnalyticsService handles sending analytics events
*/

import api from "../axios"
import axios from "axios"

// endpoint which handles rate limiting and forwards the events to mixpanel
const ANALYTICS_ENDPOINT = "https://analytics.olake.io/mp/track"

const sendAnalyticsEvent = async (
Expand Down Expand Up @@ -57,6 +62,7 @@ const getSystemInfo = async () => {
}
}

// returns a unique user id for the user to track them across sessions
const getTelemetryID = async (): Promise<string> => {
try {
const response = await api.get("/telemetry-id")
Expand All @@ -77,6 +83,7 @@ export const trackEvent = async (
return
}

// if user is already logged in we'll get the username from local storage
const username = localStorage.getItem("username")
const systemInfo = await getSystemInfo()

Expand Down
3 changes: 3 additions & 0 deletions ui/src/api/services/destinationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getConnectorInLowerCase } from "../../utils/utils"

// TODO: Make it parquet on all places
const normalizeDestinationType = (type: string): string => {
//destination connector typemap
const typeMap: Record<string, string> = {
"amazon s3": "s3",
"apache iceberg": "iceberg",
Expand Down Expand Up @@ -93,6 +94,7 @@ export const destinationService = {
source_type: source_type,
source_version: source_version,
},
//timeout is 0 as test connection takes more time as it needs to connect to the destination
{ timeout: 0 },
)
return {
Expand Down Expand Up @@ -136,6 +138,7 @@ export const destinationService = {
source_type: source_type,
source_version: source_version,
},
//timeout is 300000 as spec takes more time as it needs to fetch the spec from the destination
{ timeout: 300000, signal },
)
return response.data
Expand Down
3 changes: 2 additions & 1 deletion ui/src/api/services/jobService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const jobService = {
const response = await api.post<APIResponse<TaskLog[]>>(
`${API_CONFIG.ENDPOINTS.JOBS(API_CONFIG.PROJECT_ID)}/${jobId}/tasks/${taskId}/logs`,
{ file_path: filePath },
{ timeout: 0 },
{ timeout: 0 }, // Disable timeout for this request since it can take longer
)
return response.data
} catch (error) {
Expand All @@ -110,6 +110,7 @@ export const jobService = {
}
},

//This either pauses or resumes the job
activateJob: async (
jobId: string,
activate: boolean,
Expand Down
7 changes: 4 additions & 3 deletions ui/src/api/services/sourceService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const sourceService = {
version: source.version,
config: source.config,
},
{ timeout: 0 },
{ timeout: 0 }, // Disable timeout for this request since it can take longer
)
return {
success: response.data.success,
Expand All @@ -101,7 +101,7 @@ export const sourceService = {
const response = await api.get<APIResponse<{ version: string[] }>>(
`${API_CONFIG.ENDPOINTS.SOURCES(API_CONFIG.PROJECT_ID)}/versions/?type=${type}`,
{
timeout: 0,
timeout: 0, // Disable timeout for this request since it can take longer
},
)
return response.data
Expand All @@ -123,7 +123,7 @@ export const sourceService = {
type: type.toLowerCase(),
version,
},
{ timeout: 300000, signal },
{ timeout: 300000, signal }, //timeout is 300000 as spec takes more time as it needs to fetch the spec from olake
)
return response.data
} catch (error) {
Expand All @@ -132,6 +132,7 @@ export const sourceService = {
}
},

//fetches source specific streams
getSourceStreams: async (
name: string,
type: string,
Expand Down
1 change: 1 addition & 0 deletions ui/src/modules/auth/pages/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const Login: React.FC = () => {
duration: 3,
className: "font-medium",
})
// clear form in the case of error
form.resetFields()
}
setLoading(false)
Expand Down
1 change: 1 addition & 0 deletions ui/src/modules/common/Modals/DeleteModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Entity } from "../../../types"
import { DeleteModalProps } from "../../../types/modalTypes"
import { getConnectorImage } from "../../../utils/utils"

//Entity Delete Modal
const DeleteModal = ({ fromSource }: DeleteModalProps) => {
const {
showDeleteModal,
Expand Down
9 changes: 5 additions & 4 deletions ui/src/modules/common/components/DocumentationPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
CornersOut,
CaretRight,
Info,
ArrowSquareOut,
ArrowSquareOutIcon,
} from "@phosphor-icons/react"

import { DocumentationPanelProps } from "../../../types"
Expand Down Expand Up @@ -44,6 +44,7 @@ const DocumentationPanel: React.FC<DocumentationPanelProps> = ({
if (!iframe) return

const handleLoad = () => {
// as the theme for ui is light themed we need to show only light theme in docs website as the default theme is dark
// Post message to iframe for theming
iframe.contentWindow?.postMessage({ theme: "light" }, "https://olake.io")

Expand Down Expand Up @@ -78,7 +79,7 @@ const DocumentationPanel: React.FC<DocumentationPanelProps> = ({
className="flex items-center"
onClick={openInNewTab}
icon={
<ArrowSquareOut
<ArrowSquareOutIcon
size={16}
className="mr-2"
/>
Expand Down Expand Up @@ -144,7 +145,7 @@ const DocumentationPanel: React.FC<DocumentationPanelProps> = ({
<Button
type="default"
icon={
<ArrowSquareOut
<ArrowSquareOutIcon
size={20}
weight="bold"
className="text-primary"
Expand Down Expand Up @@ -184,7 +185,7 @@ const DocumentationPanel: React.FC<DocumentationPanelProps> = ({
title="Open documentation in new tab"
placement="left"
>
<ArrowSquareOut
<ArrowSquareOutIcon
size={25}
className="cursor-pointer text-primary transition-all duration-300 ease-in-out hover:text-primary/80"
onClick={openInNewTab}
Expand Down
4 changes: 4 additions & 0 deletions ui/src/modules/common/components/Form/ArrayFieldTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* ArrayFieldTemplate is a component that renders an array of items this overrides the default array field template of rjsf
*/

import { ArrayFieldTemplateProps } from "@rjsf/utils"
import { Button } from "antd"
import { Plus, Trash } from "@phosphor-icons/react"
Expand Down
3 changes: 3 additions & 0 deletions ui/src/modules/common/components/Form/BooleanSwitchWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* BooleanSwitchWidget is a component that renders a boolean switch this overrides the default boolean field template of rjsf
*/
import { Switch } from "antd"
import { WidgetProps } from "@rjsf/utils"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function KeyValueRow({
)
}

// --- NewKeyValueRow: Renders inputs for adding a new key-value pair ---
// --- NewKeyValueRow: Renders inputs for adding a new key-value pair for type = object ---
function NewKeyValueRow({
newKey,
newValue,
Expand Down Expand Up @@ -87,6 +87,10 @@ function NewKeyValueRow({
)
}

/**
* CustomFieldTemplate is a component that renders a custom field template this overrides the default field template of rjsf Field specific layout is defined here
*/

export default function CustomFieldTemplate(props: FieldTemplateProps) {
// --- Props Destructure ---
const {
Expand Down
4 changes: 4 additions & 0 deletions ui/src/modules/common/components/Form/CustomRadioWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* CustomRadioWidget is a component that renders a radio widget this overrides the default radio field template of rjsf
*/

import React from "react"
import { Radio } from "antd"
import { WidgetProps } from "@rjsf/utils"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const DESCRIPTION_COL_STYLE = {

/** The `ObjectFieldTemplate` is the template to use to render all the inner properties of an object along with the
* title and description if available. If the object is expandable, then an `AddButton` is also rendered after all
* the properties.
* the properties. This component defines the layout for the object field template.
*
* @param props - The `ObjectFieldTemplateProps` for this component
*/
Expand Down
1 change: 1 addition & 0 deletions ui/src/modules/common/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { NAV_ITEMS } from "../../../utils/constants"
import OlakeLogo from "../../../assets/OlakeLogo.svg"
import Olake from "../../../assets/OLake.svg"

// will be shown in the later period when we have new updates
const UpdateNotification: React.FC<{ onClose: () => void }> = ({ onClose }) => (
<div className="p-4">
<div className="relative rounded-xl border border-gray-300 bg-gray-100 p-3">
Expand Down
3 changes: 3 additions & 0 deletions ui/src/modules/destinations/pages/CreateDestination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ const CreateDestination = forwardRef<
if (setupType === SETUP_TYPES.EXISTING) return

setLoading(true)
// cancels old requests when new one is made
return withAbortController(
signal =>
destinationService.getDestinationSpec(
Expand Down Expand Up @@ -306,6 +307,7 @@ const CreateDestination = forwardRef<
setShowSourceCancelModal(true)
}

//makes sure user enters destination name and version and fills all the required fields in the form
const validateDestination = async (): Promise<boolean> => {
try {
if (setupType === SETUP_TYPES.NEW) {
Expand Down Expand Up @@ -368,6 +370,7 @@ const CreateDestination = forwardRef<

try {
setShowTestingModal(true)
//test the connection and show either success or failure modal based on the result
const testResult =
await destinationService.testDestinationConnection(newDestinationData)
setShowTestingModal(false)
Expand Down
1 change: 1 addition & 0 deletions ui/src/modules/destinations/pages/DestinationEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ const DestinationEdit: React.FC<DestinationEditProps> = ({
}

setIsLoading(true)
//cancel old requests when new one is made
return withAbortController(
signal =>
destinationService.getDestinationSpec(
Expand Down
1 change: 1 addition & 0 deletions ui/src/modules/destinations/pages/Destinations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const Destinations: React.FC = () => {
}

const filteredDestinations = (): Entity[] => {
// a destination is active if it has jobs and at least one job is active
if (activeTab === "active") {
return destinations.filter(
destination =>
Expand Down
7 changes: 7 additions & 0 deletions ui/src/modules/jobs/pages/JobCreation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const JobCreation: React.FC = () => {
const [currentStep, setCurrentStep] = useState<JobCreationSteps>(
JOB_CREATION_STEPS.CONFIG as JobCreationSteps,
)
// state to toggle documentation panel
const [docsMinimized, setDocsMinimized] = useState(false)
const [sourceName, setSourceName] = useState(initialData.sourceName || "")
const [sourceConnector, setSourceConnector] = useState(
Expand All @@ -56,6 +57,8 @@ const JobCreation: React.FC = () => {
const [destinationName, setDestinationName] = useState(
initialData.destinationName || "",
)

//state to hold catalog value to open documentation panel
const [destinationCatalogType, setDestinationCatalogType] = useState<
string | null
>(null)
Expand All @@ -76,9 +79,12 @@ const JobCreation: React.FC = () => {
const [cronExpression, setCronExpression] = useState(
initialData.cronExpression || "* * * * *",
)

//once the job name is filled we will set this to true so the job name will be disabled
const [jobNameFilled, setJobNameFilled] = useState(
initialData.isJobNameFilled || false,
)
//when streams are loading we will disable back button
const [isStreamsLoading, setIsStreamsLoading] = useState(false)
const [isFromSources, setIsFromSources] = useState(true)

Expand Down Expand Up @@ -318,6 +324,7 @@ const JobCreation: React.FC = () => {
if (currentStep === JOB_CREATION_STEPS.DESTINATION) {
setCurrentStep(JOB_CREATION_STEPS.SOURCE)
} else if (currentStep === JOB_CREATION_STEPS.STREAMS) {
// when we go back from streams we need to show configured streams will be lost modal
setShowResetStreamsModal(true)
} else if (currentStep === JOB_CREATION_STEPS.SOURCE) {
setCurrentStep(JOB_CREATION_STEPS.CONFIG)
Expand Down
1 change: 1 addition & 0 deletions ui/src/modules/jobs/pages/JobHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const JobHistory: React.FC = () => {
return
}

// try fetching tasks 4 times with a delay of 1 second
if (retryCountRef.current < 4) {
retryCountRef.current++
setTimeout(fetchWithRetry, THROTTLE_DELAY)
Expand Down
3 changes: 2 additions & 1 deletion ui/src/modules/jobs/pages/Jobs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const Jobs: React.FC = () => {

const handleSyncJob = async (id: string) => {
try {
navigate(`/jobs/${id}/history`)
navigate(`/jobs/${id}/history`) // navigate to job history so that user can see the tasks running
await jobService.syncJob(id)
message.success("Job sync started successfully")
await fetchJobs()
Expand Down Expand Up @@ -89,6 +89,7 @@ const Jobs: React.FC = () => {
await fetchJobs()
}

// cancels the running job
const handleCancelJob = async (id: string) => {
try {
const response = await jobService.cancelJob(id)
Expand Down
6 changes: 5 additions & 1 deletion ui/src/modules/jobs/pages/streams/StreamConfiguration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const StreamConfiguration = ({
CombinedStreamsData | undefined
>(undefined)

// Unique stream key
// Unique stream key to differentiate a stream with same name and different namespace
const streamKey = `${stream.stream.namespace || ""}_${stream.stream.name}`

// Guard to prevent prop-driven effect from clobbering local edits
Expand All @@ -117,6 +117,7 @@ const StreamConfiguration = ({
const initialApiSyncMode = stream.stream.sync_mode

// Parse cursor field for default value
// cursor field and default will be in a:b form where a is the cursor field and b is the default field
if (
stream.stream.cursor_field &&
stream.stream.cursor_field.includes(":")
Expand Down Expand Up @@ -277,6 +278,7 @@ const StreamConfiguration = ({
}
}

// deletes the partition regex for the corresponding stream
const handleClearPartitionRegex = () => {
setActivePartitionRegex("")
setPartitionRegex("")
Expand Down Expand Up @@ -448,6 +450,7 @@ const StreamConfiguration = ({
}
}

// get columns based on primary keys and cursor fields and their properties
const getColumnOptions = () => {
const properties = stream.stream.type_schema?.properties || {}
const primaryKeys = (stream.stream.source_defined_primary_key ||
Expand Down Expand Up @@ -496,6 +499,7 @@ const StreamConfiguration = ({
})
}

// when the type is either string or timestamp we wrap the value in quotes
const formatFilterValue = (columnName: string, value: string) => {
const properties = stream.stream.type_schema?.properties || {}
const columnType = properties[columnName]?.type
Expand Down
2 changes: 2 additions & 0 deletions ui/src/modules/jobs/pages/streams/StreamHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ const StreamHeader: React.FC<StreamHeaderProps> = ({
stream: { name, namespace },
} = stream

//activestream is the stream selected in the stream panel
const isActiveStream =
activeStreamData?.stream.name === name &&
activeStreamData?.stream.namespace === namespace

//opens the stream configuration when user clicks on stream or on checkbox
const handleChange = (e: CheckboxChangeEvent) => {
toggle(e)
setActiveStreamData(stream)
Expand Down
Loading
Loading