Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reputation action component #53

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function UpdateReputationActions(
const subFieldCropsArray: SubFieldCrop[] = subFieldsArray[subFieldIndex].properties.crops;
for(let subFieldCropIndex in subFieldCropsArray){
if(subFieldCropsArray[subFieldCropIndex].crop._id?.toString() === cropId &&
subFieldCropsArray[subFieldCropIndex].farmer === farmer &&
(subFieldCropsArray[subFieldCropIndex].farmer === farmer || subFieldCropsArray[subFieldCropIndex].farmer === "") &&
subFieldCropsArray[subFieldCropIndex].reputation_actions
){
statusUpdated = (subFieldCropsArray[subFieldCropIndex].reputation_actions![actionName] != actionStatus);
Expand Down
8 changes: 5 additions & 3 deletions backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import smsRoutes from "./routes/sms-route";
import foodTrustRoutes from "./routes/food-trust-route";
import cropTemplateRoutes from "./routes/crop-template-route";
import colony from "./routes/colony-route"
import fields from "./routes/field-route"

import { SocketIOManager, SocketIOManagerInstance } from "./sockets/socket.io";
import { Server } from "http";
Expand Down Expand Up @@ -63,6 +64,7 @@ app.use("/api/lot", lotRoutes);
app.use("/api/crop", cropRoutes);
app.use("/api/dashboard", dashboardRoutes);
app.use("/api/recommendations", recommendationsRoutes);
app.use("/api/fields", fields);

app.use("/api/weather", weatherRoutes);
app.use("/api/coopManager", coopManagerRoutes);
Expand All @@ -71,9 +73,9 @@ app.use("/api/messaging", messageLogRoutes);
app.use("/api/sms", smsRoutes);

// blockchain related routes
app.use("/api/foodtrust", foodTrustRoutes)
app.use("/api/cropTemplates", cropTemplateRoutes)
app.use("/api/colony", colony)
app.use("/api/foodtrust", foodTrustRoutes);
app.use("/api/cropTemplates", cropTemplateRoutes);
app.use("/api/colony", colony);

// Static Files
const publicPath = path.resolve("public");
Expand Down
2 changes: 1 addition & 1 deletion backend/src/routes/crop-template-route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ async function updateRepActions(req: Request, res: Response) {
const farmerEthAddress = await farmerSigner.getAddress();
await colony.pay(farmerEthAddress, ethers.utils.parseUnits(payment.toString()));

res.json(docs);
res.status(200).json(docs);
}else{
throw new Error('The request must be made with a different action status than what is existing.');
}
Expand Down
22 changes: 22 additions & 0 deletions backend/src/routes/field-route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Router, Request, Response } from "express";
import { Field, FieldModel } from "../db/entities/field";

const router = Router();

router.get("/getFieldByFarmerId/:farmer_id", async(req: Request, res: Response) => {
try{
const docs = await FieldModel.findOne({farmer_id: req.params.farmer_id})
.then(doc => {
return doc;
})
.catch(err => {
return err;
})
res.json(docs);
}catch(e){
console.error(e);
res.status(500).json(e);
}
});

export default router;
34 changes: 17 additions & 17 deletions backend/src/routes/messaging-route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { TwilioInstance } from "./../integrations/twilio/twilio.service";
import { MessageLog, MessageLogModel } from "../db/entities/messageLog";
import { getFarmerIdsFromIndex, getIndexFromFarmerIds, MessageGroup, MessageGroupModel } from "../db/entities/messageGroup";
import { FarmerModel, Farmer } from "../db/entities/farmer";
import { MessageInterfaceSender } from "../integrations/messagingInterfaceSender";
// import { MessageInterfaceSender } from "../integrations/messagingInterfaceSender";

const router = Router();

const messageSender = new MessageInterfaceSender();
// const messageSender = new MessageInterfaceSender();

router.get("/", async (req, res) => {
const messages = await MessageLogModel.find({}).lean();
Expand All @@ -27,8 +27,8 @@ router.post("/sendSMSToFarmer", async (req, res) => {

try {
// const messageLog = await TwilioInstance.sendMessageToFarmer(farmer, message);
const messageLog = await messageSender.sendMessageToFarmer(farmer, message);
res.json(messageLog)
// const messageLog = await messageSender.sendMessageToFarmer(farmer, message);
// res.json(messageLog)
}
catch (e: any) {
res.status(500).send(e).end();
Expand Down Expand Up @@ -167,18 +167,18 @@ router.post('/new-thread', async (req, res) => {

try {
// const messageLogs = await TwilioInstance.sendMessageToGroup(group, body.message);
const messageLogs = await messageSender.sendMessageToGroup(group, body.message);
// const messageLogs = await messageSender.sendMessageToGroup(group, body.message);

const thread: ThreadsDTO = {
thread_id: index,
farmers,
isGroup: true,
preview: body.message,
messages: messageLogs
}
// const thread: ThreadsDTO = {
// thread_id: index,
// farmers,
// isGroup: true,
// preview: body.message,
// // messages: messageLogs
// }

// return res.json(messageLogs.map(it => it.messageRef));
return res.json(thread);
// return res.json(thread);
}
catch (e: any) {
res.status(500).send(e).end();
Expand Down Expand Up @@ -213,8 +213,8 @@ router.post('/thread', async (req, res) => {

try {
// const messageLogs = await TwilioInstance.sendMessageToGroup(group, body.message);
const messageLogs = await messageSender.sendMessageToGroup(group, body.message);
return res.json(messageLogs.map(it => it.messageRef));
// const messageLogs = await messageSender.sendMessageToGroup(group, body.message);
// return res.json(messageLogs.map(it => it.messageRef));
}
catch (e: any) {
res.status(500).send(e).end();
Expand All @@ -228,8 +228,8 @@ router.post('/thread', async (req, res) => {

try {
// const messageLog = await TwilioInstance.sendMessageToFarmer(farmer, message);
const messageLog = await messageSender.sendMessageToFarmer(farmer, message);
res.json(messageLog)
// const messageLog = await messageSender.sendMessageToFarmer(farmer, message);
// res.json(messageLog)
}
catch (e: any) {
res.status(500).send(e).end();
Expand Down
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions react-app/src/components/Crops/CropTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { CropTemplate, CropTemplateAPI} from "../../services/cropTemplate";
import { CropService } from "../../services/CropService";
import { Crop } from "../../services/crops";
import { getFarmer, Farmer } from "../../services/farmers";
import { Field } from "../../types/field";
import ReputationActions from "../Farmers/ReputationActions";

import { UpdateSubFieldWithCropTemplate, OrganizeReputationActions } from './helperFunctions';
import { ColonyAPI } from '../../services/colony';
Expand Down Expand Up @@ -274,6 +276,7 @@ const CropTemplateSelector = () => {
<Button type="button" style={{background: "green"}} onClick={handleSubmit}>Create New Template</Button>
</Column>
</Row>
<ReputationActions selectedCrop={selectedCrop}/>
</>
)
}
Expand Down
6 changes: 3 additions & 3 deletions react-app/src/components/Crops/helperFunctions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,22 @@ export async function UpdateSubFieldWithCropTemplate(

// update field.subfields.properties.crops with reputation and croptemplate in mongodb
const res = await cropTemplateAPI.addCropTemplateToField(currentField);
console.log("updated field: ", res)
}
}

export function OrganizeReputationActions(field: any): Record<string, boolean>[]{
let reputationMaps: Record<string, boolean>[] = []

const subFieldsArray: any = field.subFields;

for(let subFieldIndex in subFieldsArray){
const subFieldCropsArray: any = subFieldsArray[subFieldIndex].properties.crops;

for(let subFieldCropIndex in subFieldCropsArray){
if(subFieldCropsArray[subFieldCropIndex].reputation_actions != null){
reputationMaps.push(subFieldCropsArray[subFieldCropIndex].reputation_actions!)
}
}
}

return reputationMaps
}
109 changes: 109 additions & 0 deletions react-app/src/components/Farmers/ReputationActions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React, { useEffect, useState } from "react";
import { Field } from "../../types/field";
import { Farmer, getAllFarmers } from "../../services/farmers";
import { Column, Row, Select, SelectItem, Toggle } from "carbon-addons-iot-react";
import { FieldAPI } from "../../services/fields";
import { CropTemplateAPI } from "../../services/cropTemplate"
import { OrganizeReputationActions } from '../Crops/helperFunctions';

const fieldAPI = new FieldAPI();
const cropTemplateAPI = new CropTemplateAPI();
const ReputationActions = (props: any) => {
const [field, setField] = useState<Field>();
const [farmer, setFarmer] = useState<string>();
const [farmerList, setFarmerList] = useState<Farmer[]>([]);
const [reputationActionMap, setReputationActionMap] = useState<any>({});

const handleClick = async(key: string) => {

const response = await cropTemplateAPI.updateRepActions(field, props.selectedCrop, farmer!, key, true);
if(response.status === 200){
let newReputationActionMap = [...reputationActionMap];
newReputationActionMap[0][key] = true;
setReputationActionMap(newReputationActionMap);
}
}

const getValueMap = (actionMap: any) => {
// console.log('actionMap: ', actionMap);
let actions = []
for(let key in actionMap[0]) {
actions.push(
<Row>
<Toggle
toggled={actionMap[0][key]}
id={key}
labelA="Incomplete"
labelB="Complete"
labelText={key}
onClick={() => handleClick(key)}
/>
</Row>
)
}
return(actions);
}

const getFarmerList = async() => {
const farmers = await getAllFarmers();
setFarmerList(farmers);
}

const handleFarmerSelection = async(event:any) => {
const fieldResponse = await fieldAPI.getFieldForFarmer(event.target.value);
setFarmer(event.target.value);
setField(fieldResponse);
setReputationActionMap(OrganizeReputationActions(fieldResponse));
}

useEffect(() => {
if(!farmerList.length){
getFarmerList();
}

},[])

return(
<>
<Row>
<Column>
<Select
defaultValue="select-crop"
helperText=""
id="select-1"
labelText="Farmers"
size="md"
onChange={handleFarmerSelection}
>
<SelectItem
disabled
hidden
text="Select A Farmer"
value="select-farmer"
/>
{
farmerList.map((item: Farmer) => {
return(
<SelectItem
text={item.name}
value={item._id}
/>
)
})
}
</Select>
</Column>
</Row>
{(Object.keys(reputationActionMap).length > 0) && getValueMap(reputationActionMap).map((item) => {
return(
<>
{item}
</>
)
})
}
</>
)
}

export default ReputationActions;
2 changes: 1 addition & 1 deletion react-app/src/services/cropTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class CropTemplateAPI{
actionName : actionName,
actionStatus : actionStatus
});
return data.data
return data
}

async addCropTemplateToField(field: any): Promise<any> {
Expand Down
10 changes: 10 additions & 0 deletions react-app/src/services/fields.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import axios from 'axios';
import { Field } from '../types/field';
export class FieldAPI{
APIBase = "/api/fields/";

async getFieldForFarmer(farmer_id: any): Promise<Field> {
const data = await axios.get<Field>(this.APIBase + "getFieldByFarmerId/" + farmer_id);
return data.data;
}
}