Hi, Everyone.
I’m tunneling Forge and React to develop an add-on.
Manifest.yml
resources:
- key: main
path: static/hello-world/build
tunnel:
port: 3000
However, using the Form tag from @atlaskit/form library results in the following error:
Refused to execute inline script because it violates the following Content Security Policy directive:
"script-src 'self' https://forge.cdn.prod.atlassian-dev.net". Either the 'unsafe-inline' keyword, a hash
('sha256-QAj9SgqS0tkqFXsMg6gbHzN3KfNnrPW0N0FCdMzN3MI='), or a nonce ('nonce-...') is required to
enable inline execution.
CSP violation detected for 'script-src-elem' while serving content at http://localhost:8001/
For an app to share data with external resources or use custom CSP, follow the steps in: http://go.atlassian.com/forge-content-security-and-egress-controls
So I had been add the following to the meta tag.
<meta http-equiv="Content-Security-Policy" content="style-src 'self' 'unsafe-inline'" />
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'" />
However, the error has not been resolved, so I added the following to Manifest.yml by referring to the Permission document.
permissions:
content:
styles:
- 'unsafe-inline'
scripts:
- 'unsafe-inline'
And we proceeded with the deployment and installation.
forge deploy -e development
forge install --upgrade
And I tried a lot, but I couldn’t solve it.
How can I solve it?
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import '@atlaskit/css-reset';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.js
import React, { useEffect, useState } from 'react';
import Button from '@atlaskit/button';
import TextField from '@atlaskit/textfield';
import Form, { Field } from '@atlaskit/form';
import { invoke } from '@forge/bridge';
function App() {
const [formData, setFormData] = useState(null);
useEffect(() => {
invoke("getText", {}).then((data) => {
document.getElementById('textField').value = data;
setFormData(data);
});
}, [])
const onClick = async (e) => {
e.preventDefault();
const textField = document.getElementById('textField').value;
invoke("setText", { textField }).then((data) => console.log(`setText : ${data}`));
}
return (
<Form>
<TextField id='textField' style={styles.textField}></TextField>
<Button type="submit" appearance="primary" onClick={onClick} style={styles.button}>
Submit
</Button>
</Form>
);
}
const styles = {
button: {
marginTop: 10
}
}
export default App;