Hello , I want to customize layout per project , so I created a module : jira project setting where there is a form to select the columns that the user want to belayed in subtask panel . The problem is that the subtasks are not displayed and there is the error :
import api, { route } from '@forge/api';
// Fonction pour récupérer les détails d'une issue par sa clé
const fetchIssueByKey = async (issueKey) => {
const url = route(`/rest/api/3/issue/${issueKey}`);
const response = await api.asApp().requestJira(url);
if (!response.ok) {
const errorMessage = await response.text();
console.error('Error fetching issue:', errorMessage);
throw new Error('Failed to fetch issue');
}
const data = await response.json();
return data;
};
// Fonction de test de l'API
const testApiCall = async () => {
try {
const url = route('/rest/api/3/myself');
const response = await api.asApp().requestJira(url);
if (!response.ok) {
const errorMessage = await response.text();
console.error('Test API Call Response Error:', errorMessage);
throw new Error('Failed to test API call');
}
const data = await response.json();
console.log('Test API Call Response:', data);
} catch (error) {
console.error('Error in Test API Call:', error);
}
};
// Configuration Panel Function
const ConfigPanel = () => {
const [columns, setColumns] = useState([]);
const handleSubmit = async (formData) => {
const projectKey = formData.projectKey;
const selectedColumns = formData.columns;
const url = route(`/rest/api/3/project/${projectKey}/properties/subtask-columns`);
try {
const response = await api.asApp().requestJira(url, {
method: 'PUT',
body: JSON.stringify({ columns: selectedColumns }),
});
if (!response.ok) {
const errorMessage = await response.text();
console.error('Error saving configuration:', errorMessage);
throw new Error('Failed to save configuration');
}
} catch (error) {
console.error('Error in handleSubmit:', error);
}
// Réinitialisation du formulaire
setColumns([]);
};
return (
<ProjectSettingsPage>
<Fragment>
<Text content="Configure Subtask Columns" />
<Form onSubmit={handleSubmit}>
<Select
label="Select Columns"
isMulti
name="columns"
value={columns}
onChange={(values) => setColumns(values)}
>
<Option value="Key" label="Key" />
<Option value="Summary" label="Summary" />
<Option value="Status" label="Status" />
<Option value="Assignee" label="Assignee" />
<Option value="Priority" label="Priority" />
<Option value="Created" label="Created" />
</Select>
<Button text="Save" type="submit" />
</Form>
</Fragment>
</ProjectSettingsPage>
);
};
// Récupération de la configuration du layout
const fetchLayoutConfig = async (projectKey) => {
const url = route(`/rest/api/3/project/${projectKey}/properties/subtask-columns`);
const response = await api.asApp().requestJira(url);
if (!response.ok) {
const errorMessage = await response.text();
console.error('Error fetching layout config:', errorMessage);
throw new Error('Failed to fetch layout config');
}
const data = await response.json();
return data.columns || ['Key', 'Summary', 'Status', 'Assignee', 'Priority', 'Created'];
};
// Récupération des sous-tâches
const fetchSubtasks = async (issueKey) => {
const response = await api.asApp().requestJira(route(`/rest/api/3/search?jql=parent=${issueKey}&fields=summary,status,assignee,priority,created`));
if (!response.ok) {
const errorMessage = await response.text();
console.error('Error fetching subtasks:', errorMessage);
throw new Error('Failed to fetch subtasks');
}
const data = await response.json();
return data.issues || [];
};
// Fonction pour le panneau de sous-tâches
const SubtaskPanel = () => {
const { platformContext: { issueKey } } = useProductContext();
const [subtasks, setSubtasks] = useState([]);
const [layout, setLayout] = useState([]);
useEffect(async () => {
if (!issueKey) {
console.error('No issueKey found in context.');
return;
}
try {
const issue = await fetchIssueByKey(issueKey);
if (!issue.fields || !issue.fields.project) {
console.error('Issue or project data is missing.');
return;
}
const projectKey = issue.fields.project.key;
const layoutConfig = await fetchLayoutConfig(projectKey);
setLayout(layoutConfig);
const subtasks = await fetchSubtasks(issueKey);
setSubtasks(subtasks);
} catch (error) {
console.error('Error loading panel data:', error);
}
}, [issueKey]);
return (
<Fragment>
<Text content="Subtasks" />
<Table>
<Head>
{layout.includes('Key') && <Cell><Text content="Key" /></Cell>}
{layout.includes('Summary') && <Cell><Text content="Summary" /></Cell>}
{layout.includes('Status') && <Cell><Text content="Status" /></Cell>}
{layout.includes('Assignee') && <Cell><Text content="Assignee" /></Cell>}
{layout.includes('Priority') && <Cell><Text content="Priority" /></Cell>}
{layout.includes('Created') && <Cell><Text content="Created" /></Cell>}
</Head>
{subtasks.map(subtask => (
<Row key={subtask.id}>
{layout.includes('Key') && (
<Cell>
<Text>
<Link href={`/browse/${subtask.key}`}>{subtask.key}</Link>
</Text>
</Cell>
)}
{layout.includes('Summary') && <Cell><Text content={subtask.fields.summary} /></Cell>}
{layout.includes('Status') && <Cell><Text content={subtask.fields.status.name} /></Cell>}
{layout.includes('Assignee') && <Cell><Text content={subtask.fields.assignee ? subtask.fields.assignee.displayName : 'Unassigned'} /></Cell>}
{layout.includes('Priority') && <Cell><Text content={subtask.fields.priority ? subtask.fields.priority.name : 'N/A'} /></Cell>}
{layout.includes('Created') && <Cell><Text content={new Date(subtask.fields.created).toLocaleString()} /></Cell>}
</Row>
))}
</Table>
</Fragment>
);
};
// Export Functions
export const configFunction = render(<ConfigPanel />);
export const panelFunction = render(<IssuePanel><SubtaskPanel /></IssuePanel>);
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.