r4413 - in trunk: . src/main src/main/java/fr/ifremer/isisfish/entities src/main/java/fr/ifremer/isisfish/simulator/launcher src/main/java/fr/ifremer/isisfish/ui/input src/main/javascript src/main/javascript/templates src/main/javascript/templates/web src/main/resources/i18n
Author: echatellier Date: 2017-03-27 11:35:09 +0200 (Mon, 27 Mar 2017) New Revision: 4413 Url: http://forge.codelutin.com/projects/isis-fish/repository/revisions/4413 Log: refs #8733: Export de tous les param?\195?\168tres pour illustrer un papier Added: trunk/.babelrc trunk/package.json trunk/src/main/javascript/ trunk/src/main/javascript/templates/ trunk/src/main/javascript/templates/web/ trunk/src/main/javascript/templates/web/region-web.html Modified: trunk/ trunk/pom.xml trunk/src/main/java/fr/ifremer/isisfish/entities/RegionExportJson.java trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SSHSimulatorLauncher.java trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputHandler.java trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputUI.jaxx trunk/src/main/resources/i18n/isis-fish_en_GB.properties trunk/src/main/resources/i18n/isis-fish_fr_FR.properties Index: trunk =================================================================== --- trunk 2017-03-17 16:43:07 UTC (rev 4412) +++ trunk 2017-03-27 09:35:09 UTC (rev 4413) Property changes on: trunk ___________________________________________________________________ Modified: svn:ignore ## -13,3 +13,7 ## .idea build .gradle +node +node_modules +etc +npm-debug.log Added: trunk/.babelrc =================================================================== --- trunk/.babelrc (rev 0) +++ trunk/.babelrc 2017-03-27 09:35:09 UTC (rev 4413) @@ -0,0 +1,5 @@ +{ + "presets": [ + "env" + ] +} \ No newline at end of file Added: trunk/package.json =================================================================== --- trunk/package.json (rev 0) +++ trunk/package.json 2017-03-27 09:35:09 UTC (rev 4413) @@ -0,0 +1,10 @@ +{ + "devDependencies": { + "babel-cli": "^6.24.0", + "babel-preset-env": "^1.2.2", + "babel-html": "^0.5.0" + }, + "scripts": { + "build": "babel-html -s src/main/javascript -d target/classes" + } +} Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2017-03-17 16:43:07 UTC (rev 4412) +++ trunk/pom.xml 2017-03-27 09:35:09 UTC (rev 4413) @@ -12,7 +12,7 @@ <groupId>fr.ifremer</groupId> <artifactId>isis-fish</artifactId> <version>4.4.1.0-SNAPSHOT</version> - + <!-- POM Relationships : Inheritance : Dependencies --> <dependencies> @@ -373,7 +373,7 @@ <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> - <version>2.3.25-incubating</version> + <version>2.3.26-incubating</version> <scope>compile</scope> </dependency> @@ -608,75 +608,6 @@ </resource> </resources> - <pluginManagement> - <plugins> - <plugin> - <groupId>org.nuiton.eugene</groupId> - <artifactId>eugene-maven-plugin</artifactId> - <version>2.14</version> - </plugin> - - <plugin> - <groupId>org.nuiton.jaxx</groupId> - <artifactId>jaxx-maven-plugin</artifactId> - <version>${jaxxVersion}</version> - </plugin> - - <plugin> - <groupId>org.nuiton.i18n</groupId> - <artifactId>i18n-maven-plugin</artifactId> - <version>${nuitonI18nVersion}</version> - </plugin> - - <plugin> - <artifactId>maven-jar-plugin</artifactId> - <configuration> - <archive> - <manifest> - <addClasspath>true</addClasspath> - <mainClass>fr.ifremer.isisfish.IsisFish</mainClass> - <classpathPrefix>lib/</classpathPrefix> - </manifest> - </archive> - </configuration> - </plugin> - - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <configuration> - <systemPropertyVariables> - <java.io.tmpdir>${project.build.directory}/surefire-workdir</java.io.tmpdir> - </systemPropertyVariables> - </configuration> - <executions> - <execution> - <id>surefire-it</id> - <phase>integration-test</phase> - <goals> - <goal>test</goal> - </goals> - <configuration> - <includes> - <include>**/*IT.java</include> - </includes> - </configuration> - </execution> - </executions> - </plugin> - - <plugin> - <artifactId>maven-site-plugin</artifactId> - <dependencies> - <dependency> - <groupId>org.nuiton.jrst</groupId> - <artifactId>doxia-module-jrst</artifactId> - <version>${jrstPluginVersion}</version> - </dependency> - </dependencies> - </plugin> - </plugins> - </pluginManagement> - <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -710,6 +641,7 @@ <plugin> <groupId>org.nuiton.eugene</groupId> <artifactId>eugene-maven-plugin</artifactId> + <version>2.14</version> <executions> <execution> <id>eugene-generation</id> @@ -739,6 +671,7 @@ <plugin> <groupId>org.nuiton.jaxx</groupId> <artifactId>jaxx-maven-plugin</artifactId> + <version>${jaxxVersion}</version> <executions> <execution> <goals> @@ -756,6 +689,7 @@ <plugin> <groupId>org.nuiton.i18n</groupId> <artifactId>i18n-maven-plugin</artifactId> + <version>${nuitonI18nVersion}</version> <configuration> <entries> <entry> @@ -813,13 +747,90 @@ </execution> </executions> </plugin> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addClasspath>true</addClasspath> + <mainClass>fr.ifremer.isisfish.IsisFish</mainClass> + <classpathPrefix>lib/</classpathPrefix> + </manifest> + </archive> + </configuration> + </plugin> + + <plugin> + <groupId>com.github.eirslett</groupId> + <artifactId>frontend-maven-plugin</artifactId> + <version>1.3</version> + <configuration> + <nodeVersion>v7.7.4</nodeVersion> + </configuration> + <executions> + <execution> + <id>install node and npm</id> + <goals> + <goal>install-node-and-npm</goal> + </goals> + </execution> + <execution> + <id>npm install</id> + <goals> + <goal>npm</goal> + </goals> + <configuration> + <arguments>install</arguments> + </configuration> + </execution> + <execution> + <id>npm run</id> + <goals> + <goal>npm</goal> + </goals> + <configuration> + <arguments>run build</arguments> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> <configuration> <argLine>${argLine}</argLine> + <systemPropertyVariables> + <java.io.tmpdir>${project.build.directory}/surefire-workdir</java.io.tmpdir> + </systemPropertyVariables> </configuration> + <executions> + <execution> + <id>surefire-it</id> + <phase>integration-test</phase> + <goals> + <goal>test</goal> + </goals> + <configuration> + <includes> + <include>**/*IT.java</include> + </includes> + </configuration> + </execution> + </executions> </plugin> + + <plugin> + <artifactId>maven-site-plugin</artifactId> + <dependencies> + <dependency> + <groupId>org.nuiton.jrst</groupId> + <artifactId>doxia-module-jrst</artifactId> + <version>${jrstPluginVersion}</version> + </dependency> + </dependencies> + </plugin> </plugins> </build> Modified: trunk/src/main/java/fr/ifremer/isisfish/entities/RegionExportJson.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/entities/RegionExportJson.java 2017-03-17 16:43:07 UTC (rev 4412) +++ trunk/src/main/java/fr/ifremer/isisfish/entities/RegionExportJson.java 2017-03-27 09:35:09 UTC (rev 4413) @@ -24,7 +24,6 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; import fr.ifremer.isisfish.IsisConfig; import fr.ifremer.isisfish.types.Month; import fr.ifremer.isisfish.types.RangeOfValues; @@ -97,7 +96,7 @@ public RegionExportJson(Writer w) { try { JsonFactory f = new JsonFactory(); - g = f.createGenerator(w); + g = f.createGenerator(w)/*.useDefaultPrettyPrinter()*/; toVisit = new LinkedList<>(); visited = new HashSet<>(); @@ -231,7 +230,6 @@ public void start() { try { g.writeStartObject(); - ObjectMapper m = new ObjectMapper(); } catch (IOException eee) { throw new RuntimeException(eee); } Modified: trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SSHSimulatorLauncher.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SSHSimulatorLauncher.java 2017-03-17 16:43:07 UTC (rev 4412) +++ trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SSHSimulatorLauncher.java 2017-03-27 09:35:09 UTC (rev 4413) @@ -142,7 +142,7 @@ */ protected void initFreemarker() { - freemarkerConfiguration = new Configuration(Configuration.VERSION_2_3_0); + freemarkerConfiguration = new Configuration(Configuration.VERSION_2_3_25); // needed to overwrite "Defaults to default system encoding." // fix encoding issue on some systems Modified: trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputHandler.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputHandler.java 2017-03-17 16:43:07 UTC (rev 4412) +++ trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputHandler.java 2017-03-27 09:35:09 UTC (rev 4413) @@ -33,6 +33,7 @@ import java.awt.Cursor; import java.awt.event.ItemEvent; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import javax.swing.JOptionPane; @@ -44,9 +45,16 @@ import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; +import fr.ifremer.isisfish.IsisFish; import fr.ifremer.isisfish.entities.FisheryRegionImpl; import fr.ifremer.isisfish.logging.RegionChangeLogger; +import fr.ifremer.isisfish.simulator.launcher.SSHSimulatorLauncher; import fr.ifremer.isisfish.ui.input.spatial.AskNewSpatialUI; +import freemarker.cache.ClassTemplateLoader; +import freemarker.ext.beans.BeansWrapper; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -54,6 +62,7 @@ import org.nuiton.topia.TopiaContext; import org.nuiton.topia.TopiaException; import org.nuiton.topia.persistence.TopiaEntityContextable; +import org.nuiton.util.DesktopUtil; import org.nuiton.util.FileUtil; import fr.ifremer.isisfish.IsisFishDAOHelper; @@ -87,7 +96,12 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import org.nuiton.topia.persistence.TopiaEntity; @@ -391,7 +405,7 @@ /** * Exporter une entite json gzip */ - protected void exportJson(TopiaEntity e) { + protected void exportJson(TopiaEntity e) { try { File file = FileUtil.getFile(t("isisfish.input.menu.exportJson"), t("isisfish.common.export"), (Component)null, ".*" + RegionExportJson.FORMAT_EXTENSION + "$", t("isisfish.message.import.json.zipped")); @@ -755,4 +769,43 @@ askNewSpatialUI.setVisible(true); } } + + /** + * Realise un export JSON et affiche la page de visualisation dans un navigateur. + */ + public void exportWeb() { + try { + StringWriter outJson = new StringWriter(); + RegionExportJson json = new RegionExportJson(outJson); + + FisheryRegion fisheryRegion = inputUI.getContextValue(FisheryRegion.class); + json.export(fisheryRegion); + + Configuration freemarkerConfiguration = new Configuration(Configuration.VERSION_2_3_25); + freemarkerConfiguration.setDefaultEncoding("utf-8"); + ClassTemplateLoader templateLoader = new ClassTemplateLoader(InputHandler.class, "/"); + freemarkerConfiguration.setTemplateLoader(templateLoader); + freemarkerConfiguration.setObjectWrapper(new BeansWrapper(Configuration.VERSION_2_3_25)); + + // get template + Template template = freemarkerConfiguration.getTemplate("templates/web/region-web.html"); + Map<String, Object> root = new HashMap<>(); + root.put("fisheryRegion", fisheryRegion); + root.put("jsonExport", "\nvar jsonExport = " + outJson.toString() + ";"); + + // render template + File outFile = File.createTempFile("isis-export-", ".html"); + outFile.deleteOnExit(); + Writer outWriter = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(outFile)), StandardCharsets.UTF_8); + template.process(root, outWriter); + outWriter.flush(); + + // open file + DesktopUtil.browse(outFile.toURI()); + + } catch (IOException|TemplateException ex) { + throw new IsisFishRuntimeException("Can't export web", ex); + } + + } } Modified: trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputUI.jaxx =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputUI.jaxx 2017-03-17 16:43:07 UTC (rev 4412) +++ trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputUI.jaxx 2017-03-27 09:35:09 UTC (rev 4413) @@ -42,9 +42,11 @@ <JMenuItem id="menuRegionExport" text="isisfish.input.menu.exportRegion" enabled='{isRegionLoaded()}' onActionPerformed="handler.exportRegion()" /> <JMenuItem id="menuExportJson" text="isisfish.input.menu.exportJson" enabled='{isRegionLoaded()}' onActionPerformed="handler.exportEntityJson()" /> <JMenuItem id="menuImportJson" text="isisfish.input.menu.importJson" enabled='{isRegionLoaded()}' onActionPerformed="handler.importEntityJson()" /> - <JMenuItem id="menuChangeResolution" text="isisfish.input.menu.changeResolution" enabled='{isRegionLoaded()}' onActionPerformed="handler.changeSpatialResolution()" /> <JMenuItem id="menuRegionCopy" text="isisfish.input.menu.copyRegion" enabled='{isRegionLoaded()}' onActionPerformed="handler.copyRegion()" /> <JSeparator/> + <JMenuItem id="menuChangeResolution" text="isisfish.input.menu.changeResolution" enabled='{isRegionLoaded()}' onActionPerformed="handler.changeSpatialResolution()" /> + <JMenuItem id="menuExportWeb" text="isisfish.input.menu.exportWeb" enabled='{isRegionLoaded()}' onActionPerformed="handler.exportWeb()" /> + <JSeparator/> <JMenuItem text="isisfish.input.menu.removeLocaly" enabled='{isRegionLoaded()}' onActionPerformed="handler.removeRegion(false)" /> </JMenu> <JMenu text="isisfish.input.menu.server"> Added: trunk/src/main/javascript/templates/web/region-web.html =================================================================== --- trunk/src/main/javascript/templates/web/region-web.html (rev 0) +++ trunk/src/main/javascript/templates/web/region-web.html 2017-03-27 09:35:09 UTC (rev 4413) @@ -0,0 +1,601 @@ +<!doctype html> +<html> + <head> + <title>Region ${fisheryRegion.name}</title> + <meta charset="UTF-8"> + + <style type="text/css"> + .exportTitle { + text-align: center; + } + .category { + + } + .category > .title { + color: #044F90; + border-bottom: 1px solid; + } + .category .entity { + margin-left: 15px; + } + .category .entity > .detailblock { + margin-left: 15px; + } + .category .entity > .title { + text-decoration: underline; + cursor: pointer; + } + .warning { + color: #FFA500; + } + .error { + color: red; + } + </style> + + <script> + function render(json) { + let content = renderJsonExport(json); + document.getElementById("render").innerHTML = content; + } + + function renderJsonExport(json) { + return `<div class='category' id="regions"> + <div class='title'>Region</div> + ${renderCollection(json, json.FisheryRegion, renderFisheryRegion)} + </div> + <div class='category' id="cells"> + <div class='title'>Mailles</div> + ${renderCollection(json, json.Cell, renderCell)} + </div> + <div class='category' id="zones"> + <div class='title'>Zones</div> + ${renderCollection(json, json.Zone, renderZone)} + </div> + <div class='category' id="ports"> + <div class='title'>Ports</div> + ${renderCollection(json, json.Port, renderPort)} + </div> + <div class='category' id="species"> + <div class='title'>Species</div> + ${renderCollection(json, json.Species, renderSpecies)} + </div> + <div class='category' id='populations'> + <div class='title'>Population</div> + ${renderCollection(json, json.Population, renderPopulation)} + </div> + <div class='category' id='gears'> + <div class='title'>Gears</div> + ${renderCollection(json, json.Gear, renderGear)} + </div> + <div class='category' id='metiers'> + <div class='title'>Metiers</div> + ${renderCollection(json, json.Metier, renderMetier)} + </div> + <div class='category' id='triptypes'> + <div class='title'>Trip types</div> + ${renderCollection(json, json.TripType, renderTripType)} + </div> + <div class='category' id='vesselTypes'> + <div class='title'>Vessel types</div> + ${renderCollection(json, json.VesselType, renderVesselType)} + </div> + <div class='category' id='setofvessels'> + <div class='title'>Set of vessels</div> + ${renderCollection(json, json.SetOfVessels, renderSetOfVessels)} + </div> + <div class='category' id='strategies'> + <div class='title'>Strategies</div> + ${renderCollection(json, json.Strategy, renderStrategy)} + </div> + <div class='category' id='observations'> + <div class='title'>Observation</div> + ${renderCollection(json, json.Observation, renderObservation)} + </div> + `; + } + + function renderFisheryRegion(json, fisheryRegion) { + return `<!-- ${JSON.stringify(fisheryRegion)} --> + <div class='entity' id='${cleanEntityId(fisheryRegion)}'> + <span class='title' onclick='switchDetail(this)'>${fisheryRegion.name}</span> + <div class='detailblock'> + <div class='detail'>Latitude minimale : ${fisheryRegion.minLatitude}</div> + <div class='detail'>Latitude maximale : ${fisheryRegion.maxLatitude}</div> + <div class='detail'>Longitude minimale : ${fisheryRegion.minLongitude}</div> + <div class='detail'>Longitude maximale : ${fisheryRegion.maxLongitude}</div> + <div class='detail'>Longitude maximale : ${fisheryRegion.maxLongitude}</div> + <div class='detail'>Latitude : ${fisheryRegion.cellLengthLatitude}</div> + <div class='detail'>Longitude : ${fisheryRegion.cellLengthLongitude}</div> + <div class='detail'>Commentaire : ${fisheryRegion.comment}</div> + </div> + </div>`; + } + + function renderCell(json, cell) { + return `<!-- ${JSON.stringify(cell)} --> + <div class='entity' id='${cleanEntityId(cell)}'> + <span class='title' onclick='switchDetail(this)'>${cell.name}</span> + <div class='detailblock'> + <div class='detail'>Latitude : ${cell.latitude}</div> + <div class='detail'>Longitude : ${cell.longitude}</div> + <div class='detail'>Terre : ${cell.land}</div> + <div class='detail'>Comment : ${cell.comment}</div> + </div> + </div>`; + } + + function renderZone(json, zone) { + return `<!-- ${JSON.stringify(zone)} --> + <div class='entity' id='${cleanEntityId(zone)}'> + <span class='title' onclick='switchDetail(this)'>${zone.name}</span> + <div class='detailblock'> + <div class='detail'>Cell : ${entityIdsLinks(json, zone.cell)}</div> + <div class='detail'>Comment : ${zone.comment}</div> + </div> + </div>`; + } + + function renderPort(json, port) { + return `<!-- ${JSON.stringify(port)} --> + <div class='entity' id='${cleanEntityId(port)}'> + <span class='title' onclick='switchDetail(this)'>${port.name}</span> + <div class='detailblock'> + <div class='detail'>Cell : ${entityIdLink(json, port.cell)}</div> + <div class='detail'>Comment : ${port.comment}</div> + </div> + </div>`; + } + + function renderSpecies(json, species) { + return `<!-- ${JSON.stringify(species)} --> + <div class='entity' id='${cleanEntityId(species)}'> + <span class='title' onclick='switchDetail(this)'>${species.name}</span> + <div class='detailblock'> + <div class='detail'>Scientific name : ${species.scientificName}</div> + <div class='detail'>Code rubbin : ${species.codeRubbin}</div> + <div class='detail'>Code CEE : ${species.codeCEE}</div> + <div class='detail'>Age group type : ${species.ageGroupType}</div> + <div class='detail'>Populations : ${entityIdsLinks(json, species.population)}</div> + <div class='detail'>Comment : ${species.comment}</div> + </div> + </div>`; + } + + function renderPopulation(json, population) { + return `<!-- ${JSON.stringify(population)} --> + <div class='entity' id='${cleanEntityId(population)}'> + <span class='title' onclick='switchDetail(this)'>${population.name}</span> + <div class='detailblock'> + <div class='detail'>Geographic Id : ${population.geographicId}</div> + <div class='detail'>plusGroup : ${population.plusGroup}</div> + ${renderEquation(json, "growth", population.growth)} + ${renderEquation(json, "growthReverse", population.growthReverse)} + <div class='detail'>Comment : ${population.comment}</div> + + <div class='detail'>Population zones : ${entityIdsLinks(json, population.populationZone)}</div> + <div class='detail'>Reproduction zones : ${entityIdsLinks(json, population.reproductionZone)}</div> + <div class='detail'>Recruitment zones : ${entityIdsLinks(json, population.reproductionZone)}</div> + ${renderMatrix(json, "Mapping of reproduction zones and recruitment zones", population.mappingZoneReproZoneRecru)} + + ${renderCollection(json, population.populationSeasonInfo, renderPopulationSeasonInfo)} + + ${renderEquation(json, "naturalDeathRate", population.naturalDeathRate)} + ${renderEquation(json, "meanWeight", population.meanWeight)} + ${renderEquation(json, "maturityOgive", population.maturityOgiveEquation)} + ${renderEquation(json, "reproductionRateEquation", population.reproductionRateEquation)} + + ${renderEquation(json, "reproduction", population.reproductionEquation)} + <div class='detail'>Month gap between repro and recruitment : ${population.monthGapBetweenReproRecrutement}</div> + ${renderMatrix1D(json, "Recruitment distribution", population.recruitmentDistribution)} + ${renderEquation(json, "Recruitment equation", population.recruitmentEquation)} + <div class='detail'>Recruitment comment : ${population.recruitmentComment}</div> + + ${renderCollection(json, population.populationGroup, renderPopulationGroup)} + + ${renderMatrix(json, "Accessibility", population.capturability)} + ${renderEquation(json, "Accessibility equation", population.capturabilityEquation)} + <div class='detail'>Accessibility comment : ${population.capturabilityComment}</div> + + ${renderCollection(json, population.populationSeasonInfo, renderPopulationSeasonInfoMigration)} + <div class='detail'>Migration comment : ${population.migrationComment}</div> + + ${renderEquation(json, "Price", population.price)} + + <div class='detail'>Fbar Group Min : ${population.fbarGroupMin}</div> + <div class='detail'>Fbar Group Max : ${population.fbarGroupMax}</div> + <div class='detail'>Abundance reference month : ${population.abundanceReferenceMonth}</div> + <div class='detail'>F computing : ${population.computeFOnLandings}</div> + ${renderEquation(json, "Fishing mortality other fleets", population.fishingMortalityOtherFleets)} + </div> + </div>`; + } + + function renderPopulationSeasonInfo(json, psi) { + return `<!-- ${JSON.stringify(psi)} --> + <div class='entity' id='${cleanEntityId(psi)}'> + <span class='title' onclick='switchDetail(this)'>${psi.firstMonth} - ${psi.lastMonth}</span> + <div class='detailblock'> + <div class='detail'>Group change : ${psi.groupChange}</div> + <div class='detail'>Reproduction : ${psi.reproduction}</div> + ${renderMatrix(json, "Reproduction distribution", psi.reproductionDistribution)} + <div class='detail'>Comment : ${psi.comment}</div> + </div> + </div>`; + } + + function renderPopulationSeasonInfoMigration(json, psi) { + return `<!-- ${JSON.stringify(psi)} --> + <div class='entity' id='${cleanEntityId(psi)}'> + <span class='title' onclick='switchDetail(this)'>${psi.firstMonth} - ${psi.lastMonth}</span> + <div class='detailblock'> + <div class='detail'>Use migration equation : ${psi.useEquationMigration}</div> + ${renderEquation(json, "reproductionRateEquation", psi.migrationEquation)} + ${renderEquation(json, "reproductionRateEquation", psi.immigrationEquation)} + ${renderEquation(json, "reproductionRateEquation", psi.emigrationEquation)} + ${renderMatrix(json, "Migration matrix", psi.migrationMatrix)} + ${renderMatrix(json, "Immigration matrix", psi.immigrationMatrix)} + ${renderMatrix(json, "Emmigration matrix", psi.emigrationMatrix)} + </div> + </div>`; + } + + function renderPopulationGroup(json, pg) { + return `<!-- ${JSON.stringify(pg)} --> + <div class='entity' id='${cleanEntityId(pg)}'> + <span class='title' onclick='switchDetail(this)'>${pg["#toString"]}</span> + <div class='detailblock'> + <div class='detail'>Age : ${pg.age}</div> + <div class='detail'>Min length : ${pg.minLength}</div> + <div class='detail'>Max length : ${pg.maxLength}</div> + <div class='detail'>Comment : ${pg.comment}</div> + </div> + </div>`; + } + + function renderGear(json, gear) { + return `<!-- ${JSON.stringify(gear)} --> + <div class='entity' id='${cleanEntityId(gear)}'> + <span class='title' onclick='switchDetail(this)'>${gear.name}</span> + <div class='detailblock'> + <div class='detail'>Effort unit : ${gear.effortUnit}</div> + <div class='detail'>Standardisation factor : ${gear.standardisationFactor}</div> + <div class='detail'>Technical parameter : ${gear.parameterName}</div> + <div class='detail'>Range of values : ${gear.possibleValue}</div> + <div class='detail'>Comment : ${gear.comment}</div> + ${renderCollection(json, gear.populationSelectivity, renderSelectivity)} + </div> + </div>`; + } + + function renderSelectivity(json, selectivity) { + return `<!-- ${JSON.stringify(selectivity)} --> + <div class='entity' id='${cleanEntityId(selectivity)}'> + <span class='title' onclick='switchDetail(this)'>${selectivity['#toString']}</span> + <div class='detailblock'> + <div class='detail'>Population : ${entityIdLink(json, selectivity.population)}</div> + ${renderEquation(json, "Equation", selectivity.equation)} + </div> + </div>`; + } + + function renderMetier(json, metier) { + return `<!-- ${JSON.stringify(metier)} --> + <div class='entity' id='${cleanEntityId(metier)}'> + <span class='title' onclick='switchDetail(this)'>${metier.name}</span> + <div class='detailblock'> + <div class='detail'>Gear : ${entityIdLink(json, metier.gear)}</div> + <div class='detail'>Range of values : ${metier.gearParameterValue}</div> + <div class='detail'>Comment : ${metier.comment}</div> + ${renderCollection(json, metier.metierSeasonInfo, renderMetierSeasonInfo)} + </div> + </div>`; + } + + function renderMetierSeasonInfo(json, msi) { + return `<!-- ${JSON.stringify(msi)} --> + <div class='entity' id='${cleanEntityId(msi)}'> + <span class='title' onclick='switchDetail(this)'>${msi['#toString']}</span> + <div class='detailblock'> + <div class='detail'>Zones : ${entityIdsLinks(json, msi.zone)}</div> + <div class='detail'>Comment : ${msi.comment}</div> + ${renderCollection(json, msi.speciesTargetSpecies, renderTargetSpecies)} + </div> + </div>`; + } + + function renderTargetSpecies(json, ts) { + return `<!-- ${JSON.stringify(ts)} --> + <div class='entity' id='${cleanEntityId(ts)}'> + <span class='title' onclick='switchDetail(this)'>${ts['#toString']}</span> + <div class='detailblock'> + <div class='detail'>Species : ${entityIdLink(json, ts.species)}</div> + ${renderEquation(json, "Target factor", ts.targetFactorEquation)} + <div class='detail'>Main species for the metier : ${ts.primaryCatch}</div> + </div> + </div>`; + } + + function renderTripType(json, tripType) { + return `<!-- ${JSON.stringify(tripType)} --> + <div class='entity' id='${cleanEntityId(tripType)}'> + <span class='title' onclick='switchDetail(this)'>${tripType.name}</span> + <div class='detailblock'> + <div class='detail'>Duration : ${tripType.tripDuration}</div> + <div class='detail'>Minimum time between trips : ${tripType.minTimeBetweenTrip}</div> + <div class='detail'>Comment : ${tripType.comment}</div> + </div> + </div>`; + } + + function renderVesselType(json, vesselType) { + return `<!-- ${JSON.stringify(vesselType)} --> + <div class='entity' id='${cleanEntityId(vesselType)}'> + <span class='title' onclick='switchDetail(this)'>${vesselType.name}</span> + <div class='detailblock'> + <div class='detail'>Length : ${vesselType.length}</div> + <div class='detail'>Speed : ${vesselType.speed}</div> + <div class='detail'>Max trip duration : ${vesselType.maxTripDuration}</div> + <div class='detail'>Activity range : ${vesselType.activityRange}</div> + <div class='detail'>Minimum Crew Size : ${vesselType.minCrewSize}</div> + <div class='detail'>Travel fuel cost : ${vesselType.unitFuelCostOfTravel}</div> + <div class='detail'>Trip type : ${entityIdsLinks(json, vesselType.tripType)}</div> + <div class='detail'>Comment : ${vesselType.comment}</div> + </div> + </div>`; + } + + function renderSetOfVessels(json, setOfVessels) { + return `<!-- ${JSON.stringify(setOfVessels)} --> + <div class='entity' id='${cleanEntityId(setOfVessels)}'> + <span class='title' onclick='switchDetail(this)'>${setOfVessels.name}</span> + <div class='detailblock'> + <div class='detail'>Port : ${entityIdLink(json, setOfVessels.port)}</div> + <div class='detail'>Vessel type : ${entityIdLink(json, setOfVessels.vesselType)}</div> + <div class='detail'>numberOfVessels : ${setOfVessels.numberOfVessels}</div> + <div class='detail'>fixedCosts : ${setOfVessels.fixedCosts}</div> + ${renderEquation(json, "Technical efficiency", setOfVessels.technicalEfficiencyEquation)} + <div class='detail'>Comment : ${setOfVessels.comment}</div> + ${renderCollection(json, setOfVessels.possibleMetiers, renderEffortDescription)} + </div> + </div>`; + } + + function renderEffortDescription(json, ed) { + return `<!-- ${JSON.stringify(ed)} --> + <div class='entity' id='${cleanEntityId(ed)}'> + <span class='title' onclick='switchDetail(this)'>${ed['#toString']}</span> + <div class='detailblock'> + <div class='detail'>Possible metier : ${entityIdLink(json, ed.possibleMetiers)}</div> + <div class='detail'>Fishing operation : ${ed.fishingOperation}</div> + <div class='detail'>fishingOperationDuration : ${ed.fishingOperationDuration}</div> + <div class='detail'>gearsNumberPerOperation : ${ed.gearsNumberPerOperation}</div> + <div class='detail'>crewSize : ${ed.crewSize}</div> + <div class='detail'>unitCostOfFishing : ${ed.unitCostOfFishing}</div> + <div class='detail'>fixedCrewSalary : ${ed.fixedCrewSalary}</div> + <div class='detail'>crewShareRate : ${ed.crewShareRate}</div> + <div class='detail'>repairAndMaintenanceGearCost : ${ed.repairAndMaintenanceGearCost}</div> + <div class='detail'>landingCosts : ${ed.landingCosts}</div> + <div class='detail'>otherRunningCost : ${ed.otherRunningCost}</div> + </div> + </div>`; + } + + function renderStrategy(json, strategy) { + return `<!-- ${JSON.stringify(strategy)} --> + <div class='entity' id='${cleanEntityId(strategy)}'> + <span class='title' onclick='switchDetail(this)'>${strategy.name}</span> + <div class='detailblock'> + <div class='detail'>Set of vessels : ${entityIdLink(json, strategy.setOfVessels)}</div> + <div class='detail'>Set of vessels proportion : ${strategy.proportionSetOfVessels}</div> + <div class='detail'>Use inactivity equation : ${strategy.inactivityEquationUsed}</div> + ${renderEquation(json, "Inactivity equation", strategy.inactivityEquation)} + <div class='detail'>Comment : ${strategy.comment}</div> + ${renderCollection(json, strategy.strategyMonthInfo, renderStrategyMonthInfo)} + </div> + </div>`; + } + + function renderStrategyMonthInfo(json, smi) { + return `<!-- ${JSON.stringify(smi)} --> + <div class='entity' id='${cleanEntityId(smi)}'> + <span class='title' onclick='switchDetail(this)'>${smi['#toString']}</span> + <div class='detailblock'> + <div class='detail'>Trip type : ${entityIdLink(json, smi.tripType)}</div> + <div class='detail'>numberOfTrips : ${smi.numberOfTrips}</div> + <div class='detail'>minInactivityDays : ${smi.minInactivityDays}</div> + ${renderMatrix1D(json, "Proportion metier", smi.proportionMetier)} + </div> + </div>`; + } + + function renderObservation(json, observation) { + return `<!-- ${JSON.stringify(observation)} --> + <div class='entity' id='${cleanEntityId(observation)}'> + <span class='title' onclick='switchDetail(this)'>${observation.name}</span> + <div class='detailblock'> + ${renderMatrix(json, "Value", observation.value)} + </div> + </div>`; + } + + // apply "f" function for each entity of each id of collection + function renderCollection(json, ids, f) { + return ids.map(id => f(json, json["#entities"][id])).join("\n") + } + + // clean entity id to be used in anchor + function cleanEntityId(entity) { + return entity["#id"].replace(/#/g,'_'); + } + + // generate entity link on id with name as content + function entityLink(entity) { + return `<a href='#${cleanEntityId(entity)}'>${entity.name || entity["#toString"]}</a>`; + } + + // generate link on entity represented by his id + function entityIdLink(json, entityId) { + let entity = json["#entities"][entityId]; + let result = ""; + if (entity) { //entity found + result = entityLink(entity); + } else if (!entityId || entityId == "null") { // entity id empty + result = ""; + } else if (entityId.indexOf("fr.") == 0) { // topia id, but not found + result = `<span class='error' title='${entityId}'>Todo</span>`; + } else { // other case "Month 0" ... + result = `<span class='warning'>${entityId}</span>`; + } + return result; + } + + // generate link on entity for each id of collection + function entityIdsLinks(json, entityIds) { + return entityIds.map(id => entityIdLink(json, id)).join(", "); + } + + // render equation + function renderEquation(json, name, id) { + let equation = json["#entities"][id]; + let result = ""; + if (equation) { + result = `<div class='detail'>${name} : <pre class='highlight java'>${equation.content}</pre></div>`; + } + return result; + } + + // render matrix 1D + function renderMatrix1D(json, name, content) { + if (!content) { + return ""; + } + + // convert semantics + let contentLines = content.split('\n'); + let semantique0 = contentLines[1].substring(contentLines[1].indexOf(":") + 1).split(";").map(s => s.substring(0, s.indexOf(":"))); + + // create matrix filled with 0 + let matrix = new Array(semantique0.length); + for (var i = 0; i < semantique0.length; i++) { + matrix[i] = 0; + } + // add values in matrix with coordinate + for (let index = 3; index < contentLines.length; index++) { + if (contentLines[index]) { + let values = contentLines[index].split(";"); + matrix[values[0]] = values[1]; + } + } + + // render matrix + let html = `${name} : <table border='1'>` + + "<tr>"; + semantique0.forEach(sem => html += "<th>" + entityIdLink(json, sem) + "</th>"); + html += "</tr>"; + html += "<tr>"; + for (let i = 0; i < matrix.length; i++) { + html += "<td>" + matrix[i] + "</td>"; + } + html += "</tr>"; + html += "</table>"; + return html; + } + + // render matrix 2D + function renderMatrix(json, name, content) { + if (!content) { + return ""; + } + + // convert semantics + let contentLines = content.split('\n'); + let semantique0 = contentLines[1].substring(contentLines[1].indexOf(":") + 1).split(";").map(s => s.substring(0, s.indexOf(":"))); + let semantique1 = contentLines[2].substring(contentLines[2].indexOf(":") + 1).split(";").map(s => s.substring(0, s.indexOf(":"))); + + // create matrix filled with 0 + let matrix = new Array(semantique0.length); + for (var i = 0; i < semantique0.length; i++) { + matrix[i] = new Array(semantique1.length); + for (var j = 0; j < semantique1.length; j++) { + matrix[i][j] = 0; + } + } + // add values in matrix with coordinate + for (let index = 4; index < contentLines.length; index++) { + if (contentLines[index]) { + let values = contentLines[index].split(";"); + matrix[values[0]][values[1]] = values[2]; + } + } + + // render matrix + let html = `${name} : <table border='1'>` + + "<tr><th />"; + semantique1.forEach(sem => html += "<th>" + entityIdLink(json, sem) + "</th>"); + html += "</tr>"; + for (let i = 0; i < matrix.length; i++) { + html += "<tr><th>" + entityIdLink(json, semantique0[i]) + "</th>"; + for (let j = 0; j < matrix[i].length; j++) { + html += "<td>" + matrix[i][j] + "</td>"; + } + html += "</tr>"; + } + html += "</table>"; + return html; + } + + // display or hide details + function switchDetail(element) { + let detailBlock = element.parentNode.getElementsByClassName("detailblock")[0]; + if (detailBlock.style.display == "none") { + detailBlock.style.display = "block" + } else { + detailBlock.style.display = "none" + } + } + + // ${jsonExport} + </script> + </head> + + <body> + <h1 class="exportTitle">Region XXX</h1> + + Menu: + <div id="toc"> + <ul> + <li><a href="#regions">Region</a></li> + <li><a href="#cells">Mailles</a></li> + <li><a href="#ports">Ports</a></li> + <li><a href="#species">Species</a></li> + <li><a href="#populations">Populations</a></li> + <li><a href="#gears">Gears</a></li> + <li><a href="#metiers">Metier</a></li> + <li><a href="#triptypes">Trip types</a></li> + <li><a href="#vesseltypes">Vessel types</a></li> + <li><a href="#setofvessels">Set of vessels</a></li> + <li><a href="#strategies">Strategies</a></li> + <li><a href="#observations">Observations</a></li> + </ul> + <div> + <div id="render"> + + </div> + + <script> + render(jsonExport) + </script> + + <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.10.0/styles/default.min..." /> + <script src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.10.0/highlight.min.js"></script> + <script> + if (window.hljs) { + for (let block of document.getElementsByClassName("highlight")) { + hljs.highlightBlock(block) + } + } + </script> + + </body> +</html> \ No newline at end of file Modified: trunk/src/main/resources/i18n/isis-fish_en_GB.properties =================================================================== --- trunk/src/main/resources/i18n/isis-fish_en_GB.properties 2017-03-17 16:43:07 UTC (rev 4412) +++ trunk/src/main/resources/i18n/isis-fish_en_GB.properties 2017-03-27 09:35:09 UTC (rev 4413) @@ -491,6 +491,7 @@ isisfish.input.menu.copyRegion=Copy region isisfish.input.menu.exportJson=Export current object in JSON isisfish.input.menu.exportRegion=Export region +isisfish.input.menu.exportWeb=Export web isisfish.input.menu.importJson=Import objets from JSON isisfish.input.menu.importRegion=Import region isisfish.input.menu.importRegionSimulation=Import region from simulation Modified: trunk/src/main/resources/i18n/isis-fish_fr_FR.properties =================================================================== --- trunk/src/main/resources/i18n/isis-fish_fr_FR.properties 2017-03-17 16:43:07 UTC (rev 4412) +++ trunk/src/main/resources/i18n/isis-fish_fr_FR.properties 2017-03-27 09:35:09 UTC (rev 4413) @@ -491,6 +491,7 @@ isisfish.input.menu.copyRegion=Copier région isisfish.input.menu.exportJson=Exporter l'objet courant en JSON isisfish.input.menu.exportRegion=Exporter la région +isisfish.input.menu.exportWeb=Export web isisfish.input.menu.importJson=Importer des objets JSON isisfish.input.menu.importRegion=Importer une région isisfish.input.menu.importRegionSimulation=Importer la région d'une simulation
participants (1)
-
echatellier@users.forge.codelutin.com