rtgk-screen-web/pages/index.js

985 lines
30 KiB
JavaScript
Raw Normal View History

2024-06-20 11:26:44 +08:00
/** @format */
import { Tooltip } from "antd";
import Head from "next/head";
import react from "react";
import Header from "./components/Header/Header";
import VTab from "./components/Tab";
// import Results from "./components/Results/Results";
import localStorage from "localStorage";
import Rcwebsocket from "reconnecting-websocket";
import eqs from "../utils/eqs";
import requests, { doPost, getWsUrl, imgUrl } from "../utils/requests";
import Card from "./components/Card";
import Modal from "./components/Modal";
const { eqinfos, eqdetail, eqstatus } = eqs;
var intX;
var isImgLoad = false;
var isAlertLoad = false;
var isEqDataUpdate = false;
var _selectedtypecode, _selectedTab;
var ws, connected, wseq, connectedeq;
// eslint-disable-next-line react-hooks/rules-of-hooks
export default function Home({ results }) {
const [isLoading, setLoading] = react.useState(false);
const [selectedTab, setSelectedTab] = react.useState("-2");
const [isPop, setPop] = react.useState(false);
const [isPopAlert, setIsPopAlert] = react.useState(false);
const [popData, setPopData] = react.useState({});
const [workCenterCode, setWorkCenterCode] = react.useState();
const [queryEqList, setQueryEqList] = react.useState(null);
const [eqlist, setEqlist] = react.useState([]);
const [operations, setOperations] = react.useState([]);
const [curstation, setCurstation] = react.useState(null);
const [runningStatus, setRunningStatus] = react.useState({
0: true,
1: true,
2: true,
3: true,
4: true,
});
const [statuslist, setStatuslist] = react.useState({});
// const [watingCount, setWaitingCount] = react.useState([]);
const [typeList, setTypeList] = react.useState(null);
// const [workingCount, setWorkingCount] = react.useState([]);
const [stopCount, setStopCount] = react.useState([]);
const [alertData, setAlertData] = react.useState([]);
// const [productCount, setProductCount] = react.useState(0);
const [selectedtypecode, setselectedtypecode] = react.useState("");
const [allEquipCount, setAllEquipCount] = react.useState([]);
// if (isLoading) return <p>Loading...</p>;
var handleClose = () => {
setPop(false);
};
var popHandle = (eq) => {
setIsPopAlert(false);
setPop(!isPop);
setPopData(eq);
};
var alartPopHandle = (eq) => {
setIsPopAlert(true);
setPop(!isPop);
setPopData(eq);
};
const listHeight = react.useRef(null);
const screenref = react.useRef(null);
const headerref = react.useRef(null);
let isresize = false;
let counter = 0;
react.useEffect(() => {
getWsUrl().then((url) => {
ws?.close();
wseq?.close();
//判断只有在是edge ws才连接否则会出现异常连接不停重连
if (url.indexOf("application-ws") > -1) {
setTimeout(() => {
try {
ws = new Rcwebsocket(url);
wseq = new Rcwebsocket(url);
const onOpen = function () {
console.log("OPENED: " + url);
connected = true;
ws.send("alert");
};
const onClose = function () {
console.log("CLOSED: " + url);
ws = null;
};
const onMessage = function (event) {
var data = event.data;
try {
var jsonobj = JSON.parse(data);
if (jsonobj.length > 0) {
setAlertData(jsonobj);
}
} catch (error) { }
};
const onError = function (event) {
//alert(event.data);
};
ws.onopen = onOpen;
ws.onclose = onClose;
ws.onmessage = onMessage;
ws.onerror = onError;
const onOpeneq = function () {
console.log("eq OPENED: " + url);
connectedeq = true;
wseq.send("equip");
};
const onCloseeq = function () {
console.log("eq CLOSED: " + url);
wseq = null;
};
const onMessageeq = function (event) {
var data = event.data;
try {
var jsonobj = JSON.parse(data);
//获取数据
// setLoading(true);
bindData(jsonobj, queryEqList);
// setLoading(false);
} catch (error) { }
};
const onErroreq = function (event) {
//alert(event.data);
console.log("event:连接websocket发生异常");
};
wseq.onopen = onOpeneq;
wseq.onclose = onCloseeq;
wseq.onmessage = onMessageeq;
wseq.onerror = onErroreq;
//设置启动时选择工作中心
let curstation = localStorage.getItem("workCenterCode");
setCurstation(curstation);
} catch (error) {
console.log("连接websocket发生异常");
}
}, 2000);
}
});
}, [queryEqList]);
react.useEffect(() => {
function handleResize() {
isresize = true;
setTimeout(() => {
isresize = false;
}, 100);
}
window.addEventListener("resize", handleResize);
});
// react.useEffect(() => {
// queryStauts(queryEqList);
// }, [alertData, isImgLoad]);
react.useEffect(() => {
queryStauts(queryEqList);
}, [alertData]);
// react.useEffect(() => {
// if (queryEqList === null || queryEqList === undefined) {
// if (intX) {
// clearInterval(intX);
// intX = null;
// }
// } else if (queryEqList.length > 0) {
// if (intX) {
// clearInterval(intX);
// intX = null;
// }
// setTimeout(() => {
// intX = setInterval(() => {
// // queryFields(queryEqList);
// // queryStauts(queryEqList);
// }, interval);
// }, 2000);
// }
// }, [queryEqList]);
const getAlertData = react.useMemo(() => {
return alertData;
}, [alertData]);
const getqueryEqList = react.useMemo(() => {
return queryEqList;
}, [queryEqList]);
var factorychanged = (item) => {
setQueryEqList([]);
setAlertData([]);
setStatuslist({});
if (!item) {
return;
}
isImgLoad = false;
setLoading(true);
if (item.code === undefined) return;
console.log("执行获取所有设备" + item.code);
setWorkCenterCode(item.code);
localStorage.setItem("workCenterCode", item.code);
let eqdata = undefined;//localStorage.getItem(item.code);
if (eqdata && JSON.parse(eqdata).length !== 0) {
let ed = JSON.parse(eqdata);
getTypeList(ed);
setEqlist(ed);
queryFields(ed);
setQueryEqList(ed);
setLoading(false);
return;
} else {
isEqDataUpdate = true;
}
//获取设备明细清单
doPost(requests.fetchEquipFieldsList.url, { workCenterCode: item.code })
.then((res) => res.json())
.then((data) => {
if (data.success) {
if (!data.data) {
setTypeList(null);
setEqlist(null);
setQueryEqList(null);
return;
}
//这里如果想要按照name进行分组即如下
const retdata = data.data;
const results = GroupBy(retdata, function (item) {
return [item.code];
});
const eqlisttmp = results.map((item) => {
return {
code: item[0].code,
fileGroupId: item[0].fileGroupId,
fieldSort: item[0].fieldSort,
name: item[0].name,
operationCode: item[0].operationCode,
operationName: item[0].operationName,
operationSort: item[0].operationSort,
screenShowSerialNumber: item[0].screenShowSerialNumber,
typeCode: item[0].typeCode,
runningstatus: undefined,
typeName: item[0].typeName,
bmIotEquipmentRelationshipList: item,
};
});
getTypeList(eqlisttmp);
setEqlist(eqlisttmp);
queryFields(eqlisttmp);
setQueryEqList(eqlisttmp);
//localStorage.setItem(item.code, JSON.stringify(eqlisttmp));
isEqDataUpdate = false;
} else {
setEqlist(null);
setTypeList(null);
queryFields(null);
setQueryEqList(null);
}
})
.catch((ex) => {
console.log(ex);
setTypeList(null);
setEqlist(null);
queryFields(null);
setQueryEqList(null);
})
.finally((data) => {
setTimeout(() => {
setLoading(false);
}, 300);
});
};
function refreshData(eqfields) {
if (!eqfields) {
eqfields = eqlist;
}
if (!eqfields) {
return;
}
//把所有字段赋值
const eqfieldstmp = eqfields.map((item) => {
var obj = {};
var fields = item.bmIotEquipmentRelationshipList.map((field) => {
return field.iotField;
});
obj["equipCode"] = item.code;
fields.map((aa) => {
obj[aa] = "";
});
return obj;
});
// doPost(requests.fetchLastEqFieldsValue.url, eqfieldstmp)
// .then((res) => res.json())
// .then((data) => {
// if (data.success) {
// bindData(data.data, eqfields);
// }
// })
// .catch((ex) => {
// console.log(ex);
// })
// .finally(() => {
// setLoading(false);
// });
}
function bindData(data, eqfields) {
const zret = data;
zret.map((ret) => {
eqfields.filter((a) => {
// var eqstatus1 = a;
// if (getAlertData && getAlertData.length > 0) {
// eqstatus1.alert = getAlertData.filter((al) => {
// if (al.equipCode === eqstatus1.code) {
// return al;
// }
// });
// let alertcout = eqstatus1?.alert?.filter((aa) => {
// if (!aa?.eliminationTime) {
// return aa;
// }
// });
// eqstatus1.alertcount = alertcout.length;
// }
if (ret && ret.equipCode && a.code === ret.equipCode) {
a.bmIotEquipmentRelationshipList.map((b) => {
b.iotFieldValue = ret[b.iotField];
b.iotFieldValueTime = ret[b.iotField + "__time"];
if (
(!a.runningstatus || a.runningstatus === 0) &&
a.runningstatus !== 3
) {
a.runningstatus = Number.parseInt(ret["runningstatus"]);
}
if (Number.isNaN(a.runningstatus)) {
a.runningstatus = 0;
}
if (!b.updateTime) {
b.updateTime = ret["time"];
}
});
}
});
});
queryStauts(eqfields);
}
function GroupBy(array, fn) {
const groups = {};
array.forEach(function (item) {
const group = JSON.stringify(fn(item));
//这里利用对象的key值唯一性的创建数组
groups[group] = groups[group] || [];
groups[group].push(item);
});
//最后再利用map循环处理分组出来
return Object.keys(groups).map(function (group) {
return groups[group];
});
}
var closePop = () => {
setPop(false);
};
function dateData(property, bol) {
//property是你需要排序传入的key,bol为true时是升序false为降序
return function (a, b) {
var value1 = a[property];
var value2 = b[property];
if (bol) {
// 升序
return Date.parse(value1) - Date.parse(value2);
} else {
// 降序
return Date.parse(value2) - Date.parse(value1);
}
};
}
return (
<div className="h-screen overflow-hidden modal-container " ref={screenref}>
{isPop ? (
<Modal
title={`${popData.name} · ${isPopAlert ? "告警" : "其他"} `}
img={popData.Img}
closePopHandler={closePop}
>
{console.log(popData.alert)}
{isPopAlert ? (
<div>
<div className="overflow-x-auto">
<table className="table table-compact w-full">
<thead>
<tr className=" ">
<th>告警发生时间</th>
<th>告警内容</th>
<th>告警消除时间</th>
</tr>
</thead>
<tbody>
{popData?.alert?.sort(dateData("time", false)).map((x) => {
return (
<tr>
<td>{x.time}</td>
<td>{x.phenomenonName}</td>
<td>{x.eliminationTime}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
) : (
<div className={`grid gap-2 grid-cols-2 w-full`}>
{!popData.bmIotEquipmentRelationshipList
? ``
: popData.bmIotEquipmentRelationshipList
.filter((re) => {
if (isPopAlert && re.iotIsalarm && re.status) {
return re;
} else if (
!isPopAlert &&
!re.iotIsalarm &&
!re.iotIsMainField &&
re.status
) {
return re;
}
})
.sort((a, b) =>
parseFloat(a.fieldSort) > parseFloat(b.fieldSort) ? 1 : -1
) // .sort((a, b) => (!a.iotFieldValue ? 1 : -1))
.map((re) => {
return (
<div className="">
<label
htmlFor="field-value"
className="block text-xs text-gray-700"
>
{re.iotFieldDescribe}
</label>
{!isPopAlert ? (
<Tooltip
placement="top"
title={re.iotFieldValueTime}
mouseEnterDelay={1}
>
<div>
<input
disabled
type="text"
name="field-value"
value={re.iotFieldValue}
id="field-value"
autoComplete="given-name"
className=" mt-1 text-xs disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none
focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm h-6 border-gray-300 "
/>
</div>
</Tooltip>
) : typeof re.iotFieldValue === "boolean" ? (
re.iotFieldValue ? (
<label
name="field-value"
id="field-value"
className=" mt-1 block w-10 bg-[#eb5f2c26] text-[#EB5E2C] border-[#EB5E2C] border py-0.5 px-1.5"
>
告警{" "}
</label>
) : (
<label
name="field-value"
id="field-value"
className=" mt-1 block w-10 bg-[#7caea02f] text-[#53B59A] border-[#53B59A] border py-0.5 px-1.5"
>
正常
</label>
)
) : (
re.iotFieldValue
)}
</div>
);
})}
</div>
)}
</Modal>
) : null}
<Head>
<title>融通高科设备大屏 1.0</title>
<link rel="icon" href="/favicon.ico" />
<script src="http://localhost:8097"></script>
</Head>
{/* {selectedtypecode==='1001'
} */}
<Header
getEqData={() => {
localStorage.removeItem(workCenterCode);
factorychanged({ code: workCenterCode });
}}
runningstatuschanged={(key, value) => {
setRunningStatus((prestate) => {
return {
...prestate,
[key]: value,
};
});
}}
zzref={headerref}
selectedone={curstation}
factorychanged={factorychanged}
setTypeList={(data) => {
setTypeList(data);
}}
typechanged={(ty) => {
if(ty.name==='无'){return}
setselectedtypecode(ty?.code);
_selectedtypecode = ty?.code;
if (eqlist&&eqlist.length > 0) {
getTypeList(eqlist);
queryFields(eqlist);
}
}}
typeList={typeList}
statuslist={statuslist}
/>
{/* overflow-y-scroll scrollbar-hide */}
{/* ${
screenref.current?.clientHeight
} ${headerref.current?.clientHeight} ${
listHeight.current?.clientHeight
} ${
screenref.current?.clientHeight - headerref.current?.clientHeight <
listHeight.current?.clientHeight && !isresize
? "h-[92%]"
: "h-fit"
} */}
<VTab
className="flex flex-col h-[94%] w-full bg-white px-3 pb-3"
ops={operations}
selectedtypecode={selectedtypecode}
tabchanged={(tab) => {
if (tab) {
setSelectedTab(tab.code);
_selectedTab = tab.code;
console.log(JSON.stringify(tab));
}
}}
>
<div className="h-full w-full">
{operations
.filter((x) => {
if (selectedTab === "-1" && x.code === "-1") {
return x;
} else if (selectedTab === "-2" && x.code !== "-2") {
return x;
} else if (
selectedTab !== "-2" &&
selectedTab !== "-1" &&
x.code === selectedTab
) {
return x;
}
})
.map((op) => {
return selectedtypecode === "-001" ? (
getTabContent(op.code)
) : !op.code ||
eqlist?.filter(
(z) =>
z.operationCode === op.code &&
z.typeCode === selectedtypecode
)?.length === 0 ? (
<></>
) : (
<div>
<span className="text-[#0185FF]">
<label className=" text-lg ">{"▌"}</label>
<label className=" text-lg ">{op.name}</label>
</span>
<div className="h-3"></div>
{getTabContent(op.code)}
<div className="h-3"></div>
</div>
);
})}
</div>
</VTab>
{/* <Results results={results} /> */}
</div>
);
function getTabContent(op) {
return (
<div
ref={listHeight}
className={`" relative grid grid-flow-row gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6 text-sm text-center font-bold overflow-y-auto h-[92%] "`}
>
{isLoading ? (
<svg
className="animate-spin -ml-1 mr-3 h-5 w-5 text-red absolute top-4 right-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
// stroke-width="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
) : (
<></>
)}
{!eqlist || eqlist.length === 0
? `当前没有数据`
: eqlist
.filter((item) => {
{
if (op === item.operationCode) {
if (!item.runningstatus) {
if (runningStatus[0]) {
return item;
}
} else if (runningStatus[item.runningstatus]) {
return item;
} else if (item.runningstatus < 4 && item?.alertcount > 0) {
if (runningStatus[4] && !runningStatus[2]) {
return item;
} else if (!runningStatus[4] && runningStatus[2]) {
return item;
}
}
}
}
})
.filter((item) => {
if (item.typeCode === selectedtypecode) {
if (!item.screenShowSerialNumber)
item.screenShowSerialNumber = 1000000;
return item;
}
})
.sort((a, b) =>
a.screenShowSerialNumber > b.screenShowSerialNumber ? 1 : -1
)
.map((item, idx) => (
// eslint-disable-next-line react/jsx-key
<Card
// classNamez={isLoading ? `animate-pulse` : ``}
alertData={alertData}
key={idx}
selectedTab={selectedTab}
typecode={_selectedtypecode}
eq={item}
popHandle={popHandle}
alartPopHandle={alartPopHandle}
></Card>
))}
</div>
);
}
function getTypeList(curdata) {
var curdata = curdata.filter((zz) => zz.typeCode === _selectedtypecode);
var codes = curdata.map((zz) => zz.code);
// var _typelist = [];
var _opcodelist = [];
_opcodelist.push({
code: "-2",
name: "全部",
sort: 0,
});
var ctypes = curdata.map((zz) => {
// zz.typecode = zz.typecode;
// zz.typename = zz.bmEquipmentTypeIotVo.name;
// if (_typelist.filter((item) => item.code === zz.typeCode).length > 0) {
// } else {
// _typelist.push({
// name: zz.typeName,
// code: zz.typeCode,
// });
// }
if (
_opcodelist.filter((item) => item.code === zz.operationCode).length > 0
) {
} else {
if (zz.operationCode) {
_opcodelist.push({
code: zz.operationCode,
name: zz.operationName,
sort: zz.operationSort ?? 10000,
});
} else {
zz.operationCode = "-1";
zz.operationName = "其他";
}
}
});
if (_opcodelist.filter((x) => x.code === "-1")?.length === 0) {
_opcodelist.push({
code: "-1",
name: "其他",
sort: 100000,
});
}
var opslist = _opcodelist.sort((a, b) => (a.sort > b.sort ? 1 : -1));
setOperations(opslist);
// setTypeList(_typelist);
if (isImgLoad || !curdata) {
return;
}
curdata.map((eq) => {
if (!eq.fileGroupId) return;
doPost(requests.fetchEquipImg.url + eq.fileGroupId, {
clientId: "pc",
})
.then((res) => res.json())
.then((data) => {
if (data.success && data.rows.length > 0) {
var img = imgUrl + data.rows[0].fileCode;
doPost(img, {})
.then((res) => res.blob())
.then((file) => {
var blobUrl = URL.createObjectURL(file);
eq.Img = blobUrl;
})
.catch((ex) => {
console.log(ex);
});
} else {
// console.log(data);
}
})
.catch((ex) => {
console.log(ex);
});
});
isImgLoad = true;
}
function queryStauts(eqdata) {
if (!_selectedtypecode) {
_selectedtypecode = selectedtypecode;
}
if (!eqdata || !_selectedtypecode) {
// setLoading(false);
return;
}
var codes = eqdata
.filter((item) => {
if (item.typeCode === _selectedtypecode) {
return item;
}
})
.map((aa) => aa.code);
//获取设备状态
//接口请求物联网influxdb查询服务
//0 待产 1 生产 2 停产
if (_selectedtypecode && _selectedtypecode !== "1001") {
setStatuslist((prestate) => {
return {
...prestate,
0: codes.length,
1: 0,
2: 0,
3: 0,
4: 0,
};
});
return;
}
var alertcount = [];
if (_selectedtypecode) {
alertcount = eqdata.filter((eqstatus) => {
if (
eqstatus?.alertcount > 0 &&
eqstatus.typeCode === _selectedtypecode
) {
return eqstatus;
}
});
}
// setStatuslist((prestate) => {
// return {
// ...prestate,
// 4: alertcount?.length,
// };
// });
const alertcountl = alertcount?.length;
if (codes.length === 0) return;
var waitingcount = eqdata.filter((eqstatus) => {
if (eqstatus.runningstatus === 1) {
return eqstatus;
}
});
var workingcount = eqdata.filter((eqstatus) => {
if (eqstatus.runningstatus === 2) {
return eqstatus;
}
});
var stopcount = eqdata.filter((eqstatus) => {
if (eqstatus.runningstatus === 3) {
return eqstatus;
}
});
// setWaitingCount(waitingcount.length);
// setWorkingCount(workingcount.length);
// setStopCount(stopcount.length);
// setStatuslist((prestate) => {
// return {
// ...prestate,
// [eqstatus.runningstatus]: waitingcount.length,
// };
// });
setStatuslist((prestate) => {
return {
...prestate,
1: waitingcount.length,
2: workingcount.length,
3: stopcount.length,
4: alertcountl,
};
});
var wclist = waitingcount.map((count) => count.code);
var sclist = stopcount.map((count) => count.code);
var rclist = workingcount.map((count) => count.code);
var alertlist = alertcount?.map((count) => count.code);
var nonestate = 0;
eqdata
.filter((item) => {
if (codes.indexOf(item.code) > -1) {
return item;
}
})
.map((eq) => {
if (wclist.filter((a) => a === eq.code).length > 0) {
eq.runningstatus = 1;
// eq.updatestatus(1);
} else if (sclist.filter((a) => a === eq.code).length > 0) {
eq.runningstatus = 3;
// eq.updatestatus(3);
} else if (rclist.filter((a) => a === eq.code).length > 0) {
eq.runningstatus = 2;
// eq.updatestatus(2);
} else if (alertlist.filter((a) => a === eq.code).length > 0) {
eq.runningstatus = 4;
// eq.updatestatus(4);
} else {
eq.runningstatus = 0;
nonestate++;
}
// if (alertlist?.filter((a) => a === eq.code).length > 0) {
// eq.runningstatus = 1;
// // eq.updatestatus();
// }
});
setStatuslist((prestate) => {
return {
...prestate,
0: nonestate,
};
});
}
function queryFields(data) {
if (!data || data === undefined || data.length == 0) {
return;
}
// setLoading(true);
data.filter((item) => {
if (item.typeCode === _selectedtypecode && item.updateFields) {
item.updateFields();
}
});
// console.log(typelist);
refreshData(data);
//获取绑定的工单
// doPost(requests.fetchBindList.url, {})
// .then((res) => res.json())
// .then((data) => {
// if (data.success) {
// var bindlist = data.data;
// var arr = bindlist.map((bind) => bind.workOrderCode);
// const set = new Set(arr);
// setProductCount(set.length)
// }
// })
// .catch((ex) => {
// console.log(ex);
// });
//获取设备以及字段信息
// queryStauts(codes, eqdata);
}
// doPost(requests.fetchEquipFields.url, codes)
// .then((res) => res.json())
// .then((data) => {
// if (data.success) {
// // var fileGroupIds = curdata.map((zz) => zz.fileGroupId);
// //获取图片信息
// var eqdata = data.data;
// setEqlist(eqdata);
// setAllEquipCount(eqdata.length);
// queryStauts(codes, eqdata);
// if (isImgLoad) {
// return;
// }
// eqdata.map((eq) => {
// doPost(requests.fetchEquipImg.url + eq.fileGroupId, {
// clientId: "pc",
// })
// .then((res) => res.json())
// .then((data) => {
// if (data.success && data.rows.length > 0) {
// var img = imgUrl + data.rows[0].fileCode;
// doPost(img, {})
// .then((res) => res.blob())
// .then((file) => {
// var blobUrl = URL.createObjectURL(file);
// eq.Img = blobUrl;
// eq.updateImg();
// })
// .catch((ex) => {
// console.log(ex);
// });
// } else {
// // console.log(data);
// }
// })
// .catch((ex) => {
// console.log(ex);
// });
// });
// isImgLoad = true;
// } else {
// setEqlist([]);
// setAllEquipCount(0);
// }
// })
// .catch((ex) => {
// setEqlist([]);
// console.log(ex);
// });
// }
}
//
// export async function getStaticProps() {
// const request = await fetch(
// `&{
// requests.fetchFactory.url
// }`
// )
// .then((res) => res.json())
// .catch((ex) => console.log(ex)); // then get result and pass it with result.json
// return {
// props: {
// results: !request ? null : request.results,
// },
// };
// }