Hey all,
I have gone through the various processes of installing Forge, created the little hello world app and added it to my test instance for JSM, all good and successful.
My ultimate goal for this is a little app for Agents to select their name, another users name a start and an end date. When they submit this info it will update Assets with the second users name in the relevant field and the two date values.
I am having trouble understanding where you import the various components for the UI Kit. Basically I need a form and 4 text components which I will use for the user and date entry, the updating Assets comes next?!
Maybe I am missing a key document, I am pretty far down the rabbit hole with open chrome tabs with Forge info.
If there is something specific about this, an example or links that would be amazing.
Thanks.
Hey Steven
Iâm not sure what you have and havenât already looked at so forgive me if I tread old ground.
We have example apps for other products which should be transferrable to the JSM context.
This example makes use of forms and entries.
Let me know if thereâs any problems.
Hey Josh,
Thanks for that. All I have at the moment is an app deployed with a date picker on it.
Couldnât find how to get more components in the code without a tonne of errors in the deploy, and havenât even started to figure out how to update Assets with that info 
Thanks for the links, I did find that in a tab, just hadnât look at it for some reason.
Cheers.
Thatâs very interesting. Importing new components from @forge/ui
shouldnât cause errors in deployment.
If you havenât solved the problem would you mind sharing the error?
oh I am sure it is user error until I reverse engineer one of those apps in the examples.
I âthoughtâ I could put multiples of this in place just with different Name, label etc but it fails. Just need to hunt around for the right way to structure the jsx file when there are multiple components, which by the sounds of it will be in the link you sent through.
const App = () => {
return (
<DatePicker
name="date"
label="Leave Start Date"
description="First day of your OOO period"
onChange={(value) => console.log(value)}
/>
);
};
Hi Steven,
putting multiples of your DatePicker should work. Try wrapping all of your components in an FragmentâŠ
const App = () => {
return (
<Fragment>
<DatePicker
name=âdateâ
label=âLeave Start Dateâ
description=âFirst day of your OOO periodâ
onChange={(value) => console.log(value)}
/>
<DatePicker
name=âdate2â
label=âLeave End Dateâ
description=âLast day of your OOO periodâ
onChange={(value) => console.log(value)}
/>
</Fragment>
);
};
In React you always need parent components when nesting multiples. If all of them should work together, maybe think about wrapping all of them in a form. https://developer.atlassian.com/platform/forge/ui-kit-components/form/
EDIT: It seems the âDatePickerâ Component from the UIKit only works inside an âFormâ or âMacroConfigâ Component. So wrapping it in a âFragmentâ wonât work.
https://developer.atlassian.com/platform/forge/ui-kit-components/form/#usage-notes-3
Example:
const App = () => {
function onSubmit(formProps) {
console.log(formProps);
}
return (
<Form onSubmit={onSubmit}>
<DatePicker
name=âdateâ
label=âLeave Start Dateâ
description=âFirst day of your OOO periodâ
onChange={(value) => console.log(value)}
/>
<DatePicker
name=âdate2â
label=âLeave End Dateâ
description=âLast day of your OOO periodâ
onChange={(value) => console.log(value)}
/>
</Form>
);
};
Regards
Adrian
Thanks @AdrianSomesan, I am experimenting with the UI Kit 2 at the moment as I assume by the time I wrap my head around all of this that will be the norm.
I appreciate the code snippet.
This will help me structure the collecting of the other data as well (2 x user picker and a boolean)
THEN comes the updating the record in Assets.
Good challenge for an old guy to understand all of this 
1 Like
Hey there,
Just spending some time with this, I just canât make anything work other than a single date picker field. As soon as I try and add more fields to the form it all fails, when I deploy it the app is blank when clicked on.
If I revert it back to the single date picker, it is fine.
Trying to add a user picker, boolean and the two date fields is proving quite the challenge 
If the code snippet is short enough you could share it here and we can try on our machines.
1 Like
Hey all,
So going back through comments and other posts on here I have some success (as I said I am old and this is new so I am VERY happy to be this far through).
I have two date fields and a user select box appearing. I cannot figure out how to get a checkbox or something as a boolean (true / false) on the form yet but here is what I have.
import ForgeUI, { Checkbox, Form, DatePicker,render, ProjectPage, Fragment, Text, UserPicker } from '@forge/ui';
const App = () => {
function onSubmit(formProps) {
console.log(formProps);
}
return (
<Form onSubmit={onSubmit}>
<DatePicker
name="date"
label="Leave Start Date"
description="First day of your OOO period"
onChange={(value) => console.log(value)}
/>
<DatePicker
name="date2"
label="Leave End Date"
description="Last day of your OOO period"
onChange={(value) => console.log(value)}
/>
<UserPicker
name="User"
label="Select User"
onChange={(value) => console.log(value)}
/>
</Form>
);
};
So I am stuck with the whole true false toggle and then the next part is I imagine getting the results of this to an automation I guess to check if the person exists in assets and editing their object. All of which I imagine can be done with Forge easy enough (when you know how).
Thanks for all the replies.
S.
Hi Steven,
Iâm glad youâre making progress. 
Adding a Toggle should work exactly as adding a User PickerâŠ
import ForgeUI, { Checkbox, Form, DatePicker,render, ProjectPage, Fragment, Text, UserPicker, Toggle } from '@forge/ui';
const App = () => {
function onSubmit(formProps) {
console.log(formProps);
}
return (
<Form onSubmit={onSubmit}>
<DatePicker
name="date"
label="Leave Start Date"
description="First day of your OOO period"
onChange={(value) => console.log(value)}
/>
<DatePicker
name="date2"
label="Leave End Date"
description="Last day of your OOO period"
onChange={(value) => console.log(value)}
/>
<UserPicker
name="User"
label="Select User"
onChange={(value) => console.log(value)}
/>
<Toggle
label="Show section"
name="isSectionVisible"
onChange={(value) => console.log(value)}
/>
</Form>
);
};
Regards
Adrian
1 Like
Thanks @AdrianSomesan, apologies for the delay some family issues and then I had some leave booked.
I have this info being collected âsomewhereâ when it is entered and submitted, just not sure now how to head for updating the information into assets. I assume now I need to trigger an API call to Assets to be able to create a record if my user isnât there or update the fields if they are there?
I normally do this sort of thing via powershell scripts and am floundering with Forge and Assets at the moment.
Hi @StevenLeesSmith
your info is being âcollectedâ in the formProps parameter. In the âonSubmitâ function from my last post, you can handle this data. To work with the Insight Assets of your JSM Instance, you can use this API: Introduction
I should mention, that at the current time, this API canât really be used in a production context, since Atlassian is not enabling the access to this API via any other authentication but Basic Auth.
A simple example would be the AQL API Request from the documentation
const fetch = require('node-fetch');
fetch('https://api.atlassian.com/jsm/assets/workspace/{workspaceId}/v1/aql/objects', {
method: 'GET',
headers: {
'Accept': 'application/json'
}
})
.then(response => {
console.log(
`Response: ${response.status} ${response.statusText}`
);
return response.text();
})
.then(text => console.log(text))
.catch(err => console.error(err));
Instead of the âFetchâ library from Node.js you should use the fetch function from Atlassian Forge:
https://developer.atlassian.com/platform/forge/runtime-reference/fetch-api/
If you have any problems, feel free to ask.
Regards,
Adrian
1 Like
ah ok thanks for that. I have seen some market place apps that leverage Azure data and update Assets directly that way, I assume they would be using the API to do this or did I misunderstand your reply (yes I am literally running by the skin of my teeth understanding this).
I get the whole API, I have built scripts to integrate assets with multiple external systems and such (all with powershell). Just missing the mark on how this hangs together within Assets when there is data entered via an app.
Hi Steven,
I am not sure if I understood your problem: âJust missing the mark on how this hangs together within Assets when there is data entered via an app.â
If I got it right, you are not sure where the entered data is going and how to use the data inside an API call?
The data you enter in the UI, will end up in the handler function of your form.
In one of my previous posts, I added a code snippet of a form with a âonSubmitâ function. Inside this âonSubmitâ function, the parameter âformPropsâ carries the entered data. If you are working inside the âBackendâ(UI Kit) you can save this data via the storage api: https://developer.atlassian.com/platform/forge/runtime-reference/storage-api/
or handle it directlyâŠ
If you are using CustomUI or UI Kit 2 you can either transmit the data to the âBackendâ(UI Kit) via Invocation: https://developer.atlassian.com/platform/forge/custom-ui-bridge/invoke/
or also handle it directlyâŠ
Regards,
Adrian
Thanks for the additional info, I will go back and keep working through this⊠I will get this to work 
hmm ok just wanting to make sure I can do what I am hoping as I am going around in a pretty big circle with links at the moment.
With this collected data, once I know how to work with it (I can see it just logs it to the console in the function, is there a way to just write this to a simple object type in assets?
The user, start and end time and the value of the toggle?
Not sure what to do about an existing record and such but unclear if I am actually trying to achieve something that is reasonable.
Well here is the mess I have ended up in and it doesnât work 
import ForgeUI, { Form, DatePicker, UserPicker, Toggle, render, QueuePage } from '@forge/ui';
import fetch from '@forge/api';
const App = () => {
async function createAsset(attributeValues) {
const accessToken = 'ATATT3xFfGF0qgyC52Ig6I8bSgPFp3rfm8P5kXAIWVRzPvXUSx7mvOh29meTUfJ-erYZi766oeXqtOqUo=9B6C94EA'; // Replace with your actual access token
const assetsUrl = 'https://api.atlassian.com/jsm/assets/workspace/2ae01f14-f028-4b04ad/v1';
try {
const response = await fetch(`${assetsUrl}/object/create`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
objectTypeId: '256', // Replace with the actual object type ID
leaveStartDate: attributeValues.Name
}),
});
if (response.ok) {
const responseData = await response.json();
console.log('New asset created in Assets:', responseData);
} else {
console.error('Error creating asset in Assets:', response.statusText);
}
} catch (error) {
console.error('Error:', error);
}
}
async function onSubmit(formProps) {
const newAssetValues = {
leaveStartDate: formProps.date
// Add more attribute values as needed
};
try {
await createAsset(newAssetValues);
console.log('Asset creation successful');
} catch (error) {
console.error('Error creating asset:', error);
}
}
return (
<Form onSubmit={onSubmit}>
<DatePicker
name="date"
label="Leave Start Date"
description="First day of your OOO period"
/>
<DatePicker
name="date2"
label="Leave End Date"
description="Last day of your OOO period"
/>
<UserPicker
name="User"
label="Select User"
/>
<Toggle
label="Out of Office already"
name="isSectionVisible"
/>
{/* Add more form fields as needed */}
</Form>
);
};
export const run = render(
<QueuePage>
<App />
</QueuePage>
);
Objecttype 256 is the id from my test one and I was just assuming to put the date in the Name field for the moment to get something over, Name is text so assumed it would work.
I would say there is a bucketload wrong here, just getting myself in a tangle.
HI there,
foremost, I hope this i not your actual accessTokenâŠ
If thatâs the case, please remove that ASAP.
Your code is actually almost working 
In the âonSubmitâ function, you create a const ânewAssetValuesâ with the key âleaveStartDateâ which holds the value âformProps.dateâ.
Then you call the âcreateAssetâ function with ânewAssetValuesâ as a parameter. In your defined body howevery you try to set leaveStartDate with attributeValues.name. I think that has to be the other way around. You want the Name value to be the date. Since in the âcreateAssetsâ function you defined the parameter to be called âattributeValuesâ, you would set the name like this:
body: JSON.stringify({
objectTypeId: '256', // Replace with the actual object type ID
attributes: [
{
objectTypeAttributeId: 135, // Replace with actual Object Type Attribute Id
objectAttributeValues: [
{
value: attributeValues.leaveStartDate
}
]
},
})
Also you have to define the Attribute you want to set via a ID. So you need the Attribute ID from the Name Attribute. I never know if those âapi.atlassian.comâ calls work. So i change the prefix of the domain to be my baseUrl. In the case of the Insight calls you need to add âgateway/api/â. (https://youJiraInstance.atlassian.net/gateway/api/jsm/assets/workspace/workspaceId/v1)
Regards
Adrian
Thanks for that detailed answer, not 100% sure how that hangs together but will look in more detail tomorrow.
Token and such had been tinkered with when added to the ticket.
Appreciate your patience with this one.
1 Like