Skip to content

Commit

Permalink
Merge pull request #276 from IndustryFusion/IFDPP-358-Frontend-Backen…
Browse files Browse the repository at this point in the history
…d_CRUD_Contract

created get all contracts by asset type.
  • Loading branch information
LahariMIBS authored Nov 11, 2024
2 parents acc9685 + d8b56ce commit ce09d33
Show file tree
Hide file tree
Showing 13 changed files with 207 additions and 112 deletions.
26 changes: 22 additions & 4 deletions backend/src/endpoints/asset/asset.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class AssetService {
const assetData = [];
let typeUrl = `${this.scorpioUrl}/urn:ngsi-ld:asset-type-store`;
let typeData = await axios.get(typeUrl,{headers});
let typeArr = typeData.data["http://www.industry-fusion.org/schema#type-data"].map(item => item.value);
let typeArr = typeData.data["http://www.industry-fusion.org/schema#type-data"].value.items.map(item => item.value);
typeArr = Array.isArray(typeArr) ? typeArr : (typeArr !== "json-ld-1.1" ? [typeArr] : []);
for(let i = 0; i < typeArr.length; i++) {
let type = typeArr[i];
Expand Down Expand Up @@ -87,7 +87,7 @@ export class AssetService {
const scorpioResponse = await axios.get(`${this.scorpioUrl}/${assetId}`, {headers});
result.push(scorpioResponse.data);
} catch(err) {
console.log("Error fetching asset", i, err)
// console.log("Error fetching asset", i, err)
continue;
}
}
Expand Down Expand Up @@ -164,7 +164,7 @@ export class AssetService {
};
let typeUrl = `${this.scorpioUrl}/urn:ngsi-ld:asset-type-store`;
let typeData = await axios.get(typeUrl,{headers});
let typeArr = typeData.data["http://www.industry-fusion.org/schema#type-data"].map(item => item.value);
let typeArr = typeData.data["http://www.industry-fusion.org/schema#type-data"].value.items.map(item => item.value);
// console.log("typeArr",typeArr)
typeArr = Array.isArray(typeArr) ? typeArr : (typeArr !== "json-ld-1.1" ? [typeArr] : []);
for(let i = 0; i < typeArr.length; i++) {
Expand Down Expand Up @@ -229,6 +229,12 @@ export class AssetService {
'Authorization': req.headers['authorization']
};

// fetch asset types to find and store unique types.
let typeUrl = `${this.scorpioUrl}/urn:ngsi-ld:asset-type-store`;
let typeData = await axios.get(typeUrl,{headers});
let typeArr = typeData.data["http://www.industry-fusion.org/schema#type-data"].value.items.map(item => item.value);
typeArr = Array.isArray(typeArr) ? typeArr : (typeArr !== "json-ld-1.1" ? [typeArr] : []);
let uniqueType = [];

const response = await axios.get(`${this.ifxurl}/asset/get-owner-asset/${company_ifric_id}`,{headers: registryHeaders});
for(let i = 0; i < response.data.length; i++) {
Expand All @@ -238,10 +244,22 @@ export class AssetService {
} catch(err) {
if(err.response.status === 404) {
await axios.post(this.scorpioUrl, response.data[i], {headers});
if(typeArr.length > 0 && !typeArr.includes(response.data[i].type) && !uniqueType.some(data => data.value === response.data[i].type)){
uniqueType.push({
type: "Property",
value: response.data[i].type
});
}
}
continue;
}
}

if(uniqueType.length > 0){
typeData.data["http://www.industry-fusion.org/schema#type-data"].value.items = [...typeData.data["http://www.industry-fusion.org/schema#type-data"].value.items, ...uniqueType];
await this.deleteAssetById('urn:ngsi-ld:asset-type-store',token);
await axios.post(this.scorpioUrl, typeData.data, {headers});
}
return {
success: true,
status: 201,
Expand All @@ -261,7 +279,7 @@ export class AssetService {
};
let typeUrl = `${this.scorpioUrl}/urn:ngsi-ld:asset-type-store`;
let typeData = await axios.get(typeUrl,{headers});
let typeArr = typeData.data["http://www.industry-fusion.org/schema#type-data"].map(item => item.value);
let typeArr = typeData.data["http://www.industry-fusion.org/schema#type-data"].value.items.map(item => item.value);
typeArr = Array.isArray(typeArr) ? typeArr : (typeArr !== "json-ld-1.1" ? [typeArr] : []);
let uniqueType = [];
// sending multiple requests to scorpio to save the asset array
Expand Down
12 changes: 11 additions & 1 deletion backend/src/endpoints/contract/contract.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@ import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/commo
import { ContractService } from './contract.service';
import { CreateContractDto } from './dto/create-contract.dto';
import { UpdateContractDto } from './dto/update-contract.dto';
import { TokenService } from '../session/token.service';

@Controller('contract')
export class ContractController {
constructor(private readonly contractService: ContractService) {}
constructor(
private readonly contractService: ContractService,
private readonly tokenService: TokenService
) {}

@Get('get-contract-by-type/:contract_type')
findByType(@Param('contract_type') contract_type: string) {
return this.contractService.findByType(contract_type);
}

@Get('get-all-contract-by-asset-type')
async findAllContractByAssetTypes() {
const token = await this.tokenService.getToken();
return this.contractService.findAllContractByAssetTypes(token);
}
}
28 changes: 28 additions & 0 deletions backend/src/endpoints/contract/contract.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import axios from 'axios';
@Injectable()
export class ContractService {
private readonly ifxUrl = process.env.IFX_PLATFORM_BACKEND_URL;
private readonly scorpioUrl = process.env.SCORPIO_URL;


async findByType(contract_type: string) {
try {
Expand All @@ -15,4 +17,30 @@ export class ContractService {
throw new NotFoundException(`Failed to fetch contract by type ${contract_type}: ${err.message}`);
}
}

async findAllContractByAssetTypes(token: string) {
try {
const contractData = [];
const headers = {
Authorization: 'Bearer ' + token,
'Content-Type': 'application/ld+json',
'Accept': 'application/ld+json'
};
let typeUrl = `${this.scorpioUrl}/urn:ngsi-ld:asset-type-store`;
let typeData = await axios.get(typeUrl,{headers});
let typeArr = typeData.data["http://www.industry-fusion.org/schema#type-data"].value.items.map(item => item.value);
typeArr = Array.isArray(typeArr) ? typeArr : (typeArr !== "json-ld-1.1" ? [typeArr] : []);

for(let i = 0; i < typeArr.length; i++) {
let type = typeArr[i];
const response = await axios.get(`${this.ifxUrl}/contract/get-contract-by-asset-type/${btoa(type)}`);
if(response.data.length > 0) {
contractData.push(...response.data);
}
}
return contractData;
} catch(err) {
throw new NotFoundException(`Failed to fetch all contract by asset type: ${err.message}`);
}
}
}
110 changes: 61 additions & 49 deletions frontend/src/components/dashboard/dashboard-assets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@ import EditOnboardForm from "./edit-onboard-form";
import { Toast, ToastMessage } from "primereact/toast";
import { InputText } from "primereact/inputtext";
import "../../styles/dashboard.css";
import { useDispatch } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import { update } from '@/redux/entityId/entityIdSlice';
import { useTranslation } from "next-i18next";
import axios from "axios";
import { ProgressSpinner } from 'primereact/progressspinner';
import { fetchAssets } from '@/redux/assetManagement/assetManagementSlice';
import { RootState } from '@/redux/store';

interface PrefixedAssetProperty {
key: string;
Expand Down Expand Up @@ -61,6 +64,7 @@ const DashboardAssets: React.FC<DashboardAssetsProps> = ({ setBlockerProp, setPr
const dispatch = useDispatch();
const { t } = useTranslation(['placeholder', 'dashboard']);
const API_URL = process.env.NEXT_PUBLIC_BACKEND_API_URL;
const { assets, loading } = useSelector((state: RootState) => state.assetManagement);

const productNameBodyTemplate = (rowData: Asset): React.ReactNode => {
return <>{rowData?.product_name}</>;
Expand Down Expand Up @@ -123,14 +127,8 @@ const DashboardAssets: React.FC<DashboardAssetsProps> = ({ setBlockerProp, setPr

const handleAsset = async () => {
try {
const response = await fetchAsset();
if (response !== undefined) {
setSelectedRow(response[0]);
setAssetData(response);
setAllAssets(response);
setAssetCount(response.length)
} else {
console.error("Fetch returned undefined");
if(!assets.length) {
dispatch(fetchAssets());
}
} catch (error) {
console.error("Fetched assets:", error)
Expand Down Expand Up @@ -206,6 +204,13 @@ const DashboardAssets: React.FC<DashboardAssetsProps> = ({ setBlockerProp, setPr
}
}, [onboardAsset, showBlocker])

useEffect(() => {
setSelectedRow(assets[0]);
setAssetData(assets);
setAllAssets(assets);
setAssetCount(assets.length)
}, [assets])


return (
<>
Expand All @@ -228,48 +233,55 @@ const DashboardAssets: React.FC<DashboardAssetsProps> = ({ setBlockerProp, setPr
className="mb-10" style={{ borderRadius: "10px", width: "460px"}} />
</span>
</div>
<DataTable
ref={dataTableRef}
rows={6}
paginator
value={assetData}
className="dashboard-assets"
scrollable={true}
scrollHeight="750px"
onRowClick={(e) => handleClick(e.data as Asset)}
selectionMode="single"
selection={selectedRow}
onSelectionChange={(e) => setSelectedRow(e.value as Asset)}
rowClassName={rowClassName}
>
<Column
header={t('dashboard:productImage')}
field="product_icon"
body={productIconTemplate}
/>
<Column
header={t('dashboard:productName')}
field="product_name"
body={productNameBodyTemplate}
/>
<Column
header={t('dashboard:assetType')}
field="asset_type"
body={assetTypeBodyTemplate}
/>
<Column
header={t('dashboard:onboard')}
style={{ width: '10%' }}
body={viewBodyTemplateNew}
{loading ? (
<div className="dashboard-spinner">
<ProgressSpinner />
</div>
) : (
<DataTable
ref={dataTableRef}
rows={6}
paginator
value={assetData}
className="dashboard-assets"
scrollable={true}
scrollHeight="750px"
onRowClick={(e) => handleClick(e.data as Asset)}
selectionMode="single"
selection={selectedRow}
onSelectionChange={(e) => setSelectedRow(e.value as Asset)}
rowClassName={rowClassName}
>
<Column
header={t('dashboard:productImage')}
field="product_icon"
body={productIconTemplate}
/>
<Column
header={t('dashboard:productName')}
field="product_name"
body={productNameBodyTemplate}
/>
<Column
header={t('dashboard:assetType')}
field="asset_type"
body={assetTypeBodyTemplate}
/>
<Column
header={t('dashboard:onboard')}
style={{ width: '10%' }}
body={viewBodyTemplateNew}

/>
<Column
header={t('dashboard:view')}
style={{ width: '15%' }}
body={viewBodyTemplate}
/>
<Column
header={t('dashboard:view')}
style={{ width: '15%' }}
body={viewBodyTemplate}

/>
</DataTable>
/>
</DataTable>
)
}
</div>
</div>
{showBlocker &&
Expand Down
21 changes: 14 additions & 7 deletions frontend/src/pages/binding-request.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import { Tree } from "primereact/tree";
import { NodeService } from "@/service/NodeService";
import { Checkbox } from "primereact/checkbox";
import { getAccessGroup } from "@/utility/indexed-db";
import { getContracts } from "@/utility/contract";
import { getAllContractByAssetType } from "@/utility/contract";
import ContractCard from "@/components/bindingRequest/binding-file";
import { IoArrowBack } from "react-icons/io5";
import ContractFolders from "@/components/bindingRequest/binding-folders";
import { Toast, ToastMessage } from "primereact/toast";
import axios from "axios";
import { fetchContractsRedux } from "@/redux/contract/contractSlice";
import { updateBindingRequestContracts } from "@/redux/binding/bindingRequestSlice";
import { useDispatch, useSelector } from "react-redux";
import Sidebar from '@/components/navBar/sidebar';

const ContractManager = () => {
const [nodes, setNodes] = useState([]);
const [companyIfricId, setCompanyIfricId] = useState("");
const [selectedKey, setSelectedKey] = useState("");
// const [contractsData, setContractsData] = useState([]);
const [contractsData, setContractsData] = useState([]);
const [predictiveFilteredContractsData, setpredictiveFilteredContractsData] =
useState([]);
const [iotAnalyticsContractsData, setIotAnalyticsContractsData] = useState([]);
Expand All @@ -36,7 +36,7 @@ const ContractManager = () => {
const dispatch = useDispatch();

// Access the contracts data from Redux
const contractsData = useSelector((state: any) => state.contracts.contracts);
const bindingRequestData = useSelector((state: any) => state.bindingRequest.contracts);

const showToast = (
severity: ToastMessage["severity"],
Expand All @@ -59,7 +59,11 @@ const ContractManager = () => {
try {
const details = await getAccessGroup();
setCompanyIfricId(details.company_ifric_id);
dispatch(fetchContractsRedux(companyIfricId));

const response = await getAllContractByAssetType();
if(response?.data.length) {
dispatch(updateBindingRequestContracts(response.data));
}
} catch(error: any) {
if (axios.isAxiosError(error)) {
console.error("Error response:", error.response?.data.message);
Expand All @@ -70,11 +74,14 @@ const ContractManager = () => {
}
}
};

useEffect(() => {
getCompanyId();
});

},[]);

useEffect(() => {
setContractsData(bindingRequestData);
},[bindingRequestData]);

const handleFilterContracts = () => {
setLoading(true);
Expand Down
Loading

0 comments on commit ce09d33

Please sign in to comment.