@@ -269,14 +268,18 @@ const getProposal = (proposal_id) => {
});
};
-const FeedPage = () => {
- const QUERYAPI_ENDPOINT = `https://near-queryapi.api.pagoda.co/v1/graphql`;
+const getRfp = (rfp_id) => {
+ return Near.asyncView(contract, "get_rfp", {
+ rfp_id,
+ });
+};
+const FeedPage = () => {
State.init({
data: [],
author: "",
stage: "",
- sort: "",
+ sort: "id_desc",
category: "",
input: "",
loading: false,
@@ -286,120 +289,76 @@ const FeedPage = () => {
currentlyDisplaying: 0,
});
- const query = `query GetLatestSnapshot($offset: Int = 0, $limit: Int = 10, $where: ${proposalFeedIndexerQueryName}_bool_exp = {}) {
- ${proposalFeedIndexerQueryName}(
- offset: $offset
- limit: $limit
- order_by: {proposal_id: desc}
- where: $where
- ) {
- author_id
- block_height
- name
- category
- summary
- editor_id
- proposal_id
- ts
- timeline
- views
- labels
- linked_rfp
- }
- ${proposalFeedIndexerQueryName}_aggregate(
- order_by: {proposal_id: desc}
- where: $where
- ) {
- aggregate {
- count
- }
- }
- }`;
-
- const rfpQuery = `query GetLatestSnapshot($offset: Int = 0, $limit: Int = 10, $where: ${rfpFeedIndexerQueryName}_bool_exp = {}) {
- ${rfpFeedIndexerQueryName}(
- offset: $offset
- limit: $limit
- order_by: {rfp_id: desc}
- where: $where
- ) {
- name
- rfp_id
- }
- }`;
-
- function fetchGraphQL(operationsDoc, operationName, variables) {
- return asyncFetch(QUERYAPI_ENDPOINT, {
- method: "POST",
- headers: { "x-hasura-role": indexerHasuraRole },
- body: JSON.stringify({
- query: operationsDoc,
- variables: variables,
- operationName: operationName,
- }),
+ const makeMoreItems = () => {
+ State.update({ makeMoreLoader: true });
+ fetchProposals(state.data.length);
+ };
+
+ function searchCacheApi() {
+ let searchTerm = state.input;
+ let searchInput = encodeURI(searchTerm);
+ let searchUrl = `${cacheUrl}/proposals/search/${searchInput}`;
+
+ return asyncFetch(searchUrl, {
+ method: "GET",
+ headers: {
+ accept: "application/json",
+ },
+ }).catch((error) => {
+ console.log("Error searching cache api", error);
});
}
- function separateNumberAndText(str) {
- const numberRegex = /\d+/;
+ function searchProposals() {
+ if (state.loading) return;
+ State.update({ loading: true });
- if (numberRegex.test(str)) {
- const number = str.match(numberRegex)[0];
- const text = str.replace(numberRegex, "").trim();
- return { number: parseInt(number), text };
- } else {
- return { number: null, text: str.trim() };
- }
+ searchCacheApi().then((result) => {
+ let body = result.body;
+
+ const promises = body.records.map((proposal) => {
+ if (isNumber(proposal.linked_rfp)) {
+ getRfp(proposal.linked_rfp).then((rfp) => {
+ return { ...proposal, rfpData: rfp };
+ });
+ } else {
+ return Promise.resolve(proposal);
+ }
+ });
+ Promise.all(promises).then((proposalsWithRfpData) => {
+ State.update({ aggregatedCount: body.total_records });
+ fetchBlockHeights(proposalsWithRfpData, 0);
+ });
+ });
}
- const buildWhereClause = () => {
- let where = {};
- if (state.author) {
- where = { author_id: { _eq: state.author }, ...where };
- }
+ function fetchCacheApi(variables) {
+ let fetchUrl = `${cacheUrl}/proposals?order=${variables.order}&limit=${variables.limit}&offset=${variables.offset}`;
- if (state.category) {
- if (isInfra || isEvents) {
- where = { labels: { _contains: state.category }, ...where };
- } else {
- where = { category: { _eq: state.category }, ...where };
- }
+ if (variables.author_id) {
+ fetchUrl += `&filters.author_id=${variables.author_id}`;
}
-
- if (state.stage) {
- // timeline is stored as jsonb
- where = {
- timeline: { _cast: { String: { _regex: `${state.stage}` } } },
- ...where,
- };
+ if (variables.stage) {
+ fetchUrl += `&filters.stage=${variables.stage}`;
}
- if (state.input) {
- const { number, text } = separateNumberAndText(state.input);
- if (number) {
- where = { proposal_id: { _eq: number }, ...where };
- }
-
- if (text) {
- where = {
- _or: [
- { name: { _iregex: `${text}` } },
- { summary: { _iregex: `${text}` } },
- { description: { _iregex: `${text}` } },
- ],
- ...where,
- };
+ if (variables.category) {
+ if (isInfra || isEvents) {
+ fetchUrl += `&filters.labels=${variables.category}`;
+ } else {
+ fetchUrl += `&filters.category=${variables.category}`;
}
}
+ return asyncFetch(fetchUrl, {
+ method: "GET",
+ headers: {
+ accept: "application/json",
+ },
+ }).catch((error) => {
+ console.log("Error fetching cache api", error);
+ });
+ }
- return where;
- };
-
- const makeMoreItems = () => {
- State.update({ makeMoreLoader: true });
- fetchProposals(state.data.length);
- };
-
- const fetchProposals = (offset) => {
+ function fetchProposals(offset) {
if (!offset) {
offset = 0;
}
@@ -407,36 +366,30 @@ const FeedPage = () => {
State.update({ loading: true });
const FETCH_LIMIT = 10;
const variables = {
+ order: state.sort,
limit: FETCH_LIMIT,
offset,
- where: buildWhereClause(),
+ category: state.category ? encodeURIComponent(state.category) : "",
+ author_id: state.author ? encodeURIComponent(state.author) : "",
+ stage: state.stage ? encodeURIComponent(state.stage) : "",
};
- fetchGraphQL(query, "GetLatestSnapshot", variables).then(async (result) => {
- if (result.status === 200) {
- if (result.body.data) {
- const data = result.body.data[proposalFeedIndexerQueryName];
- const totalResult =
- result.body.data[`${proposalFeedIndexerQueryName}_aggregate`];
- const promises = data.map((item) => {
- if (isNumber(item.linked_rfp)) {
- return fetchGraphQL(rfpQuery, "GetLatestSnapshot", {
- where: { rfp_id: { _eq: item.linked_rfp } },
- }).then((result) => {
- const rfpData = result.body.data?.[rfpFeedIndexerQueryName];
- return { ...item, rfpData: rfpData[0] };
- });
- } else {
- return Promise.resolve(item);
- }
- });
- Promise.all(promises).then((res) => {
- State.update({ aggregatedCount: totalResult.aggregate.count });
- fetchBlockHeights(res, offset);
+ fetchCacheApi(variables).then((result) => {
+ const body = result.body;
+ const promises = body.records.map((proposal) => {
+ if (isNumber(proposal.linked_rfp)) {
+ getRfp(proposal.linked_rfp).then((rfp) => {
+ return { ...proposal, rfpData: rfp };
});
+ } else {
+ return Promise.resolve(proposal);
}
- }
+ });
+ Promise.all(promises).then((proposalsWithRfpData) => {
+ State.update({ aggregatedCount: body.total_records });
+ fetchBlockHeights(proposalsWithRfpData, offset);
+ });
});
- };
+ }
useEffect(() => {
State.update({ searchLoader: true });
@@ -448,48 +401,45 @@ const FeedPage = () => {
...new Set([...newItems, ...state.data].map((i) => JSON.stringify(i))),
].map((i) => JSON.parse(i));
// Sorting in the front end
- if (state.sort === "proposal_id" || state.sort === "") {
+ if (state.sort === "id_desc" || state.sort === "") {
items.sort((a, b) => b.proposal_id - a.proposal_id);
- } else if (state.sort === "views") {
- items.sort((a, b) => b.views - a.views);
}
return items;
};
const fetchBlockHeights = (data, offset) => {
- let promises = data.map((item) => getProposal(item.proposal_id));
- Promise.all(promises).then((blockHeights) => {
- data = data.map((item, index) => ({
- ...item,
- timeline: JSON.parse(item.timeline),
- social_db_post_block_height:
- blockHeights[index].social_db_post_block_height,
- }));
- if (offset) {
- let newData = mergeItems(data);
- State.update({
- data: newData,
- currentlyDisplaying: newData.length,
- loading: false,
- searchLoader: false,
- makeMoreLoader: false,
- });
- } else {
- State.update({
- data,
- currentlyDisplaying: data.length,
- loading: false,
- searchLoader: false,
- makeMoreLoader: false,
- });
- }
- });
+ data = data.map((item, index) => ({
+ ...item,
+ timeline: JSON.parse(item.timeline),
+ }));
+ if (offset) {
+ let newData = mergeItems(data);
+ State.update({
+ data: newData,
+ currentlyDisplaying: newData.length,
+ loading: false,
+ searchLoader: false,
+ makeMoreLoader: false,
+ });
+ } else {
+ State.update({
+ data,
+ currentlyDisplaying: data.length,
+ loading: false,
+ searchLoader: false,
+ makeMoreLoader: false,
+ });
+ }
};
useEffect(() => {
const handler = setTimeout(() => {
- fetchProposals();
+ if (state.input) {
+ searchProposals();
+ } else {
+ fetchProposals();
+ }
}, 1000);
return () => {
diff --git a/instances/devhub.near/widget/devhub/entity/proposal/LinkedProposalsDropdown.jsx b/instances/devhub.near/widget/devhub/entity/proposal/LinkedProposalsDropdown.jsx
index 53d6eba9e..995a38a0a 100644
--- a/instances/devhub.near/widget/devhub/entity/proposal/LinkedProposalsDropdown.jsx
+++ b/instances/devhub.near/widget/devhub/entity/proposal/LinkedProposalsDropdown.jsx
@@ -1,24 +1,15 @@
const { href } = VM.require("${REPL_DEVHUB}/widget/core.lib.url");
href || (href = () => {});
+const instance = props.instance ?? "";
+
+const { cacheUrl, contract } = VM.require(`${instance}/widget/config.data`);
+
const linkedProposals = props.linkedProposals;
const onChange = props.onChange;
const [selectedProposals, setSelectedProposals] = useState(linkedProposals);
const [proposalsOptions, setProposalsOptions] = useState([]);
-const [searchProposalId, setSearchProposalId] = useState("");
-const QUERYAPI_ENDPOINT = `https://near-queryapi.api.pagoda.co/v1/graphql`;
-const queryName = "${REPL_PROPOSAL_FEED_INDEXER_QUERY_NAME}";
-const query = `query GetLatestSnapshot($offset: Int = 0, $limit: Int = 10, $where: ${queryName}_bool_exp = {}) {
-${queryName}(
- offset: $offset
- limit: $limit
- order_by: {proposal_id: desc}
- where: $where
-) {
- name
- proposal_id
-}
-}`;
+const [textAfterHash, setTextAfterHash] = useState("");
useEffect(() => {
if (JSON.stringify(linkedProposals) !== JSON.stringify(selectedProposals)) {
@@ -32,73 +23,43 @@ useEffect(() => {
}
}, [selectedProposals]);
-function separateNumberAndText(str) {
- const numberRegex = /\d+/;
-
- if (numberRegex.test(str)) {
- const number = str.match(numberRegex)[0];
- const text = str.replace(numberRegex, "").trim();
- return { number: parseInt(number), text };
- } else {
- return { number: null, text: str.trim() };
- }
-}
+function searchCacheApi(input) {
+ let searchInput = encodeURI(input);
+ let searchUrl = `${cacheUrl}/proposals/search/${searchInput}`;
-const buildWhereClause = () => {
- let where = {};
- const { number, text } = separateNumberAndText(searchProposalId);
-
- if (number) {
- where = { proposal_id: { _eq: number }, ...where };
- }
-
- if (text) {
- where = { name: { _ilike: `%${text}%` }, ...where };
- }
-
- return where;
-};
-
-function fetchGraphQL(operationsDoc, operationName, variables) {
- return asyncFetch(QUERYAPI_ENDPOINT, {
- method: "POST",
- headers: { "x-hasura-role": "${REPL_INDEXER_HASURA_ROLE}" },
- body: JSON.stringify({
- query: operationsDoc,
- variables: variables,
- operationName: operationName,
- }),
+ return asyncFetch(searchUrl, {
+ method: "GET",
+ headers: {
+ accept: "application/json",
+ },
+ }).catch((error) => {
+ console.log("Error searching cache api", error);
});
}
-const fetchProposals = () => {
- const FETCH_LIMIT = 30;
- const variables = {
- limit: FETCH_LIMIT,
- offset: 0,
- where: buildWhereClause(),
- };
- fetchGraphQL(query, "GetLatestSnapshot", variables).then(async (result) => {
- if (result.status === 200) {
- if (result.body.data) {
- const proposalsData = result.body.data[queryName];
+function searchProposals(input) {
+ if (state.loading) return;
+ State.update({ loading: true });
- const data = [];
- for (const prop of proposalsData) {
- data.push({
- label: "# " + prop.proposal_id + " : " + prop.name,
- value: prop.proposal_id,
- });
- }
- setProposalsOptions(data);
- }
+ searchCacheApi(input).then((result) => {
+ let proposalsData = result.body.records;
+
+ const data = [];
+ for (const prop of proposalsData) {
+ data.push({
+ label: "# " + prop.proposal_id + " : " + prop.name,
+ value: prop.proposal_id,
+ });
}
+ setProposalsOptions(data);
});
-};
+}
useEffect(() => {
- fetchProposals();
-}, [searchProposalId]);
+ if (textAfterHash.trim()) {
+ searchProposals(textAfterHash);
+ }
+}, [textAfterHash]);
return (
<>
@@ -108,7 +69,7 @@ return (
-
+
);
@@ -137,7 +98,7 @@ return (