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
59 changes: 54 additions & 5 deletions .github/workflows/CI_cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ jobs:

env:
NODE_ENV: test
MODE: development
OCOTILLO_API_URL: http://localhost:8000
VITE_OCOTILLO_API_URL: http://localhost:8000
POSTGRES_USER: ${{ secrets.PG_TEST_USER }}
POSTGRES_PASSWORD: ${{ secrets.PG_TEST_PW }}
POSTGRES_DB: ${{ secrets.PG_TEST_DB }}
MODE: development
AUTHENTIK_DISABLE_AUTHENTICATION: ${{ secrets.AUTHENTIK_TEST }}

# --- DATABASE VALUES FOR DOCKER COMPOSE ---
POSTGRES_HOST: db
POSTGRES_PORT: 5432
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres

steps:
- name: Checkout frontend
uses: actions/checkout@v4
Expand All @@ -37,17 +41,62 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Debug env inside compose step
working-directory: ./api-repo
run: |
echo "POSTGRES_USER=$POSTGRES_USER"
echo "POSTGRES_PASSWORD=$POSTGRES_PASSWORD"
echo "POSTGRES_DB=$POSTGRES_DB"
echo "POSTGRES_HOST=$POSTGRES_HOST"
echo "POSTGRES_PORT=$POSTGRES_PORT"

- name: Start FastAPI backend (Docker Compose)
working-directory: ./api-repo
env:
INSTALL_DEV: true
run: |
docker compose build --build-arg INSTALL_DEV=$INSTALL_DEV app
docker compose up -d

- name: Exec inside DB container
working-directory: ./api-repo
run: docker compose exec -T db pg_isready -U $POSTGRES_USER -d $POSTGRES_DB || true

- name: Debug DB connectivity from app container
working-directory: ./api-repo
run: |
docker compose exec -T app bash -c "
echo 'Testing ping to db container:' &&
ping -c 3 db || true &&
echo 'Testing port 5432...' &&
nc -zv db 5432 || true
"

- name: Show DB logs
working-directory: ./api-repo
run: docker compose logs --tail=200 db || true

- name: Show early API logs (startup)
working-directory: ./api-repo
run: docker compose logs --tail=200 app || true

- name: Wait for FastAPI to be ready
working-directory: ./api-repo
run: |
echo "Waiting for FastAPI to be ready..."
timeout 180 bash -c 'until curl -f http://localhost:8000/docs; do sleep 3; done'
timeout 720 bash -c '
until curl -sf http://localhost:8000/docs; do
echo "FastAPI not up yet, retrying..."
sleep 3
done
'
echo "FastAPI is up and healthy"

- name: Show API logs after readiness probe
if: always()
working-directory: ./api-repo
run: docker compose logs --tail=200 app || true

- name: Seed database
working-directory: ./api-repo
run: docker compose exec -T app python -m transfers.seed
Expand Down
30 changes: 28 additions & 2 deletions src/components/Button/WellPDFDownload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { WellPDF } from '@/components'
import { ArrowDropDown, Download, Visibility } from '@mui/icons-material'
import { buildPdfFilename } from '@/utils'
import { pdf } from '@react-pdf/renderer'
import { useDataGrid } from '@refinedev/mui'

export const WellPDFDownloadButton = ({
well,
Expand All @@ -32,6 +33,22 @@ export const WellPDFDownloadButton = ({
const { data: permissions, isLoading: isPermissionsLoading } =
usePermissions<string[]>()

const {
dataGridProps: { rows: observations, loading: isObservationsloading },
} = useDataGrid({
resource: 'observation/groundwater-level',
dataProviderName: 'ocotillo',
meta: {
params: {
thing_id: well?.id,
},
},
queryOptions: {
cacheTime: 10 * 60 * 1000, // cached data for 10 minutes
staleTime: 5 * 60 * 1000, // get data fresh for 5 minutes,
},
})

const { data: assetData } = useList({
resource: 'asset',
dataProviderName: 'ocotillo',
Expand Down Expand Up @@ -70,7 +87,11 @@ export const WellPDFDownloadButton = ({

const isViewer = permissions?.includes('AMPViewer') ?? false
const disabled =
isLoading || isPermissionsLoading || !isViewer || isGenerating
isLoading ||
isPermissionsLoading ||
!isViewer ||
isGenerating ||
isObservationsloading

const handleDownload = async () => {
try {
Expand All @@ -79,7 +100,12 @@ export const WellPDFDownloadButton = ({

// Generate a PDF blob from the React PDF component
const blob = await pdf(
<WellPDF well={well} assets={assets} contacts={contacts} />
<WellPDF
well={well}
assets={assets}
contacts={contacts}
observations={observations}
/>
).toBlob()

// Create a temporary download link
Expand Down
29 changes: 13 additions & 16 deletions src/components/DynamicShowDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
import { Stack, Typography, Box } from '@mui/material'
import { TextFieldComponent as TextField } from '@refinedev/mui'
import { FieldConfigs } from '@/interfaces'

/**
* DynamicShowDisplay Component
* A component to use on the show.tsx pages to dynamically display the fields of a record.
* This component is to be used as a default on show.tsx pages. It processes the json response from the api and displays the fields
* in a basic way. More avanced shows should be created on a per entity basis.
*
*
* @param record - The record to display
* @param fieldConfigs - The field configurations for custom field display, field config interface:
* label: the label to display for the field
* formatter: a function to format the value of the field (optional)
* hidden: whether to hide the field (boolean) (optional)
*
*
* @param excludeFields - The fields to exclude
* @param autoFormatLabels - Whether to automatically format the labels
*/

//field config interface
interface FieldConfig {
label: string
formatter?: (value: any) => string | React.ReactNode
hidden?: boolean
}

//component props
interface DynamicShowDisplayProps<T> {
record: T
fieldConfigs?: Partial<Record<keyof T, FieldConfig>>
fieldConfigs?: FieldConfigs<T>
excludeFields?: Array<keyof T>
autoFormatLabels?: boolean
}
Expand All @@ -36,26 +30,29 @@ export const DynamicShowDisplay = <T extends Record<string, any>>({
record,
fieldConfigs = {},
excludeFields = [],
autoFormatLabels = true
autoFormatLabels = true,
}: DynamicShowDisplayProps<T>) => {

const formatLabel = (key: string): string => {
if (!autoFormatLabels) return key
return key
.replace(/([A-Z])/g, ' $1')
.replace(/^./, str => str.toUpperCase())
.replace(/^./, (str) => str.toUpperCase())
.replace(/_/g, ' ')
}

//handle value for rendering arrays nad objects from json response
const renderValue = (value: any): React.ReactNode => {
if (value === null || value === undefined) {
return <Typography variant="body2" color="text.secondary">-</Typography>
return (
<Typography variant="body2" color="text.secondary">
-
</Typography>
)
}
//handle arrays and objects!!
if (Array.isArray(value) || typeof value === 'object') {
return (
<Typography variant="body2" sx={{whiteSpace: 'pre-wrap' }}>
<Typography variant="body2" sx={{ whiteSpace: 'pre-wrap' }}>
{JSON.stringify(value, null, 2)}
</Typography>
)
Expand Down Expand Up @@ -92,4 +89,4 @@ export const DynamicShowDisplay = <T extends Record<string, any>>({
{record && Object.keys(record).map((key) => renderField(key))}
</Stack>
)
}
}
2 changes: 1 addition & 1 deletion src/components/SpatialSearchComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useRef, useState } from 'react'
import { Button, Modal, useTheme } from '@mui/material'
import { Button, Modal } from '@mui/material'
import wellknown from 'wellknown'
import { Place } from '@mui/icons-material'
import { Box } from '@mui/system'
Expand Down
Loading
Loading