diff --git a/.gitignore b/.gitignore
index 15bdd96..f33ace2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,12 @@
-/target
-/.idea
+Thumbs.db
+.DS_Store
+.gradle
+build/
+out/
+.idea
*.iml
+*.ipr
+*.iws
+.project
+.settings
+.classpath
diff --git a/.travis.yml b/.travis.yml
index bec923b..4e45ac2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,18 +1,23 @@
+dist: trusty
language: groovy
jdk:
-- oraclejdk7
+- oraclejdk8
sudo: false
branches:
only:
- master
-before_install:
- - wget -q https://raw.githubusercontent.com/AtlasOfLivingAustralia/travis-build-configuration/master/ala_common.sh
- - chmod +x ala_common.sh
- - source ./ala_common.sh
- - ala_travis_grails_setup_env
-script:
- - ala_travis_grails_build
+ - develop
+before_cache:
+- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
+- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
+cache:
+ directories:
+ - "$HOME/.m2"
+ - "$HOME/.gradle/caches/"
+ - "$HOME/.gradle/wrapper/"
+after_success:
+- '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && travis_retry ./gradlew publish'
env:
global:
- - secure: XXXTssBnWIBinafmyop1zf/2Pf81hpr0IisjfUd9lw4InfnbICNChS6P/ovfdtFu062xeVYbAgUQLCec1KlPDZQ32UgxFGU74EQ/1M70bJULsxd35UBpTNkhUyNQIcr9DkOhMYahvQbmySv5JGVFiT9ry/38xzQsHfYCQPs5dJY=
- - secure: FHlKa+UKFJdz/4AlfIo6rspYR6+KGOND4hk13LJN3QZCHRjM2ij9toqDxP74aH4VGpaUzEaKy1cC8hqE2F97VbptrFo2NtDEl9fJ6Z/+3lPo3tr6PZ69WZqex//bO+kkpjEn0KspLc92cCfaVOJxHWu5QcQ+C1SddfTwY5FuHPU=
+ - secure: Z6Jfqbjh+XtuJZpVEmBq3ZarQYG2Hb++md9uBKQeWyy23pM7Mh3S3enne3DNs7zyPEUYVr+udUZI5uGyKmjMKZqAgacZZeAtaj4tcJyZPJDzxCTyxzA+BlcYT3/tdmv/9jH4iwolp9CPHGZA69WhlttV9NLg9GBCpElfxi2bs7A=
+ - secure: Bl6/Y0aI9Dq3CxZBJgES+M39O62+zkxzI93/6R0g0b7e86i6v5l319Y9fi3PLQ+YsIwJDMMSPvksKOLCk+e0WrizcdF21fDcJlHyO6WrnPoZIHA+dvMJ2AORIbHtBWo5KdczDmWR9/n2UkV6xwRZ0MRZ25bZLy3AsHh/I/5FMPA=
diff --git a/README.md b/README.md
index c266d49..4b37f06 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-### specimenbrowser [![Build Status](https://travis-ci.org/AtlasOfLivingAustralia/specimenbrowser.svg?branch=master)](https://travis-ci.org/AtlasOfLivingAustralia/specimenbrowser)
+### specimenbrowser [![Build Status](https://travis-ci.com/AtlasOfLivingAustralia/specimenbrowser.svg?branch=master)](https://travis-ci.com/AtlasOfLivingAustralia/specimenbrowser)
Browsing application for specimen images in Australian collections.
This application make use of biocache, collectory and image services.
diff --git a/application.properties b/application.properties
deleted file mode 100644
index feddc65..0000000
--- a/application.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Grails Metadata file
-#Wed Feb 04 20:00:21 EST 2015
-app.grails.version=2.3.11
-app.name=specimenbrowser
-app.servlet.version=2.5
-app.version=1.3-SNAPSHOT
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..e1c932b
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,156 @@
+buildscript {
+ repositories {
+ mavenLocal()
+ maven { url "https://nexus.ala.org.au/content/groups/public/" }
+ maven { url "https://repo.grails.org/grails/core" }
+ }
+ dependencies {
+ classpath "org.grails:grails-gradle-plugin:$grailsVersion"
+ classpath "gradle.plugin.com.github.erdi.webdriver-binaries:webdriver-binaries-gradle-plugin:2.0"
+ // classpath "org.grails.plugins:hibernate5:7.0.4"
+ classpath "com.bertramlabs.plugins:asset-pipeline-gradle:3.2.4"
+ }
+}
+
+version "2.0"
+group "au.org.ala"
+
+apply plugin:"eclipse"
+apply plugin:"idea"
+apply plugin:"war"
+apply plugin:"org.grails.grails-web"
+apply plugin:"com.github.erdi.webdriver-binaries"
+apply plugin:"com.bertramlabs.asset-pipeline"
+apply plugin:"org.grails.grails-gsp"
+apply plugin:"maven-publish"
+
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
+
+repositories {
+ mavenLocal()
+ maven { url "http://nexus.ala.org.au/content/groups/public/" }
+ maven { url "https://repo.grails.org/grails/core" }
+}
+
+configurations {
+ developmentOnly
+ runtimeClasspath {
+ extendsFrom developmentOnly
+ }
+}
+
+dependencies {
+ developmentOnly("org.springframework.boot:spring-boot-devtools")
+ compile "org.springframework.boot:spring-boot-starter-logging"
+ compile "org.springframework.boot:spring-boot-autoconfigure"
+ compile "org.grails:grails-core"
+ compile "org.springframework.boot:spring-boot-starter-actuator"
+ compile "org.springframework.boot:spring-boot-starter-tomcat"
+ compile "org.grails:grails-web-boot"
+ compile "org.grails:grails-logging"
+ compile "org.grails:grails-plugin-rest"
+ compile "org.grails:grails-plugin-i18n"
+ compile "org.grails:grails-plugin-services"
+ compile "org.grails:grails-plugin-url-mappings"
+ compile "org.grails:grails-plugin-interceptors"
+ compile "org.grails.plugins:cache"
+ compile "org.grails.plugins:async"
+ compile "org.grails.plugins:events"
+ compile "org.grails.plugins:gsp"
+ compileOnly "io.micronaut:micronaut-inject-groovy"
+ console "org.grails:grails-console"
+ profile "org.grails.profiles:web"
+ runtime "org.glassfish.web:el-impl:2.1.2-b03"
+ runtime "javax.xml.bind:jaxb-api:2.3.1"
+ runtime "xml-apis:xml-apis:1.4.01"
+ runtime "com.bertramlabs.plugins:asset-pipeline-grails:3.2.4"
+ testCompile "io.micronaut:micronaut-inject-groovy"
+ testCompile "org.mockito:mockito-core"
+ testCompile "org.grails:grails-web-testing-support"
+ testCompile "org.grails.plugins:geb"
+ testCompile "org.seleniumhq.selenium:selenium-remote-driver:3.14.0"
+ testCompile "org.seleniumhq.selenium:selenium-api:3.14.0"
+ testCompile "org.seleniumhq.selenium:selenium-support:3.14.0"
+ testRuntime "org.seleniumhq.selenium:selenium-chrome-driver:3.14.0"
+ testRuntime "org.seleniumhq.selenium:selenium-firefox-driver:3.14.0"
+
+ // External config
+ compile 'org.grails.plugins:external-config:2.0.0'
+
+ // Javascript libraries
+ compile 'org.webjars:knockout:3.5.1'
+
+ // ALA Plugins
+ compile group: 'org.grails.plugins', name: 'ala-auth', version: '3.2.2'
+ compile group: 'org.grails.plugins', name: 'ala-admin-plugin', version: '2.2'
+ compile group: 'org.grails.plugins', name: 'ala-bootstrap3', version: '3.2.3'
+ compile group: 'au.org.ala.plugins.grails', name: 'images-client-plugin', version: '1.2'
+}
+
+bootRun {
+ ignoreExitValue true
+ jvmArgs(
+ '-Dspring.output.ansi.enabled=always',
+ '-noverify',
+ '-XX:TieredStopAtLevel=1',
+ '-Xmx1024m')
+ sourceResources sourceSets.main
+ String springProfilesActive = 'spring.profiles.active'
+ systemProperty springProfilesActive, System.getProperty(springProfilesActive)
+}
+
+tasks.withType(GroovyCompile) {
+ configure(groovyOptions) {
+ forkOptions.jvmArgs = ['-Xmx1024m']
+ }
+}
+
+webdriverBinaries {
+ chromedriver '2.45.0'
+ geckodriver '0.24.0'
+}
+
+tasks.withType(Test) {
+ systemProperty "geb.env", System.getProperty('geb.env')
+ systemProperty "geb.build.reportsDir", reporting.file("geb/integrationTest")
+ systemProperty "webdriver.chrome.driver", System.getProperty('webdriver.chrome.driver')
+ systemProperty "webdriver.gecko.driver", System.getProperty('webdriver.gecko.driver')
+}
+
+assets {
+ minifyJs = true
+ minifyCss = true
+}
+
+// Standard ALA import doesn't work with this version
+publishing {
+ repositories {
+ maven {
+ name 'Nexus'
+ url "https://nexus.ala.org.au/content/repositories/${project.version.endsWith('-SNAPSHOT') ? 'snapshots' : 'releases' }"
+ credentials {
+ username = System.getenv('TRAVIS_DEPLOY_USERNAME')
+ password = System.getenv('TRAVIS_DEPLOY_PASSWORD')
+ }
+ }
+ }
+ publications {
+ mavenJar(MavenPublication) {
+ pom.withXml {
+ def pomNode = asNode()
+ pomNode.dependencyManagement.replaceNode {}
+
+ // simply remove dependencies without a version
+ // version-less dependencies are handled with dependencyManagement
+ // see https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/8 for more complete solutions
+ pomNode.dependencies.dependency.findAll {
+ it.version.text().isEmpty()
+ }.each {
+ it.replaceNode {}
+ }
+ }
+ from components.web
+ }
+ }
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..f5c617a
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,5 @@
+grailsVersion=4.0.5
+gorm.version=7.0.8.RELEASE
+org.gradle.daemon=true
+org.gradle.parallel=true
+org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx1024M
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..87b738c
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..5028f28
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..af6708f
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100755
index 0000000..6d57edc
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/web-app/images/ajax-loader.gif b/grails-app/assets/images/ajax-loader.gif
similarity index 100%
rename from web-app/images/ajax-loader.gif
rename to grails-app/assets/images/ajax-loader.gif
diff --git a/grails-app/assets/javascripts/admin.js b/grails-app/assets/javascripts/admin.js
new file mode 100644
index 0000000..dd415f0
--- /dev/null
+++ b/grails-app/assets/javascripts/admin.js
@@ -0,0 +1,3 @@
+//= require /webjars/knockout/3.5.1/knockout.js
+//= require jquery.ba-bbq.min.js
+//= require utilities.js
\ No newline at end of file
diff --git a/grails-app/assets/javascripts/browser.js b/grails-app/assets/javascripts/browser.js
new file mode 100644
index 0000000..dd415f0
--- /dev/null
+++ b/grails-app/assets/javascripts/browser.js
@@ -0,0 +1,3 @@
+//= require /webjars/knockout/3.5.1/knockout.js
+//= require jquery.ba-bbq.min.js
+//= require utilities.js
\ No newline at end of file
diff --git a/web-app/js/jquery.ba-bbq.min.js b/grails-app/assets/javascripts/jquery.ba-bbq.min.js
similarity index 100%
rename from web-app/js/jquery.ba-bbq.min.js
rename to grails-app/assets/javascripts/jquery.ba-bbq.min.js
diff --git a/web-app/js/application.js b/grails-app/assets/javascripts/utilities.js
similarity index 99%
rename from web-app/js/application.js
rename to grails-app/assets/javascripts/utilities.js
index 60074ff..b8ad840 100644
--- a/web-app/js/application.js
+++ b/grails-app/assets/javascripts/utilities.js
@@ -72,4 +72,3 @@ function AjaxLauncher (baseUrl) {
list.push(callback);
};
}
-
diff --git a/grails-app/assets/stylesheets/errors.css b/grails-app/assets/stylesheets/errors.css
new file mode 100644
index 0000000..1c616d8
--- /dev/null
+++ b/grails-app/assets/stylesheets/errors.css
@@ -0,0 +1,109 @@
+h1, h2 {
+ margin: 10px 25px 5px;
+}
+
+h2 {
+ font-size: 1.1em;
+}
+
+.filename {
+ font-style: italic;
+}
+
+.exceptionMessage {
+ margin: 10px;
+ border: 1px solid #000;
+ padding: 5px;
+ background-color: #E9E9E9;
+}
+
+.stack,
+.snippet {
+ margin: 0 25px 10px;
+}
+
+.stack,
+.snippet {
+ border: 1px solid #ccc;
+ -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ box-shadow: 0 0 2px rgba(0,0,0,0.2);
+}
+
+/* error details */
+.error-details {
+ border-top: 1px solid #FFAAAA;
+ -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ border-bottom: 1px solid #FFAAAA;
+ -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ background-color:#FFF3F3;
+ line-height: 1.5;
+ overflow: hidden;
+ padding: 5px;
+ padding-left:25px;
+}
+
+.error-details dt {
+ clear: left;
+ float: left;
+ font-weight: bold;
+ margin-right: 5px;
+}
+
+.error-details dt:after {
+ content: ":";
+}
+
+.error-details dd {
+ display: block;
+}
+
+/* stack trace */
+.stack {
+ padding: 5px;
+ overflow: auto;
+ height: 150px;
+}
+
+/* code snippet */
+.snippet {
+ background-color: #fff;
+ font-family: monospace;
+}
+
+.snippet .line {
+ display: block;
+}
+
+.snippet .lineNumber {
+ background-color: #ddd;
+ color: #999;
+ display: inline-block;
+ margin-right: 5px;
+ padding: 0 3px;
+ text-align: right;
+ width: 3em;
+}
+
+.snippet .error {
+ background-color: #fff3f3;
+ font-weight: bold;
+}
+
+.snippet .error .lineNumber {
+ background-color: #faa;
+ color: #333;
+ font-weight: bold;
+}
+
+.snippet .line:first-child .lineNumber {
+ padding-top: 5px;
+}
+
+.snippet .line:last-child .lineNumber {
+ padding-bottom: 5px;
+}
\ No newline at end of file
diff --git a/web-app/css/specimenbrowser.css b/grails-app/assets/stylesheets/specimenbrowser.css
similarity index 93%
rename from web-app/css/specimenbrowser.css
rename to grails-app/assets/stylesheets/specimenbrowser.css
index 7425ab8..6988d55 100644
--- a/web-app/css/specimenbrowser.css
+++ b/grails-app/assets/stylesheets/specimenbrowser.css
@@ -1,128 +1,128 @@
-.panel-text { margin-top : 15px; font-size: 15px; line-height: 1.5em;}
-.panel h2 { line-height: 1.2em; }
-.panel h3 { line-height: 1.2em; }
-
-.space-after {
- margin-bottom: 10px;
-}
-
-.space-before {
- margin-top: 10px;
-}
-
-.large-space-after {
- margin-bottom: 20px;
-}
-
-.large-space-before {
- margin-top: 20px;
-}
-
-.center {text-align: center}
-
-.clickable {
- cursor: pointer;
- /*text-decoration: underline;*/
- color: #007fb6;
-}
-
-ul {
- list-style: none;
-}
-
-.clickable:hover,
-.clickable:focus {
- color: #00638d;
- text-decoration: underline;
-}
-
-#imagesList {
- margin:0;
-}
-
-.imgCon {
- display: inline-block;
- /*margin-right: 8px;*/
- text-align: center;
- line-height: 1.3em;
- background-color: #DDD;
- color: #DDD;
- /*padding: 5px;*/
- /*margin-bottom: 8px;*/
- margin: 2px 0 2px 0;
- position: relative;
-}
-
-.imgCon .meta {
- opacity: 0.7;
- position: absolute;
- bottom: 0;
- left: 0;
- right: 0;
- overflow: hidden;
- text-align: left;
- padding: 4px 6px 2px 8px;
-}
-
-.imgCon .full {
- color: white;
- background-color: black;
- display: none;
-}
-
-.imgCon .brief {
- color: black;
- background-color: white;
-}
-
-.imgCon .hover-target {
- display: none;
-}
-
-.imgCon:hover .full {
- display: inline-block;
-}
-
-.imgCon:hover .brief {
- display: none;
-}
-
-#taxonomyFacet .level0 {
- margin-left: 0;
-}
-
-#taxonomyFacet .level1 {
- margin-left: 4px;
-}
-
-#taxonomyFacet .level2 {
- margin-left: 8px;
-}
-
-#taxonomyFacet .level3 {
- margin-left: 12px;
-}
-
-#taxonomyFacet .level4 {
- margin-left: 16px;
-}
-
-#taxonomyFacet .level5 {
- margin-left: 20px;
-}
-
-#taxonomyFacet .level6 {
- margin-left: 24px;
-}
-
-#taxonomyFacet .level7 {
- margin-left: 28px;
-}
-
-#taxonomyFacet .level8 {
- margin-left: 32px;
-}
-
-#imageViewer {
- height: 600px;
-}
+.panel-text { margin-top : 15px; font-size: 15px; line-height: 1.5em;}
+.panel h2 { line-height: 1.2em; }
+.panel h3 { line-height: 1.2em; }
+
+.space-after {
+ margin-bottom: 10px;
+}
+
+.space-before {
+ margin-top: 10px;
+}
+
+.large-space-after {
+ margin-bottom: 20px;
+}
+
+.large-space-before {
+ margin-top: 20px;
+}
+
+.center {text-align: center}
+
+.clickable {
+ cursor: pointer;
+ /*text-decoration: underline;*/
+ color: #007fb6;
+}
+
+ul {
+ list-style: none;
+}
+
+.clickable:hover,
+.clickable:focus {
+ color: #00638d;
+ text-decoration: underline;
+}
+
+#imagesList {
+ margin:0;
+}
+
+.imgCon {
+ display: inline-block;
+ /*margin-right: 8px;*/
+ text-align: center;
+ line-height: 1.3em;
+ background-color: #DDD;
+ color: #DDD;
+ /*padding: 5px;*/
+ /*margin-bottom: 8px;*/
+ margin: 2px 0 2px 0;
+ position: relative;
+}
+
+.imgCon .meta {
+ opacity: 0.7;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+ text-align: left;
+ padding: 4px 6px 2px 8px;
+}
+
+.imgCon .full {
+ color: white;
+ background-color: black;
+ display: none;
+}
+
+.imgCon .brief {
+ color: black;
+ background-color: white;
+}
+
+.imgCon .hover-target {
+ display: none;
+}
+
+.imgCon:hover .full {
+ display: inline-block;
+}
+
+.imgCon:hover .brief {
+ display: none;
+}
+
+#taxonomyFacet .level0 {
+ margin-left: 0;
+}
+
+#taxonomyFacet .level1 {
+ margin-left: 4px;
+}
+
+#taxonomyFacet .level2 {
+ margin-left: 8px;
+}
+
+#taxonomyFacet .level3 {
+ margin-left: 12px;
+}
+
+#taxonomyFacet .level4 {
+ margin-left: 16px;
+}
+
+#taxonomyFacet .level5 {
+ margin-left: 20px;
+}
+
+#taxonomyFacet .level6 {
+ margin-left: 24px;
+}
+
+#taxonomyFacet .level7 {
+ margin-left: 28px;
+}
+
+#taxonomyFacet .level8 {
+ margin-left: 32px;
+}
+
+#imageViewer {
+ height: 600px;
+}
diff --git a/grails-app/assets/stylesheets/viewer.css b/grails-app/assets/stylesheets/viewer.css
new file mode 100644
index 0000000..756c495
--- /dev/null
+++ b/grails-app/assets/stylesheets/viewer.css
@@ -0,0 +1,5 @@
+/*
+ * CSS and extensions for the image viewer
+ *
+ *
+ */
\ No newline at end of file
diff --git a/grails-app/conf/ApplicationResources.groovy b/grails-app/conf/ApplicationResources.groovy
deleted file mode 100644
index 23bac5b..0000000
--- a/grails-app/conf/ApplicationResources.groovy
+++ /dev/null
@@ -1,14 +0,0 @@
-modules = {
- application {
- resource url:'js/application.js'
- resource url:'css/specimenbrowser.css'
- }
-
- knockout {
- resource 'js/knockout-3.0.0.js'
- }
-
- bbq {
- resource 'js/jquery.ba-bbq.min.js'
- }
-}
\ No newline at end of file
diff --git a/grails-app/conf/BuildConfig.groovy b/grails-app/conf/BuildConfig.groovy
deleted file mode 100644
index 6db0c31..0000000
--- a/grails-app/conf/BuildConfig.groovy
+++ /dev/null
@@ -1,48 +0,0 @@
-grails.servlet.version = "2.5" // Change depending on target container compliance (2.5 or 3.0)
-grails.project.class.dir = "target/classes"
-grails.project.test.class.dir = "target/test-classes"
-grails.project.test.reports.dir = "target/test-reports"
-grails.project.target.level = 1.6
-grails.project.source.level = 1.6
-//grails.project.war.file = "target/${appName}-${appVersion}.war"
-
-//grails.plugin.location."images-client-plugin" = "../images-client-plugin"
-// uncomment (and adjust settings) to fork the JVM to isolate classpaths
-grails.project.fork = [
- test: false,
- run: false,
- war: false,
- console: false
-]
-
-grails.project.dependency.resolver = "maven"
-
-grails.project.dependency.resolution = {
- // inherit Grails' default dependencies
- inherits("global") {
- // specify dependency exclusions here; for example, uncomment this to disable ehcache:
- // excludes 'ehcache'
- }
- log "error" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
- checksums true // Whether to verify checksums on resolve
- legacyResolve false // whether to do a secondary resolve on plugin installation, not advised and here for backwards compatibility
-
- repositories {
- mavenLocal()
- mavenRepo("https://nexus.ala.org.au/content/groups/public/"){
- updatePolicy 'always'
- }
- }
-
- dependencies {
-
- }
-
- plugins {
- runtime ":ala-bootstrap2:2.2"
- runtime ":images-client-plugin:0.5.3"
- compile ':cache:1.1.8'
- compile ':ala-auth:1.3.1'
- build ':tomcat:7.0.54'
- }
-}
diff --git a/grails-app/conf/Config.groovy b/grails-app/conf/Config.groovy
deleted file mode 100644
index 11139e3..0000000
--- a/grails-app/conf/Config.groovy
+++ /dev/null
@@ -1,163 +0,0 @@
-/******************************************************************************\
- * CONFIG MANAGEMENT
- \******************************************************************************/
-def appName = 'specimenbrowser'
-def ENV_NAME = "${appName.toUpperCase()}_CONFIG"
-default_config = "/data/${appName}/config/${appName}-config.properties"
-if(!grails.config.locations || !(grails.config.locations instanceof List)) {
- grails.config.locations = []
-}
-if(System.getenv(ENV_NAME) && new File(System.getenv(ENV_NAME)).exists()) {
- println "[${appName}] Including configuration file specified in environment: " + System.getenv(ENV_NAME);
- grails.config.locations.add "file:" + System.getenv(ENV_NAME)
-} else if(System.getProperty(ENV_NAME) && new File(System.getProperty(ENV_NAME)).exists()) {
- println "[${appName}] Including configuration file specified on command line: " + System.getProperty(ENV_NAME);
- grails.config.locations.add "file:" + System.getProperty(ENV_NAME)
-} else if(new File(default_config).exists()) {
- println "[${appName}] Including default configuration file: " + default_config;
- grails.config.locations.add "file:" + default_config
-} else {
- println "[${appName}] No external configuration file defined."
-}
-println "[${appName}] (*) grails.config.locations = ${grails.config.locations}"
-
-grails.project.groupId = appName // change this to alter the default package name and Maven publishing destination
-grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
-grails.mime.use.accept.header = false
-grails.mime.types = [
- all: '*/*',
- atom: 'application/atom+xml',
- css: 'text/css',
- csv: 'text/csv',
- form: 'application/x-www-form-urlencoded',
- html: ['text/html','application/xhtml+xml'],
- js: 'text/javascript',
- json: ['application/json', 'text/json'],
- multipartForm: 'multipart/form-data',
- rss: 'application/rss+xml',
- text: 'text/plain',
- xml: ['text/xml', 'application/xml']
-]
-
-// URL Mapping Cache Max Size, defaults to 5000
-//grails.urlmapping.cache.maxsize = 1000
-
-// What URL patterns should be processed by the resources plugin
-grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*']
-
-/******************************************************************************\
- * RELOADABLE CONFIG
- \******************************************************************************/
-reloadable.cfgs = ["file:/data/${appName}/config/${appName}-config.properties"]
-
-/******************************************************************************\
- * EXTERNAL SERVERS
- \******************************************************************************/
-if (!bie.baseURL) {
- bie.baseURL = "https://bie.ala.org.au"
-}
-if (!bie.searchPath) {
- bie.searchPath = "/search"
-}
-if (!biocache.baseURL) {
- biocache.baseURL = "https://biocache.ala.org.au"
-}
-if(!biocacheServicesUrl){
- biocacheServicesUrl = "https://biocache-ws.ala.org.au/ws"
-}
-if(!collectory.baseURL){
- collectory.baseURL = "https://collections.ala.org.au"
-}
-if(!collectory.servicesURL){
- collectory.servicesURL = "https://collections.ala.org.au/ws"
-}
-if (!spatial.baseURL) {
- spatial.baseURL = "https://spatial.ala.org.au"
-}
-if (!ala.baseURL) {
- ala.baseURL = "https://www.ala.org.au"
-}
-if (!ala.image.service.url) {
- ala.image.service.url = "https://images.ala.org.au"
-}
-
-// The default codec used to encode data with ${}
-grails.views.default.codec = "none" // none, html, base64
-grails.views.gsp.encoding = "UTF-8"
-grails.converters.encoding = "UTF-8"
-// enable Sitemesh preprocessing of GSP pages
-grails.views.gsp.sitemesh.preprocess = true
-// scaffolding templates configuration
-grails.scaffolding.templates.domainSuffix = 'Instance'
-
-// Set to false to use the new Grails 1.2 JSONBuilder in the render method
-grails.json.legacy.builder = false
-// enabled native2ascii conversion of i18n properties files
-grails.enable.native2ascii = true
-// packages to include in Spring bean scanning
-grails.spring.bean.packages = []
-// whether to disable processing of multi part requests
-grails.web.disable.multipart=false
-
-// request parameters to mask when logging exceptions
-grails.exceptionresolver.params.exclude = ['password']
-
-// configure auto-caching of queries by default (if false you can cache individual queries with 'cache: true')
-grails.hibernate.cache.queries = false
-
-environments {
- development {
- grails.logging.jul.usebridge = true
- grails.serverURL = "http://devt.ala.org.au:8080/specimenbrowser"
-// grails.context = ''
- }
- production {
- grails.logging.jul.usebridge = false
- // TODO: grails.serverURL = "http://www.changeme.com"
- }
-}
-
-// log4j configuration
-log4j = {
- // Example of changing the log pattern for the default console appender:
- //
- //appenders {
- // console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
- //}
-
- error 'org.codehaus.groovy.grails.web.servlet', // controllers
- 'org.codehaus.groovy.grails.web.pages', // GSP
- 'org.codehaus.groovy.grails.web.sitemesh', // layouts
- 'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
- 'org.codehaus.groovy.grails.web.mapping', // URL mapping
- 'org.codehaus.groovy.grails.commons', // core / classloading
- 'org.codehaus.groovy.grails.plugins', // plugins
- 'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
- 'org.springframework',
- 'org.hibernate',
- 'net.sf.ehcache.hibernate'
-}
-
-// Uncomment and edit the following lines to start using Grails encoding & escaping improvements
-
-/* remove this line
-// GSP settings
-grails {
- views {
- gsp {
- encoding = 'UTF-8'
- htmlcodec = 'xml' // use xml escaping instead of HTML4 escaping
- codecs {
- expression = 'html' // escapes values inside null
- scriptlet = 'none' // escapes output from scriptlets in GSPs
- taglib = 'none' // escapes output from taglibs
- staticparts = 'none' // escapes output from static template parts
- }
- }
- // escapes all not-encoded output at final stage of outputting
- filteringCodecForContentType {
- //'text/html' = 'html'
- }
- }
-}
-remove this line */
diff --git a/grails-app/conf/DataSource.groovy b/grails-app/conf/DataSource.groovy
deleted file mode 100644
index 3d6b94a..0000000
--- a/grails-app/conf/DataSource.groovy
+++ /dev/null
@@ -1,2 +0,0 @@
-dataSource {
-}
diff --git a/grails-app/conf/application.yml b/grails-app/conf/application.yml
new file mode 100644
index 0000000..38f6d00
--- /dev/null
+++ b/grails-app/conf/application.yml
@@ -0,0 +1,187 @@
+---
+grails:
+ profile: web
+ config:
+ locations:
+ - file:///data/specimenbrowser/config/specimenbrowser-config.properties
+ - file:///data/specimenbrowser/config/specimenbrowser-config.yml
+ - file:///data/specimenbrowser/config/specimenbrowser-config.groovy
+ codegen:
+ defaultPackage: au.org.ala.specimenbrowser
+ gorm:
+ reactor:
+ # Whether to translate GORM events into Reactor events
+ # Disabled by default for performance reasons
+ events: false
+info:
+ app:
+ name: '@info.app.name@'
+ version: '@info.app.version@'
+ grailsVersion: '@info.app.grailsVersion@'
+spring:
+ jmx:
+ unique-names: true
+ main:
+ banner-mode: "off"
+ groovy:
+ template:
+ check-template-location: false
+ devtools:
+ restart:
+ additional-exclude:
+ - '*.gsp'
+ - '**/*.gsp'
+ - '*.gson'
+ - '**/*.gson'
+ - 'logback.groovy'
+ - '*.properties'
+management:
+ endpoints:
+ enabled-by-default: false
+
+---
+grails:
+ mime:
+ disable:
+ accept:
+ header:
+ userAgents:
+ - Gecko
+ - WebKit
+ - Presto
+ - Trident
+ types:
+ all: '*/*'
+ atom: application/atom+xml
+ css: text/css
+ csv: text/csv
+ form: application/x-www-form-urlencoded
+ html:
+ - text/html
+ - application/xhtml+xml
+ js: text/javascript
+ json:
+ - application/json
+ - text/json
+ multipartForm: multipart/form-data
+ pdf: application/pdf
+ rss: application/rss+xml
+ text: text/plain
+ hal:
+ - application/hal+json
+ - application/hal+xml
+ xml:
+ - text/xml
+ - application/xml
+ urlmapping:
+ cache:
+ maxsize: 1000
+ controllers:
+ defaultScope: singleton
+ converters:
+ encoding: UTF-8
+ views:
+ default:
+ codec: html
+ gsp:
+ encoding: UTF-8
+ htmlcodec: xml
+ codecs:
+ expression: html
+ scriptlet: html
+ taglib: none
+ staticparts: none
+management:
+ endpoints:
+ jmx:
+ unique-names: true
+
+---
+hibernate:
+ cache:
+ queries: false
+ use_second_level_cache: false
+ use_query_cache: false
+dataSource:
+ pooled: true
+ jmxExport: true
+ driverClassName: org.h2.Driver
+ username: sa
+ password: ''
+
+environments:
+ development:
+ dataSource:
+ dbCreate: update
+ url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
+ test:
+ dataSource:
+ dbCreate: update
+ url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
+ production:
+ dataSource:
+ dbCreate: none
+ url: jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
+ properties:
+ jmxEnabled: true
+ initialSize: 5
+ maxActive: 50
+ minIdle: 5
+ maxIdle: 25
+ maxWait: 10000
+ maxAge: 600000
+ timeBetweenEvictionRunsMillis: 5000
+ minEvictableIdleTimeMillis: 60000
+ validationQuery: SELECT 1
+ validationQueryTimeout: 3
+ validationInterval: 15000
+ testOnBorrow: true
+ testWhileIdle: true
+ testOnReturn: false
+ jdbcInterceptors: ConnectionState
+ defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED
+---
+grails:
+ serverURL: https://specimens.ala.org.au
+bie:
+ baseURL: https://bie.ala.org.au
+ searchPath: /search
+biocache:
+ baseURL: https://biocache.ala.org.au
+ servicesUrl: https://biocache-ws.ala.org.au/ws/
+collectory:
+ baseURL: https://collections.ala.org.au
+ servicesUrl: https://collections.ala.org.au/ws/
+ resourceMapping:
+ - prefix: dr
+ path: dataResource
+ - prefix: co
+ path: collection
+ - prefix: in
+ path: institution
+ - prefix: dh
+ path: dataHub
+ - prefix: dp
+ path: dataProvider
+spatial:
+ baseURL: https://spatial.ala.org.au
+ala:
+ baseURL: https://www.ala.org.au
+ image:
+ service:
+ url: https://images.ala.org.au
+security:
+ cas:
+ appServerName: https://specimens.ala.org.au
+ casServerName: https://auth.ala.org.au
+ uriFilterPattern: /admin.*,/alaAdmin.*
+skin:
+ layout: main
+ fluidLayout: true
+ orgNameLong: Atlas of Living Australia
+specimenbrowser:
+ data:
+ url: file:///data/specimenbrowser/config/data.json
+headerAndFooter:
+ baseURL: https://www.ala.org.au/commonui-bs3-2019
+ version: 2
diff --git a/grails-app/conf/logback.groovy b/grails-app/conf/logback.groovy
new file mode 100644
index 0000000..b835215
--- /dev/null
+++ b/grails-app/conf/logback.groovy
@@ -0,0 +1,37 @@
+import grails.util.BuildSettings
+import grails.util.Environment
+import org.springframework.boot.logging.logback.ColorConverter
+import org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter
+
+import java.nio.charset.StandardCharsets
+
+conversionRule 'clr', ColorConverter
+conversionRule 'wex', WhitespaceThrowableProxyConverter
+
+// See http://logback.qos.ch/manual/groovy.html for details on configuration
+appender('STDOUT', ConsoleAppender) {
+ encoder(PatternLayoutEncoder) {
+ charset = StandardCharsets.UTF_8
+
+ pattern =
+ '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} ' + // Date
+ '%clr(%5p) ' + // Log level
+ '%clr(---){faint} %clr([%15.15t]){faint} ' + // Thread
+ '%clr(%-40.40logger{39}){cyan} %clr(:){faint} ' + // Logger
+ '%m%n%wex' // Message
+ }
+}
+
+def targetDir = BuildSettings.TARGET_DIR
+if (Environment.isDevelopmentMode() && targetDir != null) {
+ appender("FULL_STACKTRACE", FileAppender) {
+ file = "${targetDir}/stacktrace.log"
+ append = true
+ encoder(PatternLayoutEncoder) {
+ charset = StandardCharsets.UTF_8
+ pattern = "%level %logger - %msg%n"
+ }
+ }
+ logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false)
+}
+root(ERROR, ['STDOUT'])
diff --git a/grails-app/controllers/au/org/ala/specimenbrowser/AdminController.groovy b/grails-app/controllers/au/org/ala/specimenbrowser/AdminController.groovy
index 4b39620..d109554 100644
--- a/grails-app/controllers/au/org/ala/specimenbrowser/AdminController.groovy
+++ b/grails-app/controllers/au/org/ala/specimenbrowser/AdminController.groovy
@@ -1,61 +1,19 @@
package au.org.ala.specimenbrowser
-import grails.util.Environment
-import org.springframework.core.io.support.PathMatchingResourcePatternResolver
+import au.org.ala.web.AlaSecured
+import au.org.ala.web.CASRoles
+@AlaSecured(CASRoles.ROLE_ADMIN)
class AdminController {
+ def resourceService
def index() {}
- def tools() {}
- def counts() {}
-
- def settings() {
- def settings = []
- def config = grailsApplication.config.flatten()
- ['ala.baseURL','grails.serverURL','grails.config.locations','collectory.baseURL',
- 'headerAndFooter.baseURL','biocacheServicesUrl','collectory.servicesURL'
- ].each {
- settings << [key: it, value: config[it], comment: '']
- }
- [settings: settings]
- }
- def reloadConfig = {
- // clear any cached external config
- //cacheService.clear()
-
- // reload system config
- def resolver = new PathMatchingResourcePatternResolver()
- def resource = resolver.getResource(grailsApplication.config.reloadable.cfgs[0])
- def stream = null
+ def counts() {}
- try {
- stream = resource.getInputStream()
- ConfigSlurper configSlurper = new ConfigSlurper(Environment.current.name)
- if(resource.filename.endsWith('.groovy')) {
- def newConfig = configSlurper.parse(stream.text)
- grailsApplication.getConfig().merge(newConfig)
- }
- else if(resource.filename.endsWith('.properties')) {
- def props = new Properties()
- props.load(stream)
- def newConfig = configSlurper.parse(props)
- grailsApplication.getConfig().merge(newConfig)
- }
- flash.message = "Config reloaded from ${grailsApplication.config.reloadable.cfgs[0]}."
- render 'done'
- }
- catch (FileNotFoundException fnf) {
- println "No external config to reload configuration. Looking for ${grailsApplication.config.reloadable.cfgs[0]}"
- render "No external config to reload configuration. Looking for ${grailsApplication.config.reloadable.cfgs[0]}"
- }
- catch (Exception gre) {
- println "Unable to reload configuration. Please correct problem and try again: " + gre.getMessage()
- render "Unable to reload configuration - " + gre.getMessage()
- }
- finally {
- stream?.close()
- }
+ def reloadResources() {
+ resourceService.buildResources()
+ flash.message = "Resource configuration reloaded"
+ redirect controller: 'admin', action: 'index'
}
-
}
diff --git a/grails-app/controllers/au/org/ala/specimenbrowser/ViewController.groovy b/grails-app/controllers/au/org/ala/specimenbrowser/ViewController.groovy
index f1f910e..9ffe2fe 100644
--- a/grails-app/controllers/au/org/ala/specimenbrowser/ViewController.groovy
+++ b/grails-app/controllers/au/org/ala/specimenbrowser/ViewController.groovy
@@ -1,24 +1,17 @@
package au.org.ala.specimenbrowser
-import grails.converters.JSON
+import grails.config.Config
+import grails.core.support.GrailsConfigurationAware
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
-class ViewController {
+class ViewController implements GrailsConfigurationAware {
+ def resourceService
- def grailsApplication
+ URL biocacheServicesUrl
def homePage(){
- def collectionsData = []
- def md = new File("/data/specimenbrowser/config/data.json")?.text
- def js = new JsonSlurper()
- def collectionsToRender = js.parseText(md)
- collectionsToRender.each { collection ->
- def collectionMetadata = js.parseText(new URL(grailsApplication.config.collectory.servicesURL + "/collection/" + collection.uid).text)
- collectionMetadata.put("displayCollectionImage", collection.imageUrl)
- collectionsData << collectionMetadata
- }
- [collectionsData: collectionsData]
+ [collectionsData: resourceService.resources]
}
def view(String id, String recordId) {
@@ -27,31 +20,37 @@ class ViewController {
def auxData(){
def js = new JsonSlurper()
- def json = js.parseText(new URL(grailsApplication.config.biocacheServicesUrl + "/occurrence/" + params.recordId).text)
- def title = "Collection: " + json.processed.attribution.collectionName
- def data = [
- "Scientific name": json.raw.classification.scientificName,
- "Type status": json.raw.identification.typeStatus?:"",
- "Catalog Number": json.raw.occurrence.catalogNumber?:"",
- "Preparations": json.raw.occurrence.preparations?:"",
- "Sex": json.raw.occurrence.sex?:"",
- "Recorded by": json.raw.occurrence.recordedBy?:"",
- "Photographer": json.raw.occurrence.photographer?:"",
- "State": json.processed.location.stateProvince?:"",
- "Country": json.processed.location.country?:""
- ]
+ def json = js.parse(new URL(biocacheServicesUrl, "occurrence/" + params.recordId))
+ def data = [:]
+ def title
+ if (!json) {
+ title = "Unable to retrieve specimen data"
+ } else {
+ title = "Collection: " + json.processed.attribution.collectionName
+ data = [
+ "Scientific name": json.raw.classification.scientificName,
+ "Type status" : json.raw.identification.typeStatus ?: "",
+ "Catalog Number" : json.raw.occurrence.catalogNumber ?: "",
+ "Preparations" : json.raw.occurrence.preparations ?: "",
+ "Sex" : json.raw.occurrence.sex ?: "",
+ "Recorded by" : json.raw.occurrence.recordedBy ?: "",
+ "Photographer" : json.raw.occurrence.photographer ?: "",
+ "State" : json.processed.location.stateProvince ?: "",
+ "Country" : json.processed.location.country ?: ""
+ ]
- if(json.processed.location.decimalLatitude && json.processed.location.decimalLongitude){
- data.put("Coordinates", json.processed.location.decimalLatitude + " " + json.processed.location.decimalLongitude)
- }
- if(json.raw.location.locality){
- data.put("Locality", json.raw.location.locality)
- }
- if(json.processed.location.stateProvince){
- data.put("State", json.processed.location.stateProvince)
- }
- if(json.processed.location.country){
- data.put("Country", json.processed.location.country)
+ if (json.processed.location.decimalLatitude && json.processed.location.decimalLongitude) {
+ data.put("Coordinates", json.processed.location.decimalLatitude + " " + json.processed.location.decimalLongitude)
+ }
+ if (json.raw.location.locality) {
+ data.put("Locality", json.raw.location.locality)
+ }
+ if (json.processed.location.stateProvince) {
+ data.put("State", json.processed.location.stateProvince)
+ }
+ if (json.processed.location.country) {
+ data.put("Country", json.processed.location.country)
+ }
}
def model = [title:title, data:data, link:grailsApplication.config.biocache.baseURL + "/occurrence/" + params.recordId, linkText:"View full record details"]
@@ -63,4 +62,9 @@ class ViewController {
response.setContentType("application/json")
render output
}
+
+ @Override
+ void setConfiguration(Config config) {
+ biocacheServicesUrl = new URL(config.getRequiredProperty("biocache.servicesUrl"))
+ }
}
diff --git a/grails-app/conf/UrlMappings.groovy b/grails-app/controllers/specimenbrowser/UrlMappings.groovy
similarity index 57%
rename from grails-app/conf/UrlMappings.groovy
rename to grails-app/controllers/specimenbrowser/UrlMappings.groovy
index d926e15..4c20d7a 100644
--- a/grails-app/conf/UrlMappings.groovy
+++ b/grails-app/controllers/specimenbrowser/UrlMappings.groovy
@@ -1,7 +1,8 @@
-class UrlMappings {
+package specimenbrowser
- static mappings = {
+class UrlMappings {
+ static mappings = {
"/browse/$id?"{
controller = 'browse'
action = 'index'
@@ -15,15 +16,17 @@ class UrlMappings {
}
}
- "/$controller/$action?/$id?"{
- constraints {
- // apply constraints here
- }
- }
- "/"(controller: 'view', action: 'homePage')
- "/auxData/$recordId"(controller: 'view', action: 'auxData')
+ "/"(controller: 'view', action: 'homePage')
+ "/view/auxData/$recordId"(controller: 'view', action: 'auxData')
"/view/$id"(controller: 'view', action: 'view')
- "500"(view:'/error')
- }
+ "/$controller/$action?/$id?"{
+ constraints {
+ // apply constraints here
+ }
+ }
+
+ "500"(view:'/error')
+ "404"(view:'/notFound')
+ }
}
diff --git a/grails-app/i18n/messages.properties b/grails-app/i18n/messages.properties
index 0c9d7ee..b045136 100644
--- a/grails-app/i18n/messages.properties
+++ b/grails-app/i18n/messages.properties
@@ -53,3 +53,4 @@ typeMismatch.java.lang.Long=Property {0} must be a valid number
typeMismatch.java.lang.Short=Property {0} must be a valid number
typeMismatch.java.math.BigDecimal=Property {0} must be a valid number
typeMismatch.java.math.BigInteger=Property {0} must be a valid number
+typeMismatch=Property {0} is type-mismatched
diff --git a/grails-app/i18n/messages_cs_CZ.properties b/grails-app/i18n/messages_cs.properties
similarity index 98%
rename from grails-app/i18n/messages_cs_CZ.properties
rename to grails-app/i18n/messages_cs.properties
index c617dca..7345531 100644
--- a/grails-app/i18n/messages_cs_CZ.properties
+++ b/grails-app/i18n/messages_cs.properties
@@ -1,55 +1,55 @@
-default.doesnt.match.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] neodpovídá požadovanému vzoru [{3}]
-default.invalid.url.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní URL
-default.invalid.creditCard.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní číslo kreditní karty
-default.invalid.email.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní emailová adresa
-default.invalid.range.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není v povoleném rozmezí od [{3}] do [{4}]
-default.invalid.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není v povoleném rozmezí od [{3}] do [{4}]
-default.invalid.max.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] překračuje maximální povolenou hodnotu [{3}]
-default.invalid.min.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] je menší než minimální povolená hodnota [{3}]
-default.invalid.max.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] překračuje maximální velikost [{3}]
-default.invalid.min.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] je menší než minimální velikost [{3}]
-default.invalid.validator.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] neprošla validací
-default.not.inlist.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není obsažena v seznamu [{3}]
-default.blank.message=Položka [{0}] třídy [{1}] nemůže být prázdná
-default.not.equal.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] nemůže být stejná jako [{3}]
-default.null.message=Položka [{0}] třídy [{1}] nemůže být prázdná
-default.not.unique.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] musí být unikátní
-
-default.paginate.prev=Předcházející
-default.paginate.next=Následující
-default.boolean.true=Pravda
-default.boolean.false=Nepravda
-default.date.format=dd. MM. yyyy HH:mm:ss z
-default.number.format=0
-
-default.created.message={0} {1} vytvořeno
-default.updated.message={0} {1} aktualizováno
-default.deleted.message={0} {1} smazáno
-default.not.deleted.message={0} {1} nelze smazat
-default.not.found.message={0} nenalezen s id {1}
-default.optimistic.locking.failure=Jiný uživatel aktualizoval záznam {0}, právě když byl vámi editován
-
-default.home.label=Domů
-default.list.label={0} Seznam
-default.add.label=Přidat {0}
-default.new.label=Nový {0}
-default.create.label=Vytvořit {0}
-default.show.label=Ukázat {0}
-default.edit.label=Editovat {0}
-
-default.button.create.label=Vytvoř
-default.button.edit.label=Edituj
-default.button.update.label=Aktualizuj
-default.button.delete.label=Smaž
-default.button.delete.confirm.message=Jste si jistý?
-
-# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
-typeMismatch.java.net.URL=Položka {0} musí být validní URL
-typeMismatch.java.net.URI=Položka {0} musí být validní URI
-typeMismatch.java.util.Date=Položka {0} musí být validní datum
-typeMismatch.java.lang.Double=Položka {0} musí být validní desetinné číslo
-typeMismatch.java.lang.Integer=Položka {0} musí být validní číslo
-typeMismatch.java.lang.Long=Položka {0} musí být validní číslo
-typeMismatch.java.lang.Short=Položka {0} musí být validní číslo
-typeMismatch.java.math.BigDecimal=Položka {0} musí být validní číslo
-typeMismatch.java.math.BigInteger=Položka {0} musí být validní číslo
\ No newline at end of file
+default.doesnt.match.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] neodpovídá požadovanému vzoru [{3}]
+default.invalid.url.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní URL
+default.invalid.creditCard.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní číslo kreditní karty
+default.invalid.email.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní emailová adresa
+default.invalid.range.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není v povoleném rozmezí od [{3}] do [{4}]
+default.invalid.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není v povoleném rozmezí od [{3}] do [{4}]
+default.invalid.max.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] překračuje maximální povolenou hodnotu [{3}]
+default.invalid.min.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] je menší než minimální povolená hodnota [{3}]
+default.invalid.max.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] překračuje maximální velikost [{3}]
+default.invalid.min.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] je menší než minimální velikost [{3}]
+default.invalid.validator.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] neprošla validací
+default.not.inlist.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není obsažena v seznamu [{3}]
+default.blank.message=Položka [{0}] třídy [{1}] nemůže být prázdná
+default.not.equal.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] nemůže být stejná jako [{3}]
+default.null.message=Položka [{0}] třídy [{1}] nemůže být prázdná
+default.not.unique.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] musí být unikátní
+
+default.paginate.prev=Předcházející
+default.paginate.next=Následující
+default.boolean.true=Pravda
+default.boolean.false=Nepravda
+default.date.format=dd. MM. yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} vytvořeno
+default.updated.message={0} {1} aktualizováno
+default.deleted.message={0} {1} smazáno
+default.not.deleted.message={0} {1} nelze smazat
+default.not.found.message={0} nenalezen s id {1}
+default.optimistic.locking.failure=Jiný uživatel aktualizoval záznam {0}, právě když byl vámi editován
+
+default.home.label=Domů
+default.list.label={0} Seznam
+default.add.label=Přidat {0}
+default.new.label=Nový {0}
+default.create.label=Vytvořit {0}
+default.show.label=Ukázat {0}
+default.edit.label=Editovat {0}
+
+default.button.create.label=Vytvoř
+default.button.edit.label=Edituj
+default.button.update.label=Aktualizuj
+default.button.delete.label=Smaž
+default.button.delete.confirm.message=Jste si jistý?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Položka {0} musí být validní URL
+typeMismatch.java.net.URI=Položka {0} musí být validní URI
+typeMismatch.java.util.Date=Položka {0} musí být validní datum
+typeMismatch.java.lang.Double=Položka {0} musí být validní desetinné číslo
+typeMismatch.java.lang.Integer=Položka {0} musí být validní číslo
+typeMismatch.java.lang.Long=Položka {0} musí být validní číslo
+typeMismatch.java.lang.Short=Položka {0} musí být validní číslo
+typeMismatch.java.math.BigDecimal=Položka {0} musí být validní číslo
+typeMismatch.java.math.BigInteger=Položka {0} musí být validní číslo
diff --git a/grails-app/i18n/messages_de.properties b/grails-app/i18n/messages_de.properties
index a942358..0f7bfe9 100644
--- a/grails-app/i18n/messages_de.properties
+++ b/grails-app/i18n/messages_de.properties
@@ -1,55 +1,55 @@
-default.doesnt.match.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] entspricht nicht dem vorgegebenen Muster [{3}]
-default.invalid.url.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige URL
-default.invalid.creditCard.message=Das Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige Kreditkartennummer
-default.invalid.email.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige E-Mail Adresse
-default.invalid.range.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht im Wertebereich von [{3}] bis [{4}]
-default.invalid.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht im Wertebereich von [{3}] bis [{4}]
-default.invalid.max.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist größer als der Höchstwert von [{3}]
-default.invalid.min.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist kleiner als der Mindestwert von [{3}]
-default.invalid.max.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] übersteigt den Höchstwert von [{3}]
-default.invalid.min.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] unterschreitet den Mindestwert von [{3}]
-default.invalid.validator.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist ungültig
-default.not.inlist.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht in der Liste [{3}] enthalten.
-default.blank.message=Die Eigenschaft [{0}] des Typs [{1}] darf nicht leer sein
-default.not.equal.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] darf nicht gleich [{3}] sein
-default.null.message=Die Eigenschaft [{0}] des Typs [{1}] darf nicht null sein
-default.not.unique.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] darf nur einmal vorkommen
-
-default.paginate.prev=Vorherige
-default.paginate.next=Nächste
-default.boolean.true=Wahr
-default.boolean.false=Falsch
-default.date.format=dd.MM.yyyy HH:mm:ss z
-default.number.format=0
-
-default.created.message={0} {1} wurde angelegt
-default.updated.message={0} {1} wurde geändert
-default.deleted.message={0} {1} wurde gelöscht
-default.not.deleted.message={0} {1} konnte nicht gelöscht werden
-default.not.found.message={0} mit der id {1} wurde nicht gefunden
-default.optimistic.locking.failure=Ein anderer Benutzer hat das {0} Object geändert während Sie es bearbeitet haben
-
-default.home.label=Home
-default.list.label={0} Liste
-default.add.label={0} hinzufügen
-default.new.label={0} anlegen
-default.create.label={0} anlegen
-default.show.label={0} anzeigen
-default.edit.label={0} bearbeiten
-
-default.button.create.label=Anlegen
-default.button.edit.label=Bearbeiten
-default.button.update.label=Aktualisieren
-default.button.delete.label=Löschen
-default.button.delete.confirm.message=Sind Sie sicher?
-
-# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
-typeMismatch.java.net.URL=Die Eigenschaft {0} muss eine gültige URL sein
-typeMismatch.java.net.URI=Die Eigenschaft {0} muss eine gültige URI sein
-typeMismatch.java.util.Date=Die Eigenschaft {0} muss ein gültiges Datum sein
-typeMismatch.java.lang.Double=Die Eigenschaft {0} muss eine gültige Zahl sein
-typeMismatch.java.lang.Integer=Die Eigenschaft {0} muss eine gültige Zahl sein
-typeMismatch.java.lang.Long=Die Eigenschaft {0} muss eine gültige Zahl sein
-typeMismatch.java.lang.Short=Die Eigenschaft {0} muss eine gültige Zahl sein
-typeMismatch.java.math.BigDecimal=Die Eigenschaft {0} muss eine gültige Zahl sein
-typeMismatch.java.math.BigInteger=Die Eigenschaft {0} muss eine gültige Zahl sein
\ No newline at end of file
+default.doesnt.match.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] entspricht nicht dem vorgegebenen Muster [{3}]
+default.invalid.url.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige URL
+default.invalid.creditCard.message=Das Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige Kreditkartennummer
+default.invalid.email.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige E-Mail Adresse
+default.invalid.range.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht im Wertebereich von [{3}] bis [{4}]
+default.invalid.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht im Wertebereich von [{3}] bis [{4}]
+default.invalid.max.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist größer als der Höchstwert von [{3}]
+default.invalid.min.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist kleiner als der Mindestwert von [{3}]
+default.invalid.max.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] übersteigt den Höchstwert von [{3}]
+default.invalid.min.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] unterschreitet den Mindestwert von [{3}]
+default.invalid.validator.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist ungültig
+default.not.inlist.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht in der Liste [{3}] enthalten.
+default.blank.message=Die Eigenschaft [{0}] des Typs [{1}] darf nicht leer sein
+default.not.equal.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] darf nicht gleich [{3}] sein
+default.null.message=Die Eigenschaft [{0}] des Typs [{1}] darf nicht null sein
+default.not.unique.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] darf nur einmal vorkommen
+
+default.paginate.prev=Vorherige
+default.paginate.next=Nächste
+default.boolean.true=Wahr
+default.boolean.false=Falsch
+default.date.format=dd.MM.yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} wurde angelegt
+default.updated.message={0} {1} wurde geändert
+default.deleted.message={0} {1} wurde gelöscht
+default.not.deleted.message={0} {1} konnte nicht gelöscht werden
+default.not.found.message={0} mit der id {1} wurde nicht gefunden
+default.optimistic.locking.failure=Ein anderer Benutzer hat das {0} Object geändert während Sie es bearbeitet haben
+
+default.home.label=Home
+default.list.label={0} Liste
+default.add.label={0} hinzufügen
+default.new.label={0} anlegen
+default.create.label={0} anlegen
+default.show.label={0} anzeigen
+default.edit.label={0} bearbeiten
+
+default.button.create.label=Anlegen
+default.button.edit.label=Bearbeiten
+default.button.update.label=Aktualisieren
+default.button.delete.label=Löschen
+default.button.delete.confirm.message=Sind Sie sicher?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Die Eigenschaft {0} muss eine gültige URL sein
+typeMismatch.java.net.URI=Die Eigenschaft {0} muss eine gültige URI sein
+typeMismatch.java.util.Date=Die Eigenschaft {0} muss ein gültiges Datum sein
+typeMismatch.java.lang.Double=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.lang.Integer=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.lang.Long=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.lang.Short=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.math.BigDecimal=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.math.BigInteger=Die Eigenschaft {0} muss eine gültige Zahl sein
diff --git a/grails-app/i18n/messages_fr.properties b/grails-app/i18n/messages_fr.properties
index b1d665c..5572164 100644
--- a/grails-app/i18n/messages_fr.properties
+++ b/grails-app/i18n/messages_fr.properties
@@ -1,19 +1,19 @@
-default.doesnt.match.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne correspond pas au pattern [{3}]
-default.invalid.url.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas une URL valide
-default.invalid.creditCard.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas un numéro de carte de crédit valide
-default.invalid.email.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas une adresse e-mail valide
-default.invalid.range.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas contenue dans l'intervalle [{3}] à [{4}]
-default.invalid.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas contenue dans l'intervalle [{3}] à [{4}]
-default.invalid.max.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est supérieure à la valeur maximum [{3}]
-default.invalid.min.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est inférieure à la valeur minimum [{3}]
-default.invalid.max.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est supérieure à la valeur maximum [{3}]
-default.invalid.min.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est inférieure à la valeur minimum [{3}]
-default.invalid.validator.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas valide
-default.not.inlist.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne fait pas partie de la liste [{3}]
-default.blank.message=La propriété [{0}] de la classe [{1}] ne peut pas être vide
-default.not.equal.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne peut pas être égale à [{3}]
-default.null.message=La propriété [{0}] de la classe [{1}] ne peut pas être nulle
-default.not.unique.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] doit être unique
-
-default.paginate.prev=Précédent
-default.paginate.next=Suivant
+default.doesnt.match.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne correspond pas au pattern [{3}]
+default.invalid.url.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas une URL valide
+default.invalid.creditCard.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas un numéro de carte de crédit valide
+default.invalid.email.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas une adresse e-mail valide
+default.invalid.range.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas contenue dans l'intervalle [{3}] à [{4}]
+default.invalid.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas contenue dans l'intervalle [{3}] à [{4}]
+default.invalid.max.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est supérieure à la valeur maximum [{3}]
+default.invalid.min.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est inférieure à la valeur minimum [{3}]
+default.invalid.max.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est supérieure à la valeur maximum [{3}]
+default.invalid.min.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est inférieure à la valeur minimum [{3}]
+default.invalid.validator.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas valide
+default.not.inlist.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne fait pas partie de la liste [{3}]
+default.blank.message=La propriété [{0}] de la classe [{1}] ne peut pas être vide
+default.not.equal.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne peut pas être égale à [{3}]
+default.null.message=La propriété [{0}] de la classe [{1}] ne peut pas être nulle
+default.not.unique.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] doit être unique
+
+default.paginate.prev=Précédent
+default.paginate.next=Suivant
diff --git a/grails-app/i18n/messages_it.properties b/grails-app/i18n/messages_it.properties
index 462ec1c..a90f1c7 100644
--- a/grails-app/i18n/messages_it.properties
+++ b/grails-app/i18n/messages_it.properties
@@ -1,55 +1,55 @@
-default.doesnt.match.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non corrisponde al pattern [{3}]
-default.invalid.url.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un URL valido
-default.invalid.creditCard.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un numero di carta di credito valido
-default.invalid.email.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un indirizzo email valido
-default.invalid.range.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non rientra nell'intervallo valido da [{3}] a [{4}]
-default.invalid.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non rientra nell'intervallo di dimensioni valide da [{3}] a [{4}]
-default.invalid.max.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è maggiore di [{3}]
-default.invalid.min.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è minore di [{3}]
-default.invalid.max.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è maggiore di [{3}]
-default.invalid.min.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è minore di [{3}]
-default.invalid.validator.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è valida
-default.not.inlist.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è contenuta nella lista [{3}]
-default.blank.message=La proprietà [{0}] della classe [{1}] non può essere vuota
-default.not.equal.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non può essere uguale a [{3}]
-default.null.message=La proprietà [{0}] della classe [{1}] non può essere null
-default.not.unique.message=La proprietà [{0}] della classe [{1}] con valore [{2}] deve essere unica
-
-default.paginate.prev=Precedente
-default.paginate.next=Successivo
-default.boolean.true=Vero
-default.boolean.false=Falso
-default.date.format=dd/MM/yyyy HH:mm:ss z
-default.number.format=0
-
-default.created.message={0} {1} creato
-default.updated.message={0} {1} aggiornato
-default.deleted.message={0} {1} eliminato
-default.not.deleted.message={0} {1} non può essere eliminato
-default.not.found.message={0} non trovato con id {1}
-default.optimistic.locking.failure=Un altro utente ha aggiornato questo {0} mentre si era in modifica
-
-default.home.label=Home
-default.list.label={0} Elenco
-default.add.label=Aggiungi {0}
-default.new.label=Nuovo {0}
-default.create.label=Crea {0}
-default.show.label=Mostra {0}
-default.edit.label=Modifica {0}
-
-default.button.create.label=Crea
-default.button.edit.label=Modifica
-default.button.update.label=Aggiorna
-default.button.delete.label=Elimina
-default.button.delete.confirm.message=Si è sicuri?
-
-# Data binding errors. Usa "typeMismatch.$className.$propertyName per la personalizzazione (es typeMismatch.Book.author)
-typeMismatch.java.net.URL=La proprietà {0} deve essere un URL valido
-typeMismatch.java.net.URI=La proprietà {0} deve essere un URI valido
-typeMismatch.java.util.Date=La proprietà {0} deve essere una data valida
-typeMismatch.java.lang.Double=La proprietà {0} deve essere un numero valido
-typeMismatch.java.lang.Integer=La proprietà {0} deve essere un numero valido
-typeMismatch.java.lang.Long=La proprietà {0} deve essere un numero valido
-typeMismatch.java.lang.Short=La proprietà {0} deve essere un numero valido
-typeMismatch.java.math.BigDecimal=La proprietà {0} deve essere un numero valido
-typeMismatch.java.math.BigInteger=La proprietà {0} deve essere un numero valido
+default.doesnt.match.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non corrisponde al pattern [{3}]
+default.invalid.url.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un URL valido
+default.invalid.creditCard.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un numero di carta di credito valido
+default.invalid.email.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un indirizzo email valido
+default.invalid.range.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non rientra nell'intervallo valido da [{3}] a [{4}]
+default.invalid.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non rientra nell'intervallo di dimensioni valide da [{3}] a [{4}]
+default.invalid.max.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è maggiore di [{3}]
+default.invalid.min.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è minore di [{3}]
+default.invalid.max.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è maggiore di [{3}]
+default.invalid.min.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è minore di [{3}]
+default.invalid.validator.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è valida
+default.not.inlist.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è contenuta nella lista [{3}]
+default.blank.message=La proprietà [{0}] della classe [{1}] non può essere vuota
+default.not.equal.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non può essere uguale a [{3}]
+default.null.message=La proprietà [{0}] della classe [{1}] non può essere null
+default.not.unique.message=La proprietà [{0}] della classe [{1}] con valore [{2}] deve essere unica
+
+default.paginate.prev=Precedente
+default.paginate.next=Successivo
+default.boolean.true=Vero
+default.boolean.false=Falso
+default.date.format=dd/MM/yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} creato
+default.updated.message={0} {1} aggiornato
+default.deleted.message={0} {1} eliminato
+default.not.deleted.message={0} {1} non può essere eliminato
+default.not.found.message={0} non trovato con id {1}
+default.optimistic.locking.failure=Un altro utente ha aggiornato questo {0} mentre si era in modifica
+
+default.home.label=Home
+default.list.label={0} Elenco
+default.add.label=Aggiungi {0}
+default.new.label=Nuovo {0}
+default.create.label=Crea {0}
+default.show.label=Mostra {0}
+default.edit.label=Modifica {0}
+
+default.button.create.label=Crea
+default.button.edit.label=Modifica
+default.button.update.label=Aggiorna
+default.button.delete.label=Elimina
+default.button.delete.confirm.message=Si è sicuri?
+
+# Data binding errors. Usa "typeMismatch.$className.$propertyName per la personalizzazione (es typeMismatch.Book.author)
+typeMismatch.java.net.URL=La proprietà {0} deve essere un URL valido
+typeMismatch.java.net.URI=La proprietà {0} deve essere un URI valido
+typeMismatch.java.util.Date=La proprietà {0} deve essere una data valida
+typeMismatch.java.lang.Double=La proprietà {0} deve essere un numero valido
+typeMismatch.java.lang.Integer=La proprietà {0} deve essere un numero valido
+typeMismatch.java.lang.Long=La proprietà {0} deve essere un numero valido
+typeMismatch.java.lang.Short=La proprietà {0} deve essere un numero valido
+typeMismatch.java.math.BigDecimal=La proprietà {0} deve essere un numero valido
+typeMismatch.java.math.BigInteger=La proprietà {0} deve essere un numero valido
diff --git a/grails-app/i18n/messages_ja.properties b/grails-app/i18n/messages_ja.properties
index b5e4d18..d9e9b78 100644
--- a/grails-app/i18n/messages_ja.properties
+++ b/grails-app/i18n/messages_ja.properties
@@ -1,55 +1,55 @@
-default.doesnt.match.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]パターンと一致していません。
-default.invalid.url.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なURLではありません。
-default.invalid.creditCard.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なクレジットカード番号ではありません。
-default.invalid.email.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なメールアドレスではありません。
-default.invalid.range.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]から[{4}]範囲内を指定してください。
-default.invalid.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]から[{4}]以内を指定してください。
-default.invalid.max.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最大値[{3}]より大きいです。
-default.invalid.min.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最小値[{3}]より小さいです。
-default.invalid.max.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最大値[{3}]より大きいです。
-default.invalid.min.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最小値[{3}]より小さいです。
-default.invalid.validator.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、カスタムバリデーションを通過できません。
-default.not.inlist.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]リスト内に存在しません。
-default.blank.message=[{1}]クラスのプロパティ[{0}]の空白は許可されません。
-default.not.equal.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]と同等ではありません。
-default.null.message=[{1}]クラスのプロパティ[{0}]にnullは許可されません。
-default.not.unique.message=クラス[{1}]プロパティ[{0}]の値[{2}]は既に使用されています。
-
-default.paginate.prev=戻る
-default.paginate.next=次へ
-default.boolean.true=はい
-default.boolean.false=いいえ
-default.date.format=yyyy/MM/dd HH:mm:ss z
-default.number.format=0
-
-default.created.message={0}(id:{1})を作成しました。
-default.updated.message={0}(id:{1})を更新しました。
-default.deleted.message={0}(id:{1})を削除しました。
-default.not.deleted.message={0}(id:{1})は削除できませんでした。
-default.not.found.message={0}(id:{1})は見つかりませんでした。
-default.optimistic.locking.failure=この{0}は編集中に他のユーザによって先に更新されています。
-
-default.home.label=ホーム
-default.list.label={0}リスト
-default.add.label={0}を追加
-default.new.label={0}を新規作成
-default.create.label={0}を作成
-default.show.label={0}詳細
-default.edit.label={0}を編集
-
-default.button.create.label=作成
-default.button.edit.label=編集
-default.button.update.label=更新
-default.button.delete.label=削除
-default.button.delete.confirm.message=本当に削除してよろしいですか?
-
-# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
-typeMismatch.java.net.URL={0}は有効なURLでなければなりません。
-typeMismatch.java.net.URI={0}は有効なURIでなければなりません。
-typeMismatch.java.util.Date={0}は有効な日付でなければなりません。
-typeMismatch.java.lang.Double={0}は有効な数値でなければなりません。
-typeMismatch.java.lang.Integer={0}は有効な数値でなければなりません。
-typeMismatch.java.lang.Long={0}は有効な数値でなければなりません。
-typeMismatch.java.lang.Short={0}は有効な数値でなければなりません。
-typeMismatch.java.math.BigDecimal={0}は有効な数値でなければなりません。
-typeMismatch.java.math.BigInteger={0}は有効な数値でなければなりません。
+default.doesnt.match.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]パターンと一致していません。
+default.invalid.url.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なURLではありません。
+default.invalid.creditCard.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なクレジットカード番号ではありません。
+default.invalid.email.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なメールアドレスではありません。
+default.invalid.range.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]から[{4}]範囲内を指定してください。
+default.invalid.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]から[{4}]以内を指定してください。
+default.invalid.max.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最大値[{3}]より大きいです。
+default.invalid.min.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最小値[{3}]より小さいです。
+default.invalid.max.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最大値[{3}]より大きいです。
+default.invalid.min.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最小値[{3}]より小さいです。
+default.invalid.validator.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、カスタムバリデーションを通過できません。
+default.not.inlist.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]リスト内に存在しません。
+default.blank.message=[{1}]クラスのプロパティ[{0}]の空白は許可されません。
+default.not.equal.message=クラス[{1}]プロパティ[{0}]の値[{2}]に[{3}]は許可されません。
+default.null.message=[{1}]クラスのプロパティ[{0}]にnullは許可されません。
+default.not.unique.message=クラス[{1}]プロパティ[{0}]の値[{2}]は既に使用されています。
+
+default.paginate.prev=戻る
+default.paginate.next=次へ
+default.boolean.true=はい
+default.boolean.false=いいえ
+default.date.format=yyyy/MM/dd HH:mm:ss z
+default.number.format=0
+
+default.created.message={0}(id:{1})を作成しました。
+default.updated.message={0}(id:{1})を更新しました。
+default.deleted.message={0}(id:{1})を削除しました。
+default.not.deleted.message={0}(id:{1})は削除できませんでした。
+default.not.found.message={0}(id:{1})は見つかりませんでした。
+default.optimistic.locking.failure=この{0}は編集中に他のユーザによって先に更新されています。
+
+default.home.label=ホーム
+default.list.label={0}リスト
+default.add.label={0}を追加
+default.new.label={0}を新規作成
+default.create.label={0}を作成
+default.show.label={0}詳細
+default.edit.label={0}を編集
+
+default.button.create.label=作成
+default.button.edit.label=編集
+default.button.update.label=更新
+default.button.delete.label=削除
+default.button.delete.confirm.message=本当に削除してよろしいですか?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL={0}は有効なURLでなければなりません。
+typeMismatch.java.net.URI={0}は有効なURIでなければなりません。
+typeMismatch.java.util.Date={0}は有効な日付でなければなりません。
+typeMismatch.java.lang.Double={0}は有効な数値でなければなりません。
+typeMismatch.java.lang.Integer={0}は有効な数値でなければなりません。
+typeMismatch.java.lang.Long={0}は有効な数値でなければなりません。
+typeMismatch.java.lang.Short={0}は有効な数値でなければなりません。
+typeMismatch.java.math.BigDecimal={0}は有効な数値でなければなりません。
+typeMismatch.java.math.BigInteger={0}は有効な数値でなければなりません。
diff --git a/grails-app/i18n/messages_pt_BR.properties b/grails-app/i18n/messages_pt_BR.properties
index 0c368f2..b5044e2 100644
--- a/grails-app/i18n/messages_pt_BR.properties
+++ b/grails-app/i18n/messages_pt_BR.properties
@@ -8,7 +8,7 @@ default.invalid.creditCard.message=O campo [{0}] da classe [{1}] com o valor [{2
default.invalid.email.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um endereço de email válido.
default.invalid.range.message=O campo [{0}] da classe [{1}] com o valor [{2}] não está entre a faixa de valores válida de [{3}] até [{4}]
default.invalid.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] não está na faixa de tamanho válida de [{3}] até [{4}]
-default.invalid.max.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapass o valor máximo [{3}]
+default.invalid.max.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o valor máximo [{3}]
default.invalid.min.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o valor mínimo [{3}]
default.invalid.max.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o tamanho máximo de [{3}]
default.invalid.min.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o tamanho mínimo de [{3}]
@@ -16,7 +16,7 @@ default.invalid.validator.message=O campo [{0}] da classe [{1}] com o valor [{2}
default.not.inlist.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um valor dentre os permitidos na lista [{3}]
default.blank.message=O campo [{0}] da classe [{1}] não pode ficar em branco
default.not.equal.message=O campo [{0}] da classe [{1}] com o valor [{2}] não pode ser igual a [{3}]
-default.null.message=O campo [{0}] da classe [{1}] não pode ser vazia
+default.null.message=O campo [{0}] da classe [{1}] não pode ser vazio
default.not.unique.message=O campo [{0}] da classe [{1}] com o valor [{2}] deve ser único
default.paginate.prev=Anterior
@@ -30,7 +30,7 @@ default.created.message={0} {1} criado
default.updated.message={0} {1} atualizado
default.deleted.message={0} {1} removido
default.not.deleted.message={0} {1} não pode ser removido
-default.not.found.message={0} não foi encontrado com id {1}
+default.not.found.message={0} não foi encontrado com o id {1}
default.optimistic.locking.failure=Outro usuário atualizou este [{0}] enquanto você tentou salvá-lo
default.home.label=Principal
@@ -56,4 +56,4 @@ typeMismatch.java.lang.Integer=O campo {0} deve ser um número válido.
typeMismatch.java.lang.Long=O campo {0} deve ser um número válido.
typeMismatch.java.lang.Short=O campo {0} deve ser um número válido.
typeMismatch.java.math.BigDecimal=O campo {0} deve ser um número válido.
-typeMismatch.java.math.BigInteger=O campo {0} deve ser um número válido.
\ No newline at end of file
+typeMismatch.java.math.BigInteger=O campo {0} deve ser um número válido.
diff --git a/grails-app/i18n/messages_pt_PT.properties b/grails-app/i18n/messages_pt_PT.properties
index 43a6416..a386070 100644
--- a/grails-app/i18n/messages_pt_PT.properties
+++ b/grails-app/i18n/messages_pt_PT.properties
@@ -1,34 +1,34 @@
-#
-# translation by miguel.ping@gmail.com, based on pt_BR translation by Lucas Teixeira - lucastex@gmail.com
-#
-
-default.doesnt.match.message=O campo [{0}] da classe [{1}] com o valor [{2}] não corresponde ao padrão definido [{3}]
-default.invalid.url.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um URL válido
-default.invalid.creditCard.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um número válido de cartão de crédito
-default.invalid.email.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um endereço de email válido.
-default.invalid.range.message=O campo [{0}] da classe [{1}] com o valor [{2}] não está dentro dos limites de valores válidos de [{3}] a [{4}]
-default.invalid.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] está fora dos limites de tamanho válido de [{3}] a [{4}]
-default.invalid.max.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o valor máximo [{3}]
-default.invalid.min.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o valor mínimo [{3}]
-default.invalid.max.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o tamanho máximo de [{3}]
-default.invalid.min.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o tamanho mínimo de [{3}]
-default.invalid.validator.message=O campo [{0}] da classe [{1}] com o valor [{2}] não passou na validação
-default.not.inlist.message=O campo [{0}] da classe [{1}] com o valor [{2}] não se encontra nos valores permitidos da lista [{3}]
-default.blank.message=O campo [{0}] da classe [{1}] não pode ser vazio
-default.not.equal.message=O campo [{0}] da classe [{1}] com o valor [{2}] não pode ser igual a [{3}]
-default.null.message=O campo [{0}] da classe [{1}] não pode ser vazio
-default.not.unique.message=O campo [{0}] da classe [{1}] com o valor [{2}] deve ser único
-
-default.paginate.prev=Anterior
-default.paginate.next=Próximo
-
-# Mensagens de erro em atribuição de valores. Use "typeMismatch.$className.$propertyName" para personalizar(eg typeMismatch.Book.author)
-typeMismatch.java.net.URL=O campo {0} deve ser um URL válido.
-typeMismatch.java.net.URI=O campo {0} deve ser um URI válido.
-typeMismatch.java.util.Date=O campo {0} deve ser uma data válida
-typeMismatch.java.lang.Double=O campo {0} deve ser um número válido.
-typeMismatch.java.lang.Integer=O campo {0} deve ser um número válido.
-typeMismatch.java.lang.Long=O campo {0} deve ser um número valido.
-typeMismatch.java.lang.Short=O campo {0} deve ser um número válido.
-typeMismatch.java.math.BigDecimal=O campo {0} deve ser um número válido.
-typeMismatch.java.math.BigInteger=O campo {0} deve ser um número válido.
+#
+# translation by miguel.ping@gmail.com, based on pt_BR translation by Lucas Teixeira - lucastex@gmail.com
+#
+
+default.doesnt.match.message=O campo [{0}] da classe [{1}] com o valor [{2}] não corresponde ao padrão definido [{3}]
+default.invalid.url.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um URL válido
+default.invalid.creditCard.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um número válido de cartão de crédito
+default.invalid.email.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um endereço de email válido.
+default.invalid.range.message=O campo [{0}] da classe [{1}] com o valor [{2}] não está dentro dos limites de valores válidos de [{3}] a [{4}]
+default.invalid.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] está fora dos limites de tamanho válido de [{3}] a [{4}]
+default.invalid.max.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o valor máximo [{3}]
+default.invalid.min.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o valor mínimo [{3}]
+default.invalid.max.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o tamanho máximo de [{3}]
+default.invalid.min.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o tamanho mínimo de [{3}]
+default.invalid.validator.message=O campo [{0}] da classe [{1}] com o valor [{2}] não passou na validação
+default.not.inlist.message=O campo [{0}] da classe [{1}] com o valor [{2}] não se encontra nos valores permitidos da lista [{3}]
+default.blank.message=O campo [{0}] da classe [{1}] não pode ser vazio
+default.not.equal.message=O campo [{0}] da classe [{1}] com o valor [{2}] não pode ser igual a [{3}]
+default.null.message=O campo [{0}] da classe [{1}] não pode ser vazio
+default.not.unique.message=O campo [{0}] da classe [{1}] com o valor [{2}] deve ser único
+
+default.paginate.prev=Anterior
+default.paginate.next=Próximo
+
+# Mensagens de erro em atribuição de valores. Use "typeMismatch.$className.$propertyName" para personalizar(eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=O campo {0} deve ser um URL válido.
+typeMismatch.java.net.URI=O campo {0} deve ser um URI válido.
+typeMismatch.java.util.Date=O campo {0} deve ser uma data válida
+typeMismatch.java.lang.Double=O campo {0} deve ser um número válido.
+typeMismatch.java.lang.Integer=O campo {0} deve ser um número válido.
+typeMismatch.java.lang.Long=O campo {0} deve ser um número valido.
+typeMismatch.java.lang.Short=O campo {0} deve ser um número válido.
+typeMismatch.java.math.BigDecimal=O campo {0} deve ser um número válido.
+typeMismatch.java.math.BigInteger=O campo {0} deve ser um número válido.
diff --git a/grails-app/i18n/messages_ru.properties b/grails-app/i18n/messages_ru.properties
index 02239db..53a4bdc 100644
--- a/grails-app/i18n/messages_ru.properties
+++ b/grails-app/i18n/messages_ru.properties
@@ -1,31 +1,31 @@
-default.doesnt.match.message=Значение [{2}] поля [{0}] класса [{1}] не соответствует образцу [{3}]
-default.invalid.url.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым URL-адресом
-default.invalid.creditCard.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым номером кредитной карты
-default.invalid.email.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым e-mail адресом
-default.invalid.range.message=Значение [{2}] поля [{0}] класса [{1}] не попадает в допустимый интервал от [{3}] до [{4}]
-default.invalid.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) не попадает в допустимый интервал от [{3}] до [{4}]
-default.invalid.max.message=Значение [{2}] поля [{0}] класса [{1}] больше чем максимально допустимое значение [{3}]
-default.invalid.min.message=Значение [{2}] поля [{0}] класса [{1}] меньше чем минимально допустимое значение [{3}]
-default.invalid.max.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) больше чем максимально допустимый размер [{3}]
-default.invalid.min.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) меньше чем минимально допустимый размер [{3}]
-default.invalid.validator.message=Значение [{2}] поля [{0}] класса [{1}] не допустимо
-default.not.inlist.message=Значение [{2}] поля [{0}] класса [{1}] не попадает в список допустимых значений [{3}]
-default.blank.message=Поле [{0}] класса [{1}] не может быть пустым
-default.not.equal.message=Значение [{2}] поля [{0}] класса [{1}] не может быть равно [{3}]
-default.null.message=Поле [{0}] класса [{1}] не может иметь значение null
-default.not.unique.message=Значение [{2}] поля [{0}] класса [{1}] должно быть уникальным
-
-default.paginate.prev=Предыдушая страница
-default.paginate.next=Следующая страница
-
-# Ошибки при присвоении данных. Для точной настройки для полей классов используйте
-# формат "typeMismatch.$className.$propertyName" (например, typeMismatch.Book.author)
-typeMismatch.java.net.URL=Значение поля {0} не является допустимым URL
-typeMismatch.java.net.URI=Значение поля {0} не является допустимым URI
-typeMismatch.java.util.Date=Значение поля {0} не является допустимой датой
-typeMismatch.java.lang.Double=Значение поля {0} не является допустимым числом
-typeMismatch.java.lang.Integer=Значение поля {0} не является допустимым числом
-typeMismatch.java.lang.Long=Значение поля {0} не является допустимым числом
-typeMismatch.java.lang.Short=Значение поля {0} не является допустимым числом
-typeMismatch.java.math.BigDecimal=Значение поля {0} не является допустимым числом
-typeMismatch.java.math.BigInteger=Значение поля {0} не является допустимым числом
+default.doesnt.match.message=Значение [{2}] поля [{0}] класса [{1}] не соответствует образцу [{3}]
+default.invalid.url.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым URL-адресом
+default.invalid.creditCard.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым номером кредитной карты
+default.invalid.email.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым e-mail адресом
+default.invalid.range.message=Значение [{2}] поля [{0}] класса [{1}] не попадает в допустимый интервал от [{3}] до [{4}]
+default.invalid.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) не попадает в допустимый интервал от [{3}] до [{4}]
+default.invalid.max.message=Значение [{2}] поля [{0}] класса [{1}] больше чем максимально допустимое значение [{3}]
+default.invalid.min.message=Значение [{2}] поля [{0}] класса [{1}] меньше чем минимально допустимое значение [{3}]
+default.invalid.max.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) больше чем максимально допустимый размер [{3}]
+default.invalid.min.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) меньше чем минимально допустимый размер [{3}]
+default.invalid.validator.message=Значение [{2}] поля [{0}] класса [{1}] не допустимо
+default.not.inlist.message=Значение [{2}] поля [{0}] класса [{1}] не попадает в список допустимых значений [{3}]
+default.blank.message=Поле [{0}] класса [{1}] не может быть пустым
+default.not.equal.message=Значение [{2}] поля [{0}] класса [{1}] не может быть равно [{3}]
+default.null.message=Поле [{0}] класса [{1}] не может иметь значение null
+default.not.unique.message=Значение [{2}] поля [{0}] класса [{1}] должно быть уникальным
+
+default.paginate.prev=Предыдушая страница
+default.paginate.next=Следующая страница
+
+# Ошибки при присвоении данных. Для точной настройки для полей классов используйте
+# формат "typeMismatch.$className.$propertyName" (например, typeMismatch.Book.author)
+typeMismatch.java.net.URL=Значение поля {0} не является допустимым URL
+typeMismatch.java.net.URI=Значение поля {0} не является допустимым URI
+typeMismatch.java.util.Date=Значение поля {0} не является допустимой датой
+typeMismatch.java.lang.Double=Значение поля {0} не является допустимым числом
+typeMismatch.java.lang.Integer=Значение поля {0} не является допустимым числом
+typeMismatch.java.lang.Long=Значение поля {0} не является допустимым числом
+typeMismatch.java.lang.Short=Значение поля {0} не является допустимым числом
+typeMismatch.java.math.BigDecimal=Значение поля {0} не является допустимым числом
+typeMismatch.java.math.BigInteger=Значение поля {0} не является допустимым числом
diff --git a/grails-app/i18n/messages_sk.properties b/grails-app/i18n/messages_sk.properties
new file mode 100644
index 0000000..73ee0dc
--- /dev/null
+++ b/grails-app/i18n/messages_sk.properties
@@ -0,0 +1,56 @@
+default.doesnt.match.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] nezodpovedá požadovanému formátu [{3}]
+default.invalid.url.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] nie je platná URL adresa
+default.invalid.creditCard.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] nie je platné číslo kreditnej karty
+default.invalid.email.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] nie je platná emailová adresa
+default.invalid.range.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] nie je v povolenom rozmedzí od [{3}] do [{4}]
+default.invalid.size.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] nie je v povolenom rozmedzí od [{3}] do [{4}]
+default.invalid.max.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] prekračuje maximálnu povolenú hodnotu [{3}]
+default.invalid.min.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] je menšia ako minimálna povolená hodnota [{3}]
+default.invalid.max.size.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] prekračuje maximálnu veľkosť [{3}]
+default.invalid.min.size.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] je menšia ako minimálna veľkosť [{3}]
+default.invalid.validator.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] neprešla validáciou
+default.not.inlist.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] nie je obsiahnutá v zozname [{3}]
+default.blank.message=Položka [{0}] triedy [{1}] nemôže byť prázdna
+default.not.equal.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] nemôže byť rovnaká ako [{3}]
+default.null.message=Položka [{0}] triedy [{1}] nemôže byť prázdna
+default.not.unique.message=Položka [{0}] triedy [{1}] s hodnotou [{2}] musí byť unikátna
+
+default.paginate.prev=Predchádzajúce
+default.paginate.next=Nasledujúce
+default.boolean.true=Pravda
+default.boolean.false=Nepravda
+default.date.format=dd. MM. yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} vytvorené
+default.updated.message={0} {1} aktualizované
+default.deleted.message={0} {1} vymazané
+default.not.deleted.message={0} {1} nemožno zmazať
+default.not.found.message={0} nenájdené s id {1}
+default.optimistic.locking.failure=Iný používateľ aktualizoval záznam {0}, práve keď bol vami editovaný
+
+default.home.label=Domov
+default.list.label={0} Zoznam
+default.add.label=Pridať {0}
+default.new.label=Nový {0}
+default.create.label=Vytvoriť {0}
+default.show.label=Ukázať {0}
+default.edit.label=Editovať {0}
+
+default.button.create.label=Vytvor
+default.button.edit.label=Edituj
+default.button.update.label=Aktualizuj
+default.button.delete.label=Zmaž
+default.button.delete.confirm.message=Ste si istý?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Položka {0} musí byť platná URL adresa
+typeMismatch.java.net.URI=Položka {0} musí byť platná URI adresa
+typeMismatch.java.util.Date=Položka {0} musí byť platný dátum
+typeMismatch.java.lang.Double=Položka {0} musí byť desatinné číslo
+typeMismatch.java.lang.Integer=Položka {0} musí byť celé číslo
+typeMismatch.java.lang.Long=Položka {0} musí byť celé číslo
+typeMismatch.java.lang.Short=Položka {0} musí byť celé číslo
+typeMismatch.java.math.BigDecimal=Položka {0} musí byť desatinné číslo
+typeMismatch.java.math.BigInteger=Položka {0} musí byť celé číslo
+typeMismatch=Položka {0} má nezhodný typ
diff --git a/grails-app/i18n/messages_th.properties b/grails-app/i18n/messages_th.properties
index 4f4076d..fd0dbb6 100644
--- a/grails-app/i18n/messages_th.properties
+++ b/grails-app/i18n/messages_th.properties
@@ -1,55 +1,55 @@
-default.doesnt.match.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบที่กำหนดไว้ใน [{3}]
-default.invalid.url.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบ URL
-default.invalid.creditCard.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบหมายเลขบัตรเครดิต
-default.invalid.email.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบอีเมล์
-default.invalid.range.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้มีค่าที่ถูกต้องในช่วงจาก [{3}] ถึง [{4}]
-default.invalid.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้มีขนาดที่ถูกต้องในช่วงจาก [{3}] ถึง [{4}]
-default.invalid.max.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีค่าเกิดกว่าค่ามากสุด [{3}]
-default.invalid.min.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีค่าน้อยกว่าค่าต่ำสุด [{3}]
-default.invalid.max.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีขนาดเกินกว่าขนาดมากสุดของ [{3}]
-default.invalid.min.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีขนาดต่ำกว่าขนาดต่ำสุดของ [{3}]
-default.invalid.validator.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ผ่านการทวนสอบค่าที่ตั้งขึ้น
-default.not.inlist.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้อยู่ในรายการต่อไปนี้ [{3}]
-default.blank.message=คุณสมบัติ [{0}] ของคลาส [{1}] ไม่สามารถเป็นค่าว่างได้
-default.not.equal.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่สามารถเท่ากับ [{3}] ได้
-default.null.message=คุณสมบัติ [{0}] ของคลาส [{1}] ไม่สามารถเป็น null ได้
-default.not.unique.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] จะต้องไม่ซ้ำ (unique)
-
-default.paginate.prev=ก่อนหน้า
-default.paginate.next=ถัดไป
-default.boolean.true=จริง
-default.boolean.false=เท็จ
-default.date.format=dd-MM-yyyy HH:mm:ss z
-default.number.format=0
-
-default.created.message=สร้าง {0} {1} เรียบร้อยแล้ว
-default.updated.message=ปรับปรุง {0} {1} เรียบร้อยแล้ว
-default.deleted.message=ลบ {0} {1} เรียบร้อยแล้ว
-default.not.deleted.message=ไม่สามารถลบ {0} {1}
-default.not.found.message=ไม่พบ {0} ด้วย id {1} นี้
-default.optimistic.locking.failure=มีผู้ใช้ท่านอื่นปรับปรุง {0} ขณะที่คุณกำลังแก้ไขข้อมูลอยู่
-
-default.home.label=หน้าแรก
-default.list.label=รายการ {0}
-default.add.label=เพิ่ม {0}
-default.new.label=สร้าง {0} ใหม่
-default.create.label=สร้าง {0}
-default.show.label=แสดง {0}
-default.edit.label=แก้ไข {0}
-
-default.button.create.label=สร้าง
-default.button.edit.label=แก้ไข
-default.button.update.label=ปรับปรุง
-default.button.delete.label=ลบ
-default.button.delete.confirm.message=คุณแน่ใจหรือไม่ ?
-
-# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
-typeMismatch.java.net.URL=คุณสมบัติ '{0}' จะต้องเป็นค่า URL ที่ถูกต้อง
-typeMismatch.java.net.URI=คุณสมบัติ '{0}' จะต้องเป็นค่า URI ที่ถูกต้อง
-typeMismatch.java.util.Date=คุณสมบัติ '{0}' จะต้องมีค่าเป็นวันที่
-typeMismatch.java.lang.Double=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Double
-typeMismatch.java.lang.Integer=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Integer
-typeMismatch.java.lang.Long=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Long
-typeMismatch.java.lang.Short=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Short
-typeMismatch.java.math.BigDecimal=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท BigDecimal
-typeMismatch.java.math.BigInteger=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท BigInteger
+default.doesnt.match.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบที่กำหนดไว้ใน [{3}]
+default.invalid.url.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบ URL
+default.invalid.creditCard.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบหมายเลขบัตรเครดิต
+default.invalid.email.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบอีเมล์
+default.invalid.range.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้มีค่าที่ถูกต้องในช่วงจาก [{3}] ถึง [{4}]
+default.invalid.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้มีขนาดที่ถูกต้องในช่วงจาก [{3}] ถึง [{4}]
+default.invalid.max.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีค่าเกิดกว่าค่ามากสุด [{3}]
+default.invalid.min.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีค่าน้อยกว่าค่าต่ำสุด [{3}]
+default.invalid.max.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีขนาดเกินกว่าขนาดมากสุดของ [{3}]
+default.invalid.min.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีขนาดต่ำกว่าขนาดต่ำสุดของ [{3}]
+default.invalid.validator.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ผ่านการทวนสอบค่าที่ตั้งขึ้น
+default.not.inlist.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้อยู่ในรายการต่อไปนี้ [{3}]
+default.blank.message=คุณสมบัติ [{0}] ของคลาส [{1}] ไม่สามารถเป็นค่าว่างได้
+default.not.equal.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่สามารถเท่ากับ [{3}] ได้
+default.null.message=คุณสมบัติ [{0}] ของคลาส [{1}] ไม่สามารถเป็น null ได้
+default.not.unique.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] จะต้องไม่ซ้ำ (unique)
+
+default.paginate.prev=ก่อนหน้า
+default.paginate.next=ถัดไป
+default.boolean.true=จริง
+default.boolean.false=เท็จ
+default.date.format=dd-MM-yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message=สร้าง {0} {1} เรียบร้อยแล้ว
+default.updated.message=ปรับปรุง {0} {1} เรียบร้อยแล้ว
+default.deleted.message=ลบ {0} {1} เรียบร้อยแล้ว
+default.not.deleted.message=ไม่สามารถลบ {0} {1}
+default.not.found.message=ไม่พบ {0} ด้วย id {1} นี้
+default.optimistic.locking.failure=มีผู้ใช้ท่านอื่นปรับปรุง {0} ขณะที่คุณกำลังแก้ไขข้อมูลอยู่
+
+default.home.label=หน้าแรก
+default.list.label=รายการ {0}
+default.add.label=เพิ่ม {0}
+default.new.label=สร้าง {0} ใหม่
+default.create.label=สร้าง {0}
+default.show.label=แสดง {0}
+default.edit.label=แก้ไข {0}
+
+default.button.create.label=สร้าง
+default.button.edit.label=แก้ไข
+default.button.update.label=ปรับปรุง
+default.button.delete.label=ลบ
+default.button.delete.confirm.message=คุณแน่ใจหรือไม่ ?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=คุณสมบัติ '{0}' จะต้องเป็นค่า URL ที่ถูกต้อง
+typeMismatch.java.net.URI=คุณสมบัติ '{0}' จะต้องเป็นค่า URI ที่ถูกต้อง
+typeMismatch.java.util.Date=คุณสมบัติ '{0}' จะต้องมีค่าเป็นวันที่
+typeMismatch.java.lang.Double=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Double
+typeMismatch.java.lang.Integer=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Integer
+typeMismatch.java.lang.Long=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Long
+typeMismatch.java.lang.Short=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Short
+typeMismatch.java.math.BigDecimal=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท BigDecimal
+typeMismatch.java.math.BigInteger=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท BigInteger
diff --git a/grails-app/i18n/messages_zh_CN.properties b/grails-app/i18n/messages_zh_CN.properties
index 782580b..b89bc93 100644
--- a/grails-app/i18n/messages_zh_CN.properties
+++ b/grails-app/i18n/messages_zh_CN.properties
@@ -1,18 +1,18 @@
-default.blank.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u4E0D\u80FD\u4E3A\u7A7A
-default.doesnt.match.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0E\u5B9A\u4E49\u7684\u6A21\u5F0F [{3}]\u4E0D\u5339\u914D
-default.invalid.creditCard.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u4FE1\u7528\u5361\u53F7
-default.invalid.email.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u5408\u6CD5\u7684\u7535\u5B50\u90AE\u4EF6\u5730\u5740
-default.invalid.max.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u6BD4\u6700\u5927\u503C [{3}]\u8FD8\u5927
-default.invalid.max.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u6BD4\u6700\u5927\u503C [{3}]\u8FD8\u5927
-default.invalid.min.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u6BD4\u6700\u5C0F\u503C [{3}]\u8FD8\u5C0F
-default.invalid.min.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u6BD4\u6700\u5C0F\u503C [{3}]\u8FD8\u5C0F
-default.invalid.range.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u5728\u5408\u6CD5\u7684\u8303\u56F4\u5185( [{3}] \uFF5E [{4}] )
-default.invalid.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u4E0D\u5728\u5408\u6CD5\u7684\u8303\u56F4\u5185( [{3}] \uFF5E [{4}] )
-default.invalid.url.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u5408\u6CD5\u7684URL
-default.invalid.validator.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u672A\u80FD\u901A\u8FC7\u81EA\u5B9A\u4E49\u7684\u9A8C\u8BC1
-default.not.equal.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0E[{3}]\u4E0D\u76F8\u7B49
-default.not.inlist.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u5728\u5217\u8868\u7684\u53D6\u503C\u8303\u56F4\u5185
-default.not.unique.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u5FC5\u987B\u662F\u552F\u4E00\u7684
-default.null.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u4E0D\u80FD\u4E3Anull
-default.paginate.next=\u4E0B\u9875
-default.paginate.prev=\u4E0A\u9875
+default.blank.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u4E0D\u80FD\u4E3A\u7A7A
+default.doesnt.match.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0E\u5B9A\u4E49\u7684\u6A21\u5F0F [{3}]\u4E0D\u5339\u914D
+default.invalid.creditCard.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u4FE1\u7528\u5361\u53F7
+default.invalid.email.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u5408\u6CD5\u7684\u7535\u5B50\u90AE\u4EF6\u5730\u5740
+default.invalid.max.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u6BD4\u6700\u5927\u503C [{3}]\u8FD8\u5927
+default.invalid.max.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u6BD4\u6700\u5927\u503C [{3}]\u8FD8\u5927
+default.invalid.min.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u6BD4\u6700\u5C0F\u503C [{3}]\u8FD8\u5C0F
+default.invalid.min.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u6BD4\u6700\u5C0F\u503C [{3}]\u8FD8\u5C0F
+default.invalid.range.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u5728\u5408\u6CD5\u7684\u8303\u56F4\u5185( [{3}] \uFF5E [{4}] )
+default.invalid.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u4E0D\u5728\u5408\u6CD5\u7684\u8303\u56F4\u5185( [{3}] \uFF5E [{4}] )
+default.invalid.url.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u5408\u6CD5\u7684URL
+default.invalid.validator.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u672A\u80FD\u901A\u8FC7\u81EA\u5B9A\u4E49\u7684\u9A8C\u8BC1
+default.not.equal.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0E[{3}]\u4E0D\u76F8\u7B49
+default.not.inlist.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u5728\u5217\u8868\u7684\u53D6\u503C\u8303\u56F4\u5185
+default.not.unique.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u5FC5\u987B\u662F\u552F\u4E00\u7684
+default.null.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u4E0D\u80FD\u4E3Anull
+default.paginate.next=\u4E0B\u9875
+default.paginate.prev=\u4E0A\u9875
diff --git a/grails-app/init/specimenbrowser/Application.groovy b/grails-app/init/specimenbrowser/Application.groovy
new file mode 100644
index 0000000..5c45de4
--- /dev/null
+++ b/grails-app/init/specimenbrowser/Application.groovy
@@ -0,0 +1,13 @@
+package specimenbrowser
+
+import grails.boot.GrailsApp
+import grails.boot.config.GrailsAutoConfiguration
+
+import groovy.transform.CompileStatic
+
+@CompileStatic
+class Application extends GrailsAutoConfiguration {
+ static void main(String[] args) {
+ GrailsApp.run(Application, args)
+ }
+}
\ No newline at end of file
diff --git a/grails-app/conf/BootStrap.groovy b/grails-app/init/specimenbrowser/BootStrap.groovy
similarity index 77%
rename from grails-app/conf/BootStrap.groovy
rename to grails-app/init/specimenbrowser/BootStrap.groovy
index 1287dae..4f53207 100644
--- a/grails-app/conf/BootStrap.groovy
+++ b/grails-app/init/specimenbrowser/BootStrap.groovy
@@ -1,3 +1,5 @@
+package specimenbrowser
+
class BootStrap {
def init = { servletContext ->
diff --git a/grails-app/services/au/org/ala/specimenbrowser/ResourceService.groovy b/grails-app/services/au/org/ala/specimenbrowser/ResourceService.groovy
new file mode 100644
index 0000000..661ae33
--- /dev/null
+++ b/grails-app/services/au/org/ala/specimenbrowser/ResourceService.groovy
@@ -0,0 +1,60 @@
+package au.org.ala.specimenbrowser
+
+import grails.config.Config
+import grails.core.support.GrailsConfigurationAware
+import groovy.json.JsonSlurper
+
+class ResourceService implements GrailsConfigurationAware {
+ /** The location of the resource configuration file */
+ URL resourceConfigurationUrl
+ /** The location of the collectory web services */
+ URL collectoryServicesUrl
+ /** The mappsings from collectory UIDs to resource types, eg co -> collection, dr -> dataResource */
+ List resourceMappings
+ /** The list of resource metadata for each resource that is displayed */
+ List resources
+
+ /**
+ * Collect the resource information
+ */
+ def buildResources() {
+ resources = []
+ def js = new JsonSlurper()
+ def collectionsToRender = js.parse(resourceConfigurationUrl)
+ collectionsToRender.each { collection ->
+ def path = resourcePath(collection.uid)
+ def metadataUrl = new URL(collectoryServicesUrl, path + "/" + collection.uid)
+ try {
+ def collectionMetadata = js.parse(metadataUrl)
+ collectionMetadata.put("displayCollectionImage", collection.imageUrl)
+ this.resources << collectionMetadata
+ } catch (Exception ex) {
+ log.error("Unable to access while building collections " + metadataUrl, ex)
+ }
+ }
+ }
+
+
+ /**
+ * Get the path to the resource in the collectory, based on the resource UID prefix
+ *
+ * @param uid The resource UID (eg. co12, dr1456)
+ * @return The path to that resource (eg collection, dataResource)
+ */
+ String resourcePath(String uid) {
+ def mapping = resourceMappings.find { m -> uid.startsWith(m.prefix) }
+ if (mapping) {
+ return mapping.path
+ }
+ throw new IllegalArgumentException("Unable to find collectory path for " + uid)
+ }
+
+ @Override
+ void setConfiguration(Config config) {
+ resourceConfigurationUrl = new URL(config.getRequiredProperty("specimenbrowser.data.url"))
+ collectoryServicesUrl = new URL(config.getRequiredProperty("collectory.servicesUrl"))
+ resourceMappings = config.getRequiredProperty("collectory.resourceMapping", List)
+ buildResources()
+ }
+
+}
diff --git a/grails-app/views/admin/counts.gsp b/grails-app/views/admin/counts.gsp
index d5a92ce..0d7e639 100644
--- a/grails-app/views/admin/counts.gsp
+++ b/grails-app/views/admin/counts.gsp
@@ -2,25 +2,33 @@
-
- Settings - Admin - Specimen image browser - Atlas of Living Australia
-
-
- var biocacheServicesUrl = "${grailsApplication.config.biocacheServicesUrl}",
- collectoryServicesURL = "${grailsApplication.config.collectory.servicesURL}",
+
+
+ Image Counts - Specimen image browser - Atlas of Living Australia
+
+
+ var biocacheServicesUrl = "${grailsApplication.config.biocache.servicesUrl}",
+ collectoryServicesURL = "${grailsApplication.config.collectory.servicesUrl}",
browseUrl = "${createLink(controller: 'browse')}";
-
+
-
- Image counts
-
+
+
Image Counts
+
This page displays all collections and data resources that have images associated with them.
+
+
+
+
Resource UID
Resource
Number of images
+
+
+
@@ -30,21 +38,15 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/grails-app/views/admin/index.gsp b/grails-app/views/admin/index.gsp
index 826bad3..7abd5f2 100644
--- a/grails-app/views/admin/index.gsp
+++ b/grails-app/views/admin/index.gsp
@@ -1,12 +1,27 @@
-
+
+
Admin - Specimen image browser - Atlas of Living Australia
-
-
+
+
+
-
-
\ No newline at end of file
diff --git a/grails-app/views/admin/tools.gsp b/grails-app/views/admin/tools.gsp
deleted file mode 100644
index 2d7c1ac..0000000
--- a/grails-app/views/admin/tools.gsp
+++ /dev/null
@@ -1,81 +0,0 @@
-<%@ page import="org.apache.commons.lang.StringEscapeUtils" %>
-
-
-
-
- Tools - Admin - Specimen image browser - Atlas of Living Australia
-
-
-
-
- Tools
-
-
-
-
Tool
-
Description
-
-
-
-
-
-
-
-
- Reads any defined config files and merges new config with old. Usually used after a change is
- made to external config files. Note that this cannot remove a config item as the result is a
- union of the old and new config.
-
-
-
-
-
-
\ No newline at end of file
diff --git a/grails-app/views/browse/index.gsp b/grails-app/views/browse/index.gsp
index c02fa13..dba1450 100644
--- a/grails-app/views/browse/index.gsp
+++ b/grails-app/views/browse/index.gsp
@@ -2,32 +2,26 @@
+
Specimens | Atlas of Living Australia
-
-
- var biocacheServicesUrl = "${grailsApplication.config.biocacheServicesUrl}",
+
+
+
+ var biocacheServicesUrl = "${grailsApplication.config.biocache.servicesUrl}",
biocacheWebappUrl = "${grailsApplication.config.biocache.baseURL}",
- collectoryServicesURL = "${grailsApplication.config.collectory.servicesURL}",
+ collectoryServicesURL = "${grailsApplication.config.collectory.servicesUrl}",
collectoryURL = "${grailsApplication.config.collectory.baseURL}",
imageViewerBaseUrl = "${createLink(controller: 'view', action: 'view')}",
entityUid = "${uid}";
-
+
-
-
Tag Libraries: ${grailsApplication.tagLibClasses.size()}
-
-
Installed Plugins
-
-
-
${plugin.name} - ${plugin.version}
-
-
-
-
-
Welcome to Grails
-
Congratulations, you have successfully started your first Grails application! At the moment
- this is the default page, feel free to modify it to either redirect to a controller or display whatever
- content you may choose. Below is a list of controllers that are currently deployed in this application,
- click on each to execute its default action:
-
-
-
-
-
- var pageTracker = _gat._getTracker("UA-4355440-1");
- pageTracker._initData();
- pageTracker._trackPageview();
-
- // show warning if using IE6
- if ($.browser.msie && $.browser.version.slice(0,1) == '6') {
- $('#header').prepend($('
WARNING: This page is not compatible with IE6.' +
- ' Many functions will still work but layout and image transparency will be disrupted.
'));
- }
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/grails-app/views/notFound.gsp b/grails-app/views/notFound.gsp
new file mode 100644
index 0000000..4c873ba
--- /dev/null
+++ b/grails-app/views/notFound.gsp
@@ -0,0 +1,14 @@
+
+
+
+ Page Not Found
+
+
+
+
+
+
Error: Page Not Found (404)
+
Path: ${request.forwardURI}
+
+
+
diff --git a/grails-app/views/view/homePage.gsp b/grails-app/views/view/homePage.gsp
index 9927ab2..2108e96 100644
--- a/grails-app/views/view/homePage.gsp
+++ b/grails-app/views/view/homePage.gsp
@@ -1,35 +1,37 @@
-
-
- Images of specimens | Atlas of Living Australia
-
-
-
-
Images of specimens from Australia’s Natural History Collections
-
- Images from Australia's Natural History collections made available by the museums and herbaria of Australia.
- To view images from all collections, click here.
-
-
-
-
-
-
-
-
-
-
${collection.name}
-
${collection.institution.name}
-
-
-
-
-
-
-
-
-
-
-
+
+
+ Images of specimens | Atlas of Living Australia
+
+
+
+
+
Images of specimens from Australia’s Natural History Collections
+
+
+ Images from Australia's Natural History collections made available by the museums and herbaria of Australia.
+ To view images from all collections, click here.
-
\ No newline at end of file
diff --git a/grails-release-plugin-bug-workaround_pom.xml b/grails-release-plugin-bug-workaround_pom.xml
deleted file mode 100644
index 92fb0d7..0000000
--- a/grails-release-plugin-bug-workaround_pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
- 4.0.0
- au.org.ala
- SET_ARTIFACT_ID
- war
- SET_VERSION_STRING
- SET_NAME
-
-
-
diff --git a/grails-wrapper.jar b/grails-wrapper.jar
new file mode 100644
index 0000000..b9bd249
Binary files /dev/null and b/grails-wrapper.jar differ
diff --git a/grailsw b/grailsw
new file mode 100755
index 0000000..8d0cc12
--- /dev/null
+++ b/grailsw
@@ -0,0 +1,152 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Grails start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRAILS_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-XX:+TieredCompilation" "-XX:TieredStopAtLevel=1" "-XX:CICompilerCount=3"'
+
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+JAR_PATH=$APP_HOME/grails-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+ JAR_PATH=`cygpath --path --mixed "$JAR_PATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRAILS_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRAILS_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRAILS_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRAILS_OPTS
+
+exec "$JAVACMD" -jar "${JVM_OPTS[@]}" "$JAR_PATH" "$@"
diff --git a/grailsw.bat b/grailsw.bat
new file mode 100755
index 0000000..14734e4
--- /dev/null
+++ b/grailsw.bat
@@ -0,0 +1,89 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Grails startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRAILS_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-XX:+TieredCompilation" "-XX:TieredStopAtLevel=1" "-XX:CICompilerCount=3"
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+set JAR_PATH=%APP_HOME%/grails-wrapper.jar
+
+@rem Execute Grails
+"%JAVA_EXE%" -jar %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRAILS_OPTS% %JAR_PATH% %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRAILS_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRAILS_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..d002523
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'specimenbrowser'
+
diff --git a/src/integration-test/resources/GebConfig.groovy b/src/integration-test/resources/GebConfig.groovy
new file mode 100644
index 0000000..0d97e35
--- /dev/null
+++ b/src/integration-test/resources/GebConfig.groovy
@@ -0,0 +1,25 @@
+import org.openqa.selenium.chrome.ChromeDriver
+import org.openqa.selenium.chrome.ChromeOptions
+import org.openqa.selenium.firefox.FirefoxDriver
+
+environments {
+
+ // run via “./gradlew -Dgeb.env=chrome iT”
+ chrome {
+ driver = { new ChromeDriver() }
+ }
+
+ // run via “./gradlew -Dgeb.env=chromeHeadless iT”
+ chromeHeadless {
+ driver = {
+ ChromeOptions o = new ChromeOptions()
+ o.addArguments('headless')
+ new ChromeDriver(o)
+ }
+ }
+
+ // run via “./gradlew -Dgeb.env=firefox iT”
+ firefox {
+ driver = { new FirefoxDriver() }
+ }
+}
diff --git a/test/unit/au/org/ala/specimenbrowser/AdminControllerTests.groovy b/test/unit/au/org/ala/specimenbrowser/AdminControllerTests.groovy
deleted file mode 100644
index dcd7b59..0000000
--- a/test/unit/au/org/ala/specimenbrowser/AdminControllerTests.groovy
+++ /dev/null
@@ -1,17 +0,0 @@
-package au.org.ala.specimenbrowser
-
-
-
-import grails.test.mixin.*
-import org.junit.*
-
-/**
- * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
- */
-@TestFor(AdminController)
-class AdminControllerTests {
-
- void testSomething() {
- fail "Implement me"
- }
-}
diff --git a/test/unit/au/org/ala/specimenbrowser/ViewControllerTests.groovy b/test/unit/au/org/ala/specimenbrowser/ViewControllerTests.groovy
deleted file mode 100644
index b609ada..0000000
--- a/test/unit/au/org/ala/specimenbrowser/ViewControllerTests.groovy
+++ /dev/null
@@ -1,17 +0,0 @@
-package au.org.ala.specimenbrowser
-
-
-
-import grails.test.mixin.*
-import org.junit.*
-
-/**
- * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
- */
-@TestFor(ViewController)
-class ViewControllerTests {
-
- void testSomething() {
- fail "Implement me"
- }
-}
diff --git a/test/unit/specimenbrowser/BrowseControllerTests.groovy b/test/unit/specimenbrowser/BrowseControllerTests.groovy
deleted file mode 100644
index 922a07e..0000000
--- a/test/unit/specimenbrowser/BrowseControllerTests.groovy
+++ /dev/null
@@ -1,15 +0,0 @@
-package specimenbrowser
-
-import au.org.ala.specimenbrowser.BrowseController
-import grails.test.mixin.*
-
-/**
- * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
- */
-@TestFor(BrowseController)
-class BrowseControllerTests {
-
- void testSomething() {
- fail "Implement me"
- }
-}
diff --git a/test/unit/specimenbrowser/SpecimenTagTagLibSpec.groovy b/test/unit/specimenbrowser/SpecimenTagTagLibSpec.groovy
deleted file mode 100644
index 12b320f..0000000
--- a/test/unit/specimenbrowser/SpecimenTagTagLibSpec.groovy
+++ /dev/null
@@ -1,20 +0,0 @@
-package specimenbrowser
-
-import grails.test.mixin.TestFor
-import spock.lang.Specification
-
-/**
- * See the API for {@link grails.test.mixin.web.GroovyPageUnitTestMixin} for usage instructions
- */
-@TestFor(SpecimenTagTagLib)
-class SpecimenTagTagLibSpec extends Specification {
-
- def setup() {
- }
-
- def cleanup() {
- }
-
- void "test something"() {
- }
-}
diff --git a/upgrade-notes.md b/upgrade-notes.md
new file mode 100644
index 0000000..195d0d2
--- /dev/null
+++ b/upgrade-notes.md
@@ -0,0 +1,3 @@
+* Using wenjars version for knockout library. This is handled by an asset javascript that requires the path to the actual libraries
+* images-client-plugin contains an internal leaflet.js library
+* images-client-plugin requires the importing of xml-apis:xml-apis
\ No newline at end of file
diff --git a/web-app/WEB-INF/applicationContext.xml b/web-app/WEB-INF/applicationContext.xml
deleted file mode 100644
index a48dec0..0000000
--- a/web-app/WEB-INF/applicationContext.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- Grails application factory bean
-
-
-
-
-
- A bean that manages Grails plugins
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- utf-8
-
-
-
-
-
\ No newline at end of file
diff --git a/web-app/WEB-INF/sitemesh.xml b/web-app/WEB-INF/sitemesh.xml
deleted file mode 100644
index 72399ce..0000000
--- a/web-app/WEB-INF/sitemesh.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/web-app/WEB-INF/tld/c.tld b/web-app/WEB-INF/tld/c.tld
deleted file mode 100644
index 5e18236..0000000
--- a/web-app/WEB-INF/tld/c.tld
+++ /dev/null
@@ -1,572 +0,0 @@
-
-
-
-
- JSTL 1.2 core library
- JSTL core
- 1.2
- c
- http://java.sun.com/jsp/jstl/core
-
-
-
- Provides core validation features for JSTL tags.
-
-
- org.apache.taglibs.standard.tlv.JstlCoreTLV
-
-
-
-
-
- Catches any Throwable that occurs in its body and optionally
- exposes it.
-
- catch
- org.apache.taglibs.standard.tag.common.core.CatchTag
- JSP
-
-
-Name of the exported scoped variable for the
-exception thrown from a nested action. The type of the
-scoped variable is the type of the exception thrown.
-
- var
- false
- false
-
-
-
-
-
- Simple conditional tag that establishes a context for
- mutually exclusive conditional operations, marked by
- <when> and <otherwise>
-
- choose
- org.apache.taglibs.standard.tag.common.core.ChooseTag
- JSP
-
-
-
-
- Simple conditional tag, which evalutes its body if the
- supplied condition is true and optionally exposes a Boolean
- scripting variable representing the evaluation of this condition
-
- if
- org.apache.taglibs.standard.tag.rt.core.IfTag
- JSP
-
-
-The test condition that determines whether or
-not the body content should be processed.
-
- test
- true
- true
- boolean
-
-
-
-Name of the exported scoped variable for the
-resulting value of the test condition. The type
-of the scoped variable is Boolean.
-
- var
- false
- false
-
-
-
-Scope for var.
-
- scope
- false
- false
-
-
-
-
-
- Retrieves an absolute or relative URL and exposes its contents
- to either the page, a String in 'var', or a Reader in 'varReader'.
-
- import
- org.apache.taglibs.standard.tag.rt.core.ImportTag
- org.apache.taglibs.standard.tei.ImportTEI
- JSP
-
-
-The URL of the resource to import.
-
- url
- true
- true
-
-
-
-Name of the exported scoped variable for the
-resource's content. The type of the scoped
-variable is String.
-
- var
- false
- false
-
-
-
-Scope for var.
-
- scope
- false
- false
-
-
-
-Name of the exported scoped variable for the
-resource's content. The type of the scoped
-variable is Reader.
-
- varReader
- false
- false
-
-
-
-Name of the context when accessing a relative
-URL resource that belongs to a foreign
-context.
-
- context
- false
- true
-
-
-
-Character encoding of the content at the input
-resource.
-
- charEncoding
- false
- true
-
-
-
-
-
- The basic iteration tag, accepting many different
- collection types and supporting subsetting and other
- functionality
-
- forEach
- org.apache.taglibs.standard.tag.rt.core.ForEachTag
- org.apache.taglibs.standard.tei.ForEachTEI
- JSP
-
-
-Collection of items to iterate over.
-
- items
- false
- true
- java.lang.Object
-
- java.lang.Object
-
-
-
-
-If items specified:
-Iteration begins at the item located at the
-specified index. First item of the collection has
-index 0.
-If items not specified:
-Iteration begins with index set at the value
-specified.
-
- begin
- false
- true
- int
-
-
-
-If items specified:
-Iteration ends at the item located at the
-specified index (inclusive).
-If items not specified:
-Iteration ends when index reaches the value
-specified.
-
- end
- false
- true
- int
-
-
-
-Iteration will only process every step items of
-the collection, starting with the first one.
-
- step
- false
- true
- int
-
-
-
-Name of the exported scoped variable for the
-current item of the iteration. This scoped
-variable has nested visibility. Its type depends
-on the object of the underlying collection.
-
- var
- false
- false
-
-
-
-Name of the exported scoped variable for the
-status of the iteration. Object exported is of type
-javax.servlet.jsp.jstl.core.LoopTagStatus. This scoped variable has nested
-visibility.
-
- varStatus
- false
- false
-
-
-
-
-
- Iterates over tokens, separated by the supplied delimeters
-
- forTokens
- org.apache.taglibs.standard.tag.rt.core.ForTokensTag
- JSP
-
-
-String of tokens to iterate over.
-
- items
- true
- true
- java.lang.String
-
- java.lang.String
-
-
-
-
-The set of delimiters (the characters that
-separate the tokens in the string).
-
- delims
- true
- true
- java.lang.String
-
-
-
-Iteration begins at the token located at the
-specified index. First token has index 0.
-
- begin
- false
- true
- int
-
-
-
-Iteration ends at the token located at the
-specified index (inclusive).
-
- end
- false
- true
- int
-
-
-
-Iteration will only process every step tokens
-of the string, starting with the first one.
-
- step
- false
- true
- int
-
-
-
-Name of the exported scoped variable for the
-current item of the iteration. This scoped
-variable has nested visibility.
-
- var
- false
- false
-
-
-
-Name of the exported scoped variable for the
-status of the iteration. Object exported is of
-type
-javax.servlet.jsp.jstl.core.LoopTag
-Status. This scoped variable has nested
-visibility.
-
- varStatus
- false
- false
-
-
-
-
-
- Like <%= ... >, but for expressions.
-
- out
- org.apache.taglibs.standard.tag.rt.core.OutTag
- JSP
-
-
-Expression to be evaluated.
-
- value
- true
- true
-
-
-
-Default value if the resulting value is null.
-
- default
- false
- true
-
-
-
-Determines whether characters <,>,&,'," in the
-resulting string should be converted to their
-corresponding character entity codes. Default value is
-true.
-
- escapeXml
- false
- true
-
-
-
-
-
-
- Subtag of <choose> that follows <when> tags
- and runs only if all of the prior conditions evaluated to
- 'false'
-
- otherwise
- org.apache.taglibs.standard.tag.common.core.OtherwiseTag
- JSP
-
-
-
-
- Adds a parameter to a containing 'import' tag's URL.
-
- param
- org.apache.taglibs.standard.tag.rt.core.ParamTag
- JSP
-
-
-Name of the query string parameter.
-
- name
- true
- true
-
-
-
-Value of the parameter.
-
- value
- false
- true
-
-
-
-
-
- Redirects to a new URL.
-
- redirect
- org.apache.taglibs.standard.tag.rt.core.RedirectTag
- JSP
-
-
-The URL of the resource to redirect to.
-
- url
- false
- true
-
-
-
-Name of the context when redirecting to a relative URL
-resource that belongs to a foreign context.
-
- context
- false
- true
-
-
-
-
-
- Removes a scoped variable (from a particular scope, if specified).
-
- remove
- org.apache.taglibs.standard.tag.common.core.RemoveTag
- empty
-
-
-Name of the scoped variable to be removed.
-
- var
- true
- false
-
-
-
-Scope for var.
-
- scope
- false
- false
-
-
-
-
-
- Sets the result of an expression evaluation in a 'scope'
-
- set
- org.apache.taglibs.standard.tag.rt.core.SetTag
- JSP
-
-
-Name of the exported scoped variable to hold the value
-specified in the action. The type of the scoped variable is
-whatever type the value expression evaluates to.
-
- var
- false
- false
-
-
-
-Expression to be evaluated.
-
- value
- false
- true
-
- java.lang.Object
-
-
-
-
-Target object whose property will be set. Must evaluate to
-a JavaBeans object with setter property property, or to a
-java.util.Map object.
-
- target
- false
- true
-
-
-
-Name of the property to be set in the target object.
-
- property
- false
- true
-
-
-
-Scope for var.
-
- scope
- false
- false
-
-
-
-
-
- Creates a URL with optional query parameters.
-
- url
- org.apache.taglibs.standard.tag.rt.core.UrlTag
- JSP
-
-
-Name of the exported scoped variable for the
-processed url. The type of the scoped variable is
-String.
-
- var
- false
- false
-
-
-
-Scope for var.
-
- scope
- false
- false
-
-
-
-URL to be processed.
-
- value
- false
- true
-
-
-
-Name of the context when specifying a relative URL
-resource that belongs to a foreign context.
-
- context
- false
- true
-
-
-
-
-
- Subtag of <choose> that includes its body if its
- condition evalutes to 'true'
-
- when
- org.apache.taglibs.standard.tag.rt.core.WhenTag
- JSP
-
-
-The test condition that determines whether or not the
-body content should be processed.
-
- test
- true
- true
- boolean
-
-
-
-
diff --git a/web-app/WEB-INF/tld/fmt.tld b/web-app/WEB-INF/tld/fmt.tld
deleted file mode 100644
index 2ae4776..0000000
--- a/web-app/WEB-INF/tld/fmt.tld
+++ /dev/null
@@ -1,671 +0,0 @@
-
-
-
-
- JSTL 1.2 i18n-capable formatting library
- JSTL fmt
- 1.2
- fmt
- http://java.sun.com/jsp/jstl/fmt
-
-
-
- Provides core validation features for JSTL tags.
-
-
- org.apache.taglibs.standard.tlv.JstlFmtTLV
-
-
-
-
-
- Sets the request character encoding
-
- requestEncoding
- org.apache.taglibs.standard.tag.rt.fmt.RequestEncodingTag
- empty
-
-
-Name of character encoding to be applied when
-decoding request parameters.
-
- value
- false
- true
-
-
-
-
-
- Stores the given locale in the locale configuration variable
-
- setLocale
- org.apache.taglibs.standard.tag.rt.fmt.SetLocaleTag
- empty
-
-
-A String value is interpreted as the
-printable representation of a locale, which
-must contain a two-letter (lower-case)
-language code (as defined by ISO-639),
-and may contain a two-letter (upper-case)
-country code (as defined by ISO-3166).
-Language and country codes must be
-separated by hyphen (-) or underscore
-(_).
-
- value
- true
- true
-
-
-
-Vendor- or browser-specific variant.
-See the java.util.Locale javadocs for
-more information on variants.
-
- variant
- false
- true
-
-
-
-Scope of the locale configuration variable.
-
- scope
- false
- false
-
-
-
-
-
- Specifies the time zone for any time formatting or parsing actions
- nested in its body
-
- timeZone
- org.apache.taglibs.standard.tag.rt.fmt.TimeZoneTag
- JSP
-
-
-The time zone. A String value is interpreted as
-a time zone ID. This may be one of the time zone
-IDs supported by the Java platform (such as
-"America/Los_Angeles") or a custom time zone
-ID (such as "GMT-8"). See
-java.util.TimeZone for more information on
-supported time zone formats.
-
- value
- true
- true
-
-
-
-
-
- Stores the given time zone in the time zone configuration variable
-
- setTimeZone
- org.apache.taglibs.standard.tag.rt.fmt.SetTimeZoneTag
- empty
-
-
-The time zone. A String value is interpreted as
-a time zone ID. This may be one of the time zone
-IDs supported by the Java platform (such as
-"America/Los_Angeles") or a custom time zone
-ID (such as "GMT-8"). See java.util.TimeZone for
-more information on supported time zone
-formats.
-
- value
- true
- true
-
-
-
-Name of the exported scoped variable which
-stores the time zone of type
-java.util.TimeZone.
-
- var
- false
- false
-
-
-
-Scope of var or the time zone configuration
-variable.
-
- scope
- false
- false
-
-
-
-
-
- Loads a resource bundle to be used by its tag body
-
- bundle
- org.apache.taglibs.standard.tag.rt.fmt.BundleTag
- JSP
-
-
-Resource bundle base name. This is the bundle's
-fully-qualified resource name, which has the same
-form as a fully-qualified class name, that is, it uses
-"." as the package component separator and does not
-have any file type (such as ".class" or ".properties")
-suffix.
-
- basename
- true
- true
-
-
-
-Prefix to be prepended to the value of the message
-key of any nested <fmt:message> action.
-
- prefix
- false
- true
-
-
-
-
-
- Loads a resource bundle and stores it in the named scoped variable or
- the bundle configuration variable
-
- setBundle
- org.apache.taglibs.standard.tag.rt.fmt.SetBundleTag
- empty
-
-
-Resource bundle base name. This is the bundle's
-fully-qualified resource name, which has the same
-form as a fully-qualified class name, that is, it uses
-"." as the package component separator and does not
-have any file type (such as ".class" or ".properties")
-suffix.
-
- basename
- true
- true
-
-
-
-Name of the exported scoped variable which stores
-the i18n localization context of type
-javax.servlet.jsp.jstl.fmt.LocalizationC
-ontext.
-
- var
- false
- false
-
-
-
-Scope of var or the localization context
-configuration variable.
-
- scope
- false
- false
-
-
-
-
-
- Maps key to localized message and performs parametric replacement
-
- message
- org.apache.taglibs.standard.tag.rt.fmt.MessageTag
- JSP
-
-
-Message key to be looked up.
-
- key
- false
- true
-
-
-
-Localization context in whose resource
-bundle the message key is looked up.
-
- bundle
- false
- true
-
-
-
-Name of the exported scoped variable
-which stores the localized message.
-
- var
- false
- false
-
-
-
-Scope of var.
-
- scope
- false
- false
-
-
-
-
-
- Supplies an argument for parametric replacement to a containing
- <message> tag
-
- param
- org.apache.taglibs.standard.tag.rt.fmt.ParamTag
- JSP
-
-
-Argument used for parametric replacement.
-
- value
- false
- true
-
-
-
-
-
- Formats a numeric value as a number, currency, or percentage
-
- formatNumber
- org.apache.taglibs.standard.tag.rt.fmt.FormatNumberTag
- JSP
-
-
-Numeric value to be formatted.
-
- value
- false
- true
-
-
-
-Specifies whether the value is to be
-formatted as number, currency, or
-percentage.
-
- type
- false
- true
-
-
-
-Custom formatting pattern.
-
- pattern
- false
- true
-
-
-
-ISO 4217 currency code. Applied only
-when formatting currencies (i.e. if type is
-equal to "currency"); ignored otherwise.
-
- currencyCode
- false
- true
-
-
-
-Currency symbol. Applied only when
-formatting currencies (i.e. if type is equal
-to "currency"); ignored otherwise.
-
- currencySymbol
- false
- true
-
-
-
-Specifies whether the formatted output
-will contain any grouping separators.
-
- groupingUsed
- false
- true
-
-
-
-Maximum number of digits in the integer
-portion of the formatted output.
-
- maxIntegerDigits
- false
- true
-
-
-
-Minimum number of digits in the integer
-portion of the formatted output.
-
- minIntegerDigits
- false
- true
-
-
-
-Maximum number of digits in the
-fractional portion of the formatted output.
-
- maxFractionDigits
- false
- true
-
-
-
-Minimum number of digits in the
-fractional portion of the formatted output.
-
- minFractionDigits
- false
- true
-
-
-
-Name of the exported scoped variable
-which stores the formatted result as a
-String.
-
- var
- false
- false
-
-
-
-Scope of var.
-
- scope
- false
- false
-
-
-
-
-
- Parses the string representation of a number, currency, or percentage
-
- parseNumber
- org.apache.taglibs.standard.tag.rt.fmt.ParseNumberTag
- JSP
-
-
-String to be parsed.
-
- value
- false
- true
-
-
-
-Specifies whether the string in the value
-attribute should be parsed as a number,
-currency, or percentage.
-
- type
- false
- true
-
-
-
-Custom formatting pattern that determines
-how the string in the value attribute is to be
-parsed.
-
- pattern
- false
- true
-
-
-
-Locale whose default formatting pattern (for
-numbers, currencies, or percentages,
-respectively) is to be used during the parse
-operation, or to which the pattern specified
-via the pattern attribute (if present) is
-applied.
-
- parseLocale
- false
- true
-
-
-
-Specifies whether just the integer portion of
-the given value should be parsed.
-
- integerOnly
- false
- true
-
-
-
-Name of the exported scoped variable which
-stores the parsed result (of type
-java.lang.Number).
-
- var
- false
- false
-
-
-
-Scope of var.
-
- scope
- false
- false
-
-
-
-
-
- Formats a date and/or time using the supplied styles and pattern
-
- formatDate
- org.apache.taglibs.standard.tag.rt.fmt.FormatDateTag
- empty
-
-
-Date and/or time to be formatted.
-
- value
- true
- true
-
-
-
-Specifies whether the time, the date, or both
-the time and date components of the given
-date are to be formatted.
-
- type
- false
- true
-
-
-
-Predefined formatting style for dates. Follows
-the semantics defined in class
-java.text.DateFormat. Applied only
-when formatting a date or both a date and
-time (i.e. if type is missing or is equal to
-"date" or "both"); ignored otherwise.
-
- dateStyle
- false
- true
-
-
-
-Predefined formatting style for times. Follows
-the semantics defined in class
-java.text.DateFormat. Applied only
-when formatting a time or both a date and
-time (i.e. if type is equal to "time" or "both");
-ignored otherwise.
-
- timeStyle
- false
- true
-
-
-
-Custom formatting style for dates and times.
-
- pattern
- false
- true
-
-
-
-Time zone in which to represent the formatted
-time.
-
- timeZone
- false
- true
-
-
-
-Name of the exported scoped variable which
-stores the formatted result as a String.
-
- var
- false
- false
-
-
-
-Scope of var.
-
- scope
- false
- false
-
-
-
-
-
- Parses the string representation of a date and/or time
-
- parseDate
- org.apache.taglibs.standard.tag.rt.fmt.ParseDateTag
- JSP
-
-
-Date string to be parsed.
-
- value
- false
- true
-
-
-
-Specifies whether the date string in the
-value attribute is supposed to contain a
-time, a date, or both.
-
- type
- false
- true
-
-
-
-Predefined formatting style for days
-which determines how the date
-component of the date string is to be
-parsed. Applied only when formatting a
-date or both a date and time (i.e. if type
-is missing or is equal to "date" or "both");
-ignored otherwise.
-
- dateStyle
- false
- true
-
-
-
-Predefined formatting styles for times
-which determines how the time
-component in the date string is to be
-parsed. Applied only when formatting a
-time or both a date and time (i.e. if type
-is equal to "time" or "both"); ignored
-otherwise.
-
- timeStyle
- false
- true
-
-
-
-Custom formatting pattern which
-determines how the date string is to be
-parsed.
-
- pattern
- false
- true
-
-
-
-Time zone in which to interpret any time
-information in the date string.
-
- timeZone
- false
- true
-
-
-
-Locale whose predefined formatting styles
-for dates and times are to be used during
-the parse operation, or to which the
-pattern specified via the pattern
-attribute (if present) is applied.
-
- parseLocale
- false
- true
-
-
-
-Name of the exported scoped variable in
-which the parsing result (of type
-java.util.Date) is stored.
-
- var
- false
- false
-
-
-
-Scope of var.
-
- scope
- false
- false
-
-
-
-
diff --git a/web-app/WEB-INF/tld/grails.tld b/web-app/WEB-INF/tld/grails.tld
deleted file mode 100644
index 9bd036b..0000000
--- a/web-app/WEB-INF/tld/grails.tld
+++ /dev/null
@@ -1,550 +0,0 @@
-
-
- The Grails custom tag library
- 0.2
- grails
- http://grails.codehaus.org/tags
-
-
- link
- org.codehaus.groovy.grails.web.taglib.jsp.JspLinkTag
- JSP
-
- action
- false
- true
-
-
- controller
- false
- true
-
-
- id
- false
- true
-
-
- url
- false
- true
-
-
- params
- false
- true
-
- true
-
-
- form
- org.codehaus.groovy.grails.web.taglib.jsp.JspFormTag
- JSP
-
- action
- false
- true
-
-
- controller
- false
- true
-
-
- id
- false
- true
-
-
- url
- false
- true
-
-
- method
- true
- true
-
- true
-
-
- select
- org.codehaus.groovy.grails.web.taglib.jsp.JspSelectTag
- JSP
-
- name
- true
- true
-
-
- value
- false
- true
-
-
- optionKey
- false
- true
-
-
- optionValue
- false
- true
-
- true
-
-
- datePicker
- org.codehaus.groovy.grails.web.taglib.jsp.JspDatePickerTag
- empty
-
- name
- true
- true
-
-
- value
- false
- true
-
-
- precision
- false
- true
-
- false
-
-
- currencySelect
- org.codehaus.groovy.grails.web.taglib.jsp.JspCurrencySelectTag
- empty
-
- name
- true
- true
-
-
- value
- false
- true
-
- true
-
-
- localeSelect
- org.codehaus.groovy.grails.web.taglib.jsp.JspLocaleSelectTag
- empty
-
- name
- true
- true
-
-
- value
- false
- true
-
- true
-
-
- timeZoneSelect
- org.codehaus.groovy.grails.web.taglib.jsp.JspTimeZoneSelectTag
- empty
-
- name
- true
- true
-
-
- value
- false
- true
-
- true
-
-
- checkBox
- org.codehaus.groovy.grails.web.taglib.jsp.JspCheckboxTag
- empty
-
- name
- true
- true
-
-
- value
- true
- true
-
- true
-
-
- hasErrors
- org.codehaus.groovy.grails.web.taglib.jsp.JspHasErrorsTag
- JSP
-
- model
- false
- true
-
-
- bean
- false
- true
-
-
- field
- false
- true
-
- false
-
-
- eachError
- org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag
- JSP
-
- model
- false
- true
-
-
- bean
- false
- true
-
-
- field
- false
- true
-
- false
-
-
- renderErrors
- org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag
- JSP
-
- model
- false
- true
-
-
- bean
- false
- true
-
-
- field
- false
- true
-
-
- as
- true
- true
-
- false
-
-
- message
- org.codehaus.groovy.grails.web.taglib.jsp.JspMessageTag
- JSP
-
- code
- false
- true
-
-
- error
- false
- true
-
-
- default
- false
- true
-
- false
-
-
- remoteFunction
- org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteFunctionTag
- empty
-
- before
- false
- true
-
-
- after
- false
- true
-
-
- action
- false
- true
-
-
- controller
- false
- true
-
-
- id
- false
- true
-
-
- url
- false
- true
-
-
- params
- false
- true
-
-
- asynchronous
- false
- true
-
-
- method
- false
- true
-
-
- update
- false
- true
-
-
- onSuccess
- false
- true
-
-
- onFailure
- false
- true
-
-
- onComplete
- false
- true
-
-
- onLoading
- false
- true
-
-
- onLoaded
- false
- true
-
-
- onInteractive
- false
- true
-
- true
-
-
- remoteLink
- org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteLinkTag
- JSP
-
- before
- false
- true
-
-
- after
- false
- true
-
-
- action
- false
- true
-
-
- controller
- false
- true
-
-
- id
- false
- true
-
-
- url
- false
- true
-
-
- params
- false
- true
-
-
- asynchronous
- false
- true
-
-
- method
- false
- true
-
-
- update
- false
- true
-
-
- onSuccess
- false
- true
-
-
- onFailure
- false
- true
-
-
- onComplete
- false
- true
-
-
- onLoading
- false
- true
-
-
- onLoaded
- false
- true
-
-
- onInteractive
- false
- true
-
- true
-
-
- formRemote
- org.codehaus.groovy.grails.web.taglib.jsp.JspFormRemoteTag
- JSP
-
- before
- false
- true
-
-
- after
- false
- true
-
-
- action
- false
- true
-
-
- controller
- false
- true
-
-
- id
- false
- true
-
-
- url
- false
- true
-
-
- params
- false
- true
-
-
- asynchronous
- false
- true
-
-
- method
- false
- true
-
-
- update
- false
- true
-
-
- onSuccess
- false
- true
-
-
- onFailure
- false
- true
-
-
- onComplete
- false
- true
-
-
- onLoading
- false
- true
-
-
- onLoaded
- false
- true
-
-
- onInteractive
- false
- true
-
- true
-
-
- invokeTag
- org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag
- JSP
-
- it
- java.lang.Object
- true
- NESTED
-
-
- tagName
- true
- true
-
- true
-
-
-
diff --git a/web-app/WEB-INF/tld/spring.tld b/web-app/WEB-INF/tld/spring.tld
deleted file mode 100644
index a0a8c6f..0000000
--- a/web-app/WEB-INF/tld/spring.tld
+++ /dev/null
@@ -1,457 +0,0 @@
-
-
-
- Spring Framework JSP Tag Library
- 3.0
- spring
- http://www.springframework.org/tags
-
-
-
- Sets default HTML escape value for the current page.
- Overrides a "defaultHtmlEscape" context-param in web.xml, if any.
-
- htmlEscape
- org.springframework.web.servlet.tags.HtmlEscapeTag
- JSP
-
- Set the default value for HTML escaping, to be put
- into the current PageContext.
- defaultHtmlEscape
- true
- true
-
-
-
-
-
- Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping.
- The HTML escaping flag participates in a page-wide or application-wide setting
- (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
-
- escapeBody
- org.springframework.web.servlet.tags.EscapeBodyTag
- JSP
-
- Set HTML escaping for this tag, as boolean value. Overrides the
- default HTML escaping setting for the current page.
- htmlEscape
- false
- true
-
-
- Set JavaScript escaping for this tag, as boolean value.
- Default is false.
- javaScriptEscape
- false
- true
-
-
-
-
-
- Retrieves the message with the given code, or text if code isn't resolvable.
- The HTML escaping flag participates in a page-wide or application-wide setting
- (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
-
- message
- org.springframework.web.servlet.tags.MessageTag
- JSP
-
- A MessageSourceResolvable argument (direct or through JSP EL).
- Fits nicely when used in conjunction with Spring's own validation error
- classes which all implement the MessageSourceResolvable interface. For
- example, this allows you to iterate over all of the errors in a form,
- passing each error (using a runtime expression) as the value of this
- 'message' attribute, thus effecting the easy display of such error
- messages.
- message
- false
- true
-
-
- The code (key) to use when looking up the message.
- If code is not provided, the text attribute will be used.
- code
- false
- true
-
-
- Set optional message arguments for this tag, as a
- (comma-)delimited String (each String argument can contain JSP EL),
- an Object array (used as argument array), or a single Object (used
- as single argument).
- arguments
- false
- true
-
-
- The separator character to be used for splitting the
- arguments string value; defaults to a 'comma' (',').
- argumentSeparator
- false
- true
-
-
- Default text to output when a message for the given code
- could not be found. If both text and code are not set, the tag will
- output null.
- text
- false
- true
-
-
- The string to use when binding the result to the page,
- request, session or application scope. If not specified, the result
- gets outputted to the writer (i.e. typically directly to the JSP).
- var
- false
- true
-
-
- The scope to use when exporting the result to a variable.
- This attribute is only used when var is also set. Possible values are
- page, request, session and application.
- scope
- false
- true
-
-
- Set HTML escaping for this tag, as boolean value.
- Overrides the default HTML escaping setting for the current page.
- htmlEscape
- false
- true
-
-
- Set JavaScript escaping for this tag, as boolean value. Default is false.
- javaScriptEscape
- false
- true
-
-
-
-
-
- Retrieves the theme message with the given code, or text if code isn't resolvable.
- The HTML escaping flag participates in a page-wide or application-wide setting
- (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
-
- theme
- org.springframework.web.servlet.tags.ThemeTag
- JSP
-
- A MessageSourceResolvable argument (direct or through JSP EL).
- message
- false
- true
-
-
- The code (key) to use when looking up the message.
- If code is not provided, the text attribute will be used.
- code
- false
- true
-
-
- Set optional message arguments for this tag, as a
- (comma-)delimited String (each String argument can contain JSP EL),
- an Object array (used as argument array), or a single Object (used
- as single argument).
- arguments
- false
- true
-
-
- The separator character to be used for splitting the
- arguments string value; defaults to a 'comma' (',').
- argumentSeparator
- false
- true
-
-
- Default text to output when a message for the given code
- could not be found. If both text and code are not set, the tag will
- output null.
- text
- false
- true
-
-
- The string to use when binding the result to the page,
- request, session or application scope. If not specified, the result
- gets outputted to the writer (i.e. typically directly to the JSP).
- var
- false
- true
-
-
- The scope to use when exporting the result to a variable.
- This attribute is only used when var is also set. Possible values are
- page, request, session and application.
- scope
- false
- true
-
-
- Set HTML escaping for this tag, as boolean value.
- Overrides the default HTML escaping setting for the current page.
- htmlEscape
- false
- true
-
-
- Set JavaScript escaping for this tag, as boolean value. Default is false.
- javaScriptEscape
- false
- true
-
-
-
-
-
- Provides Errors instance in case of bind errors.
- The HTML escaping flag participates in a page-wide or application-wide setting
- (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
-
- hasBindErrors
- org.springframework.web.servlet.tags.BindErrorsTag
- JSP
-
- errors
- org.springframework.validation.Errors
-
-
- The name of the bean in the request, that needs to be
- inspected for errors. If errors are available for this bean, they
- will be bound under the 'errors' key.
- name
- true
- true
-
-
- Set HTML escaping for this tag, as boolean value.
- Overrides the default HTML escaping setting for the current page.
- htmlEscape
- false
- true
-
-
-
-
-
- Sets a nested path to be used by the bind tag's path.
-
- nestedPath
- org.springframework.web.servlet.tags.NestedPathTag
- JSP
-
- nestedPath
- java.lang.String
-
-
- Set the path that this tag should apply. E.g. 'customer'
- to allow bind paths like 'address.street' rather than
- 'customer.address.street'.
- path
- true
- true
-
-
-
-
-
- Provides BindStatus object for the given bind path.
- The HTML escaping flag participates in a page-wide or application-wide setting
- (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
-
- bind
- org.springframework.web.servlet.tags.BindTag
- JSP
-
- status
- org.springframework.web.servlet.support.BindStatus
-
-
- The path to the bean or bean property to bind status
- information for. For instance account.name, company.address.zipCode
- or just employee. The status object will exported to the page scope,
- specifically for this bean or bean property
- path
- true
- true
-
-
- Set whether to ignore a nested path, if any. Default is to not ignore.
- ignoreNestedPath
- false
- true
-
-
- Set HTML escaping for this tag, as boolean value. Overrides
- the default HTML escaping setting for the current page.
- htmlEscape
- false
- true
-
-
-
-
-
- Provides transformation of variables to Strings, using an appropriate
- custom PropertyEditor from BindTag (can only be used inside BindTag).
- The HTML escaping flag participates in a page-wide or application-wide setting
- (i.e. by HtmlEscapeTag or a 'defaultHtmlEscape' context-param in web.xml).
-
- transform
- org.springframework.web.servlet.tags.TransformTag
- JSP
-
- The value to transform. This is the actual object you want
- to have transformed (for instance a Date). Using the PropertyEditor that
- is currently in use by the 'spring:bind' tag.
- value
- true
- true
-
-
- The string to use when binding the result to the page,
- request, session or application scope. If not specified, the result gets
- outputted to the writer (i.e. typically directly to the JSP).
- var
- false
- true
-
-
- The scope to use when exported the result to a variable.
- This attribute is only used when var is also set. Possible values are
- page, request, session and application.
- scope
- false
- true
-
-
- Set HTML escaping for this tag, as boolean value. Overrides
- the default HTML escaping setting for the current page.
- htmlEscape
- false
- true
-
-
-
-
- URL tag based on the JSTL c:url tag. This variant is fully
- backwards compatible with the standard tag. Enhancements include support
- for URL template parameters.
- url
- org.springframework.web.servlet.tags.UrlTag
- JSP
-
- The URL to build. This value can include template place holders
- that are replaced with the URL encoded value of the named parameter. Parameters
- must be defined using the param tag inside the body of this tag.
- value
- true
- true
-
-
- Specifies a remote application context path. The default is the
- current application context path.
- context
- false
- true
-
-
- The name of the variable to export the URL value to.
- var
- false
- true
-
-
- The scope for the var. 'application', 'session', 'request' and
- 'page' scopes are supported. Defaults to page scope. This attribute has no
- effect unless the var attribute is also defined.
- scope
- false
- true
-
-
- Set HTML escaping for this tag, as a boolean value. Overrides the
- default HTML escaping setting for the current page.
- htmlEscape
- false
- true
-
-
- Set JavaScript escaping for this tag, as a boolean value.
- Default is false.
- javaScriptEscape
- false
- true
-
-
-
-
- Parameter tag based on the JSTL c:param tag. The sole purpose is to
- support params inside the spring:url tag.
- param
- org.springframework.web.servlet.tags.ParamTag
- JSP
-
- The name of the parameter.
- name
- true
- true
-
-
- The value of the parameter.
- value
- false
- true
-
-
-
-
- Evaluates a Spring expression (SpEL) and either prints the result or assigns it to a variable.
- eval
- org.springframework.web.servlet.tags.EvalTag
- JSP
-
- The expression to evaluate.
- expression
- true
- true
-
-
- The name of the variable to export the evaluation result to.
- var
- false
- true
-
-
- The scope for the var. 'application', 'session', 'request' and
- 'page' scopes are supported. Defaults to page scope. This attribute has no
- effect unless the var attribute is also defined.
- scope
- false
- true
-
-
- Set HTML escaping for this tag, as a boolean value. Overrides the
- default HTML escaping setting for the current page.
- htmlEscape
- false
- true
-
-
- Set JavaScript escaping for this tag, as a boolean value. Default is false.
- javaScriptEscape
- false
- true
-
-
-
-
diff --git a/web-app/css/errors.css b/web-app/css/errors.css
deleted file mode 100644
index bdb58bc..0000000
--- a/web-app/css/errors.css
+++ /dev/null
@@ -1,109 +0,0 @@
-h1, h2 {
- margin: 10px 25px 5px;
-}
-
-h2 {
- font-size: 1.1em;
-}
-
-.filename {
- font-style: italic;
-}
-
-.exceptionMessage {
- margin: 10px;
- border: 1px solid #000;
- padding: 5px;
- background-color: #E9E9E9;
-}
-
-.stack,
-.snippet {
- margin: 0 25px 10px;
-}
-
-.stack,
-.snippet {
- border: 1px solid #ccc;
- -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
- -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
- box-shadow: 0 0 2px rgba(0,0,0,0.2);
-}
-
-/* error details */
-.error-details {
- border-top: 1px solid #FFAAAA;
- -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
- -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
- box-shadow: 0 0 2px rgba(0,0,0,0.2);
- border-bottom: 1px solid #FFAAAA;
- -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
- -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
- box-shadow: 0 0 2px rgba(0,0,0,0.2);
- background-color:#FFF3F3;
- line-height: 1.5;
- overflow: hidden;
- padding: 5px;
- padding-left:25px;
-}
-
-.error-details dt {
- clear: left;
- float: left;
- font-weight: bold;
- margin-right: 5px;
-}
-
-.error-details dt:after {
- content: ":";
-}
-
-.error-details dd {
- display: block;
-}
-
-/* stack trace */
-.stack {
- padding: 5px;
- overflow: auto;
- height: 150px;
-}
-
-/* code snippet */
-.snippet {
- background-color: #fff;
- font-family: monospace;
-}
-
-.snippet .line {
- display: block;
-}
-
-.snippet .lineNumber {
- background-color: #ddd;
- color: #999;
- display: inline-block;
- margin-right: 5px;
- padding: 0 3px;
- text-align: right;
- width: 3em;
-}
-
-.snippet .error {
- background-color: #fff3f3;
- font-weight: bold;
-}
-
-.snippet .error .lineNumber {
- background-color: #faa;
- color: #333;
- font-weight: bold;
-}
-
-.snippet .line:first-child .lineNumber {
- padding-top: 5px;
-}
-
-.snippet .line:last-child .lineNumber {
- padding-bottom: 5px;
-}
\ No newline at end of file
diff --git a/web-app/css/main.css b/web-app/css/main.css
deleted file mode 100644
index a55945d..0000000
--- a/web-app/css/main.css
+++ /dev/null
@@ -1,596 +0,0 @@
-/* FONT STACK */
-body,
-input, select, textarea {
- font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
-}
-
-h1, h2, h3, h4, h5, h6 {
- line-height: 1.1;
-}
-
-/* BASE LAYOUT */
-
-html {
- background-color: #ddd;
- background-image: -moz-linear-gradient(center top, #aaa, #ddd);
- background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #aaa), color-stop(1, #ddd));
- background-image: linear-gradient(top, #aaa, #ddd);
- filter: progid:DXImageTransform.Microsoft.gradient(startColorStr = '#aaaaaa', EndColorStr = '#dddddd');
- background-repeat: no-repeat;
- height: 100%;
- /* change the box model to exclude the padding from the calculation of 100% height (IE8+) */
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-
-html.no-cssgradients {
- background-color: #aaa;
-}
-
-.ie6 html {
- height: 100%;
-}
-
-html * {
- margin: 0;
-}
-
-body {
- background: #ffffff;
- color: #333333;
- margin: 0 auto;
- max-width: 960px;
- overflow-x: hidden; /* prevents box-shadow causing a horizontal scrollbar in firefox when viewport < 960px wide */
- -moz-box-shadow: 0 0 0.3em #255b17;
- -webkit-box-shadow: 0 0 0.3em #255b17;
- box-shadow: 0 0 0.3em #255b17;
-}
-
-#grailsLogo {
- background-color: #abbf78;
-}
-
-/* replace with .no-boxshadow body if you have modernizr available */
-.ie6 body,
-.ie7 body,
-.ie8 body {
- border-color: #255b17;
- border-style: solid;
- border-width: 0 1px;
-}
-
-.ie6 body {
- height: 100%;
-}
-
-a:link, a:visited, a:hover {
- color: #48802c;
-}
-
-a:hover, a:active {
- outline: none; /* prevents outline in webkit on active links but retains it for tab focus */
-}
-
-h1 {
- color: #48802c;
- font-weight: normal;
- font-size: 1.25em;
- margin: 0.8em 0 0.3em 0;
-}
-
-ul {
- padding: 0;
-}
-
-img {
- border: 0;
-}
-
-/* GENERAL */
-
-#grailsLogo a {
- display: inline-block;
- margin: 1em;
-}
-
-.content {
-}
-
-.content h1 {
- border-bottom: 1px solid #CCCCCC;
- margin: 0.8em 1em 0.3em;
- padding: 0 0.25em;
-}
-
-.scaffold-list h1 {
- border: none;
-}
-
-.footer {
- background: #abbf78;
- color: #000;
- clear: both;
- font-size: 0.8em;
- margin-top: 1.5em;
- padding: 1em;
- min-height: 1em;
-}
-
-.footer a {
- color: #255b17;
-}
-
-.spinner {
- background: url(../images/spinner.gif) 50% 50% no-repeat transparent;
- height: 16px;
- width: 16px;
- padding: 0.5em;
- position: absolute;
- right: 0;
- top: 0;
- text-indent: -9999px;
-}
-
-/* NAVIGATION MENU */
-
-.nav {
- background-color: #efefef;
- padding: 0.5em 0.75em;
- -moz-box-shadow: 0 0 3px 1px #aaaaaa;
- -webkit-box-shadow: 0 0 3px 1px #aaaaaa;
- box-shadow: 0 0 3px 1px #aaaaaa;
- zoom: 1;
-}
-
-.nav ul {
- overflow: hidden;
- padding-left: 0;
- zoom: 1;
-}
-
-.nav li {
- display: block;
- float: left;
- list-style-type: none;
- margin-right: 0.5em;
- padding: 0;
-}
-
-.nav a {
- color: #666666;
- display: block;
- padding: 0.25em 0.7em;
- text-decoration: none;
- -moz-border-radius: 0.3em;
- -webkit-border-radius: 0.3em;
- border-radius: 0.3em;
-}
-
-.nav a:active, .nav a:visited {
- color: #666666;
-}
-
-.nav a:focus, .nav a:hover {
- background-color: #999999;
- color: #ffffff;
- outline: none;
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
-}
-
-.no-borderradius .nav a:focus, .no-borderradius .nav a:hover {
- background-color: transparent;
- color: #444444;
- text-decoration: underline;
-}
-
-.nav a.home, .nav a.list, .nav a.create {
- background-position: 0.7em center;
- background-repeat: no-repeat;
- text-indent: 25px;
-}
-
-.nav a.home {
- background-image: url(../images/skin/house.png);
-}
-
-.nav a.list {
- background-image: url(../images/skin/database_table.png);
-}
-
-.nav a.create {
- background-image: url(../images/skin/database_add.png);
-}
-
-/* CREATE/EDIT FORMS AND SHOW PAGES */
-
-fieldset,
-.property-list {
- margin: 0.6em 1.25em 0 1.25em;
- padding: 0.3em 1.8em 1.25em;
- position: relative;
- zoom: 1;
- border: none;
-}
-
-.property-list .fieldcontain {
- list-style: none;
- overflow: hidden;
- zoom: 1;
-}
-
-.fieldcontain {
- margin-top: 1em;
-}
-
-.fieldcontain label,
-.fieldcontain .property-label {
- color: #666666;
- text-align: right;
- width: 25%;
-}
-
-.fieldcontain .property-label {
- float: left;
-}
-
-.fieldcontain .property-value {
- display: block;
- margin-left: 27%;
-}
-
-label {
- cursor: pointer;
- display: inline-block;
- margin: 0 0.25em 0 0;
-}
-
-input, select, textarea {
- background-color: #fcfcfc;
- border: 1px solid #cccccc;
- font-size: 1em;
- padding: 0.2em 0.4em;
-}
-
-select {
- padding: 0.2em 0.2em 0.2em 0;
-}
-
-select[multiple] {
- vertical-align: top;
-}
-
-textarea {
- width: 250px;
- height: 150px;
- overflow: auto; /* IE always renders vertical scrollbar without this */
- vertical-align: top;
-}
-
-input[type=checkbox], input[type=radio] {
- background-color: transparent;
- border: 0;
- padding: 0;
-}
-
-input:focus, select:focus, textarea:focus {
- background-color: #ffffff;
- border: 1px solid #eeeeee;
- outline: 0;
- -moz-box-shadow: 0 0 0.5em #ffffff;
- -webkit-box-shadow: 0 0 0.5em #ffffff;
- box-shadow: 0 0 0.5em #ffffff;
-}
-
-.required-indicator {
- color: #48802C;
- display: inline-block;
- font-weight: bold;
- margin-left: 0.3em;
- position: relative;
- top: 0.1em;
-}
-
-ul.one-to-many {
- display: inline-block;
- list-style-position: inside;
- vertical-align: top;
-}
-
-.ie6 ul.one-to-many, .ie7 ul.one-to-many {
- display: inline;
- zoom: 1;
-}
-
-ul.one-to-many li.add {
- list-style-type: none;
-}
-
-/* EMBEDDED PROPERTIES */
-
-fieldset.embedded {
- background-color: transparent;
- border: 1px solid #CCCCCC;
- margin-left: 0;
- margin-right: 0;
- padding-left: 0;
- padding-right: 0;
- -moz-box-shadow: none;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-
-fieldset.embedded legend {
- margin: 0 1em;
-}
-
-/* MESSAGES AND ERRORS */
-
-.errors,
-.message {
- font-size: 0.8em;
- line-height: 2;
- margin: 1em 2em;
- padding: 0.25em;
-}
-
-.message {
- background: #f3f3ff;
- border: 1px solid #b2d1ff;
- color: #006dba;
- -moz-box-shadow: 0 0 0.25em #b2d1ff;
- -webkit-box-shadow: 0 0 0.25em #b2d1ff;
- box-shadow: 0 0 0.25em #b2d1ff;
-}
-
-.errors {
- background: #fff3f3;
- border: 1px solid #ffaaaa;
- color: #cc0000;
- -moz-box-shadow: 0 0 0.25em #ff8888;
- -webkit-box-shadow: 0 0 0.25em #ff8888;
- box-shadow: 0 0 0.25em #ff8888;
-}
-
-.errors ul,
-.message {
- padding: 0;
-}
-
-.errors li {
- list-style: none;
- background: transparent url(../images/skin/exclamation.png) 0.5em 50% no-repeat;
- text-indent: 2.2em;
-}
-
-.message {
- background: transparent url(../images/skin/information.png) 0.5em 50% no-repeat;
- text-indent: 2.2em;
-}
-
-/* form fields with errors */
-
-.error input, .error select, .error textarea {
- background: #fff3f3;
- border-color: #ffaaaa;
- color: #cc0000;
-}
-
-.error input:focus, .error select:focus, .error textarea:focus {
- -moz-box-shadow: 0 0 0.5em #ffaaaa;
- -webkit-box-shadow: 0 0 0.5em #ffaaaa;
- box-shadow: 0 0 0.5em #ffaaaa;
-}
-
-/* same effects for browsers that support HTML5 client-side validation (these have to be specified separately or IE will ignore the entire rule) */
-
-input:invalid, select:invalid, textarea:invalid {
- background: #fff3f3;
- border-color: #ffaaaa;
- color: #cc0000;
-}
-
-input:invalid:focus, select:invalid:focus, textarea:invalid:focus {
- -moz-box-shadow: 0 0 0.5em #ffaaaa;
- -webkit-box-shadow: 0 0 0.5em #ffaaaa;
- box-shadow: 0 0 0.5em #ffaaaa;
-}
-
-/* TABLES */
-
-table {
- border-top: 1px solid #DFDFDF;
- border-collapse: collapse;
- width: 100%;
- margin-bottom: 1em;
-}
-
-tr {
- border: 0;
-}
-
-tr>td:first-child, tr>th:first-child {
- padding-left: 1.25em;
-}
-
-tr>td:last-child, tr>th:last-child {
- padding-right: 1.25em;
-}
-
-td, th {
- line-height: 1.5em;
- padding: 0.5em 0.6em;
- text-align: left;
- vertical-align: top;
-}
-
-th {
- background-color: #efefef;
- background-image: -moz-linear-gradient(top, #ffffff, #eaeaea);
- background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ffffff), color-stop(1, #eaeaea));
- filter: progid:DXImageTransform.Microsoft.gradient(startColorStr = '#ffffff', EndColorStr = '#eaeaea');
- -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#eaeaea')";
- color: #666666;
- font-weight: bold;
- line-height: 1.7em;
- padding: 0.2em 0.6em;
-}
-
-thead th {
- white-space: nowrap;
-}
-
-th a {
- display: block;
- text-decoration: none;
-}
-
-th a:link, th a:visited {
- color: #666666;
-}
-
-th a:hover, th a:focus {
- color: #333333;
-}
-
-th.sortable a {
- background-position: right;
- background-repeat: no-repeat;
- padding-right: 1.1em;
-}
-
-th.asc a {
- background-image: url(../images/skin/sorted_asc.gif);
-}
-
-th.desc a {
- background-image: url(../images/skin/sorted_desc.gif);
-}
-
-.odd {
- background: #f7f7f7;
-}
-
-.even {
- background: #ffffff;
-}
-
-th:hover, tr:hover {
- background: #E1F2B6;
-}
-
-/* PAGINATION */
-
-.pagination {
- border-top: 0;
- margin: 0;
- padding: 0.3em 0.2em;
- text-align: center;
- -moz-box-shadow: 0 0 3px 1px #AAAAAA;
- -webkit-box-shadow: 0 0 3px 1px #AAAAAA;
- box-shadow: 0 0 3px 1px #AAAAAA;
- background-color: #EFEFEF;
-}
-
-.pagination a,
-.pagination .currentStep {
- color: #666666;
- display: inline-block;
- margin: 0 0.1em;
- padding: 0.25em 0.7em;
- text-decoration: none;
- -moz-border-radius: 0.3em;
- -webkit-border-radius: 0.3em;
- border-radius: 0.3em;
-}
-
-.pagination a:hover, .pagination a:focus,
-.pagination .currentStep {
- background-color: #999999;
- color: #ffffff;
- outline: none;
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
-}
-
-.no-borderradius .pagination a:hover, .no-borderradius .pagination a:focus,
-.no-borderradius .pagination .currentStep {
- background-color: transparent;
- color: #444444;
- text-decoration: underline;
-}
-
-/* ACTION BUTTONS */
-
-.buttons {
- background-color: #efefef;
- overflow: hidden;
- padding: 0.3em;
- -moz-box-shadow: 0 0 3px 1px #aaaaaa;
- -webkit-box-shadow: 0 0 3px 1px #aaaaaa;
- box-shadow: 0 0 3px 1px #aaaaaa;
- margin: 0.1em 0 0 0;
- border: none;
-}
-
-.buttons input,
-.buttons a {
- background-color: transparent;
- border: 0;
- color: #666666;
- cursor: pointer;
- display: inline-block;
- margin: 0 0.25em 0;
- overflow: visible;
- padding: 0.25em 0.7em;
- text-decoration: none;
-
- -moz-border-radius: 0.3em;
- -webkit-border-radius: 0.3em;
- border-radius: 0.3em;
-}
-
-.buttons input:hover, .buttons input:focus,
-.buttons a:hover, .buttons a:focus {
- background-color: #999999;
- color: #ffffff;
- outline: none;
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
- -moz-box-shadow: none;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-
-.no-borderradius .buttons input:hover, .no-borderradius .buttons input:focus,
-.no-borderradius .buttons a:hover, .no-borderradius .buttons a:focus {
- background-color: transparent;
- color: #444444;
- text-decoration: underline;
-}
-
-.buttons .delete, .buttons .edit, .buttons .save {
- background-position: 0.7em center;
- background-repeat: no-repeat;
- text-indent: 25px;
-}
-
-.ie6 .buttons input.delete, .ie6 .buttons input.edit, .ie6 .buttons input.save,
-.ie7 .buttons input.delete, .ie7 .buttons input.edit, .ie7 .buttons input.save {
- padding-left: 36px;
-}
-
-.buttons .delete {
- background-image: url(../images/skin/database_delete.png);
-}
-
-.buttons .edit {
- background-image: url(../images/skin/database_edit.png);
-}
-
-.buttons .save {
- background-image: url(../images/skin/database_save.png);
-}
-
-a.skip {
- position: absolute;
- left: -9999px;
-}
diff --git a/web-app/css/mobile.css b/web-app/css/mobile.css
deleted file mode 100644
index 167f502..0000000
--- a/web-app/css/mobile.css
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Styles for mobile devices */
-
-@media screen and (max-width: 480px) {
- .nav {
- padding: 0.5em;
- }
-
- .nav li {
- margin: 0 0.5em 0 0;
- padding: 0.25em;
- }
-
- /* Hide individual steps in pagination, just have next & previous */
- .pagination .step, .pagination .currentStep {
- display: none;
- }
-
- .pagination .prevLink {
- float: left;
- }
-
- .pagination .nextLink {
- float: right;
- }
-
- /* pagination needs to wrap around floated buttons */
- .pagination {
- overflow: hidden;
- }
-
- /* slightly smaller margin around content body */
- fieldset,
- .property-list {
- padding: 0.3em 1em 1em;
- }
-
- input, textarea {
- width: 100%;
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
- -ms-box-sizing: border-box;
- box-sizing: border-box;
- }
-
- select, input[type=checkbox], input[type=radio], input[type=submit], input[type=button], input[type=reset] {
- width: auto;
- }
-
- /* hide all but the first column of list tables */
- .scaffold-list td:not(:first-child),
- .scaffold-list th:not(:first-child) {
- display: none;
- }
-
- .scaffold-list thead th {
- text-align: center;
- }
-
- /* stack form elements */
- .fieldcontain {
- margin-top: 0.6em;
- }
-
- .fieldcontain label,
- .fieldcontain .property-label,
- .fieldcontain .property-value {
- display: block;
- float: none;
- margin: 0 0 0.25em 0;
- text-align: left;
- width: auto;
- }
-
- .errors ul,
- .message p {
- margin: 0.5em;
- }
-
- .error ul {
- margin-left: 0;
- }
-}
diff --git a/web-app/images/apple-touch-icon-retina.png b/web-app/images/apple-touch-icon-retina.png
deleted file mode 100644
index 5cc83ed..0000000
Binary files a/web-app/images/apple-touch-icon-retina.png and /dev/null differ
diff --git a/web-app/images/apple-touch-icon.png b/web-app/images/apple-touch-icon.png
deleted file mode 100644
index aba337f..0000000
Binary files a/web-app/images/apple-touch-icon.png and /dev/null differ
diff --git a/web-app/images/favicon.ico b/web-app/images/favicon.ico
deleted file mode 100644
index 3dfcb92..0000000
Binary files a/web-app/images/favicon.ico and /dev/null differ
diff --git a/web-app/images/grails_logo.jpg b/web-app/images/grails_logo.jpg
deleted file mode 100644
index 8be657c..0000000
Binary files a/web-app/images/grails_logo.jpg and /dev/null differ
diff --git a/web-app/images/grails_logo.png b/web-app/images/grails_logo.png
deleted file mode 100644
index 9836b93..0000000
Binary files a/web-app/images/grails_logo.png and /dev/null differ
diff --git a/web-app/images/leftnav_btm.png b/web-app/images/leftnav_btm.png
deleted file mode 100644
index 582e1eb..0000000
Binary files a/web-app/images/leftnav_btm.png and /dev/null differ
diff --git a/web-app/images/leftnav_midstretch.png b/web-app/images/leftnav_midstretch.png
deleted file mode 100644
index 3cb8a51..0000000
Binary files a/web-app/images/leftnav_midstretch.png and /dev/null differ
diff --git a/web-app/images/leftnav_top.png b/web-app/images/leftnav_top.png
deleted file mode 100644
index 6afec7d..0000000
Binary files a/web-app/images/leftnav_top.png and /dev/null differ
diff --git a/web-app/images/skin/database_add.png b/web-app/images/skin/database_add.png
deleted file mode 100644
index 802bd6c..0000000
Binary files a/web-app/images/skin/database_add.png and /dev/null differ
diff --git a/web-app/images/skin/database_delete.png b/web-app/images/skin/database_delete.png
deleted file mode 100644
index cce652e..0000000
Binary files a/web-app/images/skin/database_delete.png and /dev/null differ
diff --git a/web-app/images/skin/database_edit.png b/web-app/images/skin/database_edit.png
deleted file mode 100644
index e501b66..0000000
Binary files a/web-app/images/skin/database_edit.png and /dev/null differ
diff --git a/web-app/images/skin/database_save.png b/web-app/images/skin/database_save.png
deleted file mode 100644
index 44c06dd..0000000
Binary files a/web-app/images/skin/database_save.png and /dev/null differ
diff --git a/web-app/images/skin/database_table.png b/web-app/images/skin/database_table.png
deleted file mode 100644
index 693709c..0000000
Binary files a/web-app/images/skin/database_table.png and /dev/null differ
diff --git a/web-app/images/skin/exclamation.png b/web-app/images/skin/exclamation.png
deleted file mode 100644
index c37bd06..0000000
Binary files a/web-app/images/skin/exclamation.png and /dev/null differ
diff --git a/web-app/images/skin/house.png b/web-app/images/skin/house.png
deleted file mode 100644
index fed6221..0000000
Binary files a/web-app/images/skin/house.png and /dev/null differ
diff --git a/web-app/images/skin/information.png b/web-app/images/skin/information.png
deleted file mode 100644
index 12cd1ae..0000000
Binary files a/web-app/images/skin/information.png and /dev/null differ
diff --git a/web-app/images/skin/shadow.jpg b/web-app/images/skin/shadow.jpg
deleted file mode 100644
index b7ed44f..0000000
Binary files a/web-app/images/skin/shadow.jpg and /dev/null differ
diff --git a/web-app/images/skin/sorted_asc.gif b/web-app/images/skin/sorted_asc.gif
deleted file mode 100644
index 6b179c1..0000000
Binary files a/web-app/images/skin/sorted_asc.gif and /dev/null differ
diff --git a/web-app/images/skin/sorted_desc.gif b/web-app/images/skin/sorted_desc.gif
deleted file mode 100644
index 38b3a01..0000000
Binary files a/web-app/images/skin/sorted_desc.gif and /dev/null differ
diff --git a/web-app/images/spinner.gif b/web-app/images/spinner.gif
deleted file mode 100644
index 1ed786f..0000000
Binary files a/web-app/images/spinner.gif and /dev/null differ
diff --git a/web-app/images/springsource.png b/web-app/images/springsource.png
deleted file mode 100644
index e806d00..0000000
Binary files a/web-app/images/springsource.png and /dev/null differ
diff --git a/web-app/js/knockout-3.0.0.js b/web-app/js/knockout-3.0.0.js
deleted file mode 100644
index 1c6945a..0000000
--- a/web-app/js/knockout-3.0.0.js
+++ /dev/null
@@ -1,94 +0,0 @@
-// Knockout JavaScript library v3.0.0
-// (c) Steven Sanderson - http://knockoutjs.com/
-// License: MIT (http://www.opensource.org/licenses/mit-license.php)
-
-(function() {(function(q){var y=this||(0,eval)("this"),w=y.document,K=y.navigator,u=y.jQuery,B=y.JSON;(function(q){"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?q(module.exports||exports):"function"===typeof define&&define.amd?define(["exports"],q):q(y.ko={})})(function(F){function G(a,c){return null===a||typeof a in N?a===c:!1}function H(b,c,d,e){a.d[b]={init:function(b){a.a.f.set(b,L,{});return{controlsDescendantBindings:!0}},update:function(b,h,k,m,f){k=a.a.f.get(b,L);h=a.a.c(h());
-m=!d!==!h;var p=!k.ob;if(p||c||m!==k.Db)p&&(k.ob=a.a.Ya(a.e.childNodes(b),!0)),m?(p||a.e.S(b,a.a.Ya(k.ob)),a.Ta(e?e(f,h):f,b)):a.e.Z(b),k.Db=m}};a.g.Y[b]=!1;a.e.P[b]=!0}var a="undefined"!==typeof F?F:{};a.b=function(b,c){for(var d=b.split("."),e=a,g=0;ga.a.l(c,b[f])&&c.push(b[f]);return c},ha:function(a,b){a=a||[];for(var f=[],c=0,d=a.length;cd?f&&b.push(c):f||b.splice(d,1)},extend:function(a,b){if(b)for(var f in b)b.hasOwnProperty(f)&&
-(a[f]=b[f]);return a},K:b,Da:function(a,b){if(!a)return a;var f={},c;for(c in a)a.hasOwnProperty(c)&&(f[c]=b(a[c],c,a));return f},wa:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},Vb:function(b){b=a.a.Q(b);for(var c=w.createElement("div"),f=0,d=b.length;fh?a.setAttribute("selected",b):a.selected=b},la:function(a){return null===a||a===
-q?"":a.trim?a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},ec:function(b,c){for(var f=[],d=(b||"").split(c),e=0,g=d.length;ea.length?!1:a.substring(0,b.length)===b},Gb:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(3===a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;
-return!!a},va:function(b){return a.a.Gb(b,b.ownerDocument.documentElement)},Ra:function(b){return!!a.a.Ua(b,a.a.va)},v:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},r:function(b,d,f){var e=h&&g[d];if(e||"undefined"==typeof u)if(e||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var s=function(a){f.call(b,a)},l="on"+d;b.attachEvent(l,s);a.a.C.ea(b,function(){b.detachEvent(l,s)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(d,
-f,!1);else{if(c(b,d)){var n=f;f=function(a,b){var f=this.checked;b&&(this.checked=!0!==b.Ab);n.call(this,a);this.checked=f}}u(b).bind(d,f)}},da:function(a,b){if(!a||!a.nodeType)throw Error("element must be a DOM node when calling triggerEvent");if("undefined"!=typeof u){var f=[];c(a,b)&&f.push({Ab:a.checked});u(a).trigger(b,f)}else if("function"==typeof w.createEvent)if("function"==typeof a.dispatchEvent)f=w.createEvent(e[b]||"HTMLEvents"),f.initEvent(b,!0,!0,y,0,0,0,0,0,!1,!1,!1,!1,0,a),a.dispatchEvent(f);
-else throw Error("The supplied element doesn't support dispatchEvent");else if("undefined"!=typeof a.fireEvent)c(a,b)&&(a.checked=!0!==a.checked),a.fireEvent("on"+b);else throw Error("Browser doesn't support triggering events");},c:function(b){return a.M(b)?b():b},Ha:function(b){return a.M(b)?b.t():b},ma:function(b,c,f){if(c){var d=/\S+/g,e=b.className.match(d)||[];a.a.n(c.match(d),function(b){a.a.V(e,b,f)});b.className=e.join(" ")}},Ma:function(b,c){var f=a.a.c(c);if(null===f||f===q)f="";var d=a.e.firstChild(b);
-!d||3!=d.nodeType||a.e.nextSibling(d)?a.e.S(b,[w.createTextNode(f)]):d.data=f;a.a.Jb(b)},pb:function(a,b){a.name=b;if(7>=h)try{a.mergeAttributes(w.createElement(""),!1)}catch(f){}},Jb:function(a){9<=h&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},Hb:function(a){if(h){var b=a.style.width;a.style.width=0;a.style.width=b}},Zb:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var f=[],d=b;d<=c;d++)f.push(d);return f},Q:function(a){for(var b=[],c=0,d=a.length;c<
-d;c++)b.push(a[c]);return b},cc:6===h,dc:7===h,ja:h,ab:function(b,c){for(var f=a.a.Q(b.getElementsByTagName("input")).concat(a.a.Q(b.getElementsByTagName("textarea"))),d="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},e=[],g=f.length-1;0<=g;g--)d(f[g])&&e.push(f[g]);return e},Wb:function(b){return"string"==typeof b&&(b=a.a.la(b))?B&&B.parse?B.parse(b):(new Function("return "+b))():null},Na:function(b,c,f){if(!B||!B.stringify)throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
-return B.stringify(a.a.c(b),c,f)},Xb:function(c,d,f){f=f||{};var e=f.params||{},g=f.includeFields||this.$a,h=c;if("object"==typeof c&&"form"===a.a.v(c))for(var h=c.action,n=g.length-1;0<=n;n--)for(var r=a.a.ab(c,g[n]),v=r.length-1;0<=v;v--)e[r[v].name]=r[v].value;d=a.a.c(d);var t=w.createElement("form");t.style.display="none";t.action=h;t.method="post";for(var E in d)c=w.createElement("input"),c.name=E,c.value=a.a.Na(a.a.c(d[E])),t.appendChild(c);b(e,function(a,b){var c=w.createElement("input");c.name=
-a;c.value=b;t.appendChild(c)});w.body.appendChild(t);f.submitter?f.submitter(t):t.submit();setTimeout(function(){t.parentNode.removeChild(t)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.n);a.b("utils.arrayFirst",a.a.Ua);a.b("utils.arrayFilter",a.a.ga);a.b("utils.arrayGetDistinctValues",a.a.Va);a.b("utils.arrayIndexOf",a.a.l);a.b("utils.arrayMap",a.a.ha);a.b("utils.arrayPushAll",a.a.X);a.b("utils.arrayRemoveItem",a.a.ia);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",
-a.a.$a);a.b("utils.getFormFields",a.a.ab);a.b("utils.peekObservable",a.a.Ha);a.b("utils.postJson",a.a.Xb);a.b("utils.parseJson",a.a.Wb);a.b("utils.registerEventHandler",a.a.r);a.b("utils.stringifyJson",a.a.Na);a.b("utils.range",a.a.Zb);a.b("utils.toggleDomNodeCssClass",a.a.ma);a.b("utils.triggerEvent",a.a.da);a.b("utils.unwrapObservable",a.a.c);a.b("utils.objectForEach",a.a.K);a.b("utils.addOrRemoveItem",a.a.V);a.b("unwrap",a.a.c);Function.prototype.bind||(Function.prototype.bind=function(a){var c=
-this,d=Array.prototype.slice.call(arguments);a=d.shift();return function(){return c.apply(a,d.concat(Array.prototype.slice.call(arguments)))}});a.a.f=new function(){function a(b,h){var k=b[d];if(!k||"null"===k||!e[k]){if(!h)return q;k=b[d]="ko"+c++;e[k]={}}return e[k]}var c=0,d="__ko__"+(new Date).getTime(),e={};return{get:function(c,d){var e=a(c,!1);return e===q?q:e[d]},set:function(c,d,e){if(e!==q||a(c,!1)!==q)a(c,!0)[d]=e},clear:function(a){var b=a[d];return b?(delete e[b],a[d]=null,!0):!1},D:function(){return c++ +
-d}}};a.b("utils.domData",a.a.f);a.b("utils.domData.clear",a.a.f.clear);a.a.C=new function(){function b(b,c){var e=a.a.f.get(b,d);e===q&&c&&(e=[],a.a.f.set(b,d,e));return e}function c(d){var e=b(d,!1);if(e)for(var e=e.slice(0),m=0;m","