Skip to content

Commit

Permalink
fixes for dashboard funtionality (#280)
Browse files Browse the repository at this point in the history
* fixes for dashboard funtionality

* fixes for dashboard funtionality

* patch: render charts

---------

Co-authored-by: tinashe <[email protected]>
  • Loading branch information
tinashechiraya and tinashe authored Jan 27, 2025
1 parent 392e6d5 commit 883d5c9
Show file tree
Hide file tree
Showing 7 changed files with 360 additions and 112 deletions.
5 changes: 4 additions & 1 deletion django_project/analysis/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ class UserAnalysisResultsViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]

def perform_create(self, serializer):
serializer.save(created_by=self.request.user)
serializer.save(
created_by=self.request.user,
analysis_results=self.request.data.get('analysis_results')
)

@action(detail=False, methods=['get'])
def fetch_analysis_results(self, request):
Expand Down
38 changes: 33 additions & 5 deletions django_project/dashboard/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,34 @@

@admin.register(Dashboard)
class DashboardAdmin(admin.ModelAdmin):
list_display = ('uuid', 'privacy_type', 'created_at', 'updated_at')
list_display = (
'uuid',
'privacy_type',
'created_at',
'updated_at',
'linked_analysis_results'
)
list_filter = ('privacy_type', 'created_at', 'updated_at')
search_fields = ('uuid',)
filter_horizontal = ('organisations', 'groups', 'users')
search_fields = ('uuid', 'title')
filter_horizontal = (
'organisations',
'groups',
'users',
'analysis_results'
)
readonly_fields = ('created_at', 'updated_at')

fieldsets = (
(None, {
'fields': ('privacy_type',)
'fields': ('privacy_type', 'title')
}),
('Associations', {
'fields': ('organisations', 'groups', 'users')
'fields': (
'organisations',
'groups',
'users',
'analysis_results'
)
}),
('Configuration', {
'fields': ('config',)
Expand All @@ -24,3 +40,15 @@ class DashboardAdmin(admin.ModelAdmin):
'fields': ('created_at', 'updated_at')
}),
)

def linked_analysis_results(self, obj):
"""
Display the associated UserAnalysisResults in a human-readable format.
"""
results = obj.analysis_results.all()
return (
', '.join([str(result) for result in results])
if results else "None"
)

linked_analysis_results.short_description = "Linked Analysis Results"
132 changes: 36 additions & 96 deletions django_project/frontend/src/components/ChartCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,83 +5,8 @@ import Draggable from "react-draggable";
import LineChart from "./DashboardCharts/LineChart";
import BarChart from "./DashboardCharts/BarChart";
import PieChart from "./DashboardCharts/PieChart";


function purifyApiData(apiData: any[]) {
if (!Array.isArray(apiData)) {
throw new Error("Input data should be an array.");
}

return apiData.map((item) => {
const { analysis_results } = item;

if (!analysis_results || !analysis_results.data || !analysis_results.results) {
throw new Error("Invalid data structure.");
}

const {
latitude,
community,
landscape,
longitude,
analysisType,
} = analysis_results.data;

const {
id,
type,
columns,
version,
features,
} = analysis_results.results;

const purifiedFeatures = features.map((feature: { id: any; type: any; geometry: any; properties: any; }) => {
const {
id: featureId,
type: featureType,
geometry,
properties,
} = feature;

return {
id: featureId,
type: featureType,
geometry: geometry || {},
properties: {
EVI: parseFloat(properties.EVI.toFixed(2)),
NDVI: parseFloat(properties.NDVI.toFixed(2)),
Name: properties.Name,
area: parseFloat(properties.area.toFixed(0)),
"SOC kg/m2": parseFloat(properties["SOC kg/m2"].toFixed(2)),
},
};
});

return {
data: {
latitude,
community,
landscape,
longitude,
analysisType,
},
results: {
id,
type,
columns: {
EVI: columns.EVI,
NDVI: columns.NDVI,
Name: columns.Name,
area: columns.area,
"SOC kg/m2": columns["SOC kg/m2"],
},
version,
features: purifiedFeatures,
},
};
});
}

import { RenderResult } from "./DashboardCharts/CombinedCharts";
import { Analysis } from "../store/analysisSlice";


interface ChartCardProps {
Expand Down Expand Up @@ -112,7 +37,6 @@ const ChartCard: React.FC<ChartCardProps> = ({ config, className }) => {

// Check if config.chartType is "chart" or "map"
const isChart = config.config.preference === "chart";
console.log('config ',config.config)


const getChartComponent = () => {
Expand All @@ -126,20 +50,33 @@ const ChartCard: React.FC<ChartCardProps> = ({ config, className }) => {
</Box>
);
}

// If chart type is defined, render corresponding chart component
const data = purifyApiData(config.analysisResults);


switch (chartType) {
case "bar":
return <BarChart inputData={data[0]} />;
case "pie":
return <PieChart inputData={data[0]} />;
default:
return <LineChart inputData={data[0]} />;

try {

// switch (chartType) {
// case "bar":
// return <BarChart inputData={data[0]} />;
// case "pie":
// return <PieChart inputData={data[0]} />;
// default:
// return <LineChart inputData={data[0]} />;
// }
return <RenderResult analysis={config.analysisResults[0].analysis_results as unknown as Analysis} />
} catch (error) {
console.error("Error processing data:", error);

// Fallback card in case of invalid data
return (
<Box textAlign="center" p={4}>
<Text fontSize="xl" fontWeight="bold" color="red.500">
Data Processing Error
</Text>
<Text color="black">We couldn't process the data for this chart. Please check the data source or try again later.</Text>
</Box>
);
}
};


const handleResize = (event: any, { size }: any) => {
setCardWidth(size.width);
Expand All @@ -163,7 +100,7 @@ const ChartCard: React.FC<ChartCardProps> = ({ config, className }) => {

return (
<Draggable>
<div className={className}>
<div className={className} style={{ overflow: "hidden" ,width: cardWidth+ 'px', height: cardHeight + 'px'}}>
<ResizableBox
width={cardWidth}
height={cardHeight}
Expand All @@ -172,7 +109,8 @@ const ChartCard: React.FC<ChartCardProps> = ({ config, className }) => {
onResizeStop={handleResize}
resizeHandles={["se", "s", "e"]}
>
<Card boxShadow="lg" borderRadius={8} borderWidth="1px" borderColor="gray.300">

<Card boxShadow="lg" borderRadius={8} borderWidth="1px" borderColor="gray.300" style={{ width: "auto"}}>
<CardBody>
<VStack spacing={2}>
<Text fontSize="xl" fontWeight="bold" color="black">
Expand Down Expand Up @@ -200,7 +138,9 @@ const ChartCard: React.FC<ChartCardProps> = ({ config, className }) => {
</VStack>
</CardBody>
</Card>

</ResizableBox>


{/* Settings Modal */}
<Modal isOpen={isSettingsOpen} onClose={() => setSettingsOpen(false)}>
Expand Down Expand Up @@ -244,9 +184,9 @@ const ChartCard: React.FC<ChartCardProps> = ({ config, className }) => {
value={chartType}
onChange={(e) => setChartType(e.target.value)}
>
<option value="lineChart">Line Chart</option>
<option value="barChart">Bar Chart</option>
<option value="pieChart">Pie Chart</option>
<option value="line">Line Chart</option>
<option value="bar">Bar Chart</option>
<option value="pie">Pie Chart</option>
</Select>
</Box>
<Button colorScheme="blue" onClick={handleSettingsSave} mt={4}>
Expand All @@ -256,7 +196,7 @@ const ChartCard: React.FC<ChartCardProps> = ({ config, className }) => {
</ModalBody>
</ModalContent>
</Modal>
</div>
</div>
</Draggable>
);
};
Expand Down
Loading

0 comments on commit 883d5c9

Please sign in to comment.