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

PAC-1569-added codes for Packs API fetch #2484

Merged
merged 23 commits into from
May 8, 2024

Conversation

nage1234
Copy link
Contributor

@nage1234 nage1234 commented Mar 26, 2024

Describe the Change

Still lots of changes to be added in this PR. please DO NOT MERGE.. API error handling has to be done, so dont merge this..

Changed Pages

💻 Add Preview URL for Page

Jira Tickets

🎫 PAC-1569

Backports

Can this PR be backported?
No

  • Yes. Remember to add the relevant backport labels to your PR.
  • No. Please leave a short comment below about why this PR cannot be backported.

@nage1234 nage1234 added the do-not-merge/work-in-progress Work in-progress. DO NOT MERGE label Mar 26, 2024
@nage1234 nage1234 requested a review from a team as a code owner March 26, 2024 18:13
@nage1234 nage1234 requested review from karl-cardenas-coding, lennessyy, caroldelwing and codrin-iftimie and removed request for a team March 26, 2024 18:13
@karl-cardenas-coding karl-cardenas-coding marked this pull request as draft March 26, 2024 20:02
@karl-cardenas-coding
Copy link
Contributor

@nage1234 I put the PR in draft to prevent accidental merge 😄

return doc.frontMatter.type === "integration";
function getReadMeMap(packValues) {
const map = new Map();
packValues.forEach((packValue) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reduce can be used here.
side note: you should use map.set instead of assigning attributes on this map

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateCustomData

});
return packsData;
//console.log("roots length= ", roots.length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code cleanup

package.json Outdated
@@ -45,7 +46,7 @@
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@mdx-js/react": "^3.0.0",
"antd": "^5.6.2",
"antd": "^4.22.6",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this has a high chance of breaking things

setSelectedVersion(version);
}

function getOptions() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renderVersionOptions

})}
</Tabs>
);
} else if (Object.keys(packData.packReadme).length) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can simplify this if else logic

} else if (md) {
return md;
} else {
return renderEmptyContent();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm mostly in favor of creating a function for reusability.
if it just wraps some content and is not called more than once, then you can safely inline that content in the return

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else you have to track what a function truly returns

);
}
function getProviders() {
if(packData.provider.includes("all")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (
isn't there a linter here?

Comment on lines 1 to 3
import PacksReadme from "./PacksReadme";

export default PacksReadme;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this file was created

Comment on lines 21 to 29
{isError ?(<IconMapper type={type} />) :
(<Image
preview={false}
height={52}
src={logoUrl}
alt={`${title} logo`}
onError={handleImageError}
/>)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linting


if (category1 < category2) {
return -1;
const filteredTechCards = useMemo(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this entire block is very hard to read.
My suggestion is to create a list of conditions that each card would have to accommodate.

const conditions = [];

// ....
if (selectedFilters.provider) {
   conditions.push(card => card.cloudTypes.includes(selectedFilters.provider))
}
// ...

// apply the filter only once
cards.filter(card => {
  return conditions.every(condition => condition(card))
})

Copy link
Contributor

@codrin-iftimie codrin-iftimie Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at the end you can use the fuse search to narrow things down even further and then group them by categories

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if your approach here to have the data already grouped by categories is the best.
Flat structures are easier to manipulate.

versions: getAggregatedVersions(packContent.tags, packValues, packName, layer)
}
};
return packValueMap;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just return the object?

Comment on lines 36 to 37
const packValueMap = {
fields: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why nest all of the properties under one parent key?

Comment on lines 166 to 169
counter += 1;
if (counter % 10 === 0) {
await setTimeout(2000);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need this?

@@ -54,10 +55,15 @@
"docusaurus-plugin-sass": "^0.2.5",
"docusaurus-theme-openapi-docs": "^3.0.0-beta.3",
"fuse.js": "^6.6.2",
"markdown-to-jsx": "^7.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this used?

const layer = packMDValue.spec.layer === "addon" ? packMDValue.spec.addonType : packTypeNames[packMDValue.spec.layer];
const packValues = packContent.packValues;
return {
fields: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this wraping object?

}

function getAggregatedVersions(tags, packValues, packName, layer) {
const _sortedVersions = sortVersions(tags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does _ mean?

background-color: #1c202b;
}
padding: 10px;
.packdescfirstcol {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while some classes are camel case this one is hard to read.
please make it consistent.

});
}

function renderTabs() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a lot of duplicated code that is hard to read.
side note: refactoring if else if statements in ternary operations makes it even worse.
Take a step back. What are you trying to render here?
How do you simplify it, but how I make it scalable?
You have 3 cases:
tabs, readme only, author-provided content only.
I think you boxed yourself in with thinking only at these cases.
Lets think about the happy path. You'd render tabs if the API returned readme file and the author has provided content.

const tabs = [
  readme && {label: "Readme", key: "readme", content: <Markdown children={readme} /> },
  md && {label: "Additional Details" // .... etc }
].filter(Boolean)

From here you have edge cases. Only one or no tabs might render:
Single tab would not make sense so add a check for it

if (tabs.length === 1) {
  return <><h2>{tabs[0].label}</h2>{tabs[0].content}</>
}

no tabs... no problem

if (tabs.length === 0) {
  return <div className={styles.emptyContent}> // etc
}

Why?
Well it's scalable. If in the future you add another tab this will still render perfectly.


export default function PacksReadme() {
const [selectedVersion, setSelectedVersion] = useState<string>("");
const [md, setMd] = useState<ReactElement<any, any> | null>(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does md mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use a better name for this

Comment on lines 213 to 221
let promises = new Array();
for (let i = 0; i < packDataArr.length; i++) {
const packData = packDataArr[i];
if (packData.spec.registries.length && isSelectedRegistry(packData.spec.registries, mappedRepos)) {
packMDMap[packData.spec.name] = packData;
const cloudType = packData.spec.cloudTypes.includes("all") ? "aws" : packData.spec.cloudTypes[0];
promises.push(`${packUrl}${packData.spec.name}/registries/${packData.spec.registries[0].uid}?cloudType=${cloudType}&layer=${packData.spec.layer}`);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor using map

Comment on lines 22 to 36
<Select
className={filterStyles.selectbox}
mode="multiple"
allowClear
placeholder="Search"
onChange={(item) => setSelectedSearchFilters({ category: item as string[] })}
>
{categories.map((category) => {
return (
<Select.Option key={category}>
{packTypeNames[category as keyof typeof packTypeNames]}
</Select.Option>
);
})}
</Select>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create a component for this and reuse it bellow as well. remove unnecessary code duplication

Comment on lines 43 to 50
const additionalFilters = Array.isArray(_values) ? _values.reduce((acc, _value) => {
acc.push({
name: _value,
values: true
});
return acc;
}, [] as SearchFilter[]) : [];
_selectedFilters = _selectedFilters.concat(additionalFilters);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this has to be so different then the normal data structure.
Please try to use typescript to have a consistent data structure / interface for all filters

Comment on lines 15 to 19
const handleClick = () => {
history.push({
pathname: `/integrations/packs/${name}`,
});
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so basically a Link

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what you created here makes the component less accessible.

Comment on lines 208 to 212
const urls = packDataArr.map((packData) => {
packMDMap[packData.spec.name] = packData;
const cloudType = packData.spec.cloudTypes.includes("all") ? "aws" : packData.spec.cloudTypes[0];
return (`${packUrl}${packData.spec.name}/registries/${packData.spec.registries[0].uid}?cloudType=${cloudType}&layer=${packData.spec.layer}`);
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this map should return functions that return promises directly.
we thunk the promises to avoid triggering them.

}
};
importComponent();
}, []);

const packData = useMemo(() => {
const { packs, repositories } = usePluginData("plugin-packs-integrations") as PacksIntegrationsPluginData;
const _packData = packs.filter((pack) => pack.fields.name === packName)[0];
const _packData = packs.find((pack) => pack.name === packName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const pack =

key: string,
name: string
}
export default function FilterSelect({ selectMode, options, setSelectedSearchFilters }: FilterSelectProps) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value and onChange as props

return Promise.allSettled(
urls.map(url => limit(() => (api[method](url, payload)).catch(e => e)))
);
function callRateLimitAPI(url, method, payload) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

callRateLimitAPI(delayedApiCall) {
 return limit(delayedApiCall)
}

const tempPackArr = packDataArr.concat(response[0]?.value.data.items);
if (response[0]?.value.data.listmeta.continue) {
return fetchPackListItems("?limit=100&continue=" + response[0]?.value.data.listmeta.continue, tempPackArr, counter);
const response = await callRateLimitAPI("/v1/packs/search" + queryParams, 'post', payload);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await callRateLimitAPI(() => api.post(`/v1/packs/search${queryParams}, payload));

})
const results = await callRateLimitAPI(urls, 'get', {});
const url = `${packUrl}${packData.spec.name}/registries/${packData.spec.registries[0].uid}?cloudType=${cloudType}&layer=${packData.spec.layer}`;
return callRateLimitAPI(url, 'get', {});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

callRateLimitAPI(() => api.get(url));

return (
<div className={filterStyles.wrapper}>
<Select
className={filterStyles.selectBox}
mode={selectMode as "tags" | "multiple" | undefined}
allowClear={true}
placeholder="Search"
onChange={(item: any) => setSelectedSearchFilters(item)}
onChange={(item: any) => onChange(item)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onChange={onChange}

@@ -3,27 +3,24 @@ import { Select } from "antd";
import filterStyles from "./CategorySelector.module.scss";
interface FilterSelectProps {
selectMode?: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selectMode?: SelectProps["mode"]

import type {SelectProps} from "antd"

<div className={styles.filterItems}>
<CustomLabel label="Type" />
<FilterSelect
selectMode="multiple"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value={selectedFilters.type}

@nage1234 nage1234 removed the do-not-merge/work-in-progress Work in-progress. DO NOT MERGE label May 3, 2024
@codrin-iftimie codrin-iftimie marked this pull request as ready for review May 8, 2024 07:20
@codrin-iftimie codrin-iftimie merged commit 4f0a818 into PAC-938_nageswari May 8, 2024
9 of 12 checks passed
@codrin-iftimie codrin-iftimie deleted the PAC-1569_nageswari branch May 8, 2024 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants