trying to call an external endpoint inside a jira issue panel app - javascript

In my code, when I try to call an external endpoint from the Jira issue panel app, I get a log "try" and the fetch doesn't happen.
I would appreciate it, if someone could help me.
Thanks in advance!
import ForgeUI, {
IssuePanel,
useProductContext,
useEffect,
} from "#forge/ui";
import { url } from "./constants";
import API, { fetch } from "#forge/api";
const Panel = () => {
const productContext = useProductContext();
const fetchTaskItems = async (issueID) => {
const requestOptions = {
method: "GET",
mode: "cors",
headers: { "Content-Type": "application/json" },
};
try {
console.log("try");
const res = await fetch(
url + `experience/task/item/${issueID}`,
requestOptions
);
console.log(res);
} catch (err) {
console.log(err.message);
}
};
useEffect(() => {
const currentIssueId = productContext.platformContext.issueKey;
console.log("Current issue ID:", currentIssueId);
fetchTaskItems(currentIssueId);
}, []);

You can import userAction from ForgeUI
import ForgeUI, {useAction} from "#forge/ui";
Then call your fetchTaskItems like this
const [req] = useAction(
(value) => value,
async () => await fetchTaskItems()
);
let me know if it works,

Related

Unable to Map Array of MongoDB Documents Returned from Backend into React Components

I am trying to get my front-end to call to the back-end for all the "blog posts" that are stored in my MongoDB database. At the moment there is only one document for testing.
On the backend I have this api endpoint:
app.get("/api/blogs", async (req, res) => {
console.log("Getting blog items...");
try{
const blogs = await blogActions.getBlogItems();
res.status(200).json({blogs});
} catch (err) {
console.log(err)
}
});
This calls to a separate JS file with this function:
const { MongoClient } = require('mongodb');
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);
const connection = async () => {
try {
const database = client.db('personalwebsite');
const blogs = database.collection('blogs');
return blogs;
} catch (err) {
console.log(err);
}
}
const getBlogItems = async () => {
const conn = await connection();
try {
return await conn.find({}).toArray();
} catch (err) {
console.log(err);
}
};
Then in my React front-end I am trying to take the returned array and set it to an Array there in order to map over it and create a new BlogItem component for each blog returned from the database:
import { useState, useEffect } from "react";
import Navbar from "../components/Navbar.tsx";
import BlogItem from "../components/BlogItem.tsx";
import '../styles/Blog.css';
export default function Blog () {
const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);
const [isAdmin, setIsAdmin] = useState<boolean>(false);
const [token, setToken] = useState<string>('');
const [blogs, setBlogs] = useState([]);
useEffect(() => {
setToken(localStorage.getItem('token'));
async function checkToken () {
const response = await fetch('/api/token', {
method: 'POST',
headers: {
'Content-type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
if (response.ok){
const jsonResponse = await response.json();
if (jsonResponse.delete){
localStorage.clear();
return false;
}
return true;
} else {
console.log("Failed to fetch status of the User Login Session.");
}
}
async function checkIfAdmin () {
const response = await fetch('/api/users/permissions', {
method: 'POST',
headers: {
'Content-type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
if(response.ok) {
const jsonResponse = await response.json();
if (jsonResponse.role === 'admin') {
setIsAdmin(true);
} else {
setIsAdmin(false);
}
}
}
async function getBlogItems () {
try {
const response = await fetch('/api/blogs');
const data = await response.json();
console.log("Before setBlogs", data.blogs)
if(data.blogs.length > 0) {
setBlogs(data.blogs);
}
} catch (err) {
console.log(err);
}
}
if (token) {
checkToken().then(isValid => {
if (!isValid) return;
checkIfAdmin();
});
}
getBlogItems();
}, [])
console.log("After setBlogs", blogs);
return (
<div className="App">
<Navbar />
<main className="main-content">
<div className="blogs-container">
{blogs.length > 0 ? (
blogs.map((blog) => (
<BlogItem
key={blog._id}
title={blog.title}
shortDesc={blog.shortDesc}
imgSrc={blog.imgSrc}
pubDate={blog.pubDate}
/>
))
) : (
<div>Loading...</div>
)}
</div>
<div className="most-popular"></div>
</main>
</div>
);
}
I have tried quite a few different methods for trying to get this to work correctly. At first I thought it was just a problem with the data not being returned quickly enough but even after getting the code to wait for the data to be returned and getting the Array to set. I get an error that Objects are not valid as a React child.
This is meant to be an array of Objects so that I can access the properties of each object for the elements in the component but I cannot get it to work for the life of me. I spent awhile using ChatGPT to try and get some progress out of it but this seems to be a problem that requires human intervention instead.
So this is annoying but the issue wasn't with the rest of my code but actually that the BlogItem component had the props wrapped only in parentheses.
Here is the component:
export default function BlogItem ({title, shortDesc, imgSrc, pubDate}) {
return (
<div className="blog-item">
<img src={imgSrc} className="blog-image" />
<h1 className="blog-title">{title === "" ? "Placeholder Title" : title }</h1>
<p className="blog-short-desc">{shortDesc}</p>
<p className="blog-date">{pubDate}</p>
</div>
);
}
The fix was that title, shortDesc, imgSrc, pubDate. All needed to be wrapped in Curly Braces. It now works :\

How to fix the problem with sign up on localhost?

I've got a problem with sign up request on my local machine. When I set a project on my local machine from docker and tried to sign up to mt local server(localhost:3000), I got an error 401 Unauthorized, but I don't get this error when I git clone project fron github and run npm run dev. And it works fine when the project on my web server in internet.
Tokens should be saved in local storage, but there are no tokens at all.
I tried to set {withCredentials: true} but it didn't work too.
//storage.js
const storage = {
get: (key) => {return localStorage.getItem(key)}
}
export const getAccessToken = () => {
return storage.get('accessToken')
}
//authApi.js
import {$api_id} from '../api'
export const AuthApi = {
async signup(payload) {
const response = await $api_id.post('/auth/signup', payload)
return response
},
async signin(payload) {
const response = await $api_id.post('/auth/signin', payload)
return response
}
}
//api.js
import axios, {AxiosResponse} from 'axios'
import {getAccessToken, getDeviceId} from 'utils'
export const API_URL = process.env.NEXT_PUBLIC_API_KEY
$api_id.baseURL = process.env.NEXT_PUBLIC_API_KEY
export const $api_id = axios.create({
withCredentials: false,
baseURL: API_ID_URL,
})
$api_id.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${getAccessToken()}` //getAccessToken(storage.get('accessToken'))
if(config.data.avatar) {
const formData = new FormData()
formData.append('deviceId', getDeviceId()) //getDeviceId(storage.get("deviceId")) - fingerprintjs
Object.entries(config.data).forEach(([name, value]) => {
formData.append(name, value)
})
config.data = formData
} else {
let data
if(typeof config.data === 'string') {
data = JSON.parse(config.data)
} else {
data = config.data
}
if(!data.deviceId) {
data.deviceId = getDeviceId()
}
// console.log({data})
}
Thanks!

how to call api recursively until nested stack keys are finished

here is my question how to call api recursively untill nested data stack keys are finished
here is my full explaination in image
i found this relatable code for recursion api call at this post recursive api call
function callFW() {
d3.json(url, async function(data) {
Tree["uid"] = data.request.uid
Tree["hid"] = data.firmware.meta_data.hid
Tree["size"] = data.firmware.meta_data.size
Tree["children"] = [];
await BuildTree(data.firmware.meta_data.included_files,Tree["children"]);
console.log(Tree)
})
}
async function BuildTree(included_files, fatherNode) {
if (included_files.length > 0) {
let promises = included_files.map( item => {
let url = endpoint + "file_object/" + item + "?summary=true";
return axios.get(url)
});
const results = await Promise.all(promises);
for(let response of results){
var node = {}
node["uid"] = response.data.request.uid
node["hid"] = response.data.file_object.meta_data.hid
node["size"] = response.data.file_object.meta_data.size
node["children"] = []
fatherNode.push(node)
await BuildTree(response.data.file_object.meta_data.included_files, node["children"]);
};
}
};
this is im using custom useRecurseFetch for getting post api result
but i have no idea how to change this code for recursive api call
import React from 'react';
import qs from 'qs';
import axios from 'axios';
const useRecurseFetch = query => {
const [status, setStatus] = React.useState('idle');
const [result, setResult] = React.useState([]);
const [findClass, setFindClass] = React.useState([]);
// console.log(passVariable);
var data;
data = qs.stringify({
query: `http://www.blabla{ ${query}/category}`,
});
// eslint-disable-next-line no-undef
var Grant = process.env.REACT_APP_GRANT;
// eslint-disable-next-line no-undef
var Client = process.env.REACT_APP_CLIENT;
// eslint-disable-next-line no-undef
var Key = process.env.REACT_APP_KEY;
// eslint-disable-next-line no-undef
var Auth = process.env.REACT_APP_AUTH;
// eslint-disable-next-line no-undef
var Query = process.env.REACT_APP_QUERY;
const queryCall = React.useCallback(
async token => {
if (!token) {
return;
} else {
setStatus('Loading');
var config = {
method: 'POST',
url: `${Query}`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization:
token.data.token_type + ' ' + token.data.access_token,
},
data: data,
};
axios(config)
.then(response => {
setResult(response.data.results.bindings);
let originalResult = response.data.results.bindings
.filter(ek => ek.class !== undefined && ek)
.map(el => el.obj.value);
setFindClass(originalResult);
setStatus('success');
})
.catch(function (error) {
setStatus('error');
});
}
},
[data]
);
React.useEffect(() => {
const authInitiate = () => {
var data = qs.stringify({
grant_type: `${Grant}`,
client_id: `${Client}`,
client_secret: `${Key}`,
});
var config = {
method: 'POST',
url: `${Auth}`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: data,
};
axios(config)
.then(response => {
queryCall(response);
})
.catch(function (error) {
console.log(error);
});
};
authInitiate();
}, [queryCall]);
return [status, result, findClass];
};
export default useRecurseFetch;
please any one can help me out with this code, im unable to figure out whats going in this code
anyhelp is really saved my day and really so appreciatable
here i called useRecurseFetch custom function in app.js
const [loadingStatus, mainData, addDataToPostItemArray] = useRecurseFetch(
`<kk:cat>`
);
please any one can help me out please im stuck with this process of calling api

How to post new object to the existing json (clientside ReactJS + server side NodeJS and Express)

Pretty new with NodeJS and Express but want to figure out it is possible to add new objects after loading api via client side. So in the first place it should load the api via server-side which contains the existing objects and output on the client side, and when that is loaded I want to add new objects that I post via server side. So the new posted object should be added added to the json.
Client Side
import { useEffect, useState } from 'react';
import axios from 'axios';
export const App = () => {
const [inputValue, setInputValue] = useState("");
const [posts, setPosts] = useState([]);
useEffect(() => {
const headers = { "Content-Type": "application/json" };
try {
const getData = async () => {
const result = await axios.get('http://localhost:5000', headers);
console.log(result.data);
};
getData();
} catch (error) {
console.log(error);
}
}, []);
const postReview = async value => {
const headers = { "Content-Type": "application/json" };
let data = {
name: value
};
try {
const getData = async () => {
const result = await axios.post('http://localhost:5000/songs', data, headers);
console.log(result.data);
};
getData();
} catch (error) {
console.log(error);
}
};
const submitReview = () => {
postReview(inputValue);
};
return (
<div className="App">
<input
placeholder="Place review"
onChange={e => setInputValue(e.target.value)}
/>
<button onClick={() => submitReview()}>Send</button>
</div>
);
};
export default App;
Server Side
const express = require('express');
const cors = require('cors');
const axios = require('axios');
const app = express();
const port = 5000;
app.use(cors({ origin: '*' }));
app.use(express.json());
app.get("/", async (req, res, next) => {
try {
const { data } = await axios.get('https://raw.githubusercontent.com/XiteTV/frontend-coding-exercise/main/data/dataset.json');
res.status(200).send(data.videos);
} catch (ex) {
res.status(500).send(data.videos);
}
});
app.post('/songs', async (req, res) => {
console.log(reviews.length);
});
I didn't understand what you meant, but I think you want to add more objects to the list of posts, if so, use the following:
setPosts([
...posts,
{
//New post object
}
])
You can post directly in their API.
const postReview = async review => {
const headers = {
"content-type": "application/json",
"Access-Control-Allow-Origin": "*"
};
// axios post request to that api
const response = await axios
.post('https://jsonplaceholder.typicode.com/posts',
{review},
{headers});
};
They described this on their site. Further read

How to pre-fetch data using prefetchQuery with React-Query

I am trying to pre-fetch data using react-query prefetchQuery. When I am inspecting browser DevTools network tab I can see that data that was requested for prefetchQuery is coming from the back-end but for some reason when I look into react-query DevTools it does generate the key in the cache but for some reason the Data is not there. Let me know what I am doing wrong.
import { useState, useEffect } from 'react';
import { useQuery, useQueryClient } from 'react-query';
import axios from 'axios';
const baseURL = process.env.api;
async function getSubCategoryListByCategoryId(id) {
// await new Promise((resolve) => setTimeout(resolve, 300));
console.log(`${baseURL}/category/subcategories/${id}`);
try {
const { data } = await axios.request({
baseURL,
url: `/category/subcategories/${id}`,
method: 'get',
});
console.log('data getSubCategoryListByCategoryId index: ', data);
return data;
} catch (error) {
console.log('getSubCategoryListByCategoryId error:', error);
}
}
// const initialState = {
// };
const ProductCreate = () => {
const [values, setValues] = useState(initialState);
const queryClient = useQueryClient();
const { data, isLoading, isError, error, isFetching } = useQuery(
'categoryList',
getPosts
);
const dataList = JSON.parse(data);
useEffect(() => {
setValues({ ...values, categories: dataList });
dataList.map((item) => {
console.log('useEffect values.categories item.id: ', item._id);
queryClient.prefetchQuery(
['subCategoryListByCategoryId', item._id],
getSubCategoryListByCategoryId(item._id)
);
});
}, []);
return <h1>Hello</h1>;
};
export default ProductCreate;
The second parameter to prefetchQuery expects a function that will fetch the data, similar to the queryFn passed to useQuery.
But here, you are invoking the function, thus passing the result of it into prefetchQuery:
getSubCategoryListByCategoryId(item._id)
if you want to do that, you can manually prime the query via queryClient.setQueryData, which accepts a key and the data for that key passed to it.
otherwise, the fix is probably just:
() => getSubCategoryListByCategoryId(item._id)

Categories

Resources