diff --git a/scripts/build.js b/scripts/build.js index a1fd49ee..4c28b847 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -21,7 +21,7 @@ process.env.NODE_ENV = 'production'; const chalk = require('chalk'); const webpack = require('webpack'); -const config = require('../conf/webpack/webpack.config.prod.js'); +const config = require('../src/main/js/conf/webpack/webpack.config.prod.js'); function formatSize(bytes) { if (bytes === 0) { diff --git a/src/main/java/fr/cnes/sonar/plugin/web/ReportPluginPageDefinition.java b/src/main/java/fr/cnes/sonar/plugin/web/ReportPluginPageDefinition.java index 698cf5f5..22b3dec4 100644 --- a/src/main/java/fr/cnes/sonar/plugin/web/ReportPluginPageDefinition.java +++ b/src/main/java/fr/cnes/sonar/plugin/web/ReportPluginPageDefinition.java @@ -30,9 +30,13 @@ public class ReportPluginPageDefinition implements PageDefinition { */ @Override public void define(Context context) { - Page.Builder page = Page.builder(PluginStringManager.getProperty("homepage.url")); - page.setName(PluginStringManager.getProperty("homepage.name")); - page.setScope(Page.Scope.GLOBAL); - context.addPage(page.build()); + context.addPage(Page.builder(PluginStringManager.getProperty("homepage.url")) + .setName(PluginStringManager.getProperty("homepage.name")) + .setScope(Page.Scope.GLOBAL) + .build()); + context.addPage(Page.builder(PluginStringManager.getProperty("projectpage.url")) + .setName(PluginStringManager.getProperty("projectpage.name")) + .setScope(Page.Scope.COMPONENT) + .build()); } } diff --git a/src/main/js/project_page/index.js b/src/main/js/project_page/index.js new file mode 100644 index 00000000..a358b842 --- /dev/null +++ b/src/main/js/project_page/index.js @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +// Necessary for setting up, because of Webpack. + +import React from "react"; +import CnesReportProject from "./view/CnesReportProject"; +import "./style.css"; + + +// This creates a page for any component (project, portfolio, etc). +// +// You can access it at /project/extension/example/project_page?id={COMPONENT_ID} +window.registerExtension('cnesreport/projectreport', function (options) { + // options.el contains the DOM node we can use for our app. Prepare our node + // so our Backbone View can correctly target it. + return ; + +}); diff --git a/src/main/js/project_page/style.css b/src/main/js/project_page/style.css new file mode 100644 index 00000000..bdccd0b0 --- /dev/null +++ b/src/main/js/project_page/style.css @@ -0,0 +1,81 @@ +/* General Styles */ +.maintenance-title { + font-size: 35px; + color: #333; + margin-top: 20px; + text-align: center; +} + +#generation-form { + margin: 20px auto; + max-width: 500px; + padding: 20px; + background-color: #f9f9f9; + border: 1px solid #ccc; + border-radius: 5px; +} + +.forminput { + margin-bottom: 15px; +} + +.login-label { + display: block; + margin-bottom: 5px; + color: #555; +} + +.login-input { + width: 100%; + padding: 10px; + font-size: 16px; + border: 1px solid #ccc; + border-radius: 5px; + box-sizing: border-box; +} + +/* Button Styles */ +#generation { + display: block; + margin: 0 auto; + font-size: 20px; + padding: 10px 20px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +#generation:hover { + background-color: #45a049; +} + +#generation:active { + transform: translateY(2px); +} + +/* Checkbox Styles */ +.checkbox-label { + display: block; + margin-bottom: 5px; + color: #555; +} + +.checkbox-input { + margin-right: 5px; +} + +/* Optional: Styles for success/error messages */ +.success-message { + color: green; + font-weight: bold; + margin-top: 10px; +} + +.error-message { + color: red; + font-weight: bold; + margin-top: 10px; +} diff --git a/src/main/js/project_page/view/CnesReportProject.js b/src/main/js/project_page/view/CnesReportProject.js new file mode 100644 index 00000000..84c8977b --- /dev/null +++ b/src/main/js/project_page/view/CnesReportProject.js @@ -0,0 +1,177 @@ +/** + * Main JS component of the plugin + * Written with ReactJS + */ + +import React from "react"; + +import { initiatePluginToken, isCompatible } from "../../common/api"; + +export default class CnesReportProject extends React.PureComponent { + state = { + loading: true, + token: "", + author: "", + languages: [{id: 'en_US', name: 'English'}, {id: 'fr_FR', name: 'French'}], + enableDocx: true, + enableMd: true, + enableXlsx: true, + enableCsv: true, + enableConf: true, + isSupported: true + }; + + onChangeAuthor = (event) => { + this.setState({ author: event.target.value }) + }; + + onChangeCheckbox = (stateParam) => { + switch (stateParam) { + case 'enableDocx': + this.setState({enableDocx: !this.state.enableDocx}); + break; + case 'enableMd': + this.setState({enableMd: !this.state.enableMd}); + break; + case 'enableXlsx': + this.setState({enableXlsx: !this.state.enableXlsx}); + break; + case 'enableCsv': + this.setState({enableCsv: !this.state.enableCsv}); + break; + case 'enableConf': + this.setState({enableConf: !this.state.enableConf}); + break; + } + } + + // disable generate button if no checkbox is checked to prevent the generation of an empty zip + shouldDisableGeneration = () => { + return !(this.state.enableDocx || this.state.enableMd || this.state.enableXlsx + || this.state.enableCsv || this.state.enableConf); + } + + componentDidMount() { + // Initialize compatibility check + isCompatible().then(isSupported => { + this.setState({ isSupported }); + }); + + // Initialize data in form + initiatePluginToken().then(tokenInfo => { + this.setState({ token: tokenInfo.token, author: tokenInfo.author, loading: false }); + }); + } + + render() { + if (this.state.loading) { + return

Loading ...

; + } + + const options = this.props.options; + + let languagesList = this.state.languages.map((item, i) => { + return ( + + ) + }) + + return ( +
+
+

Generate a report for this project and branch

+ { !this.state.isSupported && +
+

This SonarQube version is not supported by this cnesreport version.

+

For further information, please refer to the compatibility matrix on the project GitHub page.

+
+ } +
+
+ + +
+
+ + + + + +
+
+ {/* + We need a hidden field for each checkbox in case it is unchecked because otherwise no value is sent and + we want that if we don't fill in a parameter then the api uses the default value i.e. the document is + generated. + */} + + this.onChangeCheckbox('enableDocx')}/> + +
+
+ + this.onChangeCheckbox('enableMd')}/> + +
+
+ + this.onChangeCheckbox('enableXlsx')}/> + +
+
+ + this.onChangeCheckbox('enableCsv')}/> + +
+
+ + this.onChangeCheckbox('enableConf')}/> + +
+
+ +
+ This operation may take some time, please wait while the report is being generated. +
+
+
+ ); + } +} diff --git a/src/main/resources/plugin.properties b/src/main/resources/plugin.properties index c77f2fdf..29eb5726 100644 --- a/src/main/resources/plugin.properties +++ b/src/main/resources/plugin.properties @@ -17,6 +17,8 @@ homepage.url=cnesreport/report homepage.name=CNES Report +projectpage.url=cnesreport/projectreport +projectpage.name=Generate Project Report plugin.since=6.5 plugin.defaultHost=http://localhost:%s%s