diff options
Diffstat (limited to 'idrop-web/grails-app')
20 files changed, 1237 insertions, 16 deletions
diff --git a/idrop-web/grails-app/conf/BuildConfig.groovy b/idrop-web/grails-app/conf/BuildConfig.groovy index bfa180a..4faa39c 100755 --- a/idrop-web/grails-app/conf/BuildConfig.groovy +++ b/idrop-web/grails-app/conf/BuildConfig.groovy @@ -28,11 +28,15 @@ grails.project.dependency.resolution = { test 'org.mockito:mockito-all:1.8.1' compile 'commons-io:commons-io:2.1' provided 'junit:junit:4.8.1' - compile ('org.irods.jargon:jargon-core:3.3.1-SNAPSHOT') { excludes ([group:'org.jglobus'])} - compile ('org.irods.jargon:jargon-data-utils:3.3.1-SNAPSHOT') { excludes ([group:'org.jglobus'])} - compile ('org.irods.jargon:jargon-ticket:3.3.1-SNAPSHOT') { excludes ([group:'org.jglobus'])} - compile ('org.irods.jargon:jargon-user-profile:3.3.1-SNAPSHOT') { excludes ([group:'org.jglobus'])} - compile ('org.irods.jargon:jargon-user-tagging:3.3.1-SNAPSHOT') { excludes ([group:'org.jglobus'])} + compile ('org.irods.jargon:jargon-core:3.3.3-SNAPSHOT') { excludes ([group:'org.jglobus'])} + compile ('org.irods.jargon:jargon-data-utils:3.3.3-SNAPSHOT') { excludes ([group:'org.jglobus'])} + compile ('org.irods.jargon:jargon-ticket:3.3.3-SNAPSHOT') { excludes ([group:'org.jglobus'])} + compile ('org.irods.jargon:jargon-user-profile:3.3.3-SNAPSHOT') { excludes ([group:'org.jglobus'])} + compile ('org.irods.jargon:jargon-user-tagging:3.3.3-SNAPSHOT') { excludes ([group:'org.jglobus'])} + compile ('org.irods.jargon:jargon-workflow:3.3.3-SNAPSHOT') { excludes ([group:'org.jglobus'])} + compile ('org.irods.jargon:jargon-ruleservice:3.3.3-SNAPSHOT') { excludes ([group:'org.jglobus'])} + + provided 'javax.servlet:servlet-api:2.5' compile 'org.jsoup:jsoup:0.2.2' diff --git a/idrop-web/grails-app/conf/Config.groovy b/idrop-web/grails-app/conf/Config.groovy index 9b743cc..50d0426 100755 --- a/idrop-web/grails-app/conf/Config.groovy +++ b/idrop-web/grails-app/conf/Config.groovy @@ -48,7 +48,7 @@ environments { idrop.config.idrop.lite.use.applet.dir=false */ -idrop.config.idrop.lite.applet.jar="idrop-lite-2.0.1-SNAPSHOT-jar-with-dependencies.jar" +idrop.config.idrop.lite.applet.jar="idrop-lite-b964-SNAPSHOT-jar-with-dependencies.jar" idrop.config.idrop.lite.codebase="http://iren-web.renci.org/idrop-snapshot" idrop.config.idrop.lite.use.applet.dir=false diff --git a/idrop-web/grails-app/conf/spring/resources.groovy b/idrop-web/grails-app/conf/spring/resources.groovy index 0e15cc8..d7f25e6 100755 --- a/idrop-web/grails-app/conf/spring/resources.groovy +++ b/idrop-web/grails-app/conf/spring/resources.groovy @@ -7,6 +7,8 @@ beans = { sharingService(org.irods.mydrop.service.SharingService) { irodsAccessObjectFactory = ref("irodsAccessObjectFactory") } + ruleProcessingService(org.irods.mydrop.service.RuleProcessingService) { irodsAccessObjectFactory = ref("irodsAccessObjectFactory") } + browseController(org.irods.mydrop.controller.BrowseController) { irodsAccessObjectFactory = ref("irodsAccessObjectFactory") @@ -48,6 +50,10 @@ beans = { homeController(org.irods.mydrop.controller.HomeController) { irodsAccessObjectFactory = ref("irodsAccessObjectFactory") } + + ruleController(org.irods.mydrop.controller.RuleController) { + irodsAccessObjectFactory = ref("irodsAccessObjectFactory") + } shoppingCartController(org.irods.mydrop.controller.ShoppingCartController) { diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy index 1fee905..235a682 100755 --- a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy +++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy @@ -14,12 +14,14 @@ import org.irods.jargon.datautils.image.MediaHandlingUtils import org.irods.jargon.datautils.pagination.PagingActions import org.irods.jargon.datautils.pagination.PagingAnalyser import org.irods.jargon.datautils.sharing.* +import org.irods.jargon.ruleservice.composition.Rule import org.irods.jargon.ticket.TicketDistributionContext import org.irods.jargon.usertagging.domain.IRODSStarredFileOrCollection import org.irods.jargon.usertagging.tags.FreeTaggingService import org.irods.jargon.usertagging.tags.IRODSTaggingService import org.irods.jargon.usertagging.tags.TaggingServiceFactory import org.irods.mydrop.config.ViewState +import org.irods.mydrop.service.RuleProcessingService import org.irods.mydrop.service.StarringService import org.irods.mydrop.service.ViewStateService @@ -34,6 +36,7 @@ class BrowseController { TaggingServiceFactory taggingServiceFactory StarringService starringService ViewStateService viewStateService + RuleProcessingService ruleProcessingService IRODSAccount irodsAccount def grailsApplication @@ -769,9 +772,21 @@ class BrowseController { if (commentTag) { comment = commentTag.getTagData() } - + + + Rule rule = null + if (ruleProcessingService.isRule(absPath)) { + log.info("is a .r file, see if a rule") + try { + + rule = ruleProcessingService.loadRuleFromIrodsFile(irodsAccount, absPath) + } catch (JargonException je) { + log.error("exception attempting to load rule, do not show tab") + } + } + mav.view = "dataObjectInfo" - mav.model = [dataObject:retObj,tags:freeTags,comment:comment,getThumbnail:getThumbnail,renderMedia:renderMedia,isDataObject:isDataObject,irodsStarredFileOrCollection:irodsStarredFileOrCollection,showLite:collectionAndDataObjectListAndSearchAO.getIRODSServerProperties().isTheIrodsServerAtLeastAtTheGivenReleaseVersion("rods3.0")] + mav.model = [dataObject:retObj,tags:freeTags,comment:comment,getThumbnail:getThumbnail,renderMedia:renderMedia,isDataObject:isDataObject,irodsStarredFileOrCollection:irodsStarredFileOrCollection,showLite:collectionAndDataObjectListAndSearchAO.getIRODSServerProperties().isTheIrodsServerAtLeastAtTheGivenReleaseVersion("rods3.0"), rule:rule] return mav } else { log.info("getting free tags for collection") diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/FileController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/FileController.groovy index 971b89e..714c505 100755 --- a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/FileController.groovy +++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/FileController.groovy @@ -236,7 +236,7 @@ class FileController { IRODSFile targetFile = irodsFileFactory.instanceIRODSFile(absPath) try { - targetFile.delete() + targetFile.deleteWithForceOption() log.info("file deleted") render(view:"deleteResult", model:[absPath:targetFile.parent]) } catch (CatNoAccessException e) { diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/HomeController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/HomeController.groovy index e5f0337..171f05c 100755 --- a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/HomeController.groovy +++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/HomeController.groovy @@ -59,6 +59,10 @@ class HomeController { // TODO: refactor, add check to see if on same grid, in which case the account should not be changed String mungedIRODSURI = irodsURIString.replaceAll(" ", "&&space&&") URI irodsURI = new URI(mungedIRODSURI) + + log.info("irodsURI ${irodsURI}") + + String filePath = irodsURI.getPath() log.info("irodsFilePath:${filePath}") filePath = filePath.replaceAll("&&space&&", " ") diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/RuleController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/RuleController.groovy new file mode 100644 index 0000000..49c502c --- /dev/null +++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/RuleController.groovy @@ -0,0 +1,437 @@ +package org.irods.mydrop.controller + +import org.irods.jargon.core.connection.IRODSAccount +import org.irods.jargon.core.exception.JargonException +import org.irods.jargon.core.pub.IRODSAccessObjectFactory +import org.irods.jargon.core.pub.RuleProcessingAO +import org.irods.jargon.core.pub.domain.DelayedRuleExecution +import org.irods.jargon.core.rule.IRODSRuleExecResult +import org.irods.jargon.ruleservice.composition.Rule +import org.irods.jargon.ruleservice.formatting.HtmlLogTableFormatter +import org.irods.mydrop.service.RuleProcessingService + + +class RuleController { + + IRODSAccessObjectFactory irodsAccessObjectFactory + IRODSAccount irodsAccount + RuleProcessingService ruleProcessingService + def grailsApplication + + /** + * Interceptor grabs IRODSAccount from the SecurityContextHolder + */ + def beforeInterceptor = [action:this.&auth] + + def auth() { + if(!session["SPRING_SECURITY_CONTEXT"]) { + redirect(controller:"login", action:"login") + return false + } + irodsAccount = session["SPRING_SECURITY_CONTEXT"] + } + + def afterInterceptor = { + log.debug("closing the session") + irodsAccessObjectFactory.closeSession() + } + + /** + * List the contents of the delayed execution queue + * @return + */ + def delayExecQueue() { + log.info("delayExecQueue()") + List<DelayedRuleExecution> rules = ruleProcessingService.listDelayedRuleExecutions(irodsAccount, 0) + render(view:"delayExecQueue", model:[rules:rules]) + } + + + def deleteDelayExecQueue = { + log.info("deleteDelayExecQueue") + + log.info("params: ${params}") + + def rulesToDelete = params['selectDetail'] + + // if nothing selected, just jump out and return a message + if (!rulesToDelete) { + log.info("no rules to delete") + List<DelayedRuleExecution> rules = ruleProcessingService.listDelayedRuleExecutions(irodsAccount, 0) + render(view:"_ruleDelayExecQueueDetails", model:[rules:rules]) + } + + log.info("rulesToDelete: ${rulesToDelete}") + + + RuleProcessingAO ruleAO = irodsAccessObjectFactory.getRuleProcessingAO(irodsAccount) + + if (!rulesToDelete) { + log.info("nothing to delete") + } else if (rulesToDelete instanceof Object[]) { + log.debug "is array" + rulesToDelete.each{ + log.info "ruleToDelete: ${it}" + def idVal = parseRuleId(it) + if (idVal != -1) { + log.info("deleting id:${idVal}") + ruleAO.purgeRuleFromDelayedExecQueue(idVal) + } + } + } else { + log.debug "not array" + log.info "deleting: ${rulesToDelete}..." + def idVal = parseRuleId(rulesToDelete) + if (idVal != -1) { + log.info("deleting id:${idVal}") + ruleAO.purgeRuleFromDelayedExecQueue(idVal) + } + + } + + List<DelayedRuleExecution> rules = ruleProcessingService.listDelayedRuleExecutions(irodsAccount, 0) + + render(view:"_ruleDelayExecQueueDetails", model:[rules:rules]) + + } + + private int parseRuleId(String ruleId) { + if (!ruleId) { + throw new IllegalArgumentException("null ruleId") + } + + int idx = ruleId.indexOf("select-"); + if (idx == -1) { + return -1 + } + + + return Integer.valueOf(ruleId.substring(7)) + + } + + + def updateRule() { + log.info("update rule") + log.info("params:${params}") + + def absPath = params['ruleAbsPath'] + if (absPath == null) { + log.error "no ruleAbsPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + def ruleBody = params['ruleBody'] + if (!ruleBody) { + log.error "no ruleBody in request " + def message = message(code:"error.no.rule.body") + response.sendError(500,message) + } + + List<String> inputParams = new ArrayList<String>() + List<String> inputParamValues = new ArrayList<String>() + List<String> outputParams = new ArrayList<String>() + + def parmKey = params['inputParamName'] + def parmValue = params['inputParamValue'] + + if (parmKey) { + + if (parmKey instanceof Object[]) { + inputParams = parmKey + } else { + inputParams.add(parmKey) + } + + if (!parmValue) { + log.error "no param values for param keys in request " + def message = message(code:"error.invalid.request") + response.sendError(500,message) + } + + if (parmValue instanceof Object[]) { + inputParamValues = parmValue + } else { + inputParamValues.add(parmValue) + } + } + + parmKey = params['outputParamName'] + + if (parmKey) { + + if (parmKey instanceof Object[]) { + outputParams = parmKey + } else { + outputParams.add(parmKey) + } + } + + + List<String> concatParams = new ArrayList<String>() + for (int i = 0; i < inputParams.size(); i++) { + concatParams.add(inputParams[i] + "=" + inputParamValues[i]) + } + + Rule rule = ruleProcessingService.storeRule(irodsAccount, absPath, ruleBody, concatParams, outputParams) + log.info("rule stored:${rule}") + render(view:"_ruleDetails", model:[absPath:absPath, rule:rule]) + } + + def addRuleInputParameterDialog() { + log.info("addRuleInputParameterDialog()") + log.info("params:${params}") + + def absPath = params['ruleAbsPath'] + if (!absPath) { + log.error "no ruleAbsPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + render(view:"addParameterDialog", model:[absPath:absPath, isInputParameter:true]) + } + + def addRuleOutputParameterDialog() { + log.info("addRuleOutputParameterDialog()") + log.info("params:${params}") + + def absPath = params['ruleAbsPath'] + if (!absPath) { + log.error "no ruleAbsPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + render(view:"addParameterDialog", model:[absPath:absPath, isInputParameter:false]) + } + + def deleteRuleInputParameter() { + log.info("deleteRuleInputParameter()") + log.info("params:${params}") + + def absPath = params['ruleAbsPath'] + if (!absPath) { + log.error "no ruleAbsPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + + def parmKey = params['inputParamName'] + if (!parmKey) { + log.error "no parmkey in request " + def message = message(code:"error.invalid.request") + response.sendError(500,message) + } + + Rule rule = ruleProcessingService.deleteInputParam(irodsAccount, absPath, parmKey) + log.info("rule stored:${rule}") + render(view:"_ruleDetails", model:[absPath:absPath, rule:rule]) + } + + def deleteRuleOutputParameter() { + log.info("deleteRuleOutputParameter()") + log.info("params:${params}") + + def absPath = params['ruleAbsPath'] + if (!absPath) { + log.error "no ruleAbsPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + + def parmKey = params['outputParamName'] + if (!parmKey) { + log.error "no parmkey in request " + def message = message(code:"error.invalid.request") + response.sendError(500,message) + } + + Rule rule = ruleProcessingService.deleteOutputParam(irodsAccount, absPath, parmKey) + log.info("rule stored:${rule}") + render(view:"_ruleDetails", model:[absPath:absPath, rule:rule]) + } + + def reloadRule() { + + log.info("reloadRule()") + + def absPath = params['absPath'] + if (absPath == null) { + log.error "no absPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + try { + def rule = ruleProcessingService.loadRuleFromIrodsFile(irodsAccount, absPath) + log.info("found rule:${rule}") + render(view:"_ruleDetails", model:[absPath:absPath, rule:rule]) + } catch (JargonException je) { + log.error("unable to load rule", je) + def message = message(code:"error.unable.to.load.rule") + response.sendError(500,message) + } + } + + + + def index() { + + log.info("index()") + + def absPath = params['absPath'] + if (absPath == null) { + log.error "no absPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + try { + def rule = ruleProcessingService.loadRuleFromIrodsFile(irodsAccount, absPath) + log.info("found rule:${rule}") + render(view:"index", model:[absPath:absPath, rule:rule]) + } catch (JargonException je) { + log.error("unable to load rule", je) + def message = message(code:"error.unable.to.load.rule") + response.sendError(500,message) + } + } + + + def runRule() { + log.info("runRule()") + log.info("params:${params}") + + def absPath = params['ruleAbsPath'] + if (absPath == null) { + log.error "no ruleAbsPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + def ruleBody = params['ruleBody'] + if (!ruleBody) { + log.error "no ruleBody in request " + def message = message(code:"error.no.rule.body") + response.sendError(500,message) + } + + List<String> inputParams = new ArrayList<String>() + List<String> inputParamValues = new ArrayList<String>() + List<String> outputParams = new ArrayList<String>() + + def parmKey = params['inputParamName'] + def parmValue = params['inputParamValue'] + + if (parmKey) { + + if (parmKey instanceof Object[]) { + inputParams = parmKey + } else { + inputParams.add(parmKey) + } + + if (!parmValue) { + log.error "no param values for param keys in request " + def message = message(code:"error.invalid.request") + response.sendError(500,message) + } + + if (parmValue instanceof Object[]) { + inputParamValues = parmValue + } else { + inputParamValues.add(parmValue) + } + } + + parmKey = params['outputParamName'] + + if (parmKey) { + + if (parmKey instanceof Object[]) { + outputParams = parmKey + } else { + outputParams.add(parmKey) + } + } + + List<String> concatParams = new ArrayList<String>() + for (int i = 0; i < inputParams.size(); i++) { + concatParams.add(inputParams[i] + "=" + inputParamValues[i]) + } + + try { + IRODSRuleExecResult ruleResult = ruleProcessingService.executeRule(irodsAccount, ruleBody, concatParams, outputParams) + log.info("rule result:${ruleResult}") + def execOut = HtmlLogTableFormatter.formatAsBootstrap2Table(ruleResult.ruleExecOut, "Std Out") + def errorOut = HtmlLogTableFormatter.formatAsBootstrap2Table(ruleResult.ruleExecErr, "Error Out") + render(view:"ruleResult", model:[ruleResult:ruleResult, execOut:execOut, errorOut:errorOut]) + } catch (JargonException je) { + def message = HtmlLogTableFormatter.formatAsBootstrap2Table(je.message, "Error") + def stackTrace = HtmlLogTableFormatter.formatStackTraceAsBootstrap2Table(je) + render(view:"ruleErrorResult", model:[message:message,stackTrace:stackTrace]) + } + } + + + def submitAddOutputParameterDialog() { + log.info("submitAddOutputParameterDialog") + log.info("params:${params}") + + def absPath = params['ruleAbsPath'] + if (absPath == null) { + log.error "no ruleAbsPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + def parmKey = params['addParameterName'] + + if (!parmKey) { + log.error "no param key in request " + def message = message(code:"error.no.param.key") + response.sendError(500,message) + } + + + Rule rule = ruleProcessingService.addRuleOutputParam(irodsAccount, absPath, parmKey) + log.info("rule stored:${rule}") + render(view:"_ruleDetails", model:[absPath:absPath, rule:rule]) + } + + def submitAddInputParameterDialog() { + log.info("submitAddInputParameterDialog") + log.info("params:${params}") + + def absPath = params['ruleAbsPath'] + if (absPath == null) { + log.error "no ruleAbsPath in request " + def message = message(code:"error.no.path.provided") + response.sendError(500,message) + } + + def parmKey = params['addParameterName'] + def parmValue = params['addParameterValue'] + + if (!parmKey) { + log.error "no param key in request " + def message = message(code:"error.no.param.key") + response.sendError(500,message) + } + + if (!parmValue) { + log.error "no param values for param value in request " + def message = message(code:"error.no.param.value") + response.sendError(500,message) + } + + + Rule rule = ruleProcessingService.addRuleInputParam(irodsAccount, absPath, parmKey, parmValue) + log.info("rule stored:${rule}") + render(view:"_ruleDetails", model:[absPath:absPath, rule:rule]) + } +} diff --git a/idrop-web/grails-app/i18n/messages.properties b/idrop-web/grails-app/i18n/messages.properties index 6d60c26..1ba19c7 100755 --- a/idrop-web/grails-app/i18n/messages.properties +++ b/idrop-web/grails-app/i18n/messages.properties @@ -3,6 +3,9 @@ text.account=Account text.actions=Actions text.add.metadata=Add Metadata text.add.all.to.cart=Add all selected items to the cart +text.add.input.parm=Add input parameter +text.add.output.parm=Add output parameter +text.add.parameter=Add parameter text.add.share=Add a share text.add.to.cart=Add to Cart text.address=Address @@ -40,10 +43,10 @@ text.email=Email text.file=File text.file.name=File Name text.first.name=First Name -text.forward=Page Forward text.find.path.in.tree=Open the path in the tree text.folders.shared.with.me=Folders shared with me text.folders.shared.by.me=Folders shared by me +text.frequency=Frequency text.gallery=Gallery text.grant=Grant public access text.guest.login=Use a guest login @@ -52,8 +55,10 @@ text.home=Home text.host=Host text.id=ID text.info=Info +text.input.parameters=Input Parameters text.idrop.lite=Idrop Lite text.irods.uri=iRODS URI +text.last.exec.time=Last Exec Time text.last.name=Last Name text.length=Size text.login=Login @@ -64,8 +69,11 @@ text.name=Name text.new.folder=New Folder text.object.path=Object Path text.optional=(Optional) +text.output.parameters=Output Parameters text.owner=Owner text.owner.zone=Owner Zone +text.parameter.name=Parameter Name +text.parameter.value=Parameter Value text.parent=Parent Collection text.path=Path text.password=Password @@ -84,6 +92,9 @@ text.replication.status=Replication Status text.rename=Rename text.resource=Resource text.resource.group=Resource Group +text.rule=Rule +text.rule.body=Rule Body +text.run.rule=Run Rule text.search=Search text.set.as.root=Set this as the root of the tree text.set.default.resource=Set default resource @@ -125,7 +136,6 @@ text.ticket.file.limit=Write File Limit text.ticket.url=Ticket URL text.ticket.url.landing=Show landing page text.title=Title -text.tags=Tags text.timestamp=Timestamp text.type=Type text.tools=Tools @@ -143,7 +153,6 @@ text.nickname=Nick Name text.value=Value text.view=View text.zone=Zone -text.new.folder=New Folder # page headings @@ -179,12 +188,17 @@ browse.page.prompt=Select a directory or file to see info and actions # messages error.confirm.password.missing=Confirmation password is null or blank error.nothing.selected=Nothing was selected for the action +error.invalid.request=Invalid Request +error.in.rule.execution=An error occurred in processing the rule error.no.access.permission=No access permission error.no.action=No action found error.no.audit.access=This user does not have permission to view audit data error.no.data.found=No data found +error.no.rule.body=No rule body was entered error.no.share.name=No share name was provided, please enter a share name error.no.ticket.found=No ticket was found +error.no.param.key=No key entered for parameter +error.no.param.value=No value entered for parameter error.data.error=Invalid data entered error.unable.to.find.acl=Unable to find ACL data error.no.description.provided=No description provided @@ -220,7 +234,6 @@ message.error.in.upload=An error occurred in uploading this file. If the proble message.login=Please enter your credentials to log into iRODS message.password.updated=The password was successfully updated message.resource.updated=Default storage resource updated successfully -message.update.successful=Update successful message.no.access=You do not have access rights to perform that operation message.no.starred=No starred files or folders to display message.cannot.create.profile=A profile cannot be created for this user, this may be a mis-configuration diff --git a/idrop-web/grails-app/services/org/irods/mydrop/service/RuleProcessingService.groovy b/idrop-web/grails-app/services/org/irods/mydrop/service/RuleProcessingService.groovy new file mode 100644 index 0000000..44d74a4 --- /dev/null +++ b/idrop-web/grails-app/services/org/irods/mydrop/service/RuleProcessingService.groovy @@ -0,0 +1,85 @@ +package org.irods.mydrop.service + +import org.irods.jargon.core.connection.IRODSAccount +import org.irods.jargon.core.pub.IRODSAccessObjectFactory +import org.irods.jargon.core.pub.RuleProcessingAO +import org.irods.jargon.core.utils.LocalFileUtils +import org.irods.jargon.core.utils.MiscIRODSUtils +import org.irods.jargon.ruleservice.composition.RuleCompositionService +import org.irods.jargon.ruleservice.composition.RuleCompositionServiceImpl + + +class RuleProcessingService { + + static transactional = false + IRODSAccessObjectFactory irodsAccessObjectFactory + + def loadRuleFromIrodsFile(IRODSAccount irodsAccount, String rulePath) { + + RuleCompositionService ruleService = new RuleCompositionServiceImpl(irodsAccessObjectFactory, irodsAccount) + log.info("attempting to retrieve rule for ${rulePath}") + + return ruleService.loadRuleFromIrods(rulePath) + } + + def storeRule(IRODSAccount irodsAccount, String rulePath, String ruleBody, List<String> inputParameters, List<String> outputParameters) { + + log.info("storeRule") + RuleCompositionService ruleService = new RuleCompositionServiceImpl(irodsAccessObjectFactory, irodsAccount) + return ruleService.storeRuleFromParts(rulePath, ruleBody, inputParameters, outputParameters) + } + + def executeRule(IRODSAccount irodsAccount, String ruleBody, List<String> inputParameters, List<String> outputParameters) { + + log.info("executeRule") + RuleCompositionService ruleService = new RuleCompositionServiceImpl(irodsAccessObjectFactory, irodsAccount) + return ruleService.executeRuleFromParts(ruleBody, inputParameters, outputParameters) + } + + def isRule(String rulePath) { + if (!rulePath) { + return false + } + + def fileName = MiscIRODSUtils.getLastPathComponentForGiveAbsolutePath(rulePath) + def fileExtension = LocalFileUtils.getFileExtension(fileName) + log.info("extension is:${fileExtension}") + + if (fileExtension && fileExtension == ".r") { + return true + } else { + return false + } + } + + def deleteOutputParam(IRODSAccount irodsAccount, String absPath, String parameter) { + log.info("deleteOutputParam") + RuleCompositionService ruleService = new RuleCompositionServiceImpl(irodsAccessObjectFactory, irodsAccount) + return ruleService.deleteOutputParameterFromRule(absPath, parameter) + } + + + def deleteInputParam(IRODSAccount irodsAccount, String absPath, String parameter) { + log.info("deleteInputParam") + RuleCompositionService ruleService = new RuleCompositionServiceImpl(irodsAccessObjectFactory, irodsAccount) + return ruleService.deleteInputParameterFromRule(absPath, parameter) + } + + def addRuleInputParam(IRODSAccount irodsAccount, String absPath, String parameterName, String parameterValue) { + log.info("addInputParam") + RuleCompositionService ruleService = new RuleCompositionServiceImpl(irodsAccessObjectFactory, irodsAccount) + return ruleService.addInputParameterToRule(absPath, parameterName, parameterValue) + } + + def addRuleOutputParam(IRODSAccount irodsAccount, String absPath, String parameterName) { + log.info("addOutputParam") + RuleCompositionService ruleService = new RuleCompositionServiceImpl(irodsAccessObjectFactory, irodsAccount) + return ruleService.addOutputParameterToRule(absPath, parameterName) + } + + def listDelayedRuleExecutions(IRODSAccount irodsAccount, int offset) { + log.info("listDelayedRuleExecutions()") + RuleProcessingAO ruleProcessingAO = irodsAccessObjectFactory.getRuleProcessingAO(irodsAccount) + return ruleProcessingAO.listAllDelayedRuleExecutions(offset) + } +} diff --git a/idrop-web/grails-app/views/browse/dataObjectInfo.gsp b/idrop-web/grails-app/views/browse/dataObjectInfo.gsp index e37c7c7..4105810 100644 --- a/idrop-web/grails-app/views/browse/dataObjectInfo.gsp +++ b/idrop-web/grails-app/views/browse/dataObjectInfo.gsp @@ -25,8 +25,6 @@ </h3> </div> - - <ul class="nav nav-tabs" id="infoTabs"> <li class="active"><a href="#info" id="infoTab"><g:message code="text.info" /></a></li> @@ -41,6 +39,11 @@ </g:if> <li><a href="#audit" id="auditTab"><g:message code="text.audit" /></a></li> + <g:if + test="${rule}"> + <li><a href="#rule" id="ruleTab"><g:message + code="text.rule" /></a></li> + </g:if> </ul> <div class="tab-content"> @@ -246,6 +249,12 @@ <div class="tab-pane" id="audit"> <div id="infoAccordionAuditInner"></div> </div> + <g:if + test="${rule}"> + <div class="tab-pane" id="rule"> + <div id="infoAccordionRuleInner"></div> + </div> + </g:if> </div> </div> @@ -285,6 +294,10 @@ showAuditView(selectedPath, "#infoAccordionAuditInner"); }); + $('#ruleTab').on('shown', function(e) { + showRuleView(selectedPath, "#infoAccordionRuleInner"); + }); + }); function callUpdateTags() { diff --git a/idrop-web/grails-app/views/browse/index.gsp b/idrop-web/grails-app/views/browse/index.gsp index ec5ac6b..ab16a69 100755 --- a/idrop-web/grails-app/views/browse/index.gsp +++ b/idrop-web/grails-app/views/browse/index.gsp @@ -8,7 +8,7 @@ <g:hiddenField name="mode" id="mode" value="${mode}"/>
<g:hiddenField name="viewStateBrowseOptionVal" id="viewStateBrowseOptionVal" value="${viewState.browseView}"/>
<g:hiddenField name="presetPath" id="presetPath" value="${viewState.rootPath}"/>
- <g:hiddenField id="viewStateSelectedPath" name="viewStateSelectedPath" value="${viewState.selectedPath}"/>
+ <g:hiddenField id="viewStateSelectedPath" name="viewStateSelectedPath" value="${absPath}"/>
<g:render template="/browse/browseTabContent" />
</div>
diff --git a/idrop-web/grails-app/views/common/_topbar.gsp b/idrop-web/grails-app/views/common/_topbar.gsp index fee43d3..2edf9ce 100755 --- a/idrop-web/grails-app/views/common/_topbar.gsp +++ b/idrop-web/grails-app/views/common/_topbar.gsp @@ -29,6 +29,7 @@ <g:message code="text.tools" /><b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="${grailsApplication.config.idrop.config.idrop.jnlp}" id="idropDesktop")>iDrop Desktop</a></li> + <li id="topbarRule" class="topbarItem"><g:link controller="rule" action="delayExecQueue">User Rules</g:link></li> </ul> </li> diff --git a/idrop-web/grails-app/views/home/link.gsp b/idrop-web/grails-app/views/home/link.gsp index d8bfef5..a7e1531 100755 --- a/idrop-web/grails-app/views/home/link.gsp +++ b/idrop-web/grails-app/views/home/link.gsp @@ -17,6 +17,7 @@ return false; } baseAbsPath = escape(baseAbsPath); + //alert(baseAbsPath); window.location.href = context + "/browse/index?mode=path&absPath=" + baseAbsPath; }); </script>
\ No newline at end of file diff --git a/idrop-web/grails-app/views/rule/_ruleDelayExecQueueDetails.gsp b/idrop-web/grails-app/views/rule/_ruleDelayExecQueueDetails.gsp new file mode 100644 index 0000000..9e9afa9 --- /dev/null +++ b/idrop-web/grails-app/views/rule/_ruleDelayExecQueueDetails.gsp @@ -0,0 +1,61 @@ + <form id="delayExecForm" name="delayExecForm"> + +<table id="delayExecQueueTable" class="table table-striped table-hover" + cellspacing="0" cellpadding="0" border="0"> + <thead> + <tr> + <th> + <div class="btn-group"> + <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">Action<span + class="caret"></span></a> + <ul class="dropdown-menu"> + <li id="menuDeleteDetails"><a href="#deleteAllDetails" + onclick="deleteRulesBulkAction()"><g:message code="text.delete.all" /></a></li> + <!-- dropdown menu links --> + </ul> + </div> + + </th> + <th><g:message code="text.name" /></th> + <th><g:message code="text.user" /></th> + <th><g:message code="text.last.exec.time" /></th> + <th><g:message code="text.frequency" /></th> + + </tr> + </thead> + <tbody> + <g:each in="${rules}" var="rule"> + + <tr id="rule-${rule.id}"> + + <td><g:checkBox name="selectDetail" + value="select-${rule.id}" checked="false" /> + </td> + <td> + ${rule.name} + </td> + <td> + ${rule.userName} + </td> + <td> + ${rule.lastExecTime} + </td> + <td> + ${rule.frequency} + </td> + </tr> + </g:each> + + </tbody> + + <tfoot> + <tr> + <td></td> + <td></td> + <td></td> + <td></td> + <td></td> + </tr> + </tfoot> + </table> + </form>
\ No newline at end of file diff --git a/idrop-web/grails-app/views/rule/_ruleDetails.gsp b/idrop-web/grails-app/views/rule/_ruleDetails.gsp new file mode 100644 index 0000000..96c526d --- /dev/null +++ b/idrop-web/grails-app/views/rule/_ruleDetails.gsp @@ -0,0 +1,95 @@ + +<g:if test="${flash.error}"> + <script> + $(function() { setErrorMessage("${flash.error}"); }); + </script> + </g:if> + + <g:if test="${flash.message}"> + <script> + $(function() { setMessage("${flash.message}");}); + </script> + </g:if> + + +<div id="addParamDialogDiv"> +<!-- area for hanging dialogs --> +</div> + +<g:form name="ruleDetailsForm" id="ruleDetailsForm"> + <fieldset> + <label></label> + <g:textArea id="ruleBody" name="ruleBody" value="${rule.ruleBody}" rows="80" cols="100"/> + + <g:hiddenField name="ruleAbsPath" value="${absPath}" id="ruleAbsPath"/> + + <table class="table alert alert-info"> + <caption><g:message code="text.input.parameters"/></caption> + + <g:each in="${rule.inputParameters}"> + + <tr> + <g:hiddenField name="inputParamName" value="${it.uniqueName}" id="inputParamName"/> + <td>${it.uniqueName}</td> + <td><g:textField name="inputParamValue" id="inputParamValue" value="${it.getStringValue()}" size="80"/></td> + <td><i class='icon-remove' onclick='deleteInputParam(${"\"" + it.uniqueName + "\""})'></i></td> + </tr> + + </g:each> + </table> + <div id="inputParamsToolbar" > + <button type="button" id="addInputParameterButton" + value="addInputParameter" + onclick="callAddInputParameter()"> + <i class="icon-plus"></i><g:message code="text.add.input.parm" /> + </button> + </div> + + + <br/> + <table class="table alert alert-info"> + <caption><g:message code="text.output.parameters"/></caption> + + <g:each in="${rule.outputParameters}"> + <tr> + <g:hiddenField name="outputParamName" value="${it.uniqueName}" id="outputParamName"/> + <td>${it.uniqueName}</td> + <td><i class='icon-remove' onclick='deleteOutputParam(${"\"" + it.uniqueName + "\""})'></i></td> + </tr> + + </g:each> + + </table> + <div id="outputParamsToolbar" > + <button type="button" id="addOutputParameterButton" + value="addOutputParameter" + onclick="callAddOutputParameter()"> + <i class="icon-plus"></i><g:message code="text.add.output.parm" /> + </button> + </div> + + </fieldset> +</g:form> +<script type="text/javascript"> + +var editor = null; +$(function() { + /* var myCodeMirror = CodeMirror.fromTextArea(document.getElementById('ruleBody'),{ + mode: 'clike', + lineNumbers: true, + theme: "blackboard" + }); */ + + var uiOptions = { path : 'js/', searchMode: 'popup' } + var codeMirrorOptions = { + mode: 'text/x-rule', + lineNumbers: true, + theme: "eclipse" + } + + //then create the editor + editor = new CodeMirrorUI(document.getElementById('ruleBody'),uiOptions,codeMirrorOptions); + +}); +</script> +
\ No newline at end of file diff --git a/idrop-web/grails-app/views/rule/addParameterDialog.gsp b/idrop-web/grails-app/views/rule/addParameterDialog.gsp new file mode 100644 index 0000000..f891c31 --- /dev/null +++ b/idrop-web/grails-app/views/rule/addParameterDialog.gsp @@ -0,0 +1,154 @@ +<div id="addParameterDialog"> + + <div class="modal-header"> + <h3> + <g:message code="text.add.parameter" /> + </h3> + </div> + + <div class="modal-body"> + <label for="addParameterName"><g:message + code="text.parameter.name" />:<g:textField name="addParameterName" + id="addParameterName" /></label> + <g:hiddenField name="newParameterAbsPath" id="newParameterAbsPath" + value="${absPath }" /> + <g:if test="${isInputParameter}"> + <label for="addParameterValue"><g:message + code="text.parameter.value" />:<g:textField + name="addParameterValue" id="addParameterValue" /></label> + </g:if> + <g:hiddenField name="isInputParameter" id="isInputParameter" + value="${isInputParameter}" /> + + + </div> + + <div class="modal-footer"> + <g:if test="${isInputParameter}"> + <button type="button" id="updateNewParameterButton" value="update" + onclick="submitAddInputParameterDialog()")> + <g:message code="default.button.update.label" /> + </button> + </g:if> + <g:else> + <button type="button" id="updateNewParameterButton" value="update" + onclick="submitAddOutputParameterDialog()")> + <g:message code="default.button.update.label" /> + </button> + </g:else> + <button type="button" id="cancelAddButton" value="cancelAdd" + onclick="closeAddParameterDialog()")> + <g:message code="text.cancel" /> + </button> + </div> + +</div> + +<script> + $(function() { + $("#addParameterDialog").dialog({ + "modal" : true, + "width" : "500px" + }); + }); + + function submitAddInputParameterDialog() { + + var absPath = $("#newParameterAbsPath").val(); + if (absPath == null || absPath == "") { + setErrorMessage("no absPath for rule"); + return false; + } + + var inputParamKey = $("#addParameterName").val(); + if (inputParamKey == null || inputParamKey == "") { + setErrorMessage("no input parameter key for rule"); + return false; + } + + var inputParamValue = $("#addParameterValue").val(); + if (inputParamValue == null || inputParamValue == "") { + setErrorMessage("no input parameter value for rule"); + return false; + } + + var params = { + ruleAbsPath : absPath, + addParameterName : inputParamKey, + addParameterValue : inputParamValue + } + var url = "/rule/submitAddInputParameterDialog"; + + showBlockingPanel(); + + var jqxhr = $.post(context + url, params, "html") + .success( + function(returnedData, status, xhr) { + var continueReq = checkForSessionTimeout( + returnedData, xhr); + if (!continueReq) { + unblockPanel(); + return false; + } + $("#ruleDetailDiv").html(returnedData); + + $("#addParameterDialog").dialog("close"); + $("#addParameterDialog").html(""); + unblockPanel(); + + }).error(function(xhr, status, error) { + unblockPanel(); + + setErrorMessage(xhr.responseText); + }); + } + + function closeAddParameterDialog() { + $("#addParameterDialog").dialog("close"); + $("#addParameterDialog").html(""); + } + + function submitAddOutputParameterDialog() { + + var absPath = $("#newParameterAbsPath").val(); + if (absPath == null || absPath == "") { + setErrorMessage("no absPath for rule"); + return false; + } + + var inputParamKey = $("#addParameterName").val(); + if (inputParamKey == null || inputParamKey == "") { + setErrorMessage("no input parameter key for rule"); + return false; + } + + var params = { + ruleAbsPath : absPath, + addParameterName : inputParamKey, + } + var url = "/rule/submitAddOutputParameterDialog"; + + showBlockingPanel(); + + var jqxhr = $.post(context + url, params, "html") + .success( + function(returnedData, status, xhr) { + var continueReq = checkForSessionTimeout( + returnedData, xhr); + if (!continueReq) { + unblockPanel(); + return false; + } + $("#ruleDetailDiv").html(returnedData); + + $("#addParameterDialog").dialog("close"); + $("#addParameterDialog").html(""); + unblockPanel(); + + }).error(function(xhr, status, error) { + unblockPanel(); + + setErrorMessage(xhr.responseText); + }); + } +</script> diff --git a/idrop-web/grails-app/views/rule/delayExecQueue.gsp b/idrop-web/grails-app/views/rule/delayExecQueue.gsp new file mode 100644 index 0000000..8ad4dec --- /dev/null +++ b/idrop-web/grails-app/views/rule/delayExecQueue.gsp @@ -0,0 +1,39 @@ +<head> +<meta name="layout" content="mainNoSidebar" /> +</head> +<div id="delayExecQueueDiv"> + <g:render template="ruleDelayExecQueueDetails" /> +</div> +<script> +$(document).ready(function() { + + $.ajaxSetup({ + cache : false + }); + $("#topbarTools").addClass("active"); + }); + + +function deleteRulesBulkAction() { + + var formData = $("#delayExecForm").serializeArray(); + showBlockingPanel(); + + var jqxhr = $.post(context + "/rule/deleteDelayExecQueue", formData, "html") + .success(function(returnedData, status, xhr) { + var continueReq = checkForSessionTimeout(returnedData, xhr); + if (!continueReq) { + return false; + } + + setMessage("Delete action successful"); + $("#delayExecQueueDiv").html(returnedData); + unblockPanel(); + }).error(function(xhr, status, error) { + setErrorMessage(xhr.responseText); + unblockPanel(); + }); + +} + +</script>
\ No newline at end of file diff --git a/idrop-web/grails-app/views/rule/index.gsp b/idrop-web/grails-app/views/rule/index.gsp new file mode 100644 index 0000000..8ee551f --- /dev/null +++ b/idrop-web/grails-app/views/rule/index.gsp @@ -0,0 +1,229 @@ +<head> + +<g:javascript library="codemirror" /> +<g:javascript library="addon/search/searchcursor" /> +<g:javascript library="codemirror-ui" /> + + +<g:javascript library="clike" /> +<link rel="stylesheet" href="${resource(dir:'css',file:'codemirror.css')}" /> +<link rel="stylesheet" href="${resource(dir:'css',file:'codemirror-ui.css')}" /> + +<link rel="stylesheet" href="${resource(dir:'css',file:'eclipse.css')}" /> + +</head> +<h3><a ><g:message code="text.rule" /></a></h3> +<div id="detailsTopSection"> + + <div id="detailsToolbar" > + <button type="button" id="reloadRuleButton" class="ruleEdit" + value="reloadRule" + onclick="callReloadRule()"> + <i class="icon-refresh"></i><g:message code="default.button.reload.label" /> + </button> + <span id="saveRuleButton"><button type="button" id="saveRuleButton" class="ruleEdit" + value="saveRule" + onclick="callSaveRule()"><i class="icon-ok"></i> + <g:message code="text.update" /> + </button></span> + <span id="runRuleButton"><button type="button" id="runRuleButton" + value="runRule" + onclick="callRunRule()"><i class="icon-play"></i> + <g:message code="text.run.rule" /> + </button></span> + </button></span> + <span id="showRuleButton"><button hidden type="button" id="showRuleButton" class="ruleResultView" + value="showRule" + onclick="callShowRule()"><i class="icon-edit"></i> + <g:message code="text.edit" /> + </button></span> + </div> + </div> + + <div id="ruleDetailDiv"> + <!-- div for audit table --> + <g:render template="/rule/ruleDetails" /> + </div> + + <div id="ruleResultDiv"> + <!-- result of rule exec --> + + + </div> + + <script type="text/javascript"> + + + function deleteInputParam(param) { + + if (!param) { + return false; + } + + var absPath = $("#ruleAbsPath").val(); + if (absPath == null || absPath == "") { + setErrorMessage("no absPath for rule"); + return false; + } + + var params = { + ruleAbsPath : absPath, + inputParamName : param + } + + + var jqxhr = $.post(context + "/rule/deleteRuleInputParameter", params, "html").success( + function(returnedData, status, xhr) { + var continueReq = checkForSessionTimeout(returnedData, xhr); + if (!continueReq) { + return false; + } + setMessage("Parameter deleted"); + $("#ruleDetailDiv").html(returnedData); + }).error(function(xhr, status, error) { + setErrorMessage(xhr.responseText); + }); + } + + + function deleteOutputParam(param) { + var absPath = $("#ruleAbsPath").val(); + if (absPath == null || absPath == "") { + setErrorMessage("no absPath for rule"); + return false; + } + + var params = { + ruleAbsPath : absPath, + outputParamName : param + } + + + var jqxhr = $.post(context + "/rule/deleteRuleOutputParameter", params, "html").success( + function(returnedData, status, xhr) { + var continueReq = checkForSessionTimeout(returnedData, xhr); + if (!continueReq) { + return false; + } + setMessage("Parameter deleted"); + $("#ruleDetailDiv").html(returnedData); + }).error(function(xhr, status, error) { + setErrorMessage(xhr.responseText); + }); } + + function callSaveRule() { + editor.mirror.save(); + var formData = $("#ruleDetailsForm").serializeArray(); + var jqxhr = $.post(context + "/rule/updateRule", formData, "html").success( + function(returnedData, status, xhr) { + var continueReq = checkForSessionTimeout(returnedData, xhr); + if (!continueReq) { + return false; + } + setMessage("rule saved"); + $("#ruleDetailDiv").html(returnedData); + }).error(function(xhr, status, error) { + setErrorMessage(xhr.responseText); + }); + + + } + + function callShowRule() { + + $("#ruleDetailDiv").show("slow"); + $(".ruleEdit").show("slow"); + $("#ruleResultDiv").html(""); + $("#ruleResultDiv").hide("slow"); + $(".ruleResultView").hide("slow"); + + } + + function callReloadRule(absPath) { + var absPath = $("#ruleAbsPath").val(); + if (absPath == null || absPath == "") { + showError("no absPath for rule"); + return false; + } + + var params = { + absPath : absPath + + } + var jqxhr = $.get(context + "/rule/reloadRule", params, "html").success( + function(returnedData, status, xhr) { + var continueReq = checkForSessionTimeout(returnedData, xhr); + if (!continueReq) { + return false; + } + $("#ruleDetailDiv").html(returnedData); + }).error(function(xhr, status, error) { + setErrorMessage(xhr.responseText); + }); + + + } + + function callRunRule() { + editor.mirror.save(); + var formData = $("#ruleDetailsForm").serializeArray(); + $("#ruleDetailDiv").hide("slow"); + $(".ruleEdit").hide("slow"); + $("#ruleResultDiv").html(""); + $("#ruleResultDiv").show("slow"); + $(".ruleResultView").show("slow"); + + showBlockingPanel(); + + var jqxhr = $.post(context + "/rule/runRule", formData, "html").success( + function(returnedData, status, xhr) { + var continueReq = checkForSessionTimeout(returnedData, xhr); + if (!continueReq) { + unblockPanel(); + return false; + } + $("#ruleResultDiv").html(returnedData); + unblockPanel(); + + + + }).error(function(xhr, status, error) { + unblockPanel(); + + setErrorMessage(xhr.responseText); + }); + } + + function callAddInputParameter() { + + var absPath = $("#ruleAbsPath").val(); + if (absPath == null || absPath == "") { + setErrorMessage("no absPath for rule"); + return false; + } + + var params = { + ruleAbsPath : absPath + } + var url = "/rule/addRuleInputParameterDialog"; + + lcSendValueWithParamsAndPlugHtmlInDiv(url, params, "#addParamDialogDiv", null); + } + + function callAddOutputParameter() { + var absPath = $("#ruleAbsPath").val(); + if (absPath == null || absPath == "") { + setErrorMessage("no absPath for rule"); + return false; + } + + var params = { + ruleAbsPath : absPath + } + var url = "/rule/addRuleOutputParameterDialog"; + + lcSendValueWithParamsAndPlugHtmlInDiv(url, params, "#addParamDialogDiv", null); + } + + + </script> diff --git a/idrop-web/grails-app/views/rule/ruleErrorResult.gsp b/idrop-web/grails-app/views/rule/ruleErrorResult.gsp new file mode 100644 index 0000000..fb05fbf --- /dev/null +++ b/idrop-web/grails-app/views/rule/ruleErrorResult.gsp @@ -0,0 +1,23 @@ + +<div class="container"> + <div class="row-fluid content"> + <div class="span12 alert alert-error"> + <h2><g:message code="error.in.rule.execution" /></h2> + </div> + </div> + <div class="row-fluid content alert alert-success"> + <div class="span12"> + ${message} + </div> + </div> + <div class="row-fluid content alert alert-error"> + <div class="span12"> + ${stackTrace} + </div> + </div> +</div> + + + + + diff --git a/idrop-web/grails-app/views/rule/ruleResult.gsp b/idrop-web/grails-app/views/rule/ruleResult.gsp new file mode 100644 index 0000000..077a950 --- /dev/null +++ b/idrop-web/grails-app/views/rule/ruleResult.gsp @@ -0,0 +1,41 @@ + +<div class="container"> + <div class="row-fluid content"> + <div class="span12"> + + <table class="table"> + <g:each in="${ruleResult.outputParameterResults.keySet()}"> + + <g:if test="${it == "ruleExecOut" || it == "ruleExecErrorOut" }"> + </g:if> + <g:else> + <tr> + <td> + ${it} + </td> + <td> + ${ruleResult.outputParameterResults.get(it).resultObject} + </td> + </tr> + </g:else> + </g:each> + </table> + + </div> + </div> + <div class="row-fluid content alert alert-success"> + <div class="span12"> + ${execOut} + </div> + </div> + <div class="row-fluid content alert alert-error"> + <div class="span12"> + ${errorOut} + </div> + </div> +</div> + + + + + |