Commit 5f847624 authored by Théophile BORNON's avatar Théophile BORNON

electron build + google code

parent 41e956b8
......@@ -11,6 +11,8 @@
# production
/build
/dist
# misc
.DS_Store
.env.local
......
var DIRECTORY = "1mSXxKP1lDxNwTIUSJK2EDiTJMA2dRphJ";
function create(data) {
main(data);
}
function main(data) {
// Creating form
var form = FormApp.create(data.name);
var formFile = DriveApp.getFileById(form.getId());
// Creating spreadsheet for answers
var ss = SpreadsheetApp.create(data.name);
var ssFile = DriveApp.getFileById(ss.getId());
// Creating spreadsheet which is going to be published
var publishedSS = SpreadsheetApp.create("Resulats");
var publishedSSFile = DriveApp.getFileById(publishedSS.getId());
// Add published spreadsheet id to answer spreadsheet metadata
ss.addDeveloperMetadata("resultsID", publishedSS.getId());
ssFile.setDescription(publishedSS.getId());
buildForm(data, form);
form.setDestination(FormApp.DestinationType.SPREADSHEET, ss.getId());
ScriptApp.newTrigger('onDeposit')
.forForm(form)
.onFormSubmit()
.create();
// Set first row for published results
var sheet = publishedSS.getSheets()[0];
buildResults(data, sheet);
// Save data structure
var dataF = DriveApp.createFile("data.json", JSON.stringify(data), 'application/json');
var dataFile = DriveApp.getFileById(dataF.getId());
// Add data file id to answer spreadsheet metadata
ss.addDeveloperMetadata("dataID", dataFile.getId());
var fileIds = { "data": dataFile.getId(), "results": publishedSS.getId() };
ssFile.setDescription(JSON.stringify(fileIds));
// Create folder
var folder = DriveApp.createFolder(data.name);
var mainFolder = DriveApp.getFolderById(DIRECTORY);
mainFolder.addFolder(folder);
folder.addFile(formFile);
folder.addFile(ssFile);
folder.addFile(publishedSSFile);
folder.addFile(dataFile);
Logger.log("Published file id : %s\nData file id : %s", publishedSSFile.getId(), dataFile.getId());
// Move files to folder
folder.getParents().next().removeFolder(folder);
formFile.getParents().next().removeFile(formFile);
ssFile.getParents().next().removeFile(ssFile);
publishedSSFile.getParents().next().removeFile(publishedSSFile);
dataFile.getParents().next().removeFile(dataFile);
}
function buildResults(data, publishedSS) {
var header = [];
var itemNumber = [];
for (var i = 0; i < data.sections.length; i++) {
itemNumber[i] = 0;
for (var j = 0; j < data.sections[i].categories.length; j++) {
if (i !== 1) {
for (var k = 0; k < data.sections[i].categories[j].subCategories.length; k++) {
itemNumber[i]++;
header.push(data.sections[i].categories[j].subCategories[k].name);
}
} else {
header.push(data.sections[i].categories[j].name);
itemNumber[i]++;
}
}
}
header.push("Total");
publishedSS.appendRow(header);
publishedSS.setFrozenRows(1);
publishedSS
.getRange(1, 1, 1, itemNumber[0])
.setBackground("#D3D3D3");
publishedSS
.getRange(1, itemNumber[0] + 1, 1, itemNumber[1])
.setBackground("#90EE90");
publishedSS
.getRange(1, itemNumber[0] + itemNumber[1] + 1, 1, 1)
.setBackground("#FFDAB9")
publishedSS
.getRange(2, 1, 200, header.length)
.setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID);
publishedSS
.getRange(1, 1, 1, header.length)
.setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID_THICK)
.setFontWeight("bold");
}
function buildForm(data, form) {
for (var h = 0; h < data.sections.length; h++) {
var section = data.sections[h];
form
.addPageBreakItem()
.setTitle(section.name || "");
for (var i = 0; i < section.categories.length; i++) {
var category = section.categories[i];
form.addSectionHeaderItem()
.setTitle(category.name || "")
.setHelpText(category.description || "");
for (var j = 0; j < category.subCategories.length; j++) {
var subCategory = category.subCategories[j];
if (subCategory.type === "text") {
form
.addTextItem()
.setTitle(subCategory.name || "")
.setHelpText(subCategory.description || "")
.setRequired(subCategory.required != undefined ? subCategory.required : true);
} else {
form
.addScaleItem()
.setTitle(subCategory.name)
.setBounds(0, 10)
.setLabels(
subCategory.lower || "Nul",
subCategory.upper || "Excellent"
)
.setHelpText(subCategory.description || "")
.setRequired(subCategory.required != undefined ? subCategory.required : true);
}
}
}
}
}
function setMarks(data, itemResponses) {
var categories = data.sections[1].categories;
// On parcourt les réponses du questionnaire
for (var h = 0; h < itemResponses.length; h++) {
var itemResponse = itemResponses[h];
var title = itemResponse.getItem().getTitle();
// On parcourt les catégories existantes
for (var i = 0; i < categories.length; i++) {
var category = categories[i];
// On parcourt les sous catégories
for (var j = 0; j < category.subCategories.length; j++) {
var subCategory = category.subCategories[j];
// Si le nom de la sous catégorie correspond à celui de la réponse
if (subCategory.name === title) {
// Alors on met la note
subCategory.mark = itemResponse.getResponse();
}
}
}
}
return categories;
}
function calculateAverage(categories) {
var sectionTotal = 0;
var sectionCoeff = 0;
for (var i = 0; i < categories.length; i++) {
var category = categories[i];
var categoryTotal = 0;
var categoryCoeff = 0;
for (var j = 0; j < category.subCategories.length; j++) {
var subCategory = categories[i].subCategories[j];
categoryTotal += (subCategory.mark || 0) * (subCategory.coeff || 1);
categoryCoeff += (subCategory.coeff || 1);
}
category.avg = categoryTotal / categoryCoeff;
sectionTotal += category.avg * (category.coeff || 1);
sectionCoeff += (category.coeff || 1);
}
var avg = sectionTotal / sectionCoeff;
return { avg: avg, categories: categories };
}
// Fonction appelée lorsque l'on clique sur générer sur le forumlaire
function doPost(e) {
var data = JSON.parse(e.postData.contents);
create(data);
return ContentService.createTextOutput("Ok");
}
function onDeposit(e) {
var form = FormApp.openById(e.source.getId());
var ss = SpreadsheetApp.openById(form.getDestinationId());
var ssFile = DriveApp.getFileById(form.getDestinationId());
var fileIds = JSON.parse(ssFile.getDescription());
var published = SpreadsheetApp.openById(fileIds.results);
var publishedSheet = published.getSheets()[0];
var dataString = DriveApp.getFileById(fileIds.data).getBlob().getDataAsString();
var data = JSON.parse(dataString);
var itemResponses = e.response.getItemResponses();
var categories = setMarks(data, itemResponses);
var results = calculateAverage(categories);
var newRow = [];
for (var i = 0; i < data.sections.length; i++) {
for (var j = 0; j < data.sections[i].categories.length; j++) {
if (i !== 1) {
for (var k = 0; k < data.sections[i].categories[j].subCategories.length; k++) {
newRow.push(itemResponses[newRow.length].getResponse());
}
} else {
newRow.push(results.categories[j].avg);
}
}
if (i == 1)
newRow.push(results.avg)
}
publishedSheet.appendRow(newRow);
}
\ No newline at end of file
{
"name": "formgenerator",
"version": "0.1.0",
"main": "public/electron.js",
"homepage": "./",
"private": true,
"dependencies": {
"@material-ui/core": "^4.2.0",
"@material-ui/icons": "^4.2.1",
"electron-is-dev": "^1.1.0",
"file-saver": "^2.0.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
......@@ -14,7 +17,11 @@
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"electron-dev": "concurrently \"yarn start\" \"wait-on http://localhost:3000 && electron .\"",
"postinstall": "electron-builder install-app-deps",
"preelectron-pack": "yarn build",
"electron-pack": "electron-builder"
},
"eslintConfig": {
"extends": "react-app"
......@@ -30,5 +37,25 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"concurrently": "^4.1.1",
"electron": "^5.0.6",
"electron-builder": "^21.0.15",
"typescript": "^3.5.3",
"wait-on": "^3.3.0"
},
"author": {
"name": "Théophile BORNON",
"email": "theophile.bornon@protonmail.com"
},
"build": {
"appId": "com.devinci.forgenerator",
"productName": "Form Generator",
"copyright": "Copyright © 2019 ${author}",
"files": [
"build/**/*",
"node_modules/**/*"
]
}
}
\ No newline at end of file
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const isDev = require('electron-is-dev');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({width: 1920, height: 1080});
mainWindow.removeMenu();
mainWindow.maximize();
mainWindow.setTitle("Générateur de questionnaires");
mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, '../build/index.html')}`);
if (isDev) {
// Open the DevTools.
//BrowserWindow.addDevToolsExtension('<location to your react chrome extension>');
mainWindow.webContents.openDevTools();
}
mainWindow.on('closed', () => mainWindow = null);
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
\ No newline at end of file
/*global google */
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { saveAs } from "file-saver";
import './App.css';
......@@ -13,6 +11,7 @@ import AppBar from "@material-ui/core/AppBar";
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from "@material-ui/core/Button";
import CircularProgress from '@material-ui/core/CircularProgress';
import Section from "./Section";
......@@ -46,6 +45,12 @@ function App() {
}
);
const [url, setURL] = useState({ url: "", requesting: false });
useEffect(() => {
setURL({ ...url, url: localStorage.getItem("url") || "" })
}, [])
const save = () => {
let name = prompt("Nom du fichier");
let blob = new Blob([JSON.stringify(state)], { type: "application/json" });
......@@ -53,7 +58,22 @@ function App() {
}
const generate = () => {
const data = { name: state.name, sections: state.sections };
setURL({ ...url, requesting: true });
fetch(url.url, {
method: "POST",
body: JSON.stringify(data)
})
.then(res => {
setURL({ ...url, requesting: false });
alert("Questionnaire crée")
})
.catch(err => {
setURL({ ...url, requesting: false });
alert(err.message)
console.error(err);
});
}
const loadConfig = () => {
......@@ -62,10 +82,13 @@ function App() {
config = JSON.parse(state.config)
} catch (e) {
alert("Impossible de charger cette configuration")
console.error(e);
return;
}
setState({ ...config })
setState({ ...state, ...config })
}
const saveURL = () => {
localStorage.setItem("url", url.url);
}
const addSection = () => {
......@@ -87,7 +110,10 @@ function App() {
}
const handleChange = e => {
if (e.target.name !== "url")
setState({ ...state, [e.target.name]: e.target.value });
else
setURL({ url: e.target.value });
}
return (
......@@ -164,6 +190,9 @@ function App() {
>
Générer le formulaire
</Button>
{url.requesting &&
<CircularProgress/>
}
</Grid>
</Grid>
</Paper>
......@@ -206,6 +235,44 @@ function App() {
</Grid>
</Paper>
</Grid>
<Grid item className={classes.margin} xs={12} md={10} lg={8}>
<Paper className={classes.paper}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="h5" component="h3">
URL de l'application
</Typography>
<Divider />
</Grid>
<Grid item xs={12}>
<TextField
label="URL"
fullWidth
multiline
margin="normal"
variant="outlined"
name="url"
value={url.url}
onChange={handleChange}
/>
</Grid>
<Grid item xs={12}>
<Button
size="medium"
variant="contained"
color="primary"
onClick={saveURL}
>
Sauvegarder l'URL
</Button>
</Grid>
</Grid>
</Paper>
</Grid>
</Grid>
);
}
......
......@@ -25,7 +25,10 @@ export default function Category(props) {
const { category, setCategory } = props;
const handleChange = e => {
if (e.target.id !== "coeff")
setCategory({ ...category, [e.target.id]: e.target.value })
else
setCategory({ ...category, [e.target.id]: parseInt(e.target.value) })
}
const addSubCategory = () => {
......
......@@ -7,7 +7,6 @@ import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";
import Divider from "@material-ui/core/Divider";
import Typography from "@material-ui/core/Typography";
import TextField from "@material-ui/core/TextField";
......@@ -33,7 +32,7 @@ export default function SubCategory(props) {
if (e.target.type === "text")
setSubCategory({ ...subCategory, [e.target.id]: e.target.value })
else if (e.target.type === "number" && parseInt(e.target.value) >= 1)
setSubCategory({ ...subCategory, [e.target.id]: e.target.value })
setSubCategory({ ...subCategory, [e.target.id]: parseInt(e.target.value) })
else if (e.target.type === "checkbox")
if (e.target.id === "type")
setSubCategory({ ...subCategory, type: (e.target.checked ? "text" : "") })
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment