diff --git a/client/apollo/js/JSONUtils.js b/client/apollo/js/JSONUtils.js index 64ca9e749b..f242b7c08a 100644 --- a/client/apollo/js/JSONUtils.js +++ b/client/apollo/js/JSONUtils.js @@ -362,10 +362,6 @@ JSONUtils.createApolloFeature = function( jfeature, specified_type, useName, spe afeature.type.name = typename; } - // if (useName && name) { - // afeature.name = name; - // } - var id = jfeature.get('id'); var name = jfeature.get('name'); if (useName) { diff --git a/client/apollo/js/View/Track/AnnotTrack.js b/client/apollo/js/View/Track/AnnotTrack.js index 653ba73a53..a6c1935a96 100644 --- a/client/apollo/js/View/Track/AnnotTrack.js +++ b/client/apollo/js/View/Track/AnnotTrack.js @@ -330,7 +330,11 @@ define([ filteredTrack.type = trackConfig.type; filteredTrack.category = trackConfig.category; filteredTrack.urlTemplate = trackConfig.urlTemplate; + filteredTrack.storeClass = trackConfig.storeClass; filteredTrack.visible = visible; + if(trackConfig.apollo){ + filteredTrack.apollo = trackConfig.apollo; + } filteredTrackList.push(filteredTrack); } diff --git a/grails-app/conf/Config.groovy b/grails-app/conf/Config.groovy index b024f6e319..f5c85fada2 100644 --- a/grails-app/conf/Config.groovy +++ b/grails-app/conf/Config.groovy @@ -400,7 +400,7 @@ auditLog { jbrowse { git { url = "https://github.com/gmod/jbrowse" - branch = "1.16.2-release" + branch = "1.16.3-release" // branch = "dev" // tag = "15dfd2309f2d508d8bed782d0f68b38dd9927bb4" alwaysPull = true diff --git a/grails-app/controllers/org/bbop/apollo/JbrowseController.groovy b/grails-app/controllers/org/bbop/apollo/JbrowseController.groovy index 3ec0e89ec1..add3b39709 100644 --- a/grails-app/controllers/org/bbop/apollo/JbrowseController.groovy +++ b/grails-app/controllers/org/bbop/apollo/JbrowseController.groovy @@ -1,12 +1,11 @@ package org.bbop.apollo import grails.converters.JSON -import grails.transaction.NotTransactional import liquibase.util.file.FilenameUtils import org.apache.shiro.SecurityUtils import org.bbop.apollo.gwt.shared.ClientTokenGenerator import org.bbop.apollo.gwt.shared.FeatureStringEnum -import org.bbop.apollo.sequence.Range +import org.bbop.apollo.sequence.Range // this line is needed, even if hte import doesn't show it import org.codehaus.groovy.grails.web.json.JSONArray import org.codehaus.groovy.grails.web.json.JSONObject @@ -16,7 +15,6 @@ import java.text.SimpleDateFormat import static org.springframework.http.HttpStatus.NOT_FOUND -//@CompileStatic class JbrowseController { private static final int DEFAULT_BUFFER_SIZE = 10240; // ..bytes = 10KB. @@ -395,7 +393,6 @@ class JbrowseController { * @param tracksArray */ - @NotTransactional def pruneTracks(JSONArray tracksArray){ JSONArray returnArray = new JSONArray() diff --git a/grails-app/controllers/org/bbop/apollo/OrganismController.groovy b/grails-app/controllers/org/bbop/apollo/OrganismController.groovy index 37861dd805..490b5abf2e 100644 --- a/grails-app/controllers/org/bbop/apollo/OrganismController.groovy +++ b/grails-app/controllers/org/bbop/apollo/OrganismController.groovy @@ -6,6 +6,7 @@ import grails.transaction.Transactional import org.bbop.apollo.gwt.shared.FeatureStringEnum import org.bbop.apollo.gwt.shared.GlobalPermissionEnum import org.bbop.apollo.gwt.shared.PermissionEnum +import org.bbop.apollo.gwt.shared.track.TrackTypeEnum import org.bbop.apollo.report.OrganismSummary import org.codehaus.groovy.grails.web.converters.exceptions.ConverterException import org.codehaus.groovy.grails.web.json.JSONArray @@ -299,6 +300,67 @@ class OrganismController { render returnObject as JSON } + @RestApiMethod(description = "Removes an added track from an existing organism returning a JSON object containing all tracks for the current organism.", path = "/organism/removeTrackFromOrganism", verb = RestApiVerb.POST) + @RestApiParams(params = [ + @RestApiParam(name = "username", type = "email", paramType = RestApiParamType.QUERY) + , @RestApiParam(name = "password", type = "password", paramType = RestApiParamType.QUERY) + , @RestApiParam(name = "organism", type = "string", paramType = RestApiParamType.QUERY, description = "ID or commonName that can be used to uniquely identify an organism") + , @RestApiParam(name = "trackLabel", type = "string", paramType = RestApiParamType.QUERY, description = "Name of track") + ]) + @Transactional + def removeTrackFromOrganism() { + JSONObject returnObject = new JSONObject() + JSONObject requestObject = permissionService.handleInput(request, params) + println "removing track from organism with ${requestObject}" + + if (!requestObject.containsKey(FeatureStringEnum.ORGANISM.value)) { + returnObject.put("error", "/removeTrackFromOrganism requires '${FeatureStringEnum.ORGANISM.value}'.") + response.setStatus(HttpServletResponse.SC_BAD_REQUEST) + render returnObject as JSON + return + } + + if (!requestObject.containsKey(FeatureStringEnum.TRACK_LABEL.value)) { + returnObject.put("error", "/removeTrackFromOrganism requires '${FeatureStringEnum.TRACK_LABEL.value}'.") + response.setStatus(HttpServletResponse.SC_BAD_REQUEST) + render returnObject as JSON + return + } + + try { + permissionService.checkPermissions(requestObject, PermissionEnum.ADMINISTRATE) + Organism organism = preferenceService.getOrganismForTokenInDB(requestObject.get(FeatureStringEnum.ORGANISM.value)?.id) + println "organism ${organism}" + // find in the extended track list and remove + String extendedDirectoryName = configWrapperService.commonDataDirectory + File.separator + organism.id + "-" + organism.commonName + File extendedDirectory = new File(extendedDirectoryName) + if (!extendedDirectory.exists()) { + returnObject.put("error", "No temporary directory found to remove tracks from ${extendedDirectoryName}") + render returnObject as JSON + return + } + File extendedTrackListJsonFile = new File(extendedDirectoryName + File.separator + EXTENDED_TRACKLIST) + JSONObject extendedTrackListObject = JSON.parse(extendedTrackListJsonFile.text) + JSONArray extendedTracksArray = extendedTrackListObject.getJSONArray(FeatureStringEnum.TRACKS.value) + println "input tracks ${extendedTracksArray as JSON}" + + extendedTracksArray = trackService.removeTrackFromArray(extendedTracksArray, requestObject.get(FeatureStringEnum.TRACK_LABEL.value)) + println "output tracks ${extendedTracksArray as JSON}" + extendedTrackListObject.put(FeatureStringEnum.TRACKS.value,extendedTracksArray) + extendedTrackListJsonFile.write(extendedTrackListObject.toString()) + println "final object ${extendedTrackListObject as JSON}" + println "write to file ${extendedTrackListJsonFile.absolutePath}" + render returnObject as JSON + } catch (Exception ce) { + log.error ce.message + returnObject.put("error", ce.message) + render returnObject as JSON + return + } + + } + + @RestApiMethod(description = "Adds a track to an existing organism returning a JSON object containing all tracks for the current organism.", path = "/organism/addTrackToOrganism", verb = RestApiVerb.POST) @RestApiParams(params = [ @RestApiParam(name = "username", type = "email", paramType = RestApiParamType.QUERY) @@ -314,6 +376,15 @@ class OrganismController { JSONObject returnObject = new JSONObject() JSONObject requestObject = permissionService.handleInput(request, params) +// println "input request object ${requestObject}" +// println "request ${request}" + println "input params ${params}" +// println "request trackFile: ${request.getFile("trackFile")}" +// if(request.getFile(FeatureStringEnum.TRACK_DATA.value)){ +//// File tempFile = File.createTempFile("trackFile","tmp") +//// trackFileData.transferTo(tempFile) +//// requestObject.put("trackFile") +// } if (!requestObject.containsKey(FeatureStringEnum.ORGANISM.value)) { @@ -346,7 +417,7 @@ class OrganismController { JSONObject trackConfigObject try { - trackConfigObject = JSON.parse(params.get(FeatureStringEnum.TRACK_CONFIG.value)) as JSONObject + trackConfigObject = JSON.parse(params.get(FeatureStringEnum.TRACK_CONFIG.value) as String) as JSONObject } catch (ConverterException ce) { log.error ce.message returnObject.put("error", ce.message) @@ -363,7 +434,7 @@ class OrganismController { try { permissionService.checkPermissions(requestObject, PermissionEnum.ADMINISTRATE) - log.debug "user ${requestObject.get(FeatureStringEnum.USERNAME.value)} is admin" +// log.debug "user ${requestObject.get(FeatureStringEnum.USERNAME.value)} is admin" Organism organism = preferenceService.getOrganismForTokenInDB(requestObject.get(FeatureStringEnum.ORGANISM.value)) if (organism) { @@ -373,12 +444,13 @@ class OrganismController { File commonDataDirectory = new File(configWrapperService.commonDataDirectory) CommonsMultipartFile trackDataFile = request.getFile(FeatureStringEnum.TRACK_DATA.value) - CommonsMultipartFile trackFile = request.getFile("trackFile") - CommonsMultipartFile trackFileIndex = request.getFile("trackFileIndex") + CommonsMultipartFile trackFile = request.getFile(FeatureStringEnum.TRACK_FILE.value) + CommonsMultipartFile trackFileIndex = request.getFile(FeatureStringEnum.TRACK_FILE_INDEX.value) + println "file paths? ${trackFile}" if (organismDirectory.getParentFile().getCanonicalPath() == commonDataDirectory.getCanonicalPath()) { // organism data is in common data directory - log.debug "organism data is in common data directory" + println "organism data is in common data directory" File trackListJsonFile = new File(organism.directory + File.separator + TRACKLIST) JSONObject trackListObject = JSON.parse(trackListJsonFile.text) JSONArray tracksArray = trackListObject.getJSONArray(FeatureStringEnum.TRACKS.value) @@ -414,7 +486,9 @@ class OrganismController { } else { // trackDataFile is null; use data from trackFile and trackFileIndex, if available if (trackFile) { + println "using track file" if (trackService.findTrackFromArray(tracksArray, trackConfigObject.get(FeatureStringEnum.LABEL.value)) == null) { + println "found track from array" // add track config to trackList.json tracksArray.add(trackConfigObject) try { @@ -444,6 +518,7 @@ class OrganismController { } } else { // organism data is somewhere on the server where we don't want to modify anything + println "adding to existing organism" File trackListJsonFile = new File(organism.directory + File.separator + TRACKLIST) JSONObject trackListObject = JSON.parse(trackListJsonFile.text) JSONArray tracksArray = trackListObject.getJSONArray(FeatureStringEnum.TRACKS.value) @@ -451,20 +526,22 @@ class OrganismController { log.error "an entry for track with label '${trackConfigObject.get(FeatureStringEnum.LABEL.value)}' already exists in ${organism.directory}/${TRACKLIST}" returnObject.put("error", "an entry for track with label '${trackConfigObject.get(FeatureStringEnum.LABEL.value)}' already exists in ${organism.directory}/${TRACKLIST}.") } else { + println "will be a new track" String extendedDirectoryName = configWrapperService.commonDataDirectory + File.separator + organism.id + "-" + organism.commonName File extendedDirectory = new File(extendedDirectoryName) if (extendedDirectory.exists()) { // extended organism directory present in common data directory - log.debug "extended organism directory ${extendedDirectoryName} present in common data directory" + println "extended organism directory ${extendedDirectoryName} present in common data directory" } else { // make a new extended organism directory in common data directory - log.debug "creating extended organism directory ${extendedDirectoryName} in common data directory" + println "creating extended organism directory ${extendedDirectoryName} in common data directory" if (extendedDirectory.mkdirs()) { // write extendedTrackList.json File extendedTrackListJsonFile = new File(extendedDirectoryName + File.separator + EXTENDED_TRACKLIST) def trackListJsonWriter = extendedTrackListJsonFile.newWriter() trackListJsonWriter << "{'${FeatureStringEnum.TRACKS.value}':[]}" trackListJsonWriter.close() + println "added to the trackListJsonWriter ${extendedTrackListJsonFile.text}" } else { log.error "Cannot create directory ${extendedDirectoryName}" returnObject.put("error", "Cannot create directory ${extendedDirectoryName}.") @@ -502,6 +579,75 @@ class OrganismController { returnObject.put("error", e.message) } } + } else { + if (trackFile) { + println "using track file for existing organism" + if (trackService.findTrackFromArray(tracksArray, trackConfigObject.get(FeatureStringEnum.LABEL.value)) == null) { + println "found track from array" + // add track config to trackList.json + File extendedTrackListJsonFile = new File(extendedDirectoryName + File.separator + EXTENDED_TRACKLIST) + if(!extendedTrackListJsonFile.exists()){ + println "file does not exist so creating" + def trackListJsonWriter = extendedTrackListJsonFile.newWriter() + trackListJsonWriter << "{'${FeatureStringEnum.TRACKS.value}':[]}" + trackListJsonWriter.close() + println "added to the trackListJsonWriter ${extendedTrackListJsonFile.text}" + } + else{ + println "FILE EXISTS, so nothing to do ${extendedTrackListJsonFile.text}" + } + JSONObject extendedTrackListObject = JSON.parse(extendedTrackListJsonFile.text) + JSONArray extendedTracksArray = extendedTrackListObject.getJSONArray(FeatureStringEnum.TRACKS.value) + if (trackService.findTrackFromArray(extendedTracksArray, trackConfigObject.get(FeatureStringEnum.LABEL.value)) != null) { + log.error "an entry for track with label '${trackConfigObject.get(FeatureStringEnum.LABEL.value)}' already exists in ${organism.directory}/${TRACKLIST}" + returnObject.put("error", "an entry for track with label '${trackConfigObject.get(FeatureStringEnum.LABEL.value)}' already exists in ${organism.directory}/${TRACKLIST}.") + } + else { + try { +// String urlTemplate = trackConfigObject.get(FeatureStringEnum.URL_TEMPLATE.value) +// String trackDirectoryName = urlTemplate.split("/").first() +// String path = organismDirectoryName + File.separator + trackDirectoryName + String path = extendedDirectoryName + File.separator + "raw" + println "tranfer config object ${trackConfigObject as JSON}" + println "transfer key ${trackConfigObject.key}" + println "transfer key 2 ${trackConfigObject.get("key")}" + TrackTypeEnum trackTypeEnum = org.bbop.apollo.gwt.shared.track.TrackTypeEnum.valueOf(trackConfigObject.apollo.type) + println "track type enum ${trackTypeEnum}" + + String newFileName = trackTypeEnum ? trackConfigObject.key + "." + trackTypeEnum.suffix : trackFile.originalFilename + + fileService.storeWithNewName(trackFile, path, trackConfigObject.key,newFileName) + println "trying to store with track file index ${trackFileIndex.getOriginalFilename()}" + if (trackFileIndex.getOriginalFilename()) { + String newFileNameIndex = trackTypeEnum ? trackConfigObject.key + "." + trackTypeEnum.suffixIndex : trackFileIndex.originalFilename + println "Storing with track file index ${trackFileIndex.getOriginalFilename()}" +// fileService.store(trackFileIndex, path) + fileService.storeWithNewName(trackFileIndex, path, trackConfigObject.key,newFileNameIndex) + println "STORED with track file index ${trackFileIndex}" + } + + extendedTracksArray.add(trackConfigObject) + extendedTrackListObject.put(FeatureStringEnum.TRACKS.value,extendedTracksArray) + println "array ${extendedTracksArray as JSON}" + println "object ${extendedTrackListObject as JSON}" + + // write to trackList.json + def trackListJsonWriter = extendedTrackListJsonFile.newWriter() + trackListJsonWriter << extendedTrackListObject.toString(4) + trackListJsonWriter.close() + returnObject.put(FeatureStringEnum.TRACKS.value, tracksArray) + } + catch (IOException e) { + log.error e.printStackTrace() + returnObject.put("error", e.message) + } + } + println "trackJsonWriter: -> ${extendedTrackListJsonFile.absolutePath}, ${extendedTrackListJsonFile.text}" + } else { + log.error "an entry for track with label '${trackConfigObject.get(FeatureStringEnum.LABEL.value)}' already exists in ${organism.directory}/${TRACKLIST}" + returnObject.put("error", "an entry for track with label '${trackConfigObject.get(FeatureStringEnum.LABEL.value)}' already exists in ${organism.directory}/${TRACKLIST}.") + } + } } } } @@ -968,11 +1114,11 @@ class OrganismController { organism.metadata = organismJson.metadata ? organismJson.metadata.toString() : organism.metadata organism.directory = organismJson.directory organism.publicMode = organismJson.publicMode ?: false - madeObsolete = !organism.obsolete && organismJson.obsolete + madeObsolete = !organism.obsolete && organismJson.obsolete organism.obsolete = organismJson.obsolete ?: false organism.nonDefaultTranslationTable = organismJson.nonDefaultTranslationTable ?: null if (checkOrganism(organism)) { - if(madeObsolete){ + if (madeObsolete) { // TODO: remove all organism permissions permissionService.removeAllPermissions(organism) } @@ -1085,7 +1231,7 @@ class OrganismController { if (permissionService.hasGlobalPermissions(requestObject, GlobalPermissionEnum.ADMIN)) { organismList = showObsolete ? Organism.all : Organism.findAllByObsolete(false) } else { - organismList = permissionService.getOrganismsForCurrentUser(requestObject).filter(){ o -> !o.obsolete } + organismList = permissionService.getOrganismsForCurrentUser(requestObject).filter() { o -> !o.obsolete } } } diff --git a/grails-app/services/org/bbop/apollo/FileService.groovy b/grails-app/services/org/bbop/apollo/FileService.groovy index c0ede51e7a..2b02a31982 100644 --- a/grails-app/services/org/bbop/apollo/FileService.groovy +++ b/grails-app/services/org/bbop/apollo/FileService.groovy @@ -147,9 +147,9 @@ class FileService { continue; } - FileOutputStream fos = new FileOutputStream(outputFile); - IOUtils.copy(tais, fos); - fos.close(); + FileOutputStream fos = new FileOutputStream(outputFile) + IOUtils.copy(tais, fos) + fos.close() } if (tempDir) { @@ -170,6 +170,32 @@ class FileService { } } + def storeWithNewName(CommonsMultipartFile file, String path, String directoryName,String newName ) { + File pathFile = new File(path) + if (!pathFile.exists()) { + pathFile.mkdirs() + } + int suffixIndex = newName.indexOf(".") + if(suffixIndex<1){ + throw new RuntimeException("Invalid filename, must have a suffix: [" +newName+"]") + } + String suffix = newName.substring(suffixIndex) + String updatedName = directoryName.replaceAll(" ","_") + suffix +// /opt/temporary/apollo/6503-nf_test3/raw || test2 || volvox-sorted.bam +// /opt/temporary/apollo/6503-nf_test3/raw || test2 .bam + String destinationFileName = path + File.separator + updatedName + File destinationFile = new File(destinationFileName) + try { + println "NEW NAME transferring track file to ${destinationFileName}" + file.transferTo(destinationFile) +// destinationFile.renameTo(new File()) + println "NEW NAME DONE transferringfile to ${destinationFileName.size()}" + + } catch (Exception e) { + println e.message + } + } + def store(CommonsMultipartFile file, String path, String directoryName = null, boolean tempDir = false) { File pathFile = new File(path) @@ -182,10 +208,12 @@ class FileService { File destinationFile = new File(destinationFileName) try { - log.debug "transferring track file to ${destinationFileName}" + println "transferring track file to ${destinationFileName}" file.transferTo(destinationFile) + println "DONE transferringfile to ${destinationFileName.size()}" + } catch (Exception e) { - log.error e.message + println e.message } } diff --git a/grails-app/services/org/bbop/apollo/TrackService.groovy b/grails-app/services/org/bbop/apollo/TrackService.groovy index c6c607aeec..f9f97f02b4 100644 --- a/grails-app/services/org/bbop/apollo/TrackService.groovy +++ b/grails-app/services/org/bbop/apollo/TrackService.groovy @@ -483,6 +483,26 @@ class TrackService { return null } + /** + * + * @param tracksArray + * @param trackName + * @return + */ + @NotTransactional + def removeTrackFromArray(JSONArray tracksArray, String trackName) { + JSONArray returnArray = new JSONArray() + for (int i = 0; i < tracksArray.size(); i++) { + JSONObject obj = tracksArray.getJSONObject(i) + println "obj ${obj.label} vs ${trackName}" + if (obj.getString("label") != trackName) { + returnArray.add(obj) + } + } + + return returnArray + } + /** * Removes plugins included in annot.json (which is just WebApollo) * @param pluginsArray diff --git a/install_jbrowse.sh b/install_jbrowse.sh index 49c7986865..284ce3088b 100755 --- a/install_jbrowse.sh +++ b/install_jbrowse.sh @@ -1,6 +1,6 @@ #!/bin/bash -./apollo install-tools +./apollo jbrowse-tools #done_message () { # if [ $? == 0 ]; then diff --git a/sample-h2-apollo-config.groovy b/sample-h2-apollo-config.groovy index 4290bd8359..df58dd26e6 100644 --- a/sample-h2-apollo-config.groovy +++ b/sample-h2-apollo-config.groovy @@ -77,7 +77,7 @@ environments { //jbrowse { // git { // url= "https://github.com/GMOD/jbrowse" -// tag = "1.16.2-release" +// tag = "1.16.3-release" //// branch = "dev" //// hash = "09b71099bf73c50d37a0e911baf06b4975e3f6ca" // alwaysPull = true diff --git a/sample-mysql-apollo-config.groovy b/sample-mysql-apollo-config.groovy index bd0fbd4367..d8f6ad1855 100644 --- a/sample-mysql-apollo-config.groovy +++ b/sample-mysql-apollo-config.groovy @@ -76,7 +76,7 @@ environments { //jbrowse { // git { // url= "https://github.com/GMOD/jbrowse" -// tag = "1.16.2-release" +// tag = "1.16.3-release" //// branch = "dev" //// hash = "09b71099bf73c50d37a0e911baf06b4975e3f6ca" // alwaysPull = true diff --git a/sample-postgres-apollo-config.groovy b/sample-postgres-apollo-config.groovy index 242c4caed9..61ef34d8b7 100644 --- a/sample-postgres-apollo-config.groovy +++ b/sample-postgres-apollo-config.groovy @@ -121,7 +121,7 @@ environments { //jbrowse { // git { // url= "https://github.com/GMOD/jbrowse" -// tag = "1.16.2-release" +// tag = "1.16.3-release" //// branch = "dev" //// hash = "09b71099bf73c50d37a0e911baf06b4975e3f6ca" // alwaysPull = true diff --git a/src/gwt/org/bbop/apollo/gwt/client/TrackPanel.java b/src/gwt/org/bbop/apollo/gwt/client/TrackPanel.java index 8aa3f83997..dddc2b0e03 100644 --- a/src/gwt/org/bbop/apollo/gwt/client/TrackPanel.java +++ b/src/gwt/org/bbop/apollo/gwt/client/TrackPanel.java @@ -4,6 +4,7 @@ import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; +import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyUpEvent; @@ -17,24 +18,32 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.*; +import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.view.client.ListDataProvider; import org.bbop.apollo.gwt.client.dto.TrackInfo; import org.bbop.apollo.gwt.client.event.OrganismChangeEvent; import org.bbop.apollo.gwt.client.event.OrganismChangeEventHandler; +import org.bbop.apollo.gwt.client.rest.OrganismRestService; +import org.bbop.apollo.gwt.client.rest.RestService; import org.bbop.apollo.gwt.client.rest.UserRestService; +import org.bbop.apollo.gwt.client.track.TrackConfigurationTemplate; import org.bbop.apollo.gwt.shared.FeatureStringEnum; +import org.bbop.apollo.gwt.shared.track.TrackTypeEnum; import org.gwtbootstrap3.client.shared.event.HiddenEvent; import org.gwtbootstrap3.client.shared.event.HiddenHandler; import org.gwtbootstrap3.client.shared.event.ShowEvent; import org.gwtbootstrap3.client.shared.event.ShowHandler; import org.gwtbootstrap3.client.ui.*; +import org.gwtbootstrap3.client.ui.Button; import org.gwtbootstrap3.client.ui.Panel; import org.gwtbootstrap3.client.ui.TextBox; import org.gwtbootstrap3.client.ui.constants.HeadingSize; import org.gwtbootstrap3.client.ui.constants.Pull; import org.gwtbootstrap3.client.ui.constants.Toggle; import org.gwtbootstrap3.extras.bootbox.client.Bootbox; +import org.gwtbootstrap3.extras.bootbox.client.callback.ConfirmCallback; import org.gwtbootstrap3.extras.toggleswitch.client.ui.ToggleSwitch; import java.util.ArrayList; @@ -63,6 +72,8 @@ interface TrackUiBinder extends UiBinder { HTML trackCount; @UiField HTML trackDensity; + @UiField + Button addTrackButton; @UiField ToggleSwitch trackListToggle; @@ -73,7 +84,62 @@ interface TrackUiBinder extends UiBinder { Tree optionTree; @UiField static PanelGroup dataGrid; - + @UiField + static Modal addTrackModal; + @UiField + com.google.gwt.user.client.ui.Button saveNewTrack; + @UiField + Button cancelNewTrack; + @UiField + FileUpload uploadTrackFile; + @UiField + FileUpload uploadTrackFileIndex; + @UiField + FormPanel newTrackForm; + @UiField + TextArea configuration; + @UiField + Hidden hiddenOrganism; + @UiField + FlowPanel flowPanel; + @UiField + AnchorListItem selectBam; + @UiField + AnchorListItem selectBigWig; + @UiField + AnchorListItem selectGFF3; + @UiField + AnchorListItem selectGFF3Tabix; + @UiField + AnchorListItem selectVCF; + @UiField + AnchorListItem selectBamCanvas; + @UiField + AnchorListItem selectBigWigXY; + // @UiField +// AnchorListItem selectGFF3Canvas; + @UiField + AnchorListItem selectVCFCanvas; + @UiField + com.google.gwt.user.client.ui.TextBox trackFileName; + @UiField + Button configurationButton; + @UiField + TabLayoutPanel southTabs; + @UiField + Container northContainer; + @UiField + HTML trackNameHTML; + @UiField + HTML trackConfigurationHTML; + @UiField + HTML trackFileHTML; + @UiField + HTML trackFileIndexHTML; + @UiField + HTML categoryNameHTML; + @UiField + com.google.gwt.user.client.ui.TextBox categoryName; public static ListDataProvider dataProvider = new ListDataProvider<>(); private static List trackInfoList = new ArrayList<>(); @@ -84,15 +150,55 @@ interface TrackUiBinder extends UiBinder { private static Map checkBoxMap = new TreeMap<>(); private static Map trackBodyMap = new TreeMap<>(); + public TrackPanel() { exportStaticMethod(); Widget rootElement = ourUiBinder.createAndBindUi(this); initWidget(rootElement); - dataGrid.setWidth("100%"); + Scheduler.get().scheduleFixedDelay(new Scheduler.RepeatingCommand() { + @Override + public boolean execute() { + if (canAdminTracks()) { + addTrackButton.setVisible(true); + configuration.getElement().setPropertyString("placeholder", "Enter configuration data"); + trackFileName.getElement().setPropertyString("placeholder", "Enter track name"); + categoryName.getElement().setPropertyString("placeholder", "Enter category name"); + newTrackForm.setEncoding(FormPanel.ENCODING_MULTIPART); + newTrackForm.setMethod(FormPanel.METHOD_POST); + newTrackForm.setAction(RestService.fixUrl("organism/addTrackToOrganism")); + } else { + GWT.log("can not admin tracks"); + } + return false; + } + }, 400); + + newTrackForm.addSubmitHandler(new FormPanel.SubmitHandler() { + @Override + public void onSubmit(FormPanel.SubmitEvent event) { + addTrackModal.hide(); + } + }); + newTrackForm.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() { + @Override + public void onSubmitComplete(FormPanel.SubmitCompleteEvent event) { + loadTracks(300); + Bootbox.confirm("Track '"+trackFileName.getText()+"' added successfully. Reload to see?", new ConfirmCallback() { + @Override + public void callback(boolean result) { + if (result) { + Window.Location.reload(); + } + resetNewTrackModel(); + } + }); + } + }); + Annotator.eventBus.addHandler(OrganismChangeEvent.TYPE, new OrganismChangeEventHandler() { @Override public void onOrganismChanged(OrganismChangeEvent authenticationEvent) { @@ -102,6 +208,30 @@ public void onOrganismChanged(OrganismChangeEvent authenticationEvent) { } + private static boolean canAdminTracks() { + return MainPanel.getInstance().isCurrentUserAdmin(); + } + + private String checkForm() { + if (configurationButton.getText().startsWith("Choosing")) { + return "Specify a track type."; + } + if (configuration.getText().trim().length() < 10) { + return "Bad configuration."; + } + try { + JSONParser.parseStrict(configuration.getText().trim()); + } catch (Exception e) { + return "Invalid JSON:\n" + e.getMessage() + "\n" + configuration.getText().trim(); + } + if (uploadTrackFile.getFilename().trim().length() == 0) { + return "Data file needs to be specified."; + } + + return null; + } + + public void loadTracks(int delay) { filteredTrackInfoList.clear(); trackInfoList.clear(); @@ -117,7 +247,7 @@ public boolean execute() { }, delay); } - public void reloadIfEmpty() { + void reloadIfEmpty() { if (dataProvider.getList().isEmpty()) { loadTracks(7000); } @@ -126,6 +256,9 @@ public void reloadIfEmpty() { private void setTrackInfo(TrackInfo selectedObject) { if (selectedObject == null) { + trackName.setVisible(false); + trackType.setVisible(false); + optionTree.setVisible(false); trackName.setText(""); trackType.setText(""); optionTree.clear(); @@ -135,6 +268,9 @@ private void setTrackInfo(TrackInfo selectedObject) { optionTree.clear(); JSONObject jsonObject = selectedObject.getPayload(); setOptionDetails(jsonObject); + trackName.setVisible(true); + trackType.setVisible(true); + optionTree.setVisible(true); } } @@ -173,6 +309,168 @@ private TreeItem generateTreeItem(JSONObject jsonObject) { return treeItem; } + private void setTrackTypeAndUpdate(TrackTypeEnum trackType) { + configurationButton.setText(trackType.toString()); + configuration.setText(TrackConfigurationTemplate.generateForTypeAndKeyAndCategory(trackType, trackFileName.getText(), categoryName.getText()).toString()); + showFileOptions(trackType); + if (trackType.isIndexed()) { + showIndexOptions(trackType); + } else { + hideIndexOptions(); + } + } + + private TrackTypeEnum getTrackType() { + return TrackTypeEnum.valueOf(configurationButton.getText().replaceAll(" ", "_")); + } + + @UiHandler("uploadTrackFile") + public void uploadTrackFile(ChangeEvent event) { + if (uploadTrackFile.getFilename().endsWith(".bam")) { + selectBam(null); + } else if (uploadTrackFile.getFilename().endsWith(".vcf.gz")) { + selectVCF(null); + } else if (uploadTrackFile.getFilename().endsWith(".bw")) { + selectBigWig(null); + } else if (uploadTrackFile.getFilename().endsWith(".gff.gz") || uploadTrackFile.getFilename().endsWith(".gff3.gz")) { + selectGFF3Tabix(null); + } else if (uploadTrackFile.getFilename().endsWith(".gff") || uploadTrackFile.getFilename().endsWith(".gff3")) { + selectGFF3(null); + } else { + Bootbox.alert("Filetype suffix for " + uploadTrackFile.getFilename() + " not recognized."); + } + } + + @UiHandler("trackFileName") + public void updateTrackFileName(KeyUpEvent event) { + configuration.setText(TrackConfigurationTemplate.generateForTypeAndKeyAndCategory(getTrackType(), trackFileName.getText(), categoryName.getText()).toString()); + } + + @UiHandler("cancelNewTrack") + public void cancelNewTrackButtonHandler(ClickEvent clickEvent) { + addTrackModal.hide(); + resetNewTrackModel(); + } + + @UiHandler("saveNewTrack") + public void saveNewTrackButtonHandler(ClickEvent clickEvent) { + String resultMessage = checkForm(); + if (resultMessage == null) { + newTrackForm.submit(); + } else { + Bootbox.alert(resultMessage); + } + } + + private void showFileOptions(TrackTypeEnum typeEnum) { + saveNewTrack.setEnabled(true); + + trackNameHTML.setVisible(true); + trackFileName.setVisible(true); + + categoryName.setVisible(true); + categoryNameHTML.setVisible(true); + + trackConfigurationHTML.setVisible(true); + configuration.setVisible(true); + + trackFileHTML.setVisible(true); + uploadTrackFile.setVisible(true); + + trackFileHTML.setText("*." + typeEnum.getSuffix()); + } + + private void hideIndexOptions() { + trackFileIndexHTML.setVisible(false); + uploadTrackFileIndex.setVisible(false); + trackFileIndexHTML.setText(""); + } + + private void showIndexOptions(TrackTypeEnum typeEnum) { + trackFileIndexHTML.setVisible(true); + uploadTrackFileIndex.setVisible(true); + + trackFileIndexHTML.setText("*." + typeEnum.getSuffixIndex()); + } + + private void resetNewTrackModel() { + configurationButton.setText("Select Track Type"); + + saveNewTrack.setEnabled(false); + + trackNameHTML.setVisible(false); + trackFileName.setVisible(false); + + categoryName.setVisible(false); + categoryNameHTML.setVisible(false); + + trackConfigurationHTML.setVisible(false); + configuration.setVisible(false); + + trackFileHTML.setVisible(false); + uploadTrackFile.setVisible(false); + trackFileIndexHTML.setVisible(false); + uploadTrackFileIndex.setVisible(false); + + newTrackForm.reset(); + } + + @UiHandler("addTrackButton") + public void addTrackButtonHandler(ClickEvent clickEvent) { + hiddenOrganism.setValue(MainPanel.getInstance().getCurrentOrganism().getId()); + addTrackModal.show(); + } + + @UiHandler("selectBam") + public void selectBam(ClickEvent clickEvent) { + setTrackTypeAndUpdate(TrackTypeEnum.BAM); + } + + @UiHandler("selectBamCanvas") + public void setSelectBamCanvas(ClickEvent clickEvent) { + setTrackTypeAndUpdate(TrackTypeEnum.BAM_CANVAS); + } + + + @UiHandler("selectBigWig") + public void selectBigWig(ClickEvent clickEvent) { + setTrackTypeAndUpdate(TrackTypeEnum.BIGWIG_HEAT_MAP); + } + + @UiHandler("selectBigWigXY") + public void selectBigWigXY(ClickEvent clickEvent) { + setTrackTypeAndUpdate(TrackTypeEnum.BIGWIG_XY); + } + + @UiHandler("selectGFF3") + public void selectGFF3(ClickEvent clickEvent) { + setTrackTypeAndUpdate(TrackTypeEnum.GFF3); + } + +// @UiHandler("selectGFF3Canvas") +// public void selectGFF3Canvas(ClickEvent clickEvent) { +// setTrackTypeAndUpdate(TrackTypeEnum.GFF3_CANVAS); +// } + + @UiHandler("selectGFF3Tabix") + public void selectGFF3Tabix(ClickEvent clickEvent) { + setTrackTypeAndUpdate(TrackTypeEnum.GFF3_TABIX); + } + +// @UiHandler("selectGFF3TabixCanvas") +// public void selectGFF3TabixCanvas(ClickEvent clickEvent) { +// setTrackTypeAndUpdate(TrackTypeEnum.GFF3_TABIX_CANVAS); +// } + + @UiHandler("selectVCF") + public void selectVCF(ClickEvent clickEvent) { + setTrackTypeAndUpdate(TrackTypeEnum.VCF); + } + + @UiHandler("selectVCFCanvas") + public void selectVCFCanvas(ClickEvent clickEvent) { + setTrackTypeAndUpdate(TrackTypeEnum.VCF_CANVAS); + } @UiHandler("nameSearchBox") public void doSearch(KeyUpEvent keyUpEvent) { @@ -185,7 +483,7 @@ static void filterList() { if (trackInfo.getName().toLowerCase().contains(text.toLowerCase()) && !isReferenceSequence(trackInfo) && !isAnnotationTrack(trackInfo)) { - Integer filteredIndex = filteredTrackInfoList.indexOf(trackInfo); + int filteredIndex = filteredTrackInfoList.indexOf(trackInfo); if (filteredIndex < 0) { filteredTrackInfoList.add(trackInfo); } else { @@ -198,9 +496,40 @@ static void filterList() { renderFiltered(); } + static void removeTrack(final String label) { + Bootbox.confirm("Remove track " + label + "?", new ConfirmCallback() { + @Override + public void callback(boolean result) { + if (result) { + OrganismRestService.removeTrack( + new RequestCallback() { + @Override + public void onResponseReceived(Request request, Response response) { + Bootbox.confirm("Track '"+label + "' removed, refresh?", new ConfirmCallback() { + @Override + public void callback(boolean result) { + if (result) { + Window.Location.reload(); + } + } + }); + } + + @Override + public void onError(Request request, Throwable exception) { + Bootbox.alert("Error removing track: " + exception.getMessage()); + } + } + , MainPanel.getInstance().getCurrentOrganism(), label); + } + } + }); + } + static class TrackBodyPanel extends PanelBody { private final TrackInfo trackInfo; + private final InputGroupAddon label = new InputGroupAddon(); public TrackBodyPanel(TrackInfo trackInfo) { @@ -210,7 +539,7 @@ public TrackBodyPanel(TrackInfo trackInfo) { private void decorate() { - InputGroup inputGroup = new InputGroup(); + final InputGroup inputGroup = new InputGroup(); addStyleName("track-entry"); final CheckBoxButton selected = new CheckBoxButton(); selected.setValue(trackInfo.getVisible()); @@ -219,10 +548,46 @@ private void decorate() { inputGroupButton.add(selected); inputGroup.add(inputGroupButton); - InputGroupAddon label = new InputGroupAddon(); - label.add(new HTML(trackInfo.getName())); +// final InputGroupAddon label = new InputGroupAddon(); + HTML trackNameHTML = new HTML(trackInfo.getName()); + trackNameHTML.addStyleName("text-html-left"); + label.add(trackNameHTML); label.addStyleName("text-left"); inputGroup.add(label); + if (trackInfo.getApollo() != null && canAdminTracks()) { +// InputGroupAddon editLabel = new InputGroupAddon(); + Button removeButton = new Button("Remove"); + removeButton.setPull(Pull.RIGHT); + removeButton.addStyleName("track-edit-button"); + removeButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + removeTrack(trackInfo.getName()); +// Window.alert("removing"); + } + }); + label.add(removeButton); +// Button editButton = new Button("Edit"); +// editButton.setPull(Pull.RIGHT); +// editButton.addStyleName("track-edit-button"); +// editButton.addClickHandler(new ClickHandler() { +// @Override +// public void onClick(ClickEvent event) { +// Window.alert("editing"); +// } +// }); +// label.add(editButton); +// Button hideButton = new Button("Hide"); +// hideButton.setPull(Pull.RIGHT); +// hideButton.addStyleName("track-edit-button"); +// hideButton.addClickHandler(new ClickHandler() { +// @Override +// public void onClick(ClickEvent event) { +// Window.alert("hiding from public"); +// } +// }); +// label.add(hideButton); + } add(inputGroup); @@ -242,6 +607,8 @@ public void onValueChange(ValueChangeEvent event) { label.addDomHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { + // clear previous labels +// label.addStyleName("selected-track-link"); MainPanel.getTrackPanel().setTrackInfo(trackInfo); } }, ClickEvent.getType()); @@ -442,13 +809,14 @@ public List getTrackList() { public static void updateTracks(JSONArray array) { trackInfoList.clear(); - for (int i = 0; i < array.size(); i++) { JSONObject object = array.get(i).isObject(); TrackInfo trackInfo = new TrackInfo(); // track label can never be null, but key can be trackInfo.setName(object.get("key") == null ? object.get("label").isString().stringValue() : object.get("key").isString().stringValue()); + if (object.get("apollo") != null) trackInfo.setApollo(object.get("apollo").isObject()); + if (object.get("label") != null) trackInfo.setLabel(object.get("label").isString().stringValue()); else Bootbox.alert("Track label should not be null, please check your tracklist"); @@ -457,6 +825,9 @@ public static void updateTracks(JSONArray array) { if (object.get("urlTemplate") != null) trackInfo.setUrlTemplate(object.get("urlTemplate").isString().stringValue()); + if (object.get("storeClass") != null) + trackInfo.setStoreClass(object.get("storeClass").isString().stringValue()); + if (object.get("visible") != null) trackInfo.setVisible(object.get("visible").isBoolean().booleanValue()); else trackInfo.setVisible(false); @@ -482,13 +853,11 @@ public void updateTrackToggle(Boolean val) { RequestCallback requestCallback = new RequestCallback() { @Override public void onResponseReceived(Request request, Response response) { - JSONValue v ; + JSONValue v; try { v = JSONParser.parseStrict(response.getText()); } catch (Exception e) { - GWT.log("No organism present: "+response.getText()); - return ; -// e.printStackTrace(); + return; } JSONObject o = v.isObject(); if (o.containsKey(FeatureStringEnum.ERROR.getValue())) { diff --git a/src/gwt/org/bbop/apollo/gwt/client/TrackPanel.ui.xml b/src/gwt/org/bbop/apollo/gwt/client/TrackPanel.ui.xml index ed1869d1d0..e356f3f61d 100644 --- a/src/gwt/org/bbop/apollo/gwt/client/TrackPanel.ui.xml +++ b/src/gwt/org/bbop/apollo/gwt/client/TrackPanel.ui.xml @@ -2,17 +2,14 @@ xmlns:gwt="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:org.gwtbootstrap3.client.ui" xmlns:toggle="urn:import:org.gwtbootstrap3.extras.toggleswitch.client.ui" - xmlns:cellview="urn:import:com.google.gwt.user.cellview.client" - > +> .northPanel { padding: 0px; margin: 10px; } - - - .tableKeyName{ + .tableKeyName { font-weight: bolder; } @@ -23,16 +20,80 @@ outline: none; } + .buttonRow { + padding-top: 10px; + padding-left: 12px; + } + + .addTrackModal { + + } + + .areaFile { + } - - + + + + + + + Add Track + + + + + + + + BAM + BAM Canvas + BigWig HeatMap + BigWig XY + GFF3 + + GFF3 Tabix + + VCF + VCF Canvas + + + + + + + + + + + + + + + + + + + + + + Upload + + + + - + - - + + + + + @@ -44,75 +105,62 @@ - - + + Details - - - - - - - - - - - - - Type - - - - - - - - - - Configuration - - - - - - + + + + + + + + + + + + + + + + + + + + + + Configuration + + + + + + - - - - Feature Count - - - - - - - - - - Feature Density - - - - - - - + + + + Feature Count + + + + + + + + + + Feature Density + + + + + + + + - - - - - - - - - - - - - diff --git a/src/gwt/org/bbop/apollo/gwt/client/dto/OrganismInfo.java b/src/gwt/org/bbop/apollo/gwt/client/dto/OrganismInfo.java index f6e5157840..86a079571d 100644 --- a/src/gwt/org/bbop/apollo/gwt/client/dto/OrganismInfo.java +++ b/src/gwt/org/bbop/apollo/gwt/client/dto/OrganismInfo.java @@ -52,11 +52,14 @@ public void setBlatDb(String blatdb) { this.blatdb = blatdb; } - public boolean getPublicMode() { + public Boolean getPublicMode() { + if(publicMode==null){ + return false ; + } return publicMode; } - public void setPublicMode(boolean pm) { + public void setPublicMode(Boolean pm) { this.publicMode=pm; } @@ -134,6 +137,9 @@ public boolean isCurrent() { public Boolean getObsolete() { + if(obsolete==null){ + return false ; + } return obsolete; } diff --git a/src/gwt/org/bbop/apollo/gwt/client/dto/TrackInfo.java b/src/gwt/org/bbop/apollo/gwt/client/dto/TrackInfo.java index d2c5f39d15..f9357c6655 100644 --- a/src/gwt/org/bbop/apollo/gwt/client/dto/TrackInfo.java +++ b/src/gwt/org/bbop/apollo/gwt/client/dto/TrackInfo.java @@ -16,6 +16,8 @@ public class TrackInfo implements Comparable { private Boolean visible; private String urlTemplate ; private String category; + private String storeClass ; + private JSONObject apollo; private JSONObject payload ; @@ -82,6 +84,14 @@ public void setCategory(String category) { this.category = category; } + public String getStoreClass() { + return storeClass; + } + + public void setStoreClass(String storeClass) { + this.storeClass = storeClass; + } + public String getStandardCategory(){ if(category==null || category.trim().length()==0){ return TRACK_UNCATEGORIZED ; @@ -119,4 +129,12 @@ public int hashCode() { result = 31 * result + (getCategory() != null ? getCategory().hashCode() : 0); return result; } + + public JSONObject getApollo() { + return apollo; + } + + public void setApollo(JSONObject apollo) { + this.apollo = apollo; + } } diff --git a/src/gwt/org/bbop/apollo/gwt/client/rest/OrganismRestService.java b/src/gwt/org/bbop/apollo/gwt/client/rest/OrganismRestService.java index 4c5b2476d6..8b5216bbd3 100644 --- a/src/gwt/org/bbop/apollo/gwt/client/rest/OrganismRestService.java +++ b/src/gwt/org/bbop/apollo/gwt/client/rest/OrganismRestService.java @@ -1,5 +1,6 @@ package org.bbop.apollo.gwt.client.rest; +import com.google.gwt.core.client.GWT; import com.google.gwt.http.client.*; import com.google.gwt.json.client.*; import com.google.gwt.user.client.Window; @@ -92,6 +93,14 @@ public static void deleteOrganism(RequestCallback requestCallback, OrganismInfo RestService.sendRequest(requestCallback,"organism/deleteOrganism", OrganismInfoConverter.convertOrganismInfoToJSONObject(organismInfo)); } + public static void removeTrack(RequestCallback requestCallback, OrganismInfo organismInfo,String trackName) { + JSONObject data = new JSONObject(); + JSONObject organismObject = OrganismInfoConverter.convertOrganismInfoToJSONObject(organismInfo); + data.put(FeatureStringEnum.ORGANISM.getValue(),organismObject); + data.put(FeatureStringEnum.TRACK_LABEL.getValue(),new JSONString(trackName)); + RestService.sendRequest(requestCallback,"organism/removeTrackFromOrganism", data); + } + public static void switchOrganismById(String newOrganismId) { final LoadingDialog loadingDialog = new LoadingDialog(); diff --git a/src/gwt/org/bbop/apollo/gwt/client/rest/RestService.java b/src/gwt/org/bbop/apollo/gwt/client/rest/RestService.java index 2861e7f371..b2ea8807f9 100644 --- a/src/gwt/org/bbop/apollo/gwt/client/rest/RestService.java +++ b/src/gwt/org/bbop/apollo/gwt/client/rest/RestService.java @@ -29,7 +29,7 @@ public static void sendRequest(RequestCallback requestCallback, String url, Stri sendRequest(requestCallback, url, data, RequestBuilder.POST); } - public static void sendRequest(RequestCallback requestCallback, String url, String data, RequestBuilder.Method method) { + public static String fixUrl(String url){ String rootUrl = Annotator.getRootUrl(); if (!url.startsWith(rootUrl)) { url = rootUrl + url; @@ -41,6 +41,11 @@ public static void sendRequest(RequestCallback requestCallback, String url, Stri url += "="; url += Annotator.getClientToken(); } + return url ; + } + + public static void sendRequest(RequestCallback requestCallback, String url, String data, RequestBuilder.Method method) { + url = fixUrl(url); RequestBuilder builder = new RequestBuilder(method, URL.encode(url)); if (data != null) { builder.setRequestData(data); diff --git a/src/gwt/org/bbop/apollo/gwt/client/track/TrackConfigurationTemplate.java b/src/gwt/org/bbop/apollo/gwt/client/track/TrackConfigurationTemplate.java new file mode 100644 index 0000000000..1c7fa33ff8 --- /dev/null +++ b/src/gwt/org/bbop/apollo/gwt/client/track/TrackConfigurationTemplate.java @@ -0,0 +1,197 @@ +package org.bbop.apollo.gwt.client.track; + +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONString; +import org.bbop.apollo.gwt.shared.track.TrackTypeEnum; + +public class TrackConfigurationTemplate { + + String storeClass; + String urlTemplate; + String label; + String type; + String key; + String category; + TrackTypeEnum typeEnum; + // key is entered + + + public TrackConfigurationTemplate(String storeClass, + String urlTemplate, + String label, + String type, + String key, + String category, + TrackTypeEnum typeEnum + ) { + this.storeClass = storeClass; + this.urlTemplate = urlTemplate; + this.label = label; + this.type = type; + this.key = key; + this.category = category ; + this.typeEnum = typeEnum ; + } + + + JSONObject toJSON() { + JSONObject returnObject = new JSONObject(); + returnObject.put("storeClass", new JSONString(this.storeClass)); + returnObject.put("urlTemplate", new JSONString(this.urlTemplate)); + returnObject.put("label", new JSONString(this.label)); + returnObject.put("type", new JSONString(this.type)); + returnObject.put("key", new JSONString(this.key)); + if(category!=null && category.trim().length()>0){ + returnObject.put("category", new JSONString(this.category)); + } + JSONObject apolloDetails = new JSONObject(); + apolloDetails.put("source", new JSONString("upload")); + apolloDetails.put("type", new JSONString(this.typeEnum.name())); + returnObject.put("apollo", apolloDetails); + return returnObject; + } + + static String generateString() { + String returnString = ""; + for (int i = 0; i < 10; i++) { + returnString += String.valueOf(Math.round(Math.random() * 26)); + } + + return returnString; + } + + + public static JSONObject generateForTypeAndKeyAndCategory(TrackTypeEnum type, String key,String category) { + String randomFileName = key!=null && key.trim().length()>1 ? key : generateString() ; + switch (type) { + case BAM: + return new TrackConfigurationTemplate( + "JBrowse/Store/SeqFeature/BAM", + "raw/"+randomFileName.replaceAll(" ","_")+".bam", + randomFileName, + "JBrowse/View/Track/Alignments", + randomFileName, + category, + type + ).toJSON(); + case BAM_CANVAS: + return new TrackConfigurationTemplate( + "JBrowse/Store/SeqFeature/BAM", + "raw/"+randomFileName.replaceAll(" ","_")+".bam", + randomFileName, + "JBrowse/View/Track/Alignments2", + randomFileName, + category, + type + ).toJSON(); + case BIGWIG_HEAT_MAP: + return new TrackConfigurationTemplate( + "JBrowse/Store/BigWig", + "raw/"+randomFileName.replaceAll(" ","_")+".bw", + randomFileName, + "JBrowse/View/Track/Wiggle/Density", + randomFileName, + category, + type + ).toJSON(); + case BIGWIG_XY: + return new TrackConfigurationTemplate( + "JBrowse/Store/BigWig", + "raw/"+randomFileName.replaceAll(" ","_")+".bw", + randomFileName, + "JBrowse/View/Track/Wiggle/XYPlot", + randomFileName, + category, + type + ).toJSON(); + case VCF: + return new TrackConfigurationTemplate( + "JBrowse/Store/SeqFeature/VCFTabix", + "raw/"+randomFileName.replaceAll(" ","_")+".vcf.gz", + randomFileName, + "JBrowse/View/Track/HTMLVariants", + randomFileName, + category, + type + ).toJSON(); + case VCF_CANVAS: + return new TrackConfigurationTemplate( + "JBrowse/Store/SeqFeature/VCFTabix", + "raw/"+randomFileName.replaceAll(" ","_")+".vcf.gz", + randomFileName, + "JBrowse/View/Track/CanvasVariants", + randomFileName, + category, + type + ).toJSON(); + case GFF3: + return new TrackConfigurationTemplate( + "JBrowse/Store/SeqFeature/GFF3", + "raw/"+randomFileName.replaceAll(" ","_")+".gff", + randomFileName, + "JBrowse/View/Track/HTMLFeatures", + randomFileName, + category, + type + ).toJSON(); + case GFF3_CANVAS: + return new TrackConfigurationTemplate( + "JBrowse/Store/SeqFeature/GFF3", + "raw/"+randomFileName.replaceAll(" ","_")+".gff", + randomFileName, + "JBrowse/View/Track/CanvasFeatures", + randomFileName, + category, + type + ).toJSON(); + case GFF3_TABIX: + return new TrackConfigurationTemplate( + "JBrowse/Store/SeqFeature/GFF3Tabix", + "raw/"+randomFileName.replaceAll(" ","_")+".gff.gz", + randomFileName, + "JBrowse/View/Track/HTMLFeatures", + randomFileName, + category, + type + ).toJSON(); + case GFF3_TABIX_CANVAS: + return new TrackConfigurationTemplate( + "JBrowse/Store/SeqFeature/GFF3Tabix", + "raw/"+randomFileName.replaceAll(" ","_")+".gff.gz", + randomFileName, + "JBrowse/View/Track/CanvasFeatures", + randomFileName, + category, + type + ).toJSON(); + } + + return null; + } + + public final static String bamDefault = "" + + "{\n" + + " \"key\":\"\",\n" + + " \"storeClass\" : \"JBrowse/Store/SeqFeature/BAM\",\n" + + "\"urlTemplate\" : \"raw/.bam\",\n" + + " \"label\" : \"\",\n" + + " \"type\" : \"JBrowse/View/Track/Alignments2\"\n" + + "}\n" + + "\n"; + public final static String bamCanvasDefault = "" + + "{\n" + + " \"key\":\"\",\n" + + " \"storeClass\" : \"JBrowse/Store/SeqFeature/BAM\",\n" + + "\"urlTemplate\" : \"raw/.bam\",\n" + + " \"label\" : \"\",\n" + + " \"type\" : \"JBrowse/View/Track/Alignments2\"\n" + + "}\n" + + "\n"; + public final static String bigWig = ""; + public final static String bigWigXY = ""; + public final static String vcf = ""; + public final static String vcfCanvas = ""; + public final static String gff3Default = ""; + public final static String gff3CanvasDefault = ""; + +} diff --git a/src/gwt/org/bbop/apollo/gwt/public/theme.css b/src/gwt/org/bbop/apollo/gwt/public/theme.css index d787a16a09..a076419a8c 100644 --- a/src/gwt/org/bbop/apollo/gwt/public/theme.css +++ b/src/gwt/org/bbop/apollo/gwt/public/theme.css @@ -5,6 +5,9 @@ .input-group-addon { font-size: 12px !important; + margin-bottom: 0 !important; + padding-bottom: 0 !important; + padding-top: 0 !important; } .btn { @@ -14,7 +17,7 @@ .snackbarRight { position: fixed; right: 10px; - top :48%; + top: 48%; z-index: 1000; opacity: 80; /*rotation: 90deg;*/ @@ -48,19 +51,44 @@ padding-top: 1px !important; padding-bottom: 5px !important; } + +.track-edit-button { + padding-bottom: 1px !important; + padding-top: 0 !important; + padding-left: 5px !important; + padding-right: 5px !important; + margin: 0 !important; + display: inline; + height: 15px; + +} + .track-header { display: inline; cursor: pointer; font-size: medium; } +.text-html-left { + padding: 0; + margin: 0; + display: inline; +} + .text-left { text-align: left !important; background-color: white !important; + padding-top: 4px !important; } .panel-select { - background-color: #f5f5f5 !important; + background-color: #f5f5f5 !important; border: none !important; padding: 0 0 0 5px !important; +} + +.selected-track-link { + font-weight: bolder; + background-color: lightgrey !important; + color: cadetblue !important; } \ No newline at end of file diff --git a/src/gwt/org/bbop/apollo/gwt/shared/FeatureStringEnum.java b/src/gwt/org/bbop/apollo/gwt/shared/FeatureStringEnum.java index bd98bd0153..d0470f168a 100644 --- a/src/gwt/org/bbop/apollo/gwt/shared/FeatureStringEnum.java +++ b/src/gwt/org/bbop/apollo/gwt/shared/FeatureStringEnum.java @@ -140,6 +140,8 @@ public enum FeatureStringEnum { LABEL, URL_TEMPLATE("urlTemplate"), TRACK_DATA("trackData"), + TRACK_FILE("trackFile"), + TRACK_FILE_INDEX("trackFileIndex"), TRACK_CONFIG("trackConfig"), TRACK_LABEL("trackLabel"), CREATOR("creator"), diff --git a/src/gwt/org/bbop/apollo/gwt/shared/track/TrackTypeEnum.java b/src/gwt/org/bbop/apollo/gwt/shared/track/TrackTypeEnum.java new file mode 100644 index 0000000000..8e4b873008 --- /dev/null +++ b/src/gwt/org/bbop/apollo/gwt/shared/track/TrackTypeEnum.java @@ -0,0 +1,44 @@ +package org.bbop.apollo.gwt.shared.track; + +public enum TrackTypeEnum { + BAM("bam","bam.bai"), + BAM_CANVAS("bam","bam.bai"), + BIGWIG_HEAT_MAP("*bw"), + BIGWIG_XY("bw"), + VCF("vcf.gz","vcf.gz.tbi"), + VCF_CANVAS("vcf.gz","vcf.gz.tbi"), + GFF3("gff"), + GFF3_CANVAS("gff"), + GFF3_TABIX("gff.gz","gff.gz.tbi"), + GFF3_TABIX_CANVAS("gff.gz","gff.gz.tbi"); + + private String suffix ; + private String suffixIndex ; + + TrackTypeEnum(String suffix){ + this.suffix = suffix; + this.suffixIndex = null ; + } + + TrackTypeEnum(String suffix,String suffixIndex){ + this.suffix = suffix; + this.suffixIndex = suffixIndex; + } + + public boolean isIndexed() { + return this.suffixIndex!=null ; + } + + public String getSuffix() { + return suffix; + } + + public String getSuffixIndex() { + return suffixIndex; + } + + @Override + public String toString() { + return name().replaceAll("_"," "); + } +}