diff --git a/pom.xml b/pom.xml index ca7de46e13..5dbe658c38 100644 --- a/pom.xml +++ b/pom.xml @@ -291,7 +291,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 2.9 + 2.10 @@ -355,7 +355,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 2.9 + 2.10 @@ -389,7 +389,7 @@ org.zeroturnaround jrebel-maven-plugin - 1.0.7 + 1.1.0 generate-rebel-xml @@ -427,14 +427,14 @@ 1.8.5 4.10 - 1.6.3 + 1.6.4 2.5 3.0 - 1.9.1 + 1.10 2.4.6 2.3.18 - 7.5.1.v20110908 - 0.9.30 + 7.5.4.v20111024 + 1.0.0 1.6 UTF-8 SCM-BSD diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ServerVersionSubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ServerVersionSubCommand.java new file mode 100644 index 0000000000..e5c60f0779 --- /dev/null +++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ServerVersionSubCommand.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ +package sonia.scm.cli.cmd; + +import sonia.scm.ScmState; +import sonia.scm.client.ScmClientSession; +import sonia.scm.util.Util; + +/** + * + * @author Sebastian Sdorra + * @version 1.9 + */ +@Command( + name = "server-version", + usage = "usageServerVersion", + group = "misc" +) +public class ServerVersionSubCommand extends SubCommand +{ + + @Override + protected void run() + { + ScmClientSession session = createSession(); + ScmState state = session.getState(); + String version = null; + if ( state != null ){ + version = state.getVersion(); + + } + if ( Util.isEmpty(version) ){ + version = VersionSubCommand.DEFAULT_VERSION; + } + + output.append("scm-manager version: ").println( version ); + } + +} diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/VersionSubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/VersionSubCommand.java new file mode 100644 index 0000000000..285739f2c2 --- /dev/null +++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/VersionSubCommand.java @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cli.cmd; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.util.IOUtil; +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; +import java.io.InputStream; + +import java.util.Properties; + +/** + * + * @author Sebastian Sdorra + * @since 1.9 + */ +@Command( + name = "version", + usage = "usageVersion", + group = "misc" +) +public class VersionSubCommand extends SubCommand +{ + + /** Default version {@link String} */ + public static final String DEFAULT_VERSION = "unknown"; + + /** Path to the maven properties file of the scm-core artifact */ + public static final String MAVEN_PROPERTIES = + "/META-INF/maven/sonia.scm.clients/scm-cli-client/pom.properties"; + + /** Maven property for the version of the artifact */ + public static final String MAVEN_PROPERTY_VERSION = "version"; + + /** the logger for VersionSubCommand */ + private static final Logger logger = + LoggerFactory.getLogger(VersionSubCommand.class); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + @Override + protected void run() + { + String version = getVersion(); + + output.append("scm-cli-client version: ").println(version); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + private String getVersion() + { + String version = null; + InputStream stream = null; + + try + { + stream = VersionSubCommand.class.getResourceAsStream(MAVEN_PROPERTIES); + + if (stream != null) + { + Properties properties = new Properties(); + + properties.load(stream); + version = properties.getProperty(MAVEN_PROPERTY_VERSION); + } + } + catch (IOException ex) + { + logger.warn("could not parse maven.properties", ex); + } + finally + { + IOUtil.close(stream); + } + + if (Util.isEmpty(version)) + { + version = DEFAULT_VERSION; + } + + return version; + } +} diff --git a/scm-clients/scm-cli-client/src/main/resources/META-INF/services/sonia.scm.cli.cmd.SubCommand b/scm-clients/scm-cli-client/src/main/resources/META-INF/services/sonia.scm.cli.cmd.SubCommand index f9bccfe3b0..73e50f8940 100644 --- a/scm-clients/scm-cli-client/src/main/resources/META-INF/services/sonia.scm.cli.cmd.SubCommand +++ b/scm-clients/scm-cli-client/src/main/resources/META-INF/services/sonia.scm.cli.cmd.SubCommand @@ -59,3 +59,7 @@ sonia.scm.cli.cmd.ModifyGroupSubCommand # member sonia.scm.cli.cmd.AddMembersSubCommand sonia.scm.cli.cmd.DeleteMembersSubCommand + +# misc +sonia.scm.cli.cmd.VersionSubCommand +sonia.scm.cli.cmd.ServerVersionSubCommand diff --git a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties index b572a860c9..cebfbeaff6 100644 --- a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties +++ b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties @@ -109,4 +109,6 @@ usageListRepositories= Print a list of all repositories usageModifyGroup = Modify a group usageModifyUser = Modify a user usageModifyRepository = Modify a repository -usageStoreConfig = Stores the current configuration \ No newline at end of file +usageStoreConfig = Stores the current configuration +usageVersion = Show the version of scm-cli-client +usageServerVersion = Show the version of the scm-manager \ No newline at end of file diff --git a/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ClientChangesetHandler.java b/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ClientChangesetHandler.java index 866a0b3174..ea858cca97 100644 --- a/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ClientChangesetHandler.java +++ b/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ClientChangesetHandler.java @@ -55,4 +55,14 @@ public interface ClientChangesetHandler * @return */ public ChangesetPagingResult getChangesets(int start, int limit); + + /** + * @param path + * @param revision + * @param start + * @param limit + * @return + */ + public ChangesetPagingResult getChangesets(String path, String revision, + int start, int limit); } diff --git a/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ScmUrlProvider.java b/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ScmUrlProvider.java index 1382a0325e..11b226f11e 100644 --- a/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ScmUrlProvider.java +++ b/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ScmUrlProvider.java @@ -247,12 +247,14 @@ public class ScmUrlProvider * @param repositoryId * @since 1.8 * + * @param path + * @param revision * @param start * @param limit * @return */ - public String getRepositoryChangesetUrl(String repositoryId, int start, - int limit) + public String getRepositoryChangesetUrl(String repositoryId, String path, + String revision, int start, int limit) { String url = MessageFormat.format(getResourceUrl(URLPATTERN_CHANGESETS), repositoryId); @@ -267,11 +269,41 @@ public class ScmUrlProvider if (limit > 0) { url = url.concat(s).concat("limit=").concat(String.valueOf(limit)); + s = "&"; + } + + if (path != null) + { + url = url.concat(s).concat("path=").concat(path); + s = "&"; + } + + if (revision != null) + { + url = url.concat(s).concat("revision=").concat(revision); + s = "&"; } return url; } + /** + * Method description + * + * + * @param repositoryId + * @since 1.8 + * + * @param start + * @param limit + * @return + */ + public String getRepositoryChangesetUrl(String repositoryId, int start, + int limit) + { + return getRepositoryChangesetUrl(repositoryId, null, null, start, limit); + } + /** * Method description * diff --git a/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientChangesetHandler.java b/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientChangesetHandler.java index d451ecadca..f9f7e8beaa 100644 --- a/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientChangesetHandler.java +++ b/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientChangesetHandler.java @@ -103,6 +103,47 @@ public class JerseyClientChangesetHandler implements ClientChangesetHandler return result; } + /** + * Method description + * + * + * + * @param path + * @param revision + * @param start + * @param limit + * + * @return + */ + @Override + public ChangesetPagingResult getChangesets(String path, String revision, + int start, int limit) + { + ChangesetPagingResult result = null; + String url = + session.getUrlProvider().getRepositoryChangesetUrl(repository.getId(), + path, revision, start, limit); + WebResource resource = session.getClient().resource(url); + ClientResponse response = null; + + try + { + response = resource.get(ClientResponse.class); + + if (response.getStatus() != ScmClientException.SC_NOTFOUND) + { + ClientUtil.checkResponse(response, 200); + result = response.getEntity(ChangesetPagingResult.class); + } + } + finally + { + ClientUtil.close(response); + } + + return result; + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-core/src/main/java/sonia/scm/cache/Cache.java b/scm-core/src/main/java/sonia/scm/cache/Cache.java index 5282d6ede2..319cadcde1 100644 --- a/scm-core/src/main/java/sonia/scm/cache/Cache.java +++ b/scm-core/src/main/java/sonia/scm/cache/Cache.java @@ -33,9 +33,13 @@ package sonia.scm.cache; +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.Filter; + /** - * The main interface for the cache. - * Provides methods to add, access, and remove entries from a cache. + * The main interface for the cache. + * Provides methods to add, access, and remove entries from a cache. * * @author Sebastian Sdorra * @@ -81,6 +85,18 @@ public interface Cache */ public boolean remove(K key); + /** + * Remove all elements with matching {@link Filter} from this cache. + * The method returns true if the operation was successful. + * + * @since 1.9 + * + * @param filter - The filter to match cache keys + * + * @return true if the operation was successful + */ + public boolean removeAll(Filter filter); + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java b/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java index c5f61b6ada..f8c2ada099 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java +++ b/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java @@ -40,12 +40,19 @@ import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; /** * * @author Sebastian Sdorra */ +@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "plugin-information") public class PluginInformation implements Validateable { @@ -73,12 +80,6 @@ public class PluginInformation implements Validateable final PluginInformation other = (PluginInformation) obj; - if ((this.condition != other.condition) - && ((this.condition == null) ||!this.condition.equals(other.condition))) - { - return false; - } - if ((this.artifactId == null) ? (other.artifactId != null) : !this.artifactId.equals(other.artifactId)) @@ -93,6 +94,19 @@ public class PluginInformation implements Validateable return false; } + if ((this.category == null) + ? (other.category != null) + : !this.category.equals(other.category)) + { + return false; + } + + if ((this.condition != other.condition) + && ((this.condition == null) ||!this.condition.equals(other.condition))) + { + return false; + } + if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) @@ -114,6 +128,13 @@ public class PluginInformation implements Validateable return false; } + if ((this.screenshots != other.screenshots) + && ((this.screenshots == null) + ||!this.screenshots.equals(other.screenshots))) + { + return false; + } + if (this.state != other.state) { return false; @@ -133,6 +154,13 @@ public class PluginInformation implements Validateable return false; } + if ((this.wiki == null) + ? (other.wiki != null) + : !this.wiki.equals(other.wiki)) + { + return false; + } + return true; } @@ -147,33 +175,42 @@ public class PluginInformation implements Validateable { int hash = 5; - hash = 83 * hash + ((this.condition != null) - ? this.condition.hashCode() - : 0); - hash = 83 * hash + ((this.artifactId != null) + hash = 79 * hash + ((this.artifactId != null) ? this.artifactId.hashCode() : 0); - hash = 83 * hash + ((this.author != null) + hash = 79 * hash + ((this.author != null) ? this.author.hashCode() : 0); - hash = 83 * hash + ((this.description != null) + hash = 79 * hash + ((this.category != null) + ? this.category.hashCode() + : 0); + hash = 79 * hash + ((this.condition != null) + ? this.condition.hashCode() + : 0); + hash = 79 * hash + ((this.description != null) ? this.description.hashCode() : 0); - hash = 83 * hash + ((this.groupId != null) + hash = 79 * hash + ((this.groupId != null) ? this.groupId.hashCode() : 0); - hash = 83 * hash + ((this.name != null) + hash = 79 * hash + ((this.name != null) ? this.name.hashCode() : 0); - hash = 83 * hash + ((this.state != null) + hash = 79 * hash + ((this.screenshots != null) + ? this.screenshots.hashCode() + : 0); + hash = 79 * hash + ((this.state != null) ? this.state.hashCode() : 0); - hash = 83 * hash + ((this.url != null) + hash = 79 * hash + ((this.url != null) ? this.url.hashCode() : 0); - hash = 83 * hash + ((this.version != null) + hash = 79 * hash + ((this.version != null) ? this.version.hashCode() : 0); + hash = 79 * hash + ((this.wiki != null) + ? this.wiki.hashCode() + : 0); return hash; } @@ -202,6 +239,17 @@ public class PluginInformation implements Validateable return author; } + /** + * Method description + * + * + * @return + */ + public String getCategory() + { + return category; + } + /** * Method description * @@ -261,6 +309,17 @@ public class PluginInformation implements Validateable return name; } + /** + * Method description + * + * + * @return + */ + public List getScreenshots() + { + return screenshots; + } + /** * Method description * @@ -294,6 +353,17 @@ public class PluginInformation implements Validateable return version; } + /** + * Method description + * + * + * @return + */ + public String getWiki() + { + return wiki; + } + /** * Method description * @@ -331,6 +401,17 @@ public class PluginInformation implements Validateable this.author = author; } + /** + * Method description + * + * + * @param category + */ + public void setCategory(String category) + { + this.category = category; + } + /** * Method description * @@ -375,6 +456,17 @@ public class PluginInformation implements Validateable this.name = name; } + /** + * Method description + * + * + * @param screenshots + */ + public void setScreenshots(List screenshots) + { + this.screenshots = screenshots; + } + /** * Method description * @@ -408,6 +500,17 @@ public class PluginInformation implements Validateable this.version = version; } + /** + * Method description + * + * + * @param wiki + */ + public void setWiki(String wiki) + { + this.wiki = wiki; + } + //~--- fields --------------------------------------------------------------- /** Field description */ @@ -416,6 +519,9 @@ public class PluginInformation implements Validateable /** Field description */ private String author; + /** Field description */ + private String category; + /** Field description */ private PluginCondition condition; @@ -428,6 +534,11 @@ public class PluginInformation implements Validateable /** Field description */ private String name; + /** Field description */ + @XmlElement(name = "screenshot") + @XmlElementWrapper(name = "screenshots") + private List screenshots; + /** Field description */ private PluginState state; @@ -436,4 +547,7 @@ public class PluginInformation implements Validateable /** Field description */ private String version; + + /** Field description */ + private String wiki; } diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginInformationComparator.java b/scm-core/src/main/java/sonia/scm/plugin/PluginInformationComparator.java index cdb0777cae..fa9fb606b9 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/PluginInformationComparator.java +++ b/scm-core/src/main/java/sonia/scm/plugin/PluginInformationComparator.java @@ -78,8 +78,21 @@ public class PluginInformationComparator if (result == 0) { - result = plugin.getState().getCompareValue() - - other.getState().getCompareValue(); + PluginState state = plugin.getState(); + PluginState otherState = other.getState(); + + if ((state != null) && (otherState != null)) + { + result = state.getCompareValue() - otherState.getCompareValue(); + } + else if ((state == null) && (otherState != null)) + { + result = 1; + } + else if ((state != null) && (otherState == null)) + { + result = -1; + } } } diff --git a/scm-core/src/main/java/sonia/scm/repository/BlameViewerUtil.java b/scm-core/src/main/java/sonia/scm/repository/BlameViewerUtil.java index 69a7ded78b..e552a53d1f 100644 --- a/scm-core/src/main/java/sonia/scm/repository/BlameViewerUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/BlameViewerUtil.java @@ -57,7 +57,7 @@ import java.io.IOException; * @since 1.8 */ @Singleton -public class BlameViewerUtil extends CacheClearHook +public class BlameViewerUtil extends PartCacheClearHook { /** Field description */ @@ -104,8 +104,7 @@ public class BlameViewerUtil extends CacheClearHook * @throws NotSupportedFeatuerException * @throws RepositoryException */ - public BlameResult getBlame(String repositoryId, String revision, - String path) + public BlameResult getBlame(String repositoryId, String revision, String path) throws RepositoryException, NotSupportedFeatuerException, IOException { AssertUtil.assertIsNotEmpty(repositoryId); @@ -137,7 +136,7 @@ public class BlameViewerUtil extends CacheClearHook * @throws RepositoryException */ public BlameResult getBlame(Repository repository, String revision, - String path) + String path) throws RepositoryException, NotSupportedFeatuerException, IOException { AssertUtil.assertIsNotNull(repository); @@ -177,7 +176,7 @@ public class BlameViewerUtil extends CacheClearHook * @version Enter version here... * @author Enter your name here... */ - private static class BlameViewerCacheKey + private static class BlameViewerCacheKey implements RepositoryCacheKey { /** @@ -269,6 +268,20 @@ public class BlameViewerUtil extends CacheClearHook return hash; } + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public String getRepositoryId() + { + return repositoryId; + } + //~--- fields ------------------------------------------------------------- /** Field description */ diff --git a/scm-core/src/main/java/sonia/scm/repository/CacheClearHook.java b/scm-core/src/main/java/sonia/scm/repository/CacheClearHook.java index 7587502c00..d4dcc8ff55 100644 --- a/scm-core/src/main/java/sonia/scm/repository/CacheClearHook.java +++ b/scm-core/src/main/java/sonia/scm/repository/CacheClearHook.java @@ -38,6 +38,7 @@ package sonia.scm.repository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sonia.scm.Filter; import sonia.scm.cache.Cache; //~--- JDK imports ------------------------------------------------------------ @@ -63,15 +64,40 @@ public class CacheClearHook implements RepositoryHook * Method description * * @since 1.7 + * */ public void clearCache() { - if (logger.isDebugEnabled()) - { - logger.debug("clear cache"); - } + clearCache(null); + } - cache.clear(); + /** + * Method description + * + * @since 1.9 + * + * @param filter + */ + public void clearCache(Filter filter) + { + if (filter != null) + { + if (logger.isDebugEnabled()) + { + logger.debug("clear cache, with filter"); + } + + cache.removeAll(filter); + } + else + { + if (logger.isDebugEnabled()) + { + logger.debug("clear cache"); + } + + cache.clear(); + } } /** @@ -89,7 +115,9 @@ public class CacheClearHook implements RepositoryHook event.getRepository().getName()); } - cache.clear(); + Filter filter = createFilter(event); + + clearCache(filter); } //~--- get methods ---------------------------------------------------------- @@ -120,6 +148,20 @@ public class CacheClearHook implements RepositoryHook //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * @since 1.9 + * + * + * @param event + * @return + */ + protected Filter createFilter(RepositoryHookEvent event) + { + return null; + } + /** * Method description * diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java index ec91276384..c862cc52b6 100644 --- a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java +++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java @@ -60,4 +60,24 @@ public interface ChangesetViewer */ public ChangesetPagingResult getChangesets(int start, int max) throws IOException, RepositoryException; + + /** + * Method description + * + * + * + * + * @param path + * @param revision + * @param start + * @param max + * + * @return + * + * @throws IOException + * @throws RepositoryException + */ + public ChangesetPagingResult getChangesets(String path, String revision, + int start, int max) + throws IOException, RepositoryException; } diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerUtil.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerUtil.java index 8f12bde687..04aca7f5f4 100644 --- a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerUtil.java @@ -57,7 +57,7 @@ import java.util.Set; * @author Sebastian Sdorra * @since 1.6 */ -public class ChangesetViewerUtil extends CacheClearHook +public class ChangesetViewerUtil extends PartCacheClearHook { /** Field description */ @@ -126,6 +126,40 @@ public class ChangesetViewerUtil extends CacheClearHook return getChangesets(repository, start, max); } + /** + * Method description + * + * + * @param repositoryId + * @param path + * @param revision + * @param start + * @param max + * + * @return + * + * + * @throws IOException + * @throws NotSupportedFeatuerException + * @throws RepositoryException + */ + public ChangesetPagingResult getChangesets(String repositoryId, String path, + String revision, int start, int max) + throws IOException, RepositoryException, NotSupportedFeatuerException + { + AssertUtil.assertIsNotEmpty(repositoryId); + + Repository repository = repositoryManager.get(repositoryId); + + if (repository == null) + { + throw new RepositoryNotFoundException( + "could not find repository with id ".concat(repositoryId)); + } + + return getChangesets(repository, path, revision, start, max); + } + /** * Method description * @@ -187,6 +221,70 @@ public class ChangesetViewerUtil extends CacheClearHook return result; } + /** + * Method description + * + * + * @param repository + * @param path + * @param revision + * @param start + * @param max + * + * @return + * + * + * @throws IOException + * @throws NotSupportedFeatuerException + * @throws RepositoryException + */ + public ChangesetPagingResult getChangesets(Repository repository, + String path, String revision, int start, int max) + throws IOException, RepositoryException, NotSupportedFeatuerException + { + AssertUtil.assertIsNotNull(repository); + + ChangesetViewer viewer = repositoryManager.getChangesetViewer(repository); + + if (viewer == null) + { + throw new NotSupportedFeatuerException( + "ChangesetViewer is not supported for type ".concat( + repository.getType())); + } + + ChangesetViewerCacheKey key = + new ChangesetViewerCacheKey(repository.getId(), path, revision, start, + max); + ChangesetPagingResult result = cache.get(key); + + if (result == null) + { + result = viewer.getChangesets(path, revision, start, max); + + if (result != null) + { + if (Util.isNotEmpty(result.getChangesets())) + { + callPreProcessors(result); + callPreProcessorFactories(repository, result); + } + + cache.put(key, result); + } + else + { + throw new RepositoryException("could not fetch changesets"); + } + } + else if (logger.isDebugEnabled()) + { + logger.debug("fetch changesetviewer results from cache"); + } + + return result; + } + //~--- methods -------------------------------------------------------------- /** @@ -247,7 +345,7 @@ public class ChangesetViewerUtil extends CacheClearHook * @version Enter version here..., 11/07/24 * @author Enter your name here... */ - private class ChangesetViewerCacheKey + private class ChangesetViewerCacheKey implements RepositoryCacheKey { /** @@ -259,8 +357,26 @@ public class ChangesetViewerUtil extends CacheClearHook * @param max */ public ChangesetViewerCacheKey(String repository, int start, int max) + { + this(repository, null, null, start, max); + } + + /** + * Constructs ... + * + * + * @param repository + * @param path + * @param revision + * @param start + * @param max + */ + public ChangesetViewerCacheKey(String repository, String path, + String revision, int start, int max) { this.repository = repository; + this.path = path; + this.revision = revision; this.start = start; this.max = max; } @@ -290,6 +406,25 @@ public class ChangesetViewerUtil extends CacheClearHook final ChangesetViewerCacheKey other = (ChangesetViewerCacheKey) obj; + if ((this.revision == null) + ? (other.revision != null) + : !this.revision.equals(other.revision)) + { + return false; + } + + if (this.max != other.max) + { + return false; + } + + if ((this.path == null) + ? (other.path != null) + : !this.path.equals(other.path)) + { + return false; + } + if ((this.repository == null) ? (other.repository != null) : !this.repository.equals(other.repository)) @@ -302,11 +437,6 @@ public class ChangesetViewerUtil extends CacheClearHook return false; } - if (this.max != other.max) - { - return false; - } - return true; } @@ -319,25 +449,51 @@ public class ChangesetViewerUtil extends CacheClearHook @Override public int hashCode() { - int hash = 3; + int hash = 5; - hash = 67 * hash + ((this.repository != null) + hash = 47 * hash + ((this.revision != null) + ? this.revision.hashCode() + : 0); + hash = 47 * hash + this.max; + hash = 47 * hash + ((this.path != null) + ? this.path.hashCode() + : 0); + hash = 47 * hash + ((this.repository != null) ? this.repository.hashCode() : 0); - hash = 67 * hash + this.start; - hash = 67 * hash + this.max; + hash = 47 * hash + this.start; return hash; } + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public String getRepositoryId() + { + return repository; + } + //~--- fields ------------------------------------------------------------- /** Field description */ private int max; + /** Field description */ + private String path; + /** Field description */ private String repository; + /** Field description */ + private String revision; + /** Field description */ private int start; } diff --git a/scm-core/src/main/java/sonia/scm/repository/PartCacheClearHook.java b/scm-core/src/main/java/sonia/scm/repository/PartCacheClearHook.java new file mode 100644 index 0000000000..2a2830501e --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/PartCacheClearHook.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.Filter; + +/** + * + * @author Sebastian Sdorra + * @since 1.9 + */ +public class PartCacheClearHook extends CacheClearHook +{ + + /** + * Method description + * + * + * @param event + * + * @return + */ + @Override + protected Filter createFilter(RepositoryHookEvent event) + { + return new RepositoryFilter(event); + } +} diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserUtil.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserUtil.java index 523a19f041..9291647784 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserUtil.java @@ -59,7 +59,7 @@ import java.util.List; * @since 1.6 */ @Singleton -public class RepositoryBrowserUtil extends CacheClearHook +public class RepositoryBrowserUtil extends PartCacheClearHook { /** Field description */ @@ -205,7 +205,7 @@ public class RepositoryBrowserUtil extends CacheClearHook * @version Enter version here..., 11/08/03 * @author Enter your name here... */ - private static class RepositoryBrowserCacheKey + private static class RepositoryBrowserCacheKey implements RepositoryCacheKey { /** @@ -297,6 +297,20 @@ public class RepositoryBrowserUtil extends CacheClearHook return hash; } + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public String getRepositoryId() + { + return repositoryId; + } + //~--- fields ------------------------------------------------------------- /** Field description */ diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryCacheKey.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryCacheKey.java new file mode 100644 index 0000000000..115f19c6b6 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryCacheKey.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +/** + * + * @author Sebastian Sdorra + * @since 1.9 + */ +public interface RepositoryCacheKey +{ + + /** + * Method description + * + * + * @return + */ + public String getRepositoryId(); +} diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryFilter.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryFilter.java new file mode 100644 index 0000000000..58be4d3791 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryFilter.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.Filter; + +/** + * + * @author Sebastian Sdorra + * @since 1.9 + * + */ +public class RepositoryFilter implements Filter +{ + + /** + * Constructs ... + * + * + * @param repository + */ + public RepositoryFilter(Repository repository) + { + this(repository.getId()); + } + + /** + * Constructs ... + * + * + * @param event + */ + public RepositoryFilter(RepositoryHookEvent event) + { + this(event.getRepository()); + } + + /** + * Constructs ... + * + * + * @param repositoryId + */ + public RepositoryFilter(String repositoryId) + { + this.repositoryId = repositoryId; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param key + * + * @return + */ + @Override + public boolean accept(RepositoryCacheKey key) + { + return repositoryId.equals(key.getRepositoryId()); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String repositoryId; +} diff --git a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java index 58213e1d4b..819efb509c 100644 --- a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java @@ -43,6 +43,10 @@ import sonia.scm.config.ScmConfiguration; //~--- JDK imports ------------------------------------------------------------ import java.io.IOException; +import java.io.UnsupportedEncodingException; + +import java.net.URLDecoder; +import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -58,6 +62,9 @@ public class HttpUtil /** authentication realm for basic authentication */ public static final String AUTHENTICATION_REALM = "SONIA :: SCM Manager"; + /** Field description */ + public static final String ENCODING = "UTF-8"; + /** authentication header */ public static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; @@ -112,6 +119,52 @@ public class HttpUtil //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param value + * + * @return + * @since 1.9 + */ + public static String decode(String value) + { + try + { + value = URLDecoder.decode(value, ENCODING); + } + catch (UnsupportedEncodingException ex) + { + throw new RuntimeException("could not decode", ex); + } + + return value; + } + + /** + * Method description + * + * + * @param value + * + * @return + * @since 1.9 + */ + public static String encode(String value) + { + try + { + value = URLEncoder.encode(value, ENCODING); + } + catch (UnsupportedEncodingException ex) + { + throw new RuntimeException("could not encode", ex); + } + + return value; + } + /** * Send an unauthorized header back to the client * diff --git a/scm-core/src/main/java/sonia/scm/util/LinkTextParser.java b/scm-core/src/main/java/sonia/scm/util/LinkTextParser.java new file mode 100644 index 0000000000..6111820e48 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/util/LinkTextParser.java @@ -0,0 +1,186 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.text.MessageFormat; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author Sebastian Sdorra + */ +public class LinkTextParser +{ + + /** Field description */ + private static final Pattern REGEX_URL = + Pattern.compile( + "\\(?\\b((?:https?://|ftps?://|mailto:|www[.])[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|])"); + + /** Field description */ + private static final String REPLACE_URL = + "{0}"; + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param content + * + * @return + */ + public String parseText(String content) + { + Matcher m = REGEX_URL.matcher(content); + List tokens = new ArrayList(); + int position = 0; + String tokenContent = null; + + while (m.find()) + { + int start = m.start(); + int end = m.end(); + String replacement = m.group(); + + if (replacement.startsWith("www")) + { + replacement = "http://" + replacement; + } + + tokenContent = content.substring(position, start); + tokens.add(new Token(tokenContent)); + tokenContent = content.substring(start, end); + tokens.add(new Token(tokenContent, replacement)); + position = end; + } + + tokenContent = content.substring(position, content.length()); + tokens.add(new Token(tokenContent)); + + StringBuilder buffer = new StringBuilder(); + + for (Token token : tokens) + { + if (token.getReplacement() != null) + { + buffer.append(MessageFormat.format(REPLACE_URL, token.getValue(), + token.getReplacement())); + } + else + { + buffer.append(token.getValue().replace("<", "<").replace(">", + ">")); + } + } + + return buffer.toString(); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 11/11/06 + * @author Enter your name here... + */ + private static class Token + { + + /** + * Constructs ... + * + * + * @param value + */ + public Token(String value) + { + this.value = value; + } + + /** + * Constructs ... + * + * + * @param value + * @param replacement + */ + public Token(String value, String replacement) + { + this.value = value; + this.replacement = replacement; + } + + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getReplacement() + { + return replacement; + } + + /** + * Method description + * + * + * @return + */ + public String getValue() + { + return value; + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private String replacement; + + /** Field description */ + private String value; + } +} diff --git a/scm-core/src/main/java/sonia/scm/util/ValidationUtil.java b/scm-core/src/main/java/sonia/scm/util/ValidationUtil.java index 8a5f5f7109..6b9c31cc53 100644 --- a/scm-core/src/main/java/sonia/scm/util/ValidationUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/ValidationUtil.java @@ -55,7 +55,7 @@ public class ValidationUtil private static final String REGEX_REPOSITORYNAME = "^[A-z0-9\\.\\-_/]+$"; /** Field description */ - private static final String REGEX_USERNAME = "^[A-z0-9\\.\\-_@]+$"; + private static final String REGEX_USERNAME = "^[^ ][A-z0-9\\.\\-_@ ]+[^ ]$"; //~--- get methods ---------------------------------------------------------- diff --git a/scm-core/src/test/java/sonia/scm/util/ValidationUtilTest.java b/scm-core/src/test/java/sonia/scm/util/ValidationUtilTest.java index e18871af24..6eff3f872f 100644 --- a/scm-core/src/test/java/sonia/scm/util/ValidationUtilTest.java +++ b/scm-core/src/test/java/sonia/scm/util/ValidationUtilTest.java @@ -145,9 +145,12 @@ public class ValidationUtilTest assertTrue(ValidationUtil.isUsernameValid("Test123-git")); assertTrue(ValidationUtil.isUsernameValid("Test_user-123.git")); assertTrue(ValidationUtil.isUsernameValid("test@scm-manager.de")); + assertTrue(ValidationUtil.isUsernameValid("test 123")); // false - assertFalse(ValidationUtil.isUsernameValid("test 123")); + assertFalse(ValidationUtil.isUsernameValid(" test 123")); + assertFalse(ValidationUtil.isUsernameValid(" test 123 ")); + assertFalse(ValidationUtil.isUsernameValid("test 123 ")); assertFalse(ValidationUtil.isUsernameValid("test/123")); assertFalse(ValidationUtil.isUsernameValid("test%123")); assertFalse(ValidationUtil.isUsernameValid("test:123")); diff --git a/scm-plugin-backend/pom.xml b/scm-plugin-backend/pom.xml index 018feebe88..9da97a4fa8 100644 --- a/scm-plugin-backend/pom.xml +++ b/scm-plugin-backend/pom.xml @@ -68,6 +68,12 @@ ehcache-core ${ehcache.version} + + + com.thebuzzmedia + imgscalr-lib + 3.2 + @@ -115,4 +121,11 @@ + + + The Buzz Media Maven Repository + http://maven.thebuzzmedia.com + + + diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/BackendConfiguration.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/BackendConfiguration.java index 75b04c60d8..2546eea937 100644 --- a/scm-plugin-backend/src/main/java/sonia/scm/plugin/BackendConfiguration.java +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/BackendConfiguration.java @@ -116,6 +116,17 @@ public class BackendConfiguration return scannInterval; } + /** + * Method description + * + * + * @return + */ + public String getTrackingCode() + { + return trackingCode; + } + /** * Method description * @@ -195,6 +206,17 @@ public class BackendConfiguration this.scannInterval = scannInterval; } + /** + * Method description + * + * + * @param trackingCode + */ + public void setTrackingCode(String trackingCode) + { + this.trackingCode = trackingCode; + } + //~--- fields --------------------------------------------------------------- /** Field description */ @@ -211,7 +233,7 @@ public class BackendConfiguration private boolean multithreaded = true; /** Field description */ - @XmlElement(name= "news-url") + @XmlElement(name = "news-url") private URL newsUrl; /** Field description */ @@ -223,4 +245,8 @@ public class BackendConfiguration @XmlElement(name = "scann-interval") @XmlJavaTypeAdapter(XmlIntervalAdapter.class) private Long scannInterval; + + /** Field description */ + @XmlElement(name = "tracking-code") + private String trackingCode; } diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/Category.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/Category.java new file mode 100644 index 0000000000..57dbed6399 --- /dev/null +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/Category.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Arrays; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * + * @author Sebastian Sdorra + */ +public class Category +{ + + /** + * Constructs ... + * + * + * @param name + * @param plugins + */ + public Category(String name, PluginInformation... plugins) + { + this.name = name; + this.plugins = + new TreeSet(PluginInformationNameComparator.INSTANCE); + + if (plugins != null) + { + this.plugins.addAll(Arrays.asList(plugins)); + } + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getName() + { + return name; + } + + /** + * Method description + * + * + * @return + */ + public SortedSet getPlugins() + { + if (plugins == null) + { + plugins = new TreeSet(); + } + + return plugins; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param name + */ + public void setName(String name) + { + this.name = name; + } + + /** + * Method description + * + * + * @param plugins + */ + public void setPlugins(SortedSet plugins) + { + this.plugins = plugins; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String name; + + /** Field description */ + private SortedSet plugins; +} diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/CategoryNameComaparator.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/CategoryNameComaparator.java new file mode 100644 index 0000000000..26f560e41a --- /dev/null +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/CategoryNameComaparator.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Comparator; + +/** + * + * @author Sebastian Sdorra + */ +public class CategoryNameComaparator implements Comparator +{ + + /** Field description */ + public static final CategoryNameComaparator INSTANCE = + new CategoryNameComaparator(); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param c1 + * @param c2 + * + * @return + */ + @Override + public int compare(Category c1, Category c2) + { + return Util.compare(c1.getName(), c2.getName()); + } +} diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/PluginUtil.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/PluginUtil.java new file mode 100644 index 0000000000..e4e09c89a3 --- /dev/null +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/PluginUtil.java @@ -0,0 +1,174 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Sebastian Sdorra + */ +public class PluginUtil +{ + + /** + * Method description + * + * + * @param plugins + * + * @return + */ + public static List filterSameVersions( + List plugins) + { + List filteredPlugins = + new ArrayList(); + String version = ""; + + for (PluginInformation plugin : plugins) + { + if (!version.equals(plugin.getVersion())) + { + version = plugin.getVersion(); + filteredPlugins.add(plugin); + } + } + + return filteredPlugins; + } + + /** + * Method description + * + * + * @param allVersions + * + * @return + */ + public static List filterSnapshots( + List allVersions) + { + List filtered = new ArrayList(); + + for (PluginInformation plugin : allVersions) + { + if (!plugin.getVersion().contains("SNAPSHOT")) + { + filtered.add(plugin); + } + } + + return filtered; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param backend + * @param groupId + * @param artifactId + * + * @return + */ + public static List getFilteredPluginVersions( + PluginBackend backend, String groupId, String artifactId) + { + List pluginVersions = + PluginUtil.getPluginVersions(backend, groupId, artifactId); + + if (Util.isNotEmpty(pluginVersions)) + { + Collections.sort(pluginVersions, PluginInformationNameComparator.INSTANCE); + pluginVersions = PluginUtil.filterSameVersions(pluginVersions); + } + + return pluginVersions; + } + + /** + * Method description + * + * + * @param backend + * @param groupId + * @param artifactId + * + * @return + */ + public static PluginInformation getLatestPluginVersion(PluginBackend backend, + String groupId, String artifactId) + { + return getFilteredPluginVersions(backend, groupId, artifactId).get(0); + } + + /** + * Method description + * + * + * + * @param backend + * @param groupId + * @param artifactId + * + * @return + */ + public static List getPluginVersions( + PluginBackend backend, final String groupId, final String artifactId) + { + List pluginVersions = + backend.getPlugins(new PluginFilter() + { + @Override + public boolean accept(PluginInformation plugin) + { + return groupId.equals(plugin.getGroupId()) + && artifactId.equals(plugin.getArtifactId()); + } + }); + + return pluginVersions; + } +} diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/DetailResource.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/DetailResource.java index 85be9c70e7..3541d66813 100644 --- a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/DetailResource.java +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/DetailResource.java @@ -37,17 +37,16 @@ package sonia.scm.plugin.rest; import com.google.inject.Inject; +import sonia.scm.plugin.BackendConfiguration; import sonia.scm.plugin.PluginBackend; -import sonia.scm.plugin.PluginFilter; import sonia.scm.plugin.PluginInformation; +import sonia.scm.plugin.PluginUtil; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ import com.sun.jersey.api.view.Viewable; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -76,11 +75,13 @@ public class DetailResource extends ViewableResource * * @param context * @param backend + * @param configuration */ @Inject - public DetailResource(ServletContext context, PluginBackend backend) + public DetailResource(ServletContext context, PluginBackend backend, + BackendConfiguration configuration) { - super(context); + super(context, configuration); this.backend = backend; } @@ -102,22 +103,19 @@ public class DetailResource extends ViewableResource @DefaultValue("false") @QueryParam("snapshot") boolean snapshot) { - List pluginVersions = getPluginVersions(groupId, - artifactId); + List pluginVersions = + PluginUtil.getFilteredPluginVersions(backend, groupId, artifactId); if (Util.isEmpty(pluginVersions)) { throw new WebApplicationException(Status.NOT_FOUND); } - Collections.sort(pluginVersions, PluginInformationComparator.INSTANCE); - pluginVersions = filterSameVersions(pluginVersions); - PluginInformation latest = pluginVersions.get(0); if (!snapshot) { - pluginVersions = filterSnapshots(pluginVersions); + pluginVersions = PluginUtil.filterSnapshots(pluginVersions); } Map vars = createVarMap(latest.getName()); @@ -128,87 +126,6 @@ public class DetailResource extends ViewableResource return new Viewable("/detail", vars); } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param plugins - * - * @return - */ - private List filterSameVersions( - List plugins) - { - List filteredPlugins = - new ArrayList(); - String version = ""; - - for (PluginInformation plugin : plugins) - { - if (!version.equals(plugin.getVersion())) - { - version = plugin.getVersion(); - filteredPlugins.add(plugin); - } - } - - return filteredPlugins; - } - - /** - * Method description - * - * - * @param allVersions - * - * @return - */ - private List filterSnapshots( - List allVersions) - { - List filtered = new ArrayList(); - - for (PluginInformation plugin : allVersions) - { - if (!plugin.getVersion().contains("SNAPSHOT")) - { - filtered.add(plugin); - } - } - - return filtered; - } - - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @param groupId - * @param artifactId - * - * @return - */ - private List getPluginVersions(final String groupId, - final String artifactId) - { - List pluginVersions = - backend.getPlugins(new PluginFilter() - { - @Override - public boolean accept(PluginInformation plugin) - { - return groupId.equals(plugin.getGroupId()) - && artifactId.equals(plugin.getArtifactId()); - } - }); - - return pluginVersions; - } - //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/OverviewResource.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/OverviewResource.java index 170d9a6fb9..22bac4a7c0 100644 --- a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/OverviewResource.java +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/OverviewResource.java @@ -37,9 +37,12 @@ package sonia.scm.plugin.rest; import com.google.inject.Inject; +import sonia.scm.plugin.BackendConfiguration; +import sonia.scm.plugin.Category; +import sonia.scm.plugin.CategoryNameComaparator; import sonia.scm.plugin.PluginBackend; import sonia.scm.plugin.PluginInformation; -import sonia.scm.plugin.PluginInformationNameComparator; +import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ @@ -47,6 +50,7 @@ import com.sun.jersey.api.view.Viewable; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -63,6 +67,11 @@ import javax.ws.rs.Path; public class OverviewResource extends ViewableResource { + /** Field description */ + public static final String DEFAULT_CATEGORY = "Miscellaneous"; + + //~--- constructors --------------------------------------------------------- + /** * Constructs ... * @@ -70,11 +79,13 @@ public class OverviewResource extends ViewableResource * * @param context * @param backend + * @param configuration */ @Inject - public OverviewResource(ServletContext context, PluginBackend backend) + public OverviewResource(ServletContext context, PluginBackend backend, + BackendConfiguration configuration) { - super(context); + super(context, configuration); this.backend = backend; } @@ -89,14 +100,42 @@ public class OverviewResource extends ViewableResource @GET public Viewable overview() { - List plugins = getPluginOverview(); + List categories = getPluginOverview(); Map vars = createVarMap("Plugin Overview"); - vars.put("plugins", plugins); + vars.put("categories", categories); return new Viewable("/index", vars); } + /** + * Method description + * + * + * @param categories + * @param plugin + */ + private void append(Map categories, + PluginInformation plugin) + { + String name = plugin.getCategory(); + + if (Util.isEmpty(name)) + { + name = DEFAULT_CATEGORY; + } + + Category category = categories.get(name); + + if (category == null) + { + category = new Category(name, plugin); + categories.put(name, category); + } + + category.getPlugins().add(plugin); + } + //~--- get methods ---------------------------------------------------------- /** @@ -105,14 +144,14 @@ public class OverviewResource extends ViewableResource * * @return */ - private List getPluginOverview() + private List getPluginOverview() { List allPlugins = backend.getPlugins(); Collections.sort(allPlugins, PluginInformationComparator.INSTANCE); - List plugins = new ArrayList(); String pid = ""; + Map categoryMap = new HashMap(); for (PluginInformation p : allPlugins) { @@ -121,13 +160,15 @@ public class OverviewResource extends ViewableResource if (!currentPid.equals(pid)) { pid = currentPid; - plugins.add(p); + append(categoryMap, p); } } - Collections.sort(plugins, PluginInformationNameComparator.INSTANCE); + List categories = new ArrayList(categoryMap.values()); - return plugins; + Collections.sort(categories, CategoryNameComaparator.INSTANCE); + + return categories; } //~--- fields --------------------------------------------------------------- diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ScreenshotResource.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ScreenshotResource.java new file mode 100644 index 0000000000..4b6a02c25d --- /dev/null +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ScreenshotResource.java @@ -0,0 +1,215 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin.rest; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; + +import com.thebuzzmedia.imgscalr.Scalr; + +import sonia.scm.plugin.PluginBackend; +import sonia.scm.plugin.PluginInformation; +import sonia.scm.plugin.PluginUtil; +import sonia.scm.util.ChecksumUtil; +import sonia.scm.util.IOUtil; +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; + +import java.io.File; +import java.io.IOException; + +import java.net.URL; + +import java.util.List; + +import javax.imageio.ImageIO; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +/** + * + * @author Sebastian Sdorra + */ +@Path("/screenshot/{groupId}/{artifactId}/{number}/{size}.jpg") +public class ScreenshotResource +{ + + /** Field description */ + public static final String EXTENSION_IMAGE = ".jpg"; + + /** Field description */ + public static final String FORMAT = "jpg"; + + /** Field description */ + public static final String PATH_IMAGE = "images"; + + /** Field description */ + public static final int SIZE_LARGE = 640; + + /** Field description */ + public static final int SIZE_MEDIUM = 320; + + /** Field description */ + public static final int SIZE_SMALL = 200; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param backend + */ + @Inject + public ScreenshotResource(PluginBackend backend) + { + this.backend = backend; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param groupId + * @param artifactId + * @param number + * @param size + * + * @return + * + * @throws IOException + */ + @GET + @Produces("image/jpeg") + public Response getScreenshot(@PathParam("groupId") String groupId, + @PathParam("artifactId") String artifactId, + @PathParam("number") int number, + @PathParam("size") String size) + throws IOException + { + PluginInformation plugin = PluginUtil.getLatestPluginVersion(backend, + groupId, artifactId); + + if (plugin == null) + { + throw new WebApplicationException(Status.NOT_FOUND); + } + + List screenshots = plugin.getScreenshots(); + + if (Util.isEmpty(screenshots)) + { + throw new WebApplicationException(Status.NOT_FOUND); + } + + String screenshot = screenshots.get(number); + + if (Util.isEmpty(screenshot)) + { + throw new WebApplicationException(Status.NOT_FOUND); + } + + String checksum = ChecksumUtil.createChecksum(screenshot); + StringBuilder path = new StringBuilder(PATH_IMAGE); + + path.append(File.separator).append(groupId); + path.append(File.separator).append(artifactId).append(File.separator); + path.append(String.valueOf(number)).append(File.separator); + path.append(size).append(File.separator).append(checksum); + path.append(EXTENSION_IMAGE); + + File file = new File(backend.getBaseDirectory(), path.toString()); + + if (!file.exists()) + { + createThumbnail(file, screenshot, size.toCharArray()[0]); + } + + return Response.ok(file).build(); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param file + * @param screenshot + * @param size + * + * @throws IOException + */ + private void createThumbnail(File file, String screenshot, char size) + throws IOException + { + IOUtil.mkdirs(file.getParentFile()); + + int width = SIZE_SMALL; + + switch (size) + { + case 'l' : + width = SIZE_LARGE; + + break; + + case 'm' : + width = SIZE_MEDIUM; + } + + BufferedImage image = ImageIO.read(new URL(screenshot)); + + image = Scalr.resize(image, Scalr.Method.QUALITY, width); + ImageIO.write(image, FORMAT, file); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private PluginBackend backend; +} diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ViewableResource.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ViewableResource.java index c9cb327c0f..d4b3373646 100644 --- a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ViewableResource.java +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ViewableResource.java @@ -33,6 +33,10 @@ package sonia.scm.plugin.rest; +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.plugin.BackendConfiguration; + //~--- JDK imports ------------------------------------------------------------ import java.util.HashMap; @@ -52,10 +56,13 @@ public class ViewableResource * * * @param context + * @param configuration */ - public ViewableResource(ServletContext context) + public ViewableResource(ServletContext context, + BackendConfiguration configuration) { this.contextPath = context.getContextPath(); + this.configuration = configuration; } //~--- methods -------------------------------------------------------------- @@ -73,6 +80,7 @@ public class ViewableResource Map vars = new HashMap(); vars.put("contextPath", contextPath); + vars.put("configuration", configuration); vars.put("title", title); return vars; @@ -80,6 +88,9 @@ public class ViewableResource //~--- fields --------------------------------------------------------------- + /** Field description */ + private BackendConfiguration configuration; + /** Field description */ private String contextPath; } diff --git a/scm-plugin-backend/src/main/webapp/detail.html b/scm-plugin-backend/src/main/webapp/detail.html index 9a73d45370..ed6602aae0 100644 --- a/scm-plugin-backend/src/main/webapp/detail.html +++ b/scm-plugin-backend/src/main/webapp/detail.html @@ -9,6 +9,16 @@ Name ${latest.name} + + Category + + <#if latest.category??> + ${latest.category} + <#else> + Miscellaneous + + + GroupId ${latest.groupId} @@ -21,38 +31,88 @@ Author ${latest.author} + <#if latest.url??> + + URL + + + ${latest.url} + + + + + <#if latest.wiki??> + + Wiki + + + ${latest.wiki} + + + +

 

+<#if latest.screenshots??> + + + + +

 

+ + +

Plugin Versions

-<#list versions as version> -

${version.version}

-
-

${version.description}

- <#if version.condition??> -

Conditions

-
    - <#if version.condition.minVersion??> -
  • Minimum Version: ${version.condition.minVersion}
  • - - <#if version.condition.os??> -
  • - Operatingsystems: - <#list version.condition.os as os> - ${os}<#if os_has_next>, - -
  • - - <#if version.condition.arch??> -
  • Architecture: ${version.condition.arch}
  • - -
- -
- +<#if versions?has_content> + <#list versions as version> +

${version.version}

+
+

${version.description}

+ <#if version.condition??> +

Conditions

+
    + <#if version.condition.minVersion??> +
  • Minimum Version: ${version.condition.minVersion}
  • + + <#if version.condition.os??> +
  • + Operatingsystems: + <#list version.condition.os as os> + ${os}<#if os_has_next>, + +
  • + + <#if version.condition.arch??> +
  • Architecture: ${version.condition.arch}
  • + +
+ +
+ +<#else> + Plugin not yet released +

 

diff --git a/scm-plugin-backend/src/main/webapp/index.html b/scm-plugin-backend/src/main/webapp/index.html index b4747f7ab9..b6c078530b 100644 --- a/scm-plugin-backend/src/main/webapp/index.html +++ b/scm-plugin-backend/src/main/webapp/index.html @@ -1,18 +1,25 @@ <#include "template/header.html"> -
-<#list plugins as plugin> -

${plugin.name}

-
- ${plugin.description}
- more +
+<#list categories as category> +
+

${category.name}

+
+ <#list category.plugins as plugin> +

${plugin.name}

+
+ ${plugin.description}
+ more +
+ +
- + +
diff --git a/scm-plugin-backend/src/main/webapp/template/header.html b/scm-plugin-backend/src/main/webapp/template/header.html index 63ba817d5f..a9eb351a48 100644 --- a/scm-plugin-backend/src/main/webapp/template/header.html +++ b/scm-plugin-backend/src/main/webapp/template/header.html @@ -39,13 +39,30 @@ SCM-Manager Plugin-Backend + + + <#if configuration.trackingCode??> + +
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetViewer.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetViewer.java index ff09cb6ab9..fd24bf1e64 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetViewer.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetViewer.java @@ -93,6 +93,11 @@ public class GitChangesetViewer implements ChangesetViewer @Override public ChangesetPagingResult getChangesets(int start, int max) { + if (logger.isDebugEnabled()) + { + logger.debug("fetch changesets. start: {}, max: {}", start, max); + } + ChangesetPagingResult changesets = null; File directory = handler.getDirectory(repository); org.eclipse.jgit.lib.Repository gr = null; @@ -150,6 +155,87 @@ public class GitChangesetViewer implements ChangesetViewer return changesets; } + /** + * Method description + * + * + * @param path + * @param revision + * @param start + * @param max + * + * @return + */ + @Override + public ChangesetPagingResult getChangesets(String path, String revision, + int start, int max) + { + if (logger.isDebugEnabled()) + { + logger.debug( + "fetch changesets for path {} and revision {}. start: {}, max: {}", + new Object[] { path, + revision, start, max }); + } + + ChangesetPagingResult changesets = null; + File directory = handler.getDirectory(repository); + org.eclipse.jgit.lib.Repository gr = null; + GitChangesetConverter converter = null; + + try + { + gr = GitUtil.open(directory); + + int counter = 0; + List changesetList = new ArrayList(); + + if (!gr.getAllRefs().isEmpty()) + { + converter = new GitChangesetConverter(gr, GitUtil.ID_LENGTH); + + Git git = new Git(gr); + ObjectId revisionId = GitUtil.getRevisionId(gr, revision); + + if (revisionId != null) + { + for (RevCommit commit : + git.log().add(revisionId).addPath(path).call()) + { + if ((counter >= start) && (counter < start + max)) + { + changesetList.add(converter.createChangeset(commit)); + } + + counter++; + } + } + else if (logger.isWarnEnabled()) + { + logger.warn("could not find repository head of repository {}", + repository.getName()); + } + } + + changesets = new ChangesetPagingResult(counter, changesetList); + } + catch (NoHeadException ex) + { + logger.error("could not read changesets", ex); + } + catch (IOException ex) + { + logger.error("could not open repository", ex); + } + finally + { + IOUtil.close(converter); + GitUtil.close(gr); + } + + return changesets; + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/AbstractHgHandler.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/AbstractHgHandler.java index 200a9042a6..b6a0d8c611 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/AbstractHgHandler.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/AbstractHgHandler.java @@ -399,6 +399,7 @@ public class AbstractHgHandler } msg.append("]"); + logger.debug(msg.toString()); } ProcessBuilder pb = new ProcessBuilder(cmdList); diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java index 07ca49deca..82a27ac620 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java @@ -35,7 +35,11 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import sonia.scm.util.Util; +import sonia.scm.web.HgUtil; //~--- JDK imports ------------------------------------------------------------ @@ -58,6 +62,10 @@ public class HgChangesetViewer extends AbstractHgHandler /** Field description */ public static final String RESOURCE_LOG = "/sonia/scm/hglog.py"; + /** the logger for HgChangesetViewer */ + private static final Logger logger = + LoggerFactory.getLogger(HgChangesetViewer.class); + //~--- constructors --------------------------------------------------------- /** @@ -110,14 +118,55 @@ public class HgChangesetViewer extends AbstractHgHandler public ChangesetPagingResult getChangesets(int start, int max) throws IOException, RepositoryException { - return getChangesets(String.valueOf(start), String.valueOf(max), null, - null); + if (logger.isDebugEnabled()) + { + logger.debug("fetch changesets. start: {}, max: {}", start, max); + } + + return getChangesets(null, null, String.valueOf(start), + String.valueOf(max), null, null); } /** * Method description * * + * @param path + * @param revision + * @param start + * @param max + * + * @return + * + * @throws IOException + * @throws RepositoryException + */ + @Override + public ChangesetPagingResult getChangesets(String path, String revision, + int start, int max) + throws IOException, RepositoryException + { + revision = HgUtil.getRevision(revision); + + if (logger.isDebugEnabled()) + { + logger.debug( + "fetch changesets for path {} and revision {}. start: {}, max: {}", + new Object[] { path, + revision, start, max }); + } + + return getChangesets(path, revision, String.valueOf(start), + String.valueOf(max), null, null); + } + + /** + * Method description + * + * + * + * @param path + * @param revision * @param pageStart * @param pageLimit * @param revisionStart @@ -128,12 +177,15 @@ public class HgChangesetViewer extends AbstractHgHandler * @throws IOException * @throws RepositoryException */ - public ChangesetPagingResult getChangesets(String pageStart, - String pageLimit, String revisionStart, String revisionEnd) + public ChangesetPagingResult getChangesets(String path, String revision, + String pageStart, String pageLimit, String revisionStart, + String revisionEnd) throws IOException, RepositoryException { Map env = new HashMap(); + env.put(ENV_PATH, Util.nonNull(path)); + env.put(ENV_REVISION, Util.nonNull(revision)); env.put(ENV_PAGE_START, Util.nonNull(pageStart)); env.put(ENV_PAGE_LIMIT, Util.nonNull(pageLimit)); env.put(ENV_REVISION_START, Util.nonNull(revisionStart)); @@ -157,6 +209,12 @@ public class HgChangesetViewer extends AbstractHgHandler public ChangesetPagingResult getChangesets(String startNode, String endNode) throws IOException, RepositoryException { - return getChangesets(null, null, startNode, endNode); + if (logger.isDebugEnabled()) + { + logger.debug("fetch changesets. start-node: {}, end-node: {}", startNode, + endNode); + } + + return getChangesets(null, null, null, null, startNode, endNode); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java index 698e0f68da..00224509e8 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java @@ -41,9 +41,12 @@ import com.google.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sonia.scm.ConfigChangedListener; import sonia.scm.SCMContextProvider; +import sonia.scm.config.ScmConfiguration; import sonia.scm.io.RegexResourceProcessor; import sonia.scm.io.ResourceProcessor; +import sonia.scm.util.HttpUtil; import sonia.scm.util.IOUtil; import sonia.scm.web.HgWebConfigWriter; @@ -64,7 +67,7 @@ import javax.servlet.http.HttpServletRequest; * @author Sebastian Sdorra */ @Singleton -public class HgHookManager +public class HgHookManager implements ConfigChangedListener { /** Field description */ @@ -81,15 +84,31 @@ public class HgHookManager * * * @param context + * @param configuration */ @Inject - public HgHookManager(SCMContextProvider context) + public HgHookManager(SCMContextProvider context, + ScmConfiguration configuration) { this.context = context; + this.configuration = configuration; + this.configuration.addListener(this); } //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param config + */ + @Override + public void configChanged(ScmConfiguration config) + { + this.changed = true; + } + /** * TODO check if file exists * @@ -106,10 +125,7 @@ public class HgHookManager { if (isScriptWriteAble()) { - StringBuilder url = new StringBuilder(request.getScheme()); - - url.append("://localhost:").append(request.getServerPort()); - url.append(request.getContextPath()).append("/hook/hg/"); + String url = createUrl(request); if (hgHookScript == null) { @@ -121,10 +137,12 @@ public class HgHookManager if (logger.isDebugEnabled()) { - logger.debug("write hg hook script to '{}'", hgHookScript); + logger.debug("write hg hook script for '{}' to '{}'", url, + hgHookScript); } writeScript(hgHookScript, url.toString()); + changed = false; } } } @@ -158,6 +176,35 @@ public class HgHookManager //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param request + * + * @return + */ + private String createUrl(HttpServletRequest request) + { + String url = null; + + if (configuration.isForceBaseUrl()) + { + url = HttpUtil.getUriWithoutEndSeperator( + configuration.getBaseUrl()).concat("/hook/hg/"); + } + else + { + StringBuilder sb = new StringBuilder(request.getScheme()); + + sb.append("://localhost:").append(request.getLocalPort()); + sb.append(request.getContextPath()).append("/hook/hg/"); + url = sb.toString(); + } + + return url; + } + /** * Method description * @@ -202,14 +249,20 @@ public class HgHookManager */ private boolean isScriptWriteAble() { - return (hgHookScript == null) ||!hgHookScript.exists(); + return (hgHookScript == null) ||!hgHookScript.exists() || changed; } //~--- fields --------------------------------------------------------------- + /** Field description */ + private boolean changed = false; + /** Field description */ private String challenge = UUID.randomUUID().toString(); + /** Field description */ + private ScmConfiguration configuration; + /** Field description */ private SCMContextProvider context; diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hglog.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hglog.py index ec9ab26866..fcaa246dfc 100644 --- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hglog.py +++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hglog.py @@ -29,8 +29,10 @@ # # +# import basic packages import sys, os +# create python path pythonPath = os.environ['SCM_PYTHON_PATH'] if len(pythonPath) > 0: @@ -38,49 +40,21 @@ if len(pythonPath) > 0: for i in range(len(pathParts)): sys.path.insert(i, pathParts[i]) +# import mercurial packages from mercurial import hg, ui, commands from mercurial.node import hex from xml.sax.saxutils import escape import datetime, time -repositoryPath = os.environ['SCM_REPOSITORY_PATH'] -repo = hg.repository(ui.ui(), path = repositoryPath) - -startNode = os.environ['SCM_REVISION_START'] -endNode = os.environ['SCM_REVISION_END'] - -total = len(repo) - -if len(startNode) > 0 and len(endNode) > 0: - # start and end revision - startRev = repo[startNode].rev() -1 - endRev = repo[endNode].rev() - -else: - # paging - start = os.environ['SCM_PAGE_START'] - limit = os.environ['SCM_PAGE_LIMIT'] - - limit = int(limit) - - end = int(start) - endRev = total - end - 1 - - startRev = endRev - limit - -# fix negative start revisions -if startRev < -1: - startRev = -1 - # header -print '' -print '' -print ' ' + str(total) + '' -print ' ' +def printHeader(total): + print '' + print '' + print ' ' + str(total) + '' + print ' ' -# changesets -for i in range(endRev, startRev, -1): - ctx = repo[i] +# changeset +def printChangeset(repo, ctx): time = int(ctx.date()[0]) * 1000 branch = ctx.branch() tags = ctx.tags() @@ -99,7 +73,7 @@ for i in range(endRev, startRev, -1): authorName = authorName[0:s].strip() print ' ' - print ' ' + str(i) + ':' + hex(ctx.node()[:6]) + '' + print ' ' + str(ctx.rev()) + ':' + hex(ctx.node()[:6]) + '' print ' ' + escape(ctx.user()) + '' print ' ' + escape(ctx.description()) + '' print ' ' + str(time).split('.')[0] + '' @@ -147,7 +121,83 @@ for i in range(endRev, startRev, -1): print ' ' print ' ' - + # footer -print ' ' -print '' +def printFooter(): + print ' ' + print '' + +def printChangesetsForPath(repo, path): + rev = os.environ['SCM_REVISION'] + if len(rev) <= 0: + rev = "tip" + + fctxs = repo[rev].filectx(path) + maxRev = fctxs.rev() + + revs = [] + for i in fctxs.filelog(): + fctx = fctxs.filectx(i) + if fctx.rev() <= maxRev: + revs.append(fctx.changectx()) + + # reverse changesets + revs.reverse() + + total = len(revs) + + # handle paging + start = os.environ['SCM_PAGE_START'] + limit = os.environ['SCM_PAGE_LIMIT'] + + if len(start) > 0: + revs = revs[int(start):] + + if len(limit) > 0: + revs = revs[:int(limit)] + + # output + printHeader(total) + for ctx in revs: + printChangeset(repo, ctx) + printFooter() + +def printChangesetsForStartAndEnd(repo, startRev, endRev): + printHeader(len(repo)) + for i in range(endRev, startRev, -1): + printChangeset(repo, repo[i]) + printFooter() + +repositoryPath = os.environ['SCM_REPOSITORY_PATH'] +repo = hg.repository(ui.ui(), path = repositoryPath) + +path = os.environ['SCM_PATH'] +startNode = os.environ['SCM_REVISION_START'] +endNode = os.environ['SCM_REVISION_END'] + +if len(path) > 0: + printChangesetsForPath(repo, path) +else: + if len(startNode) > 0 and len(endNode) > 0: + # start and end revision + startRev = repo[startNode].rev() -1 + endRev = repo[endNode].rev() + else: + # paging + start = os.environ['SCM_PAGE_START'] + limit = os.environ['SCM_PAGE_LIMIT'] + + limit = int(limit) + + end = int(start) + endRev = len(repo) - end - 1 + + startRev = endRev - limit + + # fix negative start revisions + if startRev < -1: + startRev = -1 + + # print + printChangesetsForStartAndEnd(repo, startRev, endRev) + diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnChangesetViewer.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnChangesetViewer.java index f16e8c7a14..d5d540f171 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnChangesetViewer.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnChangesetViewer.java @@ -44,9 +44,12 @@ import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.io.SVNRepositoryFactory; +import sonia.scm.util.Util; + //~--- JDK imports ------------------------------------------------------------ import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -92,6 +95,11 @@ public class SvnChangesetViewer implements ChangesetViewer @Override public ChangesetPagingResult getChangesets(int start, int max) { + if (logger.isDebugEnabled()) + { + logger.debug("fetch changesets. start: {}, max: {}", start, max); + } + ChangesetPagingResult changesets = null; File directory = handler.getDirectory(repostory); SVNRepository repository = null; @@ -110,8 +118,8 @@ public class SvnChangesetViewer implements ChangesetViewer } List changesetList = new ArrayList(); - Collection entries = repository.log(new String[] { "" }, - null, startRev, endRev, true, true); + Collection entries = repository.log(null, null, startRev, + endRev, true, true); for (SVNLogEntry entry : entries) { @@ -133,6 +141,93 @@ public class SvnChangesetViewer implements ChangesetViewer return changesets; } + /** + * Method description + * + * + * @param path + * @param revision + * @param start + * @param max + * + * @return + */ + @Override + public ChangesetPagingResult getChangesets(String path, String revision, + int start, int max) + { + if (logger.isDebugEnabled()) + { + logger.debug( + "fetch changesets for path {} and revision {}. start: {}, max: {}", + new Object[] { path, + revision, start, max }); + } + + ChangesetPagingResult changesets = null; + File directory = handler.getDirectory(repostory); + SVNRepository repository = null; + + try + { + repository = SVNRepositoryFactory.create(SVNURL.fromFile(directory)); + + long startRev = repository.getLatestRevision(); + long endRev = 0; + long maxRev = startRev; + + if (Util.isNotEmpty(revision)) + { + try + { + maxRev = Long.parseLong(revision); + } + catch (NumberFormatException ex) + { + logger.error("could not parse revision ".concat(revision), ex); + } + } + + List changesetList = new ArrayList(); + Collection entries = repository.log(new String[] { path }, + null, startRev, endRev, true, true); + + for (SVNLogEntry entry : entries) + { + if (entry.getRevision() <= maxRev) + { + changesetList.add(SvnUtil.createChangeset(entry)); + } + } + + int total = changesetList.size(); + int end = total - start; + + if (end > max) + { + end = max; + } + + if (start < 0) + { + start = 0; + } + + changesetList = changesetList.subList(start, end); + changesets = new ChangesetPagingResult(total, changesetList); + } + catch (SVNException ex) + { + logger.error("could not open repository", ex); + } + finally + { + repository.closeSession(); + } + + return changesets; + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 84427e2955..f8289c3e57 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -57,6 +57,12 @@ 1.9-SNAPSHOT + + com.sun.jersey + jersey-server + ${jersey.version} + + com.sun.jersey jersey-json diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java index c3062ea369..7f6050becb 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java @@ -57,8 +57,6 @@ import java.util.ArrayList; import java.util.List; import javax.servlet.ServletContextEvent; -import sonia.scm.security.CipherHandler; -import sonia.scm.security.CipherUtil; /** * diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractManagerResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractManagerResource.java index 7c82bddc87..19854b5192 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractManagerResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractManagerResource.java @@ -45,6 +45,7 @@ import sonia.scm.Manager; import sonia.scm.ModelObject; import sonia.scm.security.ScmSecurityException; import sonia.scm.util.AssertUtil; +import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ @@ -142,9 +143,13 @@ public abstract class AbstractManagerResource404 not found, if the repository or the path could not be found *
  • 500 internal server error
  • * - * + * * @param id the id of the repository + * @param path path of a file + * @param revision the revision of the file specified by the path parameter * @param start the start value for paging * @param limit the limit value for paging - * + * * @return * * @throws IOException @@ -434,7 +437,10 @@ public class RepositoryResource @Path("{id}/changesets") @TypeHint(ChangesetPagingResult.class) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) - public Response getChangesets(@PathParam("id") String id, @DefaultValue("0") + public Response getChangesets(@PathParam("id") String id, + @QueryParam("path") String path, + @QueryParam("revision") String revision, + @DefaultValue("0") @QueryParam("start") int start, @DefaultValue("20") @QueryParam("limit") int limit) throws RepositoryException, IOException { @@ -442,8 +448,17 @@ public class RepositoryResource try { - ChangesetPagingResult changesets = changesetViewerUtil.getChangesets(id, - start, limit); + ChangesetPagingResult changesets = null; + + if (Util.isEmpty(path)) + { + changesets = changesetViewerUtil.getChangesets(id, start, limit); + } + else + { + changesets = changesetViewerUtil.getChangesets(id, path, revision, + start, limit); + } if (changesets != null) { diff --git a/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java b/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java index dc2bd185cb..802db9d45c 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java @@ -40,6 +40,12 @@ import net.sf.ehcache.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sonia.scm.Filter; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Iterator; + /** * * @author Sebastian Sdorra @@ -126,6 +132,36 @@ public class EhCache implements Cache return cache.remove(key); } + /** + * Method description + * + * + * @param filter + * + * @return + */ + @Override + public boolean removeAll(Filter filter) + { + boolean result = true; + Iterator it = cache.getKeys().iterator(); + + while (it.hasNext()) + { + K key = it.next(); + + if (filter.accept(key)) + { + if (!cache.remove(key)) + { + result = false; + } + } + } + + return result; + } + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java index 58891c3a47..5f9ca864b1 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java +++ b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java @@ -123,43 +123,82 @@ public class BasicSecurityContext implements WebSecurityContext AuthenticationResult ar = authenticator.authenticate(request, response, username, password); - if (ar != null) + if ((ar != null) && (ar.getState() == AuthenticationState.SUCCESS)) { user = ar.getUser(); try { + Set groupSet = new HashSet(); + + // load external groups + Collection extGroups = ar.getGroups(); + + if (extGroups != null) + { + groupSet.addAll(extGroups); + } + + // load internal groups + loadGroups(groupSet); + + // check for admin user + if (!user.isAdmin()) + { + user.setAdmin(isAdmin(groupSet)); + + if (logger.isDebugEnabled() && user.isAdmin()) + { + logger.debug("user '{}' is marked as admin by configuration", + user.getType(), user.getName()); + } + } + else if (logger.isDebugEnabled()) + { + logger.debug("authenticator {} marked user '{}' as admin", + user.getType(), user.getName()); + } + + // store user User dbUser = userManager.get(user.getName()); - if ((dbUser != null) && user.copyProperties(dbUser, false)) + if (dbUser != null) { - userManager.modify(dbUser); + + // if database user is an admin, set admin for the current user + if (dbUser.isAdmin()) + { + if (logger.isDebugEnabled()) + { + logger.debug("user '{}' is marked as admin by local database", + user.getType(), user.getName()); + } + + user.setAdmin(true); + } + + // modify existing user, copy properties except password and admin + if (user.copyProperties(dbUser, false)) + { + userManager.modify(dbUser); + } } + + // create new user else if (dbUser == null) { userManager.create(user); } - Collection groupCollection = ar.getGroups(); - - if (groupCollection != null) - { - groups.addAll(groupCollection); - } - - loadGroups(); - - if (!user.isAdmin()) - { - user.setAdmin(isAdmin()); - } + groups = groupSet; if (logger.isDebugEnabled()) { logGroups(); } - String credentials = dbUser.getName(); + // store encrypted credentials in session + String credentials = user.getName(); if (Util.isNotEmpty(password)) { @@ -172,6 +211,12 @@ public class BasicSecurityContext implements WebSecurityContext catch (Exception ex) { user = null; + + if (groups != null) + { + groups.clear(); + } + logger.error("authentication failed", ex); } } @@ -253,8 +298,10 @@ public class BasicSecurityContext implements WebSecurityContext /** * Method description * + * + * @param groupSet */ - private void loadGroups() + private void loadGroups(Set groupSet) { Collection groupCollection = groupManager.getGroupsForMember(user.getName()); @@ -263,7 +310,7 @@ public class BasicSecurityContext implements WebSecurityContext { for (Group group : groupCollection) { - groups.add(group.getName()); + groupSet.add(group.getName()); } } } @@ -308,9 +355,11 @@ public class BasicSecurityContext implements WebSecurityContext * Method description * * + * + * @param groups * @return */ - private boolean isAdmin() + private boolean isAdmin(Collection groups) { boolean result = false; Set adminUsers = configuration.getAdminUsers(); diff --git a/scm-webapp/src/main/resources/config/ehcache.xml b/scm-webapp/src/main/resources/config/ehcache.xml index 6243ed4551..c665c6061a 100644 --- a/scm-webapp/src/main/resources/config/ehcache.xml +++ b/scm-webapp/src/main/resources/config/ehcache.xml @@ -152,4 +152,13 @@ diskPersistent="false" /> + + diff --git a/scm-webapp/src/main/resources/logback.release.xml b/scm-webapp/src/main/resources/logback.release.xml index 434856cc98..05e383d6f7 100644 --- a/scm-webapp/src/main/resources/logback.release.xml +++ b/scm-webapp/src/main/resources/logback.release.xml @@ -50,7 +50,7 @@ ${LOGDIR}/scm-manager.log - scm-manager-%i.log + ${LOGDIR}/scm-manager-%i.log 1 10 diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/css/xtheme-scm.css b/scm-webapp/src/main/webapp/resources/extjs/resources/css/xtheme-scm.css new file mode 100644 index 0000000000..84f833ff53 --- /dev/null +++ b/scm-webapp/src/main/webapp/resources/extjs/resources/css/xtheme-scm.css @@ -0,0 +1,1401 @@ +/*! + * Ext JS Library 3.4.0 + * Copyright(c) 2006-2011 Sencha Inc. + * licensing@sencha.com + * http://www.sencha.com/license + */ +/** colors **/ +/** header font **/ +/** font **/ +/** window **/ +.ext-el-mask { + background-color: #ccc; +} +.ext-el-mask-msg { + border-color: #999; + background-color: #ddd; + background-image: url(../images/gray/panel/white-top-bottom.gif); + background-position: 0 -1px; +} +.ext-el-mask-msg div { + background-color: #eee; + border-color: #d0d0d0; + color: #222; + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-mask-loading div { + background-color: #fbfbfb; + background-image: url(../images/default/grid/loading.gif); +} +.x-item-disabled { + color: gray; +} +.x-item-disabled * { + color: gray !important; +} +.x-splitbar-proxy { + background-color: #aaa; +} +.x-color-palette a { + border-color: #fff; +} +.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel { + border-color: #CFCFCF; + background-color: #eaeaea; +} +/* +.x-color-palette em:hover, .x-color-palette span:hover{ + background-color: #eaeaea; +} +*/ +.x-color-palette em { + border-color: #aca899; +} +.x-ie-shadow { + background-color: #777; +} +.x-shadow .xsmc { + background-image: url(../images/default/shadow-c.png); +} +.x-shadow .xsml, .x-shadow .xsmr { + background-image: url(../images/default/shadow-lr.png); +} +.x-shadow .xstl, +.x-shadow .xstc, +.x-shadow .xstr, +.x-shadow .xsbl, +.x-shadow .xsbc, +.x-shadow .xsbr { + background-image: url(../images/default/shadow.png); +} +.loading-indicator { + font-size: 11px; + background-image: url(../images/default/grid/loading.gif); +} +.x-spotlight { + background-color: #ccc; +} +.x-tab-panel-header, .x-tab-panel-footer { + background-color: #eaeaea; + border-color: #d0d0d0; + overflow: hidden; + zoom: 1; +} +.x-tab-panel-header, .x-tab-panel-footer { + border-color: #d0d0d0; +} +ul.x-tab-strip-top { + background-color: #dbdbdb; + background-image: url(../images/gray/tabs/tab-strip-bg.gif); + border-bottom-color: #d0d0d0; +} +ul.x-tab-strip-bottom { + background-color: #dbdbdb; + background-image: url(../images/gray/tabs/tab-strip-btm-bg.gif); + border-top-color: #d0d0d0; +} +.x-tab-panel-header-plain .x-tab-strip-spacer, .x-tab-panel-footer-plain .x-tab-strip-spacer { + border-color: #d0d0d0; + background-color: #eaeaea; +} +.x-tab-strip span.x-tab-strip-text { + font: normal 11px arial, tahoma, helvetica, sans-serif; + color: #333; +} +.x-tab-strip-over span.x-tab-strip-text { + color: #111; +} +.x-tab-strip-active span.x-tab-strip-text { + color: #333; + font-weight: bold; +} +.x-tab-strip-disabled .x-tabs-text { + color: #aaaaaa; +} +.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner { + background-image: url(../images/gray/tabs/tabs-sprite.gif); +} +.x-tab-strip-bottom .x-tab-right { + background-image: url(../images/gray/tabs/tab-btm-inactive-right-bg.gif); +} +.x-tab-strip-bottom .x-tab-left { + background-image: url(../images/gray/tabs/tab-btm-inactive-left-bg.gif); +} +.x-tab-strip-bottom .x-tab-strip-over .x-tab-left { + background-image: url(../images/gray/tabs/tab-btm-over-left-bg.gif); +} +.x-tab-strip-bottom .x-tab-strip-over .x-tab-right { + background-image: url(../images/gray/tabs/tab-btm-over-right-bg.gif); +} +.x-tab-strip-bottom .x-tab-strip-active .x-tab-right { + background-image: url(../images/gray/tabs/tab-btm-right-bg.gif); +} +.x-tab-strip-bottom .x-tab-strip-active .x-tab-left { + background-image: url(../images/gray/tabs/tab-btm-left-bg.gif); +} +.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close { + background-image: url(../images/gray/tabs/tab-close.gif); +} +.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover { + background-image: url(../images/gray/tabs/tab-close.gif); +} +.x-tab-panel-body { + border-color: #d0d0d0; + background-color: #fff; +} +.x-tab-panel-body-top { + border-top: 0 none; +} +.x-tab-panel-body-bottom { + border-bottom: 0 none; +} +.x-tab-scroller-left { + background-image: url(../images/gray/tabs/scroll-left.gif); + border-bottom-color: #d0d0d0; +} +.x-tab-scroller-left-over { + background-position: 0 0; +} +.x-tab-scroller-left-disabled { + background-position: -18px 0; + opacity: .5; + -moz-opacity: .5; + filter: alpha(opacity=50); + cursor: default; +} +.x-tab-scroller-right { + background-image: url(../images/gray/tabs/scroll-right.gif); + border-bottom-color: #d0d0d0; +} +.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar { + border-color: #d0d0d0; +} +.x-form-field { + font: normal 12px arial, tahoma, helvetica, sans-serif; +} +.x-form-text, textarea.x-form-field { + background-color: #fff; + background-image: url(../images/default/form/text-bg.gif); + border-color: #C1C1C1; +} +.x-form-select-one { + background-color: #fff; + border-color: #C1C1C1; +} +.x-form-check-group-label { + border-bottom: 1px solid #d0d0d0; + color: #333; +} +.x-editor .x-form-check-wrap { + background-color: #fff; +} +.x-form-field-wrap .x-form-trigger { + background-image: url(../images/gray/form/trigger.gif); + border-bottom-color: #b5b8c8; +} +.x-form-field-wrap .x-form-date-trigger { + background-image: url(../images/gray/form/date-trigger.gif); +} +.x-form-field-wrap .x-form-clear-trigger { + background-image: url(../images/gray/form/clear-trigger.gif); +} +.x-form-field-wrap .x-form-search-trigger { + background-image: url(../images/gray/form/search-trigger.gif); +} +.x-trigger-wrap-focus .x-form-trigger { + border-bottom-color: #777777; +} +.x-item-disabled .x-form-trigger-over { + border-bottom-color: #b5b8c8; +} +.x-item-disabled .x-form-trigger-click { + border-bottom-color: #b5b8c8; +} +.x-form-focus, textarea.x-form-focus { + border-color: #777777; +} +.x-form-invalid, textarea.x-form-invalid { + background-color: #fff; + background-image: url(../images/default/grid/invalid_line.gif); + border-color: #c30; +} +.ext-webkit .x-form-invalid { + background-color: #fee; + border-color: #ff7870; +} +.x-form-inner-invalid, textarea.x-form-inner-invalid { + background-color: #fff; + background-image: url(../images/default/grid/invalid_line.gif); +} +.x-form-grow-sizer { + font: normal 12px arial, tahoma, helvetica, sans-serif; +} +.x-form-item { + font: normal 12px arial, tahoma, helvetica, sans-serif; +} +.x-form-invalid-msg { + color: #c0272b; + font: normal 11px arial, tahoma, helvetica, sans-serif; + background-image: url(../images/default/shared/warning.gif); +} +.x-form-empty-field { + color: gray; +} +.x-small-editor .x-form-field { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.ext-webkit .x-small-editor .x-form-field { + font-size: 12px; + font-weight: normal; + font-family: arial, tahoma, helvetica, sans-serif; +} +.x-form-invalid-icon { + background-image: url(../images/default/form/exclamation.gif); +} +.x-fieldset { + border-color: #CCCCCC; +} +.x-fieldset legend { + font: bold 11px arial, tahoma, helvetica, sans-serif; + color: #777777; +} +.x-btn { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-btn button { + font: normal 11px arial, tahoma, helvetica, sans-serif; + color: #333; +} +.x-btn em { + font-style: normal; + font-weight: normal; +} +.x-btn-tl, +.x-btn-tr, +.x-btn-tc, +.x-btn-ml, +.x-btn-mr, +.x-btn-mc, +.x-btn-bl, +.x-btn-br, +.x-btn-bc { + background-image: url(../images/gray/button/btn.gif); +} +.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text { + color: #000; +} +.x-btn-disabled * { + color: gray !important; +} +.x-btn-mc em.x-btn-arrow { + background-image: url(../images/default/button/arrow.gif); +} +.x-btn-mc em.x-btn-split { + background-image: url(../images/default/button/s-arrow.gif); +} +.x-btn-over .x-btn-mc em.x-btn-split, +.x-btn-click .x-btn-mc em.x-btn-split, +.x-btn-menu-active .x-btn-mc em.x-btn-split, +.x-btn-pressed .x-btn-mc em.x-btn-split { + background-image: url(../images/gray/button/s-arrow-o.gif); +} +.x-btn-mc em.x-btn-arrow-bottom { + background-image: url(../images/default/button/s-arrow-b-noline.gif); +} +.x-btn-mc em.x-btn-split-bottom { + background-image: url(../images/default/button/s-arrow-b.gif); +} +.x-btn-over .x-btn-mc em.x-btn-split-bottom, +.x-btn-click .x-btn-mc em.x-btn-split-bottom, +.x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, +.x-btn-pressed .x-btn-mc em.x-btn-split-bottom { + background-image: url(../images/gray/button/s-arrow-bo.gif); +} +.x-btn-group-header { + color: #666; +} +.x-btn-group-tc { + background-image: url(../images/gray/button/group-tb.gif); +} +.x-btn-group-tl { + background-image: url(../images/gray/button/group-cs.gif); +} +.x-btn-group-tr { + background-image: url(../images/gray/button/group-cs.gif); +} +.x-btn-group-bc { + background-image: url(../images/gray/button/group-tb.gif); +} +.x-btn-group-bl { + background-image: url(../images/gray/button/group-cs.gif); +} +.x-btn-group-br { + background-image: url(../images/gray/button/group-cs.gif); +} +.x-btn-group-ml { + background-image: url(../images/gray/button/group-lr.gif); +} +.x-btn-group-mr { + background-image: url(../images/gray/button/group-lr.gif); +} +.x-btn-group-notitle .x-btn-group-tc { + background-image: url(../images/gray/button/group-tb.gif); +} +.x-toolbar { + border-color: #d0d0d0; + background-color: #f0f0f0; + background-image: url(../images/gray/toolbar/bg.gif); +} +.x-toolbar td, +.x-toolbar span, +.x-toolbar input, +.x-toolbar div, +.x-toolbar select, +.x-toolbar label { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-toolbar .x-item-disabled { + color: gray; +} +.x-toolbar .x-item-disabled * { + color: gray; +} +.x-toolbar .x-btn-mc em.x-btn-split { + background-image: url(../images/default/button/s-arrow-noline.gif); +} +.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, +.x-toolbar .x-btn-click .x-btn-mc em.x-btn-split, +.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, +.x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split { + background-image: url(../images/gray/button/s-arrow-o.gif); +} +.x-toolbar .x-btn-mc em.x-btn-split-bottom { + background-image: url(../images/default/button/s-arrow-b-noline.gif); +} +.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, +.x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom, +.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, +.x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom { + background-image: url(../images/gray/button/s-arrow-bo.gif); +} +.x-toolbar .xtb-sep { + background-image: url(../images/default/grid/grid-split.gif); +} +.x-tbar-page-first { + background-image: url(../images/gray/grid/page-first.gif) !important; +} +.x-tbar-loading { + background-image: url(../images/gray/grid/refresh.gif) !important; +} +.x-tbar-page-last { + background-image: url(../images/gray/grid/page-last.gif) !important; +} +.x-tbar-page-next { + background-image: url(../images/gray/grid/page-next.gif) !important; +} +.x-tbar-page-prev { + background-image: url(../images/gray/grid/page-prev.gif) !important; +} +.x-item-disabled .x-tbar-loading { + background-image: url(../images/default/grid/loading.gif) !important; +} +.x-item-disabled .x-tbar-page-first { + background-image: url(../images/default/grid/page-first-disabled.gif) !important; +} +.x-item-disabled .x-tbar-page-last { + background-image: url(../images/default/grid/page-last-disabled.gif) !important; +} +.x-item-disabled .x-tbar-page-next { + background-image: url(../images/default/grid/page-next-disabled.gif) !important; +} +.x-item-disabled .x-tbar-page-prev { + background-image: url(../images/default/grid/page-prev-disabled.gif) !important; +} +.x-paging-info { + color: #444; +} +.x-toolbar-more-icon { + background-image: url(../images/gray/toolbar/more.gif) !important; +} +.x-resizable-handle { + background-color: #fff; +} +.x-resizable-over .x-resizable-handle-east, +.x-resizable-pinned .x-resizable-handle-east, +.x-resizable-over .x-resizable-handle-west, +.x-resizable-pinned .x-resizable-handle-west { + background-image: url(../images/gray/sizer/e-handle.gif); +} +.x-resizable-over .x-resizable-handle-south, +.x-resizable-pinned .x-resizable-handle-south, +.x-resizable-over .x-resizable-handle-north, +.x-resizable-pinned .x-resizable-handle-north { + background-image: url(../images/gray/sizer/s-handle.gif); +} +.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north { + background-image: url(../images/gray/sizer/s-handle.gif); +} +.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast { + background-image: url(../images/gray/sizer/se-handle.gif); +} +.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest { + background-image: url(../images/gray/sizer/nw-handle.gif); +} +.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast { + background-image: url(../images/gray/sizer/ne-handle.gif); +} +.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest { + background-image: url(../images/gray/sizer/sw-handle.gif); +} +.x-resizable-proxy { + border-color: #565656; +} +.x-resizable-overlay { + background-color: #fff; +} +.x-grid3 { + background-color: #fff; +} +.x-grid-panel .x-panel-mc .x-panel-body { + border-color: #d0d0d0; +} +.x-grid3-row td, .x-grid3-summary-row td { + /** ?? font-size 11px/13px ?? **/ + + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-grid3-hd-row td { + /** ?? font-size 11px/15px ?? **/ + + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-grid3-hd-row td { + border-left-color: #eee; + border-right-color: #d0d0d0; +} +.x-grid-row-loading { + background-color: #fff; + background-image: url(../images/default/shared/loading-balls.gif); +} +.x-grid3-row { + border-color: #ededed; + border-top-color: #fff; +} +.x-grid3-row-alt { + background-color: #fafafa; +} +.x-grid3-row-over { + border-color: #ddd; + background-color: #efefef; + background-image: url(../images/default/grid/row-over.gif); +} +.x-grid3-resize-proxy { + background-color: #777; +} +.x-grid3-resize-marker { + background-color: #777; +} +.x-grid3-header { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hrow2.gif); +} +.x-grid3-header-pop { + border-left-color: #d0d0d0; +} +.x-grid3-header-pop-inner { + border-left-color: #eee; + background-image: url(../images/default/grid/hd-pop.gif); +} +td.x-grid3-hd-over, +td.sort-desc, +td.sort-asc, +td.x-grid3-hd-menu-open { + border-left-color: #ACACAC; + border-right-color: #ACACAC; +} +td.x-grid3-hd-over .x-grid3-hd-inner, +td.sort-desc .x-grid3-hd-inner, +td.sort-asc .x-grid3-hd-inner, +td.x-grid3-hd-menu-open .x-grid3-hd-inner { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hrow-over2.gif); +} +.sort-asc .x-grid3-sort-icon { + background-image: url(../images/gray/grid/sort_asc.gif); +} +.sort-desc .x-grid3-sort-icon { + background-image: url(../images/gray/grid/sort_desc.gif); +} +.x-grid3-cell-text, .x-grid3-hd-text { + color: #000; +} +.x-grid3-split { + background-image: url(../images/default/grid/grid-split.gif); +} +.x-grid3-hd-text { + color: #333; +} +.x-dd-drag-proxy .x-grid3-hd-inner { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hrow-over2.gif); + border-color: #ACACAC; +} +.col-move-top { + background-image: url(../images/gray/grid/col-move-top.gif); +} +.col-move-bottom { + background-image: url(../images/gray/grid/col-move-bottom.gif); +} +.x-grid3-row-selected { + background-color: #CCCCCC !important; + background-image: none; + border-color: #ACACAC; +} +.x-grid3-cell-selected { + background-color: #CBCBCB !important; + color: #000; +} +.x-grid3-cell-selected span { + color: #000 !important; +} +.x-grid3-cell-selected .x-grid3-cell-text { + color: #000; +} +.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker { + background-color: #ebeadb !important; + background-image: url(../images/default/grid/grid-hrow.gif) !important; + color: #000; + border-top-color: #fff; + border-right-color: #6fa0df !important; +} +.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div { + color: #333 !important; +} +.x-grid3-dirty-cell { + background-image: url(../images/default/grid/dirty.gif); +} +.x-grid3-topbar, .x-grid3-bottombar { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-grid3-bottombar .x-toolbar { + border-top-color: #a9bfd3; +} +.x-props-grid .x-grid3-td-name .x-grid3-cell-inner { + background-image: url(../images/default/grid/grid3-special-col-bg.gif) !important; + color: #000 !important; +} +.x-props-grid .x-grid3-body .x-grid3-td-name { + background-color: #fff !important; + border-right-color: #eee; +} +.xg-hmenu-sort-asc .x-menu-item-icon { + background-image: url(../images/default/grid/hmenu-asc.gif); +} +.xg-hmenu-sort-desc .x-menu-item-icon { + background-image: url(../images/default/grid/hmenu-desc.gif); +} +.xg-hmenu-lock .x-menu-item-icon { + background-image: url(../images/default/grid/hmenu-lock.gif); +} +.xg-hmenu-unlock .x-menu-item-icon { + background-image: url(../images/default/grid/hmenu-unlock.gif); +} +.x-grid3-hd-btn { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hd-btn.gif); +} +.x-grid3-body .x-grid3-td-expander { + background-image: url(../images/default/grid/grid3-special-col-bg.gif); +} +.x-grid3-row-expander { + background-image: url(../images/gray/grid/row-expand-sprite.gif); +} +.x-grid3-body .x-grid3-td-checker { + background-image: url(../images/default/grid/grid3-special-col-bg.gif); +} +.x-grid3-row-checker, .x-grid3-hd-checker { + background-image: url(../images/default/grid/row-check-sprite.gif); +} +.x-grid3-body .x-grid3-td-numberer { + background-image: url(../images/default/grid/grid3-special-col-bg.gif); +} +.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner { + color: #444; +} +.x-grid3-body .x-grid3-td-row-icon { + background-image: url(../images/default/grid/grid3-special-col-bg.gif); +} +.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer, .x-grid3-body .x-grid3-row-selected .x-grid3-td-checker, .x-grid3-body .x-grid3-row-selected .x-grid3-td-expander { + background-image: url(../images/gray/grid/grid3-special-col-sel-bg.gif); +} +.x-grid3-check-col { + background-image: url(../images/default/menu/unchecked.gif); +} +.x-grid3-check-col-on { + background-image: url(../images/default/menu/checked.gif); +} +.x-grid-group, .x-grid-group-body, .x-grid-group-hd { + zoom: 1; +} +.x-grid-group-hd { + border-bottom-color: #d0d0d0; +} +.x-grid-group-hd div.x-grid-group-title { + background-image: url(../images/gray/grid/group-collapse.gif); + color: #5F5F5F; + font: bold 11px arial, tahoma, helvetica, sans-serif; +} +.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title { + background-image: url(../images/gray/grid/group-expand.gif); +} +.x-group-by-icon { + background-image: url(../images/default/grid/group-by.gif); +} +.x-cols-icon { + background-image: url(../images/default/grid/columns.gif); +} +.x-show-groups-icon { + background-image: url(../images/default/grid/group-by.gif); +} +.x-grid-empty { + color: gray; + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell { + border-right-color: #ededed; +} +.x-grid-with-col-lines .x-grid3-row { + border-top-color: #ededed; +} +.x-grid-with-col-lines .x-grid3-row-selected { + border-top-color: #B9B9B9; +} +.x-pivotgrid .x-grid3-header-offset table td { + background: url(../images/gray/grid/grid3-hrow2.gif) repeat-x 50% 100%; + border-left: 1px solid; + border-right: 1px solid; + border-left-color: #d0d0d0; + border-right-color: #d0d0d0; +} +.x-pivotgrid .x-grid3-row-headers { + background-color: #f9f9f9; +} +.x-pivotgrid .x-grid3-row-headers table td { + background: #eeeeee url(../images/default/grid/grid3-rowheader.gif) repeat-x left top; + border-left: 1px solid; + border-right: 1px solid; + border-left-color: #EEE; + border-right-color: #d0d0d0; + border-bottom: 1px solid; + border-bottom-color: #d0d0d0; + height: 18px; +} +.x-dd-drag-ghost { + color: #000; + font: normal 11px arial, tahoma, helvetica, sans-serif; + border-color: #ddd #bbb #bbb #ddd; + background-color: #fff; +} +.x-dd-drop-nodrop .x-dd-drop-icon { + background-image: url(../images/default/dd/drop-no.gif); +} +.x-dd-drop-ok .x-dd-drop-icon { + background-image: url(../images/default/dd/drop-yes.gif); +} +.x-dd-drop-ok-add .x-dd-drop-icon { + background-image: url(../images/default/dd/drop-add.gif); +} +.x-view-selector { + background-color: #D6D6D6; + border-color: #888888; +} +.x-tree-node-expanded .x-tree-node-icon { + background-image: url(../images/default/tree/folder-open.gif); +} +.x-tree-node-leaf .x-tree-node-icon { + background-image: url(../images/default/tree/leaf.gif); +} +.x-tree-node-collapsed .x-tree-node-icon { + background-image: url(../images/default/tree/folder.gif); +} +.x-tree-node-loading .x-tree-node-icon { + background-image: url(../images/default/tree/loading.gif) !important; +} +.x-tree-node .x-tree-node-inline-icon { + background-image: none; +} +.x-tree-node-loading a span { + font-style: italic; + color: #444444; +} +.ext-ie .x-tree-node-el input { + width: 15px; + height: 15px; +} +.x-tree-lines .x-tree-elbow { + background-image: url(../images/default/tree/elbow.gif); +} +.x-tree-lines .x-tree-elbow-plus { + background-image: url(../images/default/tree/elbow-plus.gif); +} +.x-tree-lines .x-tree-elbow-minus { + background-image: url(../images/default/tree/elbow-minus.gif); +} +.x-tree-lines .x-tree-elbow-end { + background-image: url(../images/default/tree/elbow-end.gif); +} +.x-tree-lines .x-tree-elbow-end-plus { + background-image: url(../images/gray/tree/elbow-end-plus.gif); +} +.x-tree-lines .x-tree-elbow-end-minus { + background-image: url(../images/gray/tree/elbow-end-minus.gif); +} +.x-tree-lines .x-tree-elbow-line { + background-image: url(../images/default/tree/elbow-line.gif); +} +.x-tree-no-lines .x-tree-elbow-plus { + background-image: url(../images/default/tree/elbow-plus-nl.gif); +} +.x-tree-no-lines .x-tree-elbow-minus { + background-image: url(../images/default/tree/elbow-minus-nl.gif); +} +.x-tree-no-lines .x-tree-elbow-end-plus { + background-image: url(../images/gray/tree/elbow-end-plus-nl.gif); +} +.x-tree-no-lines .x-tree-elbow-end-minus { + background-image: url(../images/gray/tree/elbow-end-minus-nl.gif); +} +.x-tree-arrows .x-tree-elbow-plus { + background-image: url(../images/gray/tree/arrows.gif); +} +.x-tree-arrows .x-tree-elbow-minus { + background-image: url(../images/gray/tree/arrows.gif); +} +.x-tree-arrows .x-tree-elbow-end-plus { + background-image: url(../images/gray/tree/arrows.gif); +} +.x-tree-arrows .x-tree-elbow-end-minus { + background-image: url(../images/gray/tree/arrows.gif); +} +.x-tree-node { + color: #000; + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-tree-node a, .x-dd-drag-ghost a { + color: #000; +} +.x-tree-node a span, .x-dd-drag-ghost a span { + color: #000; +} +.x-tree-node .x-tree-node-disabled a span { + color: gray !important; +} +.x-tree-node div.x-tree-drag-insert-below { + border-bottom-color: #36c; +} +.x-tree-node div.x-tree-drag-insert-above { + border-top-color: #36c; +} +.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a { + border-bottom-color: #36c; +} +.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a { + border-top-color: #36c; +} +.x-tree-node .x-tree-drag-append a span { + background-color: #ddd; + border-color: gray; +} +.x-tree-node .x-tree-node-over { + background-color: #eee; +} +.x-tree-node .x-tree-selected { + background-color: #ddd; +} +.x-tree-drop-ok-append .x-dd-drop-icon { + background-image: url(../images/default/tree/drop-add.gif); +} +.x-tree-drop-ok-above .x-dd-drop-icon { + background-image: url(../images/default/tree/drop-over.gif); +} +.x-tree-drop-ok-below .x-dd-drop-icon { + background-image: url(../images/default/tree/drop-under.gif); +} +.x-tree-drop-ok-between .x-dd-drop-icon { + background-image: url(../images/default/tree/drop-between.gif); +} +.x-date-picker { + border-color: #585858; + background-color: #fff; +} +.x-date-middle, .x-date-left, .x-date-right { + background-image: url(../images/gray/shared/hd-sprite.gif); + color: #fff; + font: bold 11 tahoma, arial, verdana, sans-serif; +} +.x-date-middle .x-btn .x-btn-text { + color: #fff; +} +.x-date-middle .x-btn-mc em.x-btn-arrow { + background-image: url(../images/gray/toolbar/btn-arrow-light.gif); +} +.x-date-right a { + background-image: url(../images/gray/shared/right-btn.gif); +} +.x-date-left a { + background-image: url(../images/gray/shared/left-btn.gif); +} +.x-date-inner th { + background-color: #D8D8D8; + background-image: url(../images/gray/panel/white-top-bottom.gif); + border-bottom-color: #AFAFAF; + font: normal 10px arial, tahoma, helvetica, sans-serif; + color: #595959; +} +.x-date-inner td { + border-color: #fff; +} +.x-date-inner a { + font: normal 11px arial, tahoma, helvetica, sans-serif; + color: #000; +} +.x-date-inner .x-date-active { + color: #000; +} +.x-date-inner .x-date-selected a { + background-image: none; + background-color: #D8D8D8; + border-color: #DCDCDC; +} +.x-date-inner .x-date-today a { + border-color: darkred; +} +.x-date-inner .x-date-selected span { + font-weight: bold; +} +.x-date-inner .x-date-prevday a, .x-date-inner .x-date-nextday a { + color: #aaa; +} +.x-date-bottom { + border-top-color: #AFAFAF; + background-color: #D8D8D8; + background: #d8d8d8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px; +} +.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover { + color: #000; + background-color: #D8D8D8; +} +.x-date-inner .x-date-disabled a { + background-color: #eee; + color: #bbb; +} +.x-date-mmenu { + background-color: #eee !important; +} +.x-date-mmenu .x-menu-item { + font-size: 10px; + color: #000; +} +.x-date-mp { + background-color: #fff; +} +.x-date-mp td { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-date-mp-btns button { + background-color: #4E565F; + color: #fff; + border-color: #C0C0C0 #434343 #434343 #C0C0C0; + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-date-mp-btns { + background-color: #D8D8D8; + background: #d8d8d8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px; +} +.x-date-mp-btns td { + border-top-color: #AFAFAF; +} +td.x-date-mp-month a, td.x-date-mp-year a { + color: #333; +} +td.x-date-mp-month a:hover, td.x-date-mp-year a:hover { + color: #333; + background-color: #FDFDFD; +} +td.x-date-mp-sel a { + background-color: #D8D8D8; + background: #d8d8d8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px; + border-color: #DCDCDC; +} +.x-date-mp-ybtn a { + background-image: url(../images/gray/panel/tool-sprites.gif); +} +td.x-date-mp-sep { + border-right-color: #d7d7d7; +} +.x-tip .x-tip-close { + background-image: url(../images/gray/qtip/close.gif); +} +.x-tip .x-tip-tc, +.x-tip .x-tip-tl, +.x-tip .x-tip-tr, +.x-tip .x-tip-bc, +.x-tip .x-tip-bl, +.x-tip .x-tip-br, +.x-tip .x-tip-ml, +.x-tip .x-tip-mr { + background-image: url(../images/gray/qtip/tip-sprite.gif); +} +.x-tip .x-tip-mc { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-tip .x-tip-ml { + background-color: #fff; +} +.x-tip .x-tip-header-text { + font: bold 11px arial, tahoma, helvetica, sans-serif; + color: #444; +} +.x-tip .x-tip-body { + font: normal 11px arial, tahoma, helvetica, sans-serif; + color: #444; +} +.x-form-invalid-tip .x-tip-tc, +.x-form-invalid-tip .x-tip-tl, +.x-form-invalid-tip .x-tip-tr, +.x-form-invalid-tip .x-tip-bc, +.x-form-invalid-tip .x-tip-bl, +.x-form-invalid-tip .x-tip-br, +.x-form-invalid-tip .x-tip-ml, +.x-form-invalid-tip .x-tip-mr { + background-image: url(../images/default/form/error-tip-corners.gif); +} +.x-form-invalid-tip .x-tip-body { + background-image: url(../images/default/form/exclamation.gif); +} +.x-tip-anchor { + background-image: url(../images/gray/qtip/tip-anchor-sprite.gif); +} +.x-menu { + background-color: #f0f0f0; + background-image: url(../images/default/menu/menu.gif); +} +.x-menu-floating { + border-color: #7D7D7D; +} +.x-menu-nosep { + background-image: none; +} +.x-menu-list-item { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-menu-item-arrow { + background-image: url(../images/gray/menu/menu-parent.gif); +} +.x-menu-sep { + background-color: #e0e0e0; + border-bottom-color: #fff; +} +a.x-menu-item { + color: #222; +} +.x-menu-item-active { + background-image: url(../images/gray/menu/item-over.gif); + background-color: #f1f1f1; + border-color: #ACACAC; +} +.x-menu-item-active a.x-menu-item { + border-color: #ACACAC; +} +.x-menu-check-item .x-menu-item-icon { + background-image: url(../images/default/menu/unchecked.gif); +} +.x-menu-item-checked .x-menu-item-icon { + background-image: url(../images/default/menu/checked.gif); +} +.x-menu-item-checked .x-menu-group-item .x-menu-item-icon { + background-image: url(../images/gray/menu/group-checked.gif); +} +.x-menu-group-item .x-menu-item-icon { + background-image: none; +} +.x-menu-plain { + background-color: #fff !important; +} +.x-menu .x-date-picker { + border-color: #AFAFAF; +} +.x-cycle-menu .x-menu-item-checked { + border-color: #B9B9B9 !important; + background-color: #f1f1f1; +} +.x-menu-scroller-top { + background-image: url(../images/default/layout/mini-top.gif); +} +.x-menu-scroller-bottom { + background-image: url(../images/default/layout/mini-bottom.gif); +} +.x-box-tl { + background-image: url(../images/default/box/corners.gif); +} +.x-box-tc { + background-image: url(../images/default/box/tb.gif); +} +.x-box-tr { + background-image: url(../images/default/box/corners.gif); +} +.x-box-ml { + background-image: url(../images/default/box/l.gif); +} +.x-box-mc { + background-color: #eee; + background-image: url(../images/default/box/tb.gif); + font-family: arial, tahoma, helvetica, sans-serif; + color: #393939; + font-size: 12px; +} +.x-box-mc h3 { + font-size: 14px; + font-weight: bold; +} +.x-box-mr { + background-image: url(../images/default/box/r.gif); +} +.x-box-bl { + background-image: url(../images/default/box/corners.gif); +} +.x-box-bc { + background-image: url(../images/default/box/tb.gif); +} +.x-box-br { + background-image: url(../images/default/box/corners.gif); +} +.x-box-blue .x-box-bl, +.x-box-blue .x-box-br, +.x-box-blue .x-box-tl, +.x-box-blue .x-box-tr { + background-image: url(../images/default/box/corners-blue.gif); +} +.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc { + background-image: url(../images/default/box/tb-blue.gif); +} +.x-box-blue .x-box-mc { + background-color: #c3daf9; +} +.x-box-blue .x-box-mc h3 { + color: #17385b; +} +.x-box-blue .x-box-ml { + background-image: url(../images/default/box/l-blue.gif); +} +.x-box-blue .x-box-mr { + background-image: url(../images/default/box/r-blue.gif); +} +.x-combo-list { + border-color: #ccc; + background-color: #ddd; + font: normal 12px arial, tahoma, helvetica, sans-serif; +} +.x-combo-list-inner { + background-color: #fff; +} +.x-combo-list-hd { + font: bold 11px arial, tahoma, helvetica, sans-serif; + color: #333; + background-image: url(../images/default/layout/panel-title-light-bg.gif); + border-bottom-color: #BCBCBC; +} +.x-resizable-pinned .x-combo-list-inner { + border-bottom-color: #BEBEBE; +} +.x-combo-list-item { + border-color: #fff; +} +.x-combo-list .x-combo-selected { + border-color: #777 !important; + background-color: #f0f0f0; +} +.x-combo-list .x-toolbar { + border-top-color: #BCBCBC; +} +.x-combo-list-small { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-panel { + border-color: #d0d0d0; +} +.x-panel-header { + color: #333; + font-weight: bold; + font-size: 11; + font-family: tahoma, arial, verdana, sans-serif; + border-color: #d0d0d0; + background-image: url(../images/gray/panel/white-top-bottom.gif); +} +.x-panel-body { + border-color: #d0d0d0; + background-color: #fff; +} +.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar { + border-color: #d0d0d0; +} +.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar { + border-top-color: #d0d0d0; +} +.x-panel-body-noheader, .x-panel-mc .x-panel-body { + border-top-color: #d0d0d0; +} +.x-panel-tl .x-panel-header { + color: #333; + font: bold 11 tahoma, arial, verdana, sans-serif; +} +.x-panel-tc { + background-image: url(../images/gray/panel/top-bottom.gif); +} +.x-panel-tl, +.x-panel-tr, +.x-panel-bl, +.x-panel-br { + background-image: url(../images/gray/panel/corners-sprite.gif); + border-bottom-color: #d0d0d0; +} +.x-panel-bc { + background-image: url(../images/gray/panel/top-bottom.gif); +} +.x-panel-mc { + font: normal 11px arial, tahoma, helvetica, sans-serif; + background-color: #f1f1f1; +} +.x-panel-ml { + background-color: #fff; + background-image: url(../images/gray/panel/left-right.gif); +} +.x-panel-mr { + background-image: url(../images/gray/panel/left-right.gif); +} +.x-tool { + background-image: url(../images/gray/panel/tool-sprites.gif); +} +.x-panel-ghost { + background-color: #f2f2f2; +} +.x-panel-ghost ul { + border-color: #d0d0d0; +} +.x-panel-dd-spacer { + border-color: #d0d0d0; +} +.x-panel-fbar td, +.x-panel-fbar span, +.x-panel-fbar input, +.x-panel-fbar div, +.x-panel-fbar select, +.x-panel-fbar label { + font: normal 11px arial, tahoma, helvetica, sans-serif; +} +.x-window-proxy { + background-color: #fcfcfc; + border-color: #d0d0d0; +} +.x-window-tl .x-window-header { + color: #555; + font: bold 11 tahoma, arial, verdana, sans-serif; +} +.x-window-tc { + background-image: url(../images/gray/window/top-bottom.png); +} +.x-window-tl { + background-image: url(../images/gray/window/left-corners.png); +} +.x-window-tr { + background-image: url(../images/gray/window/right-corners.png); +} +.x-window-bc { + background-image: url(../images/gray/window/top-bottom.png); +} +.x-window-bl { + background-image: url(../images/gray/window/left-corners.png); +} +.x-window-br { + background-image: url(../images/gray/window/right-corners.png); +} +.x-window-mc { + border-color: #d0d0d0; + font: normal 11px arial, tahoma, helvetica, sans-serif; + background-color: #e8e8e8; +} +.x-window-ml { + background-image: url(../images/gray/window/left-right.png); +} +.x-window-mr { + background-image: url(../images/gray/window/left-right.png); +} +.x-window-maximized .x-window-tc { + background-color: #fff; +} +.x-window-bbar .x-toolbar { + border-top-color: #d0d0d0; +} +.x-panel-ghost .x-window-tl { + border-bottom-color: #d0d0d0; +} +.x-panel-collapsed .x-window-tl { + border-bottom-color: #d0d0d0; +} +.x-dlg-mask { + background-color: #ccc; +} +.x-window-plain .x-window-mc { + background-color: #E8E8E8; + border-color: #D0D0D0 #EEEEEE #EEEEEE #D0D0D0; +} +.x-window-plain .x-window-body { + border-color: #EEEEEE #D0D0D0 #D0D0D0 #EEEEEE; +} +body.x-body-masked .x-window-plain .x-window-mc { + background-color: #E4E4E4; +} +.x-html-editor-wrap { + border-color: #BCBCBC; + background-color: #fff; +} +.x-html-editor-tb .x-btn-text { + background-image: url(../images/default/editor/tb-sprite.gif); +} +.x-panel-noborder .x-panel-header-noborder { + border-bottom-color: #d0d0d0; +} +.x-panel-noborder .x-panel-tbar-noborder .x-toolbar { + border-bottom-color: #d0d0d0; +} +.x-panel-noborder .x-panel-bbar-noborder .x-toolbar { + border-top-color: #d0d0d0; +} +.x-tab-panel-bbar-noborder .x-toolbar { + border-top-color: #d0d0d0; +} +.x-tab-panel-tbar-noborder .x-toolbar { + border-bottom-color: #d0d0d0; +} +.x-border-layout-ct { + background-color: #f0f0f0; +} +.x-border-layout-ct { + background-color: #f0f0f0; +} +.x-accordion-hd { + color: #222; + font-weight: normal; + background-image: url(../images/gray/panel/light-hd.gif); +} +.x-layout-collapsed { + background-color: #dfdfdf; + border-color: #d0d0d0; +} +.x-layout-collapsed-over { + background-color: #e7e7e7; +} +.x-layout-split-west .x-layout-mini { + background-image: url(../images/default/layout/mini-left.gif); +} +.x-layout-split-east .x-layout-mini { + background-image: url(../images/default/layout/mini-right.gif); +} +.x-layout-split-north .x-layout-mini { + background-image: url(../images/default/layout/mini-top.gif); +} +.x-layout-split-south .x-layout-mini { + background-image: url(../images/default/layout/mini-bottom.gif); +} +.x-layout-cmini-west .x-layout-mini { + background-image: url(../images/default/layout/mini-right.gif); +} +.x-layout-cmini-east .x-layout-mini { + background-image: url(../images/default/layout/mini-left.gif); +} +.x-layout-cmini-north .x-layout-mini { + background-image: url(../images/default/layout/mini-bottom.gif); +} +.x-layout-cmini-south .x-layout-mini { + background-image: url(../images/default/layout/mini-top.gif); +} +.x-progress-wrap { + border-color: #8E8E8E; +} +.x-progress-inner { + background-color: #E7E7E7; + background-image: url(../images/gray/qtip/bg.gif); +} +.x-progress-bar { + background-color: #BCBCBC; + background-image: url(../images/gray/progress/progress-bg.gif); + border-top-color: #E2E2E2; + border-bottom-color: #A4A4A4; + border-right-color: #A4A4A4; +} +.x-progress-text { + font-size: 11; + font-weight: bold; + color: #fff; +} +.x-progress-text-back { + color: #5F5F5F; +} +.x-list-header { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hrow2.gif); +} +.x-list-header-inner div em { + border-left-color: #ddd; + font: normal arial, tahoma, helvetica, sans-serif; +} +.x-list-body dt em { + font: normal arial, tahoma, helvetica, sans-serif; +} +.x-list-over { + background-color: #eee; +} +.x-list-selected { + background-color: #f0f0f0; +} +.x-list-resizer { + border-left-color: #555; + border-right-color: #555; +} +.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc { + background-image: url(../images/gray/grid/sort-hd.gif); + border-color: #d0d0d0; +} +.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner { + background-image: url(../images/default/slider/slider-bg.png); +} +.x-slider-horz .x-slider-thumb { + background-image: url(../images/gray/slider/slider-thumb.png); +} +.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner { + background-image: url(../images/default/slider/slider-v-bg.png); +} +.x-slider-vert .x-slider-thumb { + background-image: url(../images/gray/slider/slider-v-thumb.png); +} +.x-window-dlg .ext-mb-text, .x-window-dlg .x-window-header-text { + font-size: 12px; +} +.x-window-dlg .ext-mb-textarea { + font: normal 12px arial, tahoma, helvetica, sans-serif; +} +.x-window-dlg .x-msg-box-wait { + background-image: url(../images/default/grid/loading.gif); +} +.x-window-dlg .ext-mb-info { + background-image: url(../images/gray/window/icon-info.gif); +} +.x-window-dlg .ext-mb-warning { + background-image: url(../images/gray/window/icon-warning.gif); +} +.x-window-dlg .ext-mb-question { + background-image: url(../images/gray/window/icon-question.gif); +} +.x-window-dlg .ext-mb-error { + background-image: url(../images/gray/window/icon-error.gif); +} diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/css/xtheme-scm.less b/scm-webapp/src/main/webapp/resources/extjs/resources/css/xtheme-scm.less new file mode 100644 index 0000000000..d60188de11 --- /dev/null +++ b/scm-webapp/src/main/webapp/resources/extjs/resources/css/xtheme-scm.less @@ -0,0 +1,1417 @@ +/*! + * Ext JS Library 3.4.0 + * Copyright(c) 2006-2011 Sencha Inc. + * licensing@sencha.com + * http://www.sencha.com/license + */ + +/** colors **/ +@base-color: #F1F1F1; +@header-color: #D7D7D7; +@background-color: #FFFFFF; +@border-color: #d0d0d0; + +/** header font **/ +@header-font-color: #222222; +@header-font-weight: bold; +@header-font-family: tahoma, arial, verdana, sans-serif; +@header-font-size: 11; + +/** font **/ +@font-color: #000000; +@font-weight: normal; +@font-family: arial, tahoma, helvetica, sans-serif; +@font-size: 11px; + +/** window **/ +@window-transparency:'255'; + +.ext-el-mask { + background-color: #ccc; +} +.ext-el-mask-msg { + border-color: #999; + background-color: #ddd; + background-image: url(../images/gray/panel/white-top-bottom.gif); + background-position: 0 -1px; +} +.ext-el-mask-msg div { + background-color: #eee; + border-color: #d0d0d0; + color: #222; + font: @font-weight @font-size @font-family; +} +.x-mask-loading div { + background-color: #fbfbfb; + background-image: url(../images/default/grid/loading.gif); +} +.x-item-disabled { + color: gray; +} +.x-item-disabled * { + color: gray !important; +} +.x-splitbar-proxy { + background-color: #aaa; +} +.x-color-palette a { + border-color: #fff; +} +.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel { + border-color: #CFCFCF; + background-color: #eaeaea; +} +/* +.x-color-palette em:hover, .x-color-palette span:hover{ + background-color: #eaeaea; +} +*/ +.x-color-palette em { + border-color: #aca899; +} +.x-ie-shadow { + background-color: #777; +} +.x-shadow .xsmc { + background-image: url(../images/default/shadow-c.png); +} +.x-shadow .xsml, .x-shadow .xsmr { + background-image: url(../images/default/shadow-lr.png); +} +.x-shadow .xstl, +.x-shadow .xstc, +.x-shadow .xstr, +.x-shadow .xsbl, +.x-shadow .xsbc, +.x-shadow .xsbr { + background-image: url(../images/default/shadow.png); +} +.loading-indicator { + font-size: @font-size; + background-image: url(../images/default/grid/loading.gif); +} +.x-spotlight { + background-color: #ccc; +} +.x-tab-panel-header, .x-tab-panel-footer { + background-color: #eaeaea; + border-color: @border-color; + overflow: hidden; + zoom: 1; +} +.x-tab-panel-header, .x-tab-panel-footer { + border-color: @border-color; +} +ul.x-tab-strip-top { + background-color: #dbdbdb; + background-image: url(../images/gray/tabs/tab-strip-bg.gif); + border-bottom-color: #d0d0d0; +} +ul.x-tab-strip-bottom { + background-color: #dbdbdb; + background-image: url(../images/gray/tabs/tab-strip-btm-bg.gif); + border-top-color: #d0d0d0; +} +.x-tab-panel-header-plain .x-tab-strip-spacer, .x-tab-panel-footer-plain .x-tab-strip-spacer { + border-color: @border-color; + background-color: #eaeaea; +} +.x-tab-strip span.x-tab-strip-text { + font: @font-weight @font-size @font-family; + color: #333; +} +.x-tab-strip-over span.x-tab-strip-text { + color: #111; +} +.x-tab-strip-active span.x-tab-strip-text { + color: #333; + font-weight: bold; +} +.x-tab-strip-disabled .x-tabs-text { + color: #aaaaaa; +} +.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner { + background-image: url(../images/gray/tabs/tabs-sprite.gif); +} +.x-tab-strip-bottom .x-tab-right { + background-image: url(../images/gray/tabs/tab-btm-inactive-right-bg.gif); +} +.x-tab-strip-bottom .x-tab-left { + background-image: url(../images/gray/tabs/tab-btm-inactive-left-bg.gif); +} +.x-tab-strip-bottom .x-tab-strip-over .x-tab-left { + background-image: url(../images/gray/tabs/tab-btm-over-left-bg.gif); +} +.x-tab-strip-bottom .x-tab-strip-over .x-tab-right { + background-image: url(../images/gray/tabs/tab-btm-over-right-bg.gif); +} +.x-tab-strip-bottom .x-tab-strip-active .x-tab-right { + background-image: url(../images/gray/tabs/tab-btm-right-bg.gif); +} +.x-tab-strip-bottom .x-tab-strip-active .x-tab-left { + background-image: url(../images/gray/tabs/tab-btm-left-bg.gif); +} +.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close { + background-image: url(../images/gray/tabs/tab-close.gif); +} +.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover { + background-image: url(../images/gray/tabs/tab-close.gif); +} +.x-tab-panel-body { + border-color: @border-color; + background-color: #fff; +} +.x-tab-panel-body-top { + border-top: 0 none; +} +.x-tab-panel-body-bottom { + border-bottom: 0 none; +} +.x-tab-scroller-left { + background-image: url(../images/gray/tabs/scroll-left.gif); + border-bottom-color: #d0d0d0; +} +.x-tab-scroller-left-over { + background-position: 0 0; +} +.x-tab-scroller-left-disabled { + background-position: -18px 0; + opacity: .5; + -moz-opacity: .5; + filter: alpha(opacity=50); + cursor: default; +} +.x-tab-scroller-right { + background-image: url(../images/gray/tabs/scroll-right.gif); + border-bottom-color: #d0d0d0; +} +.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar { + border-color: @border-color; +} +.x-form-field { + font: normal 12px @font-family; +} +.x-form-text, textarea.x-form-field { + background-color: #fff; + background-image: url(../images/default/form/text-bg.gif); + border-color: #C1C1C1; +} +.x-form-select-one { + background-color: #fff; + border-color: #C1C1C1; +} +.x-form-check-group-label { + border-bottom: 1px solid @border-color; + color: #333; +} +.x-editor .x-form-check-wrap { + background-color: #fff; +} +.x-form-field-wrap .x-form-trigger { + background-image: url(../images/gray/form/trigger.gif); + border-bottom-color: #b5b8c8; +} +.x-form-field-wrap .x-form-date-trigger { + background-image: url(../images/gray/form/date-trigger.gif); +} +.x-form-field-wrap .x-form-clear-trigger { + background-image: url(../images/gray/form/clear-trigger.gif); +} +.x-form-field-wrap .x-form-search-trigger { + background-image: url(../images/gray/form/search-trigger.gif); +} +.x-trigger-wrap-focus .x-form-trigger { + border-bottom-color: #777777; +} +.x-item-disabled .x-form-trigger-over { + border-bottom-color: #b5b8c8; +} +.x-item-disabled .x-form-trigger-click { + border-bottom-color: #b5b8c8; +} +.x-form-focus, textarea.x-form-focus { + border-color: #777777; +} +.x-form-invalid, textarea.x-form-invalid { + background-color: #fff; + background-image: url(../images/default/grid/invalid_line.gif); + border-color: #c30; +} +.ext-webkit .x-form-invalid { + background-color: #fee; + border-color: #ff7870; +} +.x-form-inner-invalid, textarea.x-form-inner-invalid { + background-color: #fff; + background-image: url(../images/default/grid/invalid_line.gif); +} +.x-form-grow-sizer { + font: normal 12px @font-family; +} +.x-form-item { + font: normal 12px @font-family; +} +.x-form-invalid-msg { + color: #c0272b; + font: @font-weight @font-size @font-family; + background-image: url(../images/default/shared/warning.gif); +} +.x-form-empty-field { + color: gray; +} +.x-small-editor .x-form-field { + font: @font-weight @font-size @font-family; +} +.ext-webkit .x-small-editor .x-form-field { + font-size: @font-size + 1; + font-weight: @font-weight; + font-family: @font-family; +} +.x-form-invalid-icon { + background-image: url(../images/default/form/exclamation.gif); +} +.x-fieldset { + border-color: #CCCCCC; +} +.x-fieldset legend { + font: bold @font-size @font-family; + color: #777777; +} +.x-btn { + font: @font-weight @font-size @font-family; +} +.x-btn button { + font: @font-weight @font-size @font-family; + color: #333; +} +.x-btn em { + font-style: normal; + font-weight: normal; +} +.x-btn-tl, +.x-btn-tr, +.x-btn-tc, +.x-btn-ml, +.x-btn-mr, +.x-btn-mc, +.x-btn-bl, +.x-btn-br, +.x-btn-bc { + background-image: url(../images/gray/button/btn.gif); +} +.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text { + color: #000; +} +.x-btn-disabled * { + color: gray !important; +} +.x-btn-mc em.x-btn-arrow { + background-image: url(../images/default/button/arrow.gif); +} +.x-btn-mc em.x-btn-split { + background-image: url(../images/default/button/s-arrow.gif); +} +.x-btn-over .x-btn-mc em.x-btn-split, +.x-btn-click .x-btn-mc em.x-btn-split, +.x-btn-menu-active .x-btn-mc em.x-btn-split, +.x-btn-pressed .x-btn-mc em.x-btn-split { + background-image: url(../images/gray/button/s-arrow-o.gif); +} +.x-btn-mc em.x-btn-arrow-bottom { + background-image: url(../images/default/button/s-arrow-b-noline.gif); +} +.x-btn-mc em.x-btn-split-bottom { + background-image: url(../images/default/button/s-arrow-b.gif); +} +.x-btn-over .x-btn-mc em.x-btn-split-bottom, +.x-btn-click .x-btn-mc em.x-btn-split-bottom, +.x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, +.x-btn-pressed .x-btn-mc em.x-btn-split-bottom { + background-image: url(../images/gray/button/s-arrow-bo.gif); +} +.x-btn-group-header { + color: #666; +} +.x-btn-group-tc { + background-image: url(../images/gray/button/group-tb.gif); +} +.x-btn-group-tl { + background-image: url(../images/gray/button/group-cs.gif); +} +.x-btn-group-tr { + background-image: url(../images/gray/button/group-cs.gif); +} +.x-btn-group-bc { + background-image: url(../images/gray/button/group-tb.gif); +} +.x-btn-group-bl { + background-image: url(../images/gray/button/group-cs.gif); +} +.x-btn-group-br { + background-image: url(../images/gray/button/group-cs.gif); +} +.x-btn-group-ml { + background-image: url(../images/gray/button/group-lr.gif); +} +.x-btn-group-mr { + background-image: url(../images/gray/button/group-lr.gif); +} +.x-btn-group-notitle .x-btn-group-tc { + background-image: url(../images/gray/button/group-tb.gif); +} +.x-toolbar { + border-color: @border-color; + background-color: #f0f0f0; + background-image: url(../images/gray/toolbar/bg.gif); +} +.x-toolbar td, +.x-toolbar span, +.x-toolbar input, +.x-toolbar div, +.x-toolbar select, +.x-toolbar label { + font: @font-weight @font-size @font-family; +} +.x-toolbar .x-item-disabled { + color: gray; +} +.x-toolbar .x-item-disabled * { + color: gray; +} +.x-toolbar .x-btn-mc em.x-btn-split { + background-image: url(../images/default/button/s-arrow-noline.gif); +} +.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, +.x-toolbar .x-btn-click .x-btn-mc em.x-btn-split, +.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, +.x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split { + background-image: url(../images/gray/button/s-arrow-o.gif); +} +.x-toolbar .x-btn-mc em.x-btn-split-bottom { + background-image: url(../images/default/button/s-arrow-b-noline.gif); +} +.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, +.x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom, +.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, +.x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom { + background-image: url(../images/gray/button/s-arrow-bo.gif); +} +.x-toolbar .xtb-sep { + background-image: url(../images/default/grid/grid-split.gif); +} +.x-tbar-page-first { + background-image: url(../images/gray/grid/page-first.gif) !important; +} +.x-tbar-loading { + background-image: url(../images/gray/grid/refresh.gif) !important; +} +.x-tbar-page-last { + background-image: url(../images/gray/grid/page-last.gif) !important; +} +.x-tbar-page-next { + background-image: url(../images/gray/grid/page-next.gif) !important; +} +.x-tbar-page-prev { + background-image: url(../images/gray/grid/page-prev.gif) !important; +} +.x-item-disabled .x-tbar-loading { + background-image: url(../images/default/grid/loading.gif) !important; +} +.x-item-disabled .x-tbar-page-first { + background-image: url(../images/default/grid/page-first-disabled.gif) !important; +} +.x-item-disabled .x-tbar-page-last { + background-image: url(../images/default/grid/page-last-disabled.gif) !important; +} +.x-item-disabled .x-tbar-page-next { + background-image: url(../images/default/grid/page-next-disabled.gif) !important; +} +.x-item-disabled .x-tbar-page-prev { + background-image: url(../images/default/grid/page-prev-disabled.gif) !important; +} +.x-paging-info { + color: #444; +} +.x-toolbar-more-icon { + background-image: url(../images/gray/toolbar/more.gif) !important; +} +.x-resizable-handle { + background-color: #fff; +} +.x-resizable-over .x-resizable-handle-east, +.x-resizable-pinned .x-resizable-handle-east, +.x-resizable-over .x-resizable-handle-west, +.x-resizable-pinned .x-resizable-handle-west { + background-image: url(../images/gray/sizer/e-handle.gif); +} +.x-resizable-over .x-resizable-handle-south, +.x-resizable-pinned .x-resizable-handle-south, +.x-resizable-over .x-resizable-handle-north, +.x-resizable-pinned .x-resizable-handle-north { + background-image: url(../images/gray/sizer/s-handle.gif); +} +.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north { + background-image: url(../images/gray/sizer/s-handle.gif); +} +.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast { + background-image: url(../images/gray/sizer/se-handle.gif); +} +.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest { + background-image: url(../images/gray/sizer/nw-handle.gif); +} +.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast { + background-image: url(../images/gray/sizer/ne-handle.gif); +} +.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest { + background-image: url(../images/gray/sizer/sw-handle.gif); +} +.x-resizable-proxy { + border-color: #565656; +} +.x-resizable-overlay { + background-color: #fff; +} +.x-grid3 { + background-color: #fff; +} +.x-grid-panel .x-panel-mc .x-panel-body { + border-color: @border-color; +} +.x-grid3-row td, .x-grid3-summary-row td { + /** ?? font-size 11px/13px ?? **/ + font: @font-weight @font-size @font-family; +} +.x-grid3-hd-row td { + /** ?? font-size 11px/15px ?? **/ + font: @font-weight @font-size @font-family; +} +.x-grid3-hd-row td { + border-left-color: #eee; + border-right-color: @border-color; +} +.x-grid-row-loading { + background-color: #fff; + background-image: url(../images/default/shared/loading-balls.gif); +} +.x-grid3-row { + border-color: #ededed; + border-top-color: #fff; +} +.x-grid3-row-alt { + background-color: #fafafa; +} +.x-grid3-row-over { + border-color: #ddd; + background-color: #efefef; + background-image: url(../images/default/grid/row-over.gif); +} +.x-grid3-resize-proxy { + background-color: #777; +} +.x-grid3-resize-marker { + background-color: #777; +} +.x-grid3-header { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hrow2.gif); +} +.x-grid3-header-pop { + border-left-color: @border-color; +} +.x-grid3-header-pop-inner { + border-left-color: #eee; + background-image: url(../images/default/grid/hd-pop.gif); +} +td.x-grid3-hd-over, +td.sort-desc, +td.sort-asc, +td.x-grid3-hd-menu-open { + border-left-color: #ACACAC; + border-right-color: #ACACAC; +} +td.x-grid3-hd-over .x-grid3-hd-inner, +td.sort-desc .x-grid3-hd-inner, +td.sort-asc .x-grid3-hd-inner, +td.x-grid3-hd-menu-open .x-grid3-hd-inner { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hrow-over2.gif); +} +.sort-asc .x-grid3-sort-icon { + background-image: url(../images/gray/grid/sort_asc.gif); +} +.sort-desc .x-grid3-sort-icon { + background-image: url(../images/gray/grid/sort_desc.gif); +} +.x-grid3-cell-text, .x-grid3-hd-text { + color: #000; +} +.x-grid3-split { + background-image: url(../images/default/grid/grid-split.gif); +} +.x-grid3-hd-text { + color: #333; +} +.x-dd-drag-proxy .x-grid3-hd-inner { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hrow-over2.gif); + border-color: #ACACAC; +} +.col-move-top { + background-image: url(../images/gray/grid/col-move-top.gif); +} +.col-move-bottom { + background-image: url(../images/gray/grid/col-move-bottom.gif); +} +.x-grid3-row-selected { + background-color: #CCCCCC !important; + background-image: none; + border-color: #ACACAC; +} +.x-grid3-cell-selected { + background-color: #CBCBCB !important; + color: #000; +} +.x-grid3-cell-selected span { + color: #000 !important; +} +.x-grid3-cell-selected .x-grid3-cell-text { + color: #000; +} +.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker { + background-color: #ebeadb !important; + background-image: url(../images/default/grid/grid-hrow.gif) !important; + color: #000; + border-top-color: #fff; + border-right-color: #6fa0df !important; +} +.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div { + color: #333 !important; +} +.x-grid3-dirty-cell { + background-image: url(../images/default/grid/dirty.gif); +} +.x-grid3-topbar, .x-grid3-bottombar { + font: @font-weight @font-size @font-family; +} +.x-grid3-bottombar .x-toolbar { + border-top-color: #a9bfd3; +} +.x-props-grid .x-grid3-td-name .x-grid3-cell-inner { + background-image: url(../images/default/grid/grid3-special-col-bg.gif) !important; + color: #000 !important; +} +.x-props-grid .x-grid3-body .x-grid3-td-name { + background-color: #fff !important; + border-right-color: #eee; +} +.xg-hmenu-sort-asc .x-menu-item-icon { + background-image: url(../images/default/grid/hmenu-asc.gif); +} +.xg-hmenu-sort-desc .x-menu-item-icon { + background-image: url(../images/default/grid/hmenu-desc.gif); +} +.xg-hmenu-lock .x-menu-item-icon { + background-image: url(../images/default/grid/hmenu-lock.gif); +} +.xg-hmenu-unlock .x-menu-item-icon { + background-image: url(../images/default/grid/hmenu-unlock.gif); +} +.x-grid3-hd-btn { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hd-btn.gif); +} +.x-grid3-body .x-grid3-td-expander { + background-image: url(../images/default/grid/grid3-special-col-bg.gif); +} +.x-grid3-row-expander { + background-image: url(../images/gray/grid/row-expand-sprite.gif); +} +.x-grid3-body .x-grid3-td-checker { + background-image: url(../images/default/grid/grid3-special-col-bg.gif); +} +.x-grid3-row-checker, .x-grid3-hd-checker { + background-image: url(../images/default/grid/row-check-sprite.gif); +} +.x-grid3-body .x-grid3-td-numberer { + background-image: url(../images/default/grid/grid3-special-col-bg.gif); +} +.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner { + color: #444; +} +.x-grid3-body .x-grid3-td-row-icon { + background-image: url(../images/default/grid/grid3-special-col-bg.gif); +} +.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer, .x-grid3-body .x-grid3-row-selected .x-grid3-td-checker, .x-grid3-body .x-grid3-row-selected .x-grid3-td-expander { + background-image: url(../images/gray/grid/grid3-special-col-sel-bg.gif); +} +.x-grid3-check-col { + background-image: url(../images/default/menu/unchecked.gif); +} +.x-grid3-check-col-on { + background-image: url(../images/default/menu/checked.gif); +} +.x-grid-group, .x-grid-group-body, .x-grid-group-hd { + zoom: 1; +} +.x-grid-group-hd { + border-bottom-color: @border-color; +} +.x-grid-group-hd div.x-grid-group-title { + background-image: url(../images/gray/grid/group-collapse.gif); + color: #5F5F5F; + font: bold @font-size @font-family; +} +.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title { + background-image: url(../images/gray/grid/group-expand.gif); +} +.x-group-by-icon { + background-image: url(../images/default/grid/group-by.gif); +} +.x-cols-icon { + background-image: url(../images/default/grid/columns.gif); +} +.x-show-groups-icon { + background-image: url(../images/default/grid/group-by.gif); +} +.x-grid-empty { + color: gray; + font: @font-weight @font-size @font-family; +} +.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell { + border-right-color: #ededed; +} +.x-grid-with-col-lines .x-grid3-row { + border-top-color: #ededed; +} +.x-grid-with-col-lines .x-grid3-row-selected { + border-top-color: #B9B9B9; +} +.x-pivotgrid .x-grid3-header-offset table td { + background: url(../images/gray/grid/grid3-hrow2.gif) repeat-x 50% 100%; + border-left: 1px solid; + border-right: 1px solid; + border-left-color: @border-color; + border-right-color: @border-color; +} +.x-pivotgrid .x-grid3-row-headers { + background-color: #f9f9f9; +} +.x-pivotgrid .x-grid3-row-headers table td { + background: #eeeeee url(../images/default/grid/grid3-rowheader.gif) repeat-x left top; + border-left: 1px solid; + border-right: 1px solid; + border-left-color: #EEE; + border-right-color: @border-color; + border-bottom: 1px solid; + border-bottom-color: @border-color; + height: 18px; +} +.x-dd-drag-ghost { + color: #000; + font: @font-weight @font-size @font-family; + border-color: #ddd #bbb #bbb #ddd; + background-color: #fff; +} +.x-dd-drop-nodrop .x-dd-drop-icon { + background-image: url(../images/default/dd/drop-no.gif); +} +.x-dd-drop-ok .x-dd-drop-icon { + background-image: url(../images/default/dd/drop-yes.gif); +} +.x-dd-drop-ok-add .x-dd-drop-icon { + background-image: url(../images/default/dd/drop-add.gif); +} +.x-view-selector { + background-color: #D6D6D6; + border-color: #888888; +} +.x-tree-node-expanded .x-tree-node-icon { + background-image: url(../images/default/tree/folder-open.gif); +} +.x-tree-node-leaf .x-tree-node-icon { + background-image: url(../images/default/tree/leaf.gif); +} +.x-tree-node-collapsed .x-tree-node-icon { + background-image: url(../images/default/tree/folder.gif); +} +.x-tree-node-loading .x-tree-node-icon { + background-image: url(../images/default/tree/loading.gif) !important; +} +.x-tree-node .x-tree-node-inline-icon { + background-image: none; +} +.x-tree-node-loading a span { + font-style: italic; + color: #444444; +} +.ext-ie .x-tree-node-el input { + width: 15px; + height: 15px; +} +.x-tree-lines .x-tree-elbow { + background-image: url(../images/default/tree/elbow.gif); +} +.x-tree-lines .x-tree-elbow-plus { + background-image: url(../images/default/tree/elbow-plus.gif); +} +.x-tree-lines .x-tree-elbow-minus { + background-image: url(../images/default/tree/elbow-minus.gif); +} +.x-tree-lines .x-tree-elbow-end { + background-image: url(../images/default/tree/elbow-end.gif); +} +.x-tree-lines .x-tree-elbow-end-plus { + background-image: url(../images/gray/tree/elbow-end-plus.gif); +} +.x-tree-lines .x-tree-elbow-end-minus { + background-image: url(../images/gray/tree/elbow-end-minus.gif); +} +.x-tree-lines .x-tree-elbow-line { + background-image: url(../images/default/tree/elbow-line.gif); +} +.x-tree-no-lines .x-tree-elbow-plus { + background-image: url(../images/default/tree/elbow-plus-nl.gif); +} +.x-tree-no-lines .x-tree-elbow-minus { + background-image: url(../images/default/tree/elbow-minus-nl.gif); +} +.x-tree-no-lines .x-tree-elbow-end-plus { + background-image: url(../images/gray/tree/elbow-end-plus-nl.gif); +} +.x-tree-no-lines .x-tree-elbow-end-minus { + background-image: url(../images/gray/tree/elbow-end-minus-nl.gif); +} +.x-tree-arrows .x-tree-elbow-plus { + background-image: url(../images/gray/tree/arrows.gif); +} +.x-tree-arrows .x-tree-elbow-minus { + background-image: url(../images/gray/tree/arrows.gif); +} +.x-tree-arrows .x-tree-elbow-end-plus { + background-image: url(../images/gray/tree/arrows.gif); +} +.x-tree-arrows .x-tree-elbow-end-minus { + background-image: url(../images/gray/tree/arrows.gif); +} +.x-tree-node { + color: #000; + font: @font-weight @font-size @font-family; +} +.x-tree-node a, .x-dd-drag-ghost a { + color: #000; +} +.x-tree-node a span, .x-dd-drag-ghost a span { + color: #000; +} +.x-tree-node .x-tree-node-disabled a span { + color: gray !important; +} +.x-tree-node div.x-tree-drag-insert-below { + border-bottom-color: #36c; +} +.x-tree-node div.x-tree-drag-insert-above { + border-top-color: #36c; +} +.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a { + border-bottom-color: #36c; +} +.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a { + border-top-color: #36c; +} +.x-tree-node .x-tree-drag-append a span { + background-color: #ddd; + border-color: gray; +} +.x-tree-node .x-tree-node-over { + background-color: #eee; +} +.x-tree-node .x-tree-selected { + background-color: #ddd; +} +.x-tree-drop-ok-append .x-dd-drop-icon { + background-image: url(../images/default/tree/drop-add.gif); +} +.x-tree-drop-ok-above .x-dd-drop-icon { + background-image: url(../images/default/tree/drop-over.gif); +} +.x-tree-drop-ok-below .x-dd-drop-icon { + background-image: url(../images/default/tree/drop-under.gif); +} +.x-tree-drop-ok-between .x-dd-drop-icon { + background-image: url(../images/default/tree/drop-between.gif); +} +.x-date-picker { + border-color: #585858; + background-color: #fff; +} +.x-date-middle, .x-date-left, .x-date-right { + background-image: url(../images/gray/shared/hd-sprite.gif); + color: #fff; + font: @header-font-weight @header-font-size @header-font-family; +} +.x-date-middle .x-btn .x-btn-text { + color: #fff; +} +.x-date-middle .x-btn-mc em.x-btn-arrow { + background-image: url(../images/gray/toolbar/btn-arrow-light.gif); +} +.x-date-right a { + background-image: url(../images/gray/shared/right-btn.gif); +} +.x-date-left a { + background-image: url(../images/gray/shared/left-btn.gif); +} +.x-date-inner th { + background-color: #D8D8D8; + background-image: url(../images/gray/panel/white-top-bottom.gif); + border-bottom-color: #AFAFAF; + font: normal 10px @font-family; + color: #595959; +} +.x-date-inner td { + border-color: #fff; +} +.x-date-inner a { + font: @font-weight @font-size @font-family; + color: #000; +} +.x-date-inner .x-date-active { + color: #000; +} +.x-date-inner .x-date-selected a { + background-image: none; + background-color: #D8D8D8; + border-color: #DCDCDC; +} +.x-date-inner .x-date-today a { + border-color: darkred; +} +.x-date-inner .x-date-selected span { + font-weight: bold; +} +.x-date-inner .x-date-prevday a, .x-date-inner .x-date-nextday a { + color: #aaa; +} +.x-date-bottom { + border-top-color: #AFAFAF; + background-color: #D8D8D8; + background: #d8d8d8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px; +} +.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover { + color: #000; + background-color: #D8D8D8; +} +.x-date-inner .x-date-disabled a { + background-color: #eee; + color: #bbb; +} +.x-date-mmenu { + background-color: #eee !important; +} +.x-date-mmenu .x-menu-item { + font-size: 10px; + color: #000; +} +.x-date-mp { + background-color: #fff; +} +.x-date-mp td { + font: @font-weight @font-size @font-family; +} +.x-date-mp-btns button { + background-color: #4E565F; + color: #fff; + border-color: #C0C0C0 #434343 #434343 #C0C0C0; + font: @font-weight @font-size @font-family; +} +.x-date-mp-btns { + background-color: #D8D8D8; + background: #d8d8d8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px; +} +.x-date-mp-btns td { + border-top-color: #AFAFAF; +} +td.x-date-mp-month a, td.x-date-mp-year a { + color: #333; +} +td.x-date-mp-month a:hover, td.x-date-mp-year a:hover { + color: #333; + background-color: #FDFDFD; +} +td.x-date-mp-sel a { + background-color: #D8D8D8; + background: #d8d8d8 url(../images/gray/panel/white-top-bottom.gif) 0 -2px; + border-color: #DCDCDC; +} +.x-date-mp-ybtn a { + background-image: url(../images/gray/panel/tool-sprites.gif); +} +td.x-date-mp-sep { + border-right-color: @header-color; +} +.x-tip .x-tip-close { + background-image: url(../images/gray/qtip/close.gif); +} +.x-tip .x-tip-tc, +.x-tip .x-tip-tl, +.x-tip .x-tip-tr, +.x-tip .x-tip-bc, +.x-tip .x-tip-bl, +.x-tip .x-tip-br, +.x-tip .x-tip-ml, +.x-tip .x-tip-mr { + background-image: url(../images/gray/qtip/tip-sprite.gif); +} +.x-tip .x-tip-mc { + font: @font-weight @font-size @font-family; +} +.x-tip .x-tip-ml { + background-color: #fff; +} +.x-tip .x-tip-header-text { + font: bold @font-size @font-family; + color: #444; +} +.x-tip .x-tip-body { + font: @font-weight @font-size @font-family; + color: #444; +} +.x-form-invalid-tip .x-tip-tc, +.x-form-invalid-tip .x-tip-tl, +.x-form-invalid-tip .x-tip-tr, +.x-form-invalid-tip .x-tip-bc, +.x-form-invalid-tip .x-tip-bl, +.x-form-invalid-tip .x-tip-br, +.x-form-invalid-tip .x-tip-ml, +.x-form-invalid-tip .x-tip-mr { + background-image: url(../images/default/form/error-tip-corners.gif); +} +.x-form-invalid-tip .x-tip-body { + background-image: url(../images/default/form/exclamation.gif); +} +.x-tip-anchor { + background-image: url(../images/gray/qtip/tip-anchor-sprite.gif); +} +.x-menu { + background-color: #f0f0f0; + background-image: url(../images/default/menu/menu.gif); +} +.x-menu-floating { + border-color: #7D7D7D; +} +.x-menu-nosep { + background-image: none; +} +.x-menu-list-item { + font: @font-weight @font-size @font-family; +} +.x-menu-item-arrow { + background-image: url(../images/gray/menu/menu-parent.gif); +} +.x-menu-sep { + background-color: #e0e0e0; + border-bottom-color: #fff; +} +a.x-menu-item { + color: #222; +} +.x-menu-item-active { + background-image: url(../images/gray/menu/item-over.gif); + background-color: @base-color; + border-color: #ACACAC; +} +.x-menu-item-active a.x-menu-item { + border-color: #ACACAC; +} +.x-menu-check-item .x-menu-item-icon { + background-image: url(../images/default/menu/unchecked.gif); +} +.x-menu-item-checked .x-menu-item-icon { + background-image: url(../images/default/menu/checked.gif); +} +.x-menu-item-checked .x-menu-group-item .x-menu-item-icon { + background-image: url(../images/gray/menu/group-checked.gif); +} +.x-menu-group-item .x-menu-item-icon { + background-image: none; +} +.x-menu-plain { + background-color: #fff !important; +} +.x-menu .x-date-picker { + border-color: #AFAFAF; +} +.x-cycle-menu .x-menu-item-checked { + border-color: #B9B9B9 !important; + background-color: @base-color; +} +.x-menu-scroller-top { + background-image: url(../images/default/layout/mini-top.gif); +} +.x-menu-scroller-bottom { + background-image: url(../images/default/layout/mini-bottom.gif); +} +.x-box-tl { + background-image: url(../images/default/box/corners.gif); +} +.x-box-tc { + background-image: url(../images/default/box/tb.gif); +} +.x-box-tr { + background-image: url(../images/default/box/corners.gif); +} +.x-box-ml { + background-image: url(../images/default/box/l.gif); +} +.x-box-mc { + background-color: #eee; + background-image: url(../images/default/box/tb.gif); + font-family: @font-family; + color: #393939; + font-size: 12px; +} +.x-box-mc h3 { + font-size: 14px; + font-weight: bold; +} +.x-box-mr { + background-image: url(../images/default/box/r.gif); +} +.x-box-bl { + background-image: url(../images/default/box/corners.gif); +} +.x-box-bc { + background-image: url(../images/default/box/tb.gif); +} +.x-box-br { + background-image: url(../images/default/box/corners.gif); +} +.x-box-blue .x-box-bl, +.x-box-blue .x-box-br, +.x-box-blue .x-box-tl, +.x-box-blue .x-box-tr { + background-image: url(../images/default/box/corners-blue.gif); +} +.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc { + background-image: url(../images/default/box/tb-blue.gif); +} +.x-box-blue .x-box-mc { + background-color: #c3daf9; +} +.x-box-blue .x-box-mc h3 { + color: #17385b; +} +.x-box-blue .x-box-ml { + background-image: url(../images/default/box/l-blue.gif); +} +.x-box-blue .x-box-mr { + background-image: url(../images/default/box/r-blue.gif); +} +.x-combo-list { + border-color: #ccc; + background-color: #ddd; + font: normal 12px @font-family; +} +.x-combo-list-inner { + background-color: #fff; +} +.x-combo-list-hd { + font: bold @font-size @font-family; + color: #333; + background-image: url(../images/default/layout/panel-title-light-bg.gif); + border-bottom-color: #BCBCBC; +} +.x-resizable-pinned .x-combo-list-inner { + border-bottom-color: #BEBEBE; +} +.x-combo-list-item { + border-color: #fff; +} +.x-combo-list .x-combo-selected { + border-color: #777 !important; + background-color: #f0f0f0; +} +.x-combo-list .x-toolbar { + border-top-color: #BCBCBC; +} +.x-combo-list-small { + font: @font-weight @font-size @font-family; +} +.x-panel { + border-color: @border-color; +} +.x-panel-header { + color: #333; + font-weight: @header-font-weight; + font-size: @header-font-size; + font-family: @header-font-family; + border-color: @border-color; + background-image: url(../images/gray/panel/white-top-bottom.gif); +} +.x-panel-body { + border-color: @border-color; + background-color: #fff; +} +.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar { + border-color: @border-color; +} +.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar { + border-top-color: @border-color; +} +.x-panel-body-noheader, .x-panel-mc .x-panel-body { + border-top-color: @border-color; +} +.x-panel-tl .x-panel-header { + color: #333; + font: @header-font-weight @header-font-size @header-font-family; +} +.x-panel-tc { + background-image: url(../images/gray/panel/top-bottom.gif); +} +.x-panel-tl, +.x-panel-tr, +.x-panel-bl, +.x-panel-br { + background-image: url(../images/gray/panel/corners-sprite.gif); + border-bottom-color: @border-color; +} +.x-panel-bc { + background-image: url(../images/gray/panel/top-bottom.gif); +} +.x-panel-mc { + font: @font-weight @font-size @font-family; + background-color: @base-color; +} +.x-panel-ml { + background-color: #fff; + background-image: url(../images/gray/panel/left-right.gif); +} +.x-panel-mr { + background-image: url(../images/gray/panel/left-right.gif); +} +.x-tool { + background-image: url(../images/gray/panel/tool-sprites.gif); +} +.x-panel-ghost { + background-color: #f2f2f2; +} +.x-panel-ghost ul { + border-color: @border-color; +} +.x-panel-dd-spacer { + border-color: @border-color; +} +.x-panel-fbar td, +.x-panel-fbar span, +.x-panel-fbar input, +.x-panel-fbar div, +.x-panel-fbar select, +.x-panel-fbar label { + font: @font-weight @font-size @font-family; +} +.x-window-proxy { + background-color: #fcfcfc; + border-color: @border-color; +} +.x-window-tl .x-window-header { + color: #555; + font: @header-font-weight @header-font-size @header-font-family; +} +.x-window-tc { + background-image: url(../images/gray/window/top-bottom.png); +} +.x-window-tl { + background-image: url(../images/gray/window/left-corners.png); +} +.x-window-tr { + background-image: url(../images/gray/window/right-corners.png); +} +.x-window-bc { + background-image: url(../images/gray/window/top-bottom.png); +} +.x-window-bl { + background-image: url(../images/gray/window/left-corners.png); +} +.x-window-br { + background-image: url(../images/gray/window/right-corners.png); +} +.x-window-mc { + border-color: @border-color; + font: @font-weight @font-size @font-family; + background-color: #e8e8e8; +} +.x-window-ml { + background-image: url(../images/gray/window/left-right.png); +} +.x-window-mr { + background-image: url(../images/gray/window/left-right.png); +} +.x-window-maximized .x-window-tc { + background-color: #fff; +} +.x-window-bbar .x-toolbar { + border-top-color: @border-color; +} +.x-panel-ghost .x-window-tl { + border-bottom-color: @border-color; +} +.x-panel-collapsed .x-window-tl { + border-bottom-color: @border-color; +} +.x-dlg-mask { + background-color: #ccc; +} +.x-window-plain .x-window-mc { + background-color: #E8E8E8; + border-color: #D0D0D0 #EEEEEE #EEEEEE #D0D0D0; +} +.x-window-plain .x-window-body { + border-color: #EEEEEE #D0D0D0 #D0D0D0 #EEEEEE; +} +body.x-body-masked .x-window-plain .x-window-mc { + background-color: #E4E4E4; +} +.x-html-editor-wrap { + border-color: #BCBCBC; + background-color: #fff; +} +.x-html-editor-tb .x-btn-text { + background-image: url(../images/default/editor/tb-sprite.gif); +} +.x-panel-noborder .x-panel-header-noborder { + border-bottom-color: @border-color; +} +.x-panel-noborder .x-panel-tbar-noborder .x-toolbar { + border-bottom-color: @border-color; +} +.x-panel-noborder .x-panel-bbar-noborder .x-toolbar { + border-top-color: @border-color; +} +.x-tab-panel-bbar-noborder .x-toolbar { + border-top-color: @border-color; +} +.x-tab-panel-tbar-noborder .x-toolbar { + border-bottom-color: @border-color; +} +.x-border-layout-ct { + background-color: #f0f0f0; +} +.x-border-layout-ct { + background-color: #f0f0f0; +} +.x-accordion-hd { + color: #222; + font-weight: normal; + background-image: url(../images/gray/panel/light-hd.gif); +} +.x-layout-collapsed { + background-color: #dfdfdf; + border-color: @border-color; +} +.x-layout-collapsed-over { + background-color: #e7e7e7; +} +.x-layout-split-west .x-layout-mini { + background-image: url(../images/default/layout/mini-left.gif); +} +.x-layout-split-east .x-layout-mini { + background-image: url(../images/default/layout/mini-right.gif); +} +.x-layout-split-north .x-layout-mini { + background-image: url(../images/default/layout/mini-top.gif); +} +.x-layout-split-south .x-layout-mini { + background-image: url(../images/default/layout/mini-bottom.gif); +} +.x-layout-cmini-west .x-layout-mini { + background-image: url(../images/default/layout/mini-right.gif); +} +.x-layout-cmini-east .x-layout-mini { + background-image: url(../images/default/layout/mini-left.gif); +} +.x-layout-cmini-north .x-layout-mini { + background-image: url(../images/default/layout/mini-bottom.gif); +} +.x-layout-cmini-south .x-layout-mini { + background-image: url(../images/default/layout/mini-top.gif); +} +.x-progress-wrap { + border-color: #8E8E8E; +} +.x-progress-inner { + background-color: #E7E7E7; + background-image: url(../images/gray/qtip/bg.gif); +} +.x-progress-bar { + background-color: #BCBCBC; + background-image: url(../images/gray/progress/progress-bg.gif); + border-top-color: #E2E2E2; + border-bottom-color: #A4A4A4; + border-right-color: #A4A4A4; +} +.x-progress-text { + font-size: @header-font-size; + font-weight: @header-font-weight ; + color: #fff; +} +.x-progress-text-back { + color: #5F5F5F; +} +.x-list-header { + background-color: #f9f9f9; + background-image: url(../images/gray/grid/grid3-hrow2.gif); +} +.x-list-header-inner div em { + border-left-color: #ddd; + font: @font-weight @font-family; +} +.x-list-body dt em { + font: @font-weight @font-family; +} +.x-list-over { + background-color: #eee; +} +.x-list-selected { + background-color: #f0f0f0; +} +.x-list-resizer { + border-left-color: #555; + border-right-color: #555; +} +.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc { + background-image: url(../images/gray/grid/sort-hd.gif); + border-color: @border-color; +} +.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner { + background-image: url(../images/default/slider/slider-bg.png); +} +.x-slider-horz .x-slider-thumb { + background-image: url(../images/gray/slider/slider-thumb.png); +} +.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner { + background-image: url(../images/default/slider/slider-v-bg.png); +} +.x-slider-vert .x-slider-thumb { + background-image: url(../images/gray/slider/slider-v-thumb.png); +} +.x-window-dlg .ext-mb-text, .x-window-dlg .x-window-header-text { + font-size: 12px; +} +.x-window-dlg .ext-mb-textarea { + font: normal 12px @font-family; +} +.x-window-dlg .x-msg-box-wait { + background-image: url(../images/default/grid/loading.gif); +} +.x-window-dlg .ext-mb-info { + background-image: url(../images/gray/window/icon-info.gif); +} +.x-window-dlg .ext-mb-warning { + background-image: url(../images/gray/window/icon-warning.gif); +} +.x-window-dlg .ext-mb-question { + background-image: url(../images/gray/window/icon-question.gif); +} +.x-window-dlg .ext-mb-error { + background-image: url(../images/gray/window/icon-error.gif); +} diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/corners-blue.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/corners-blue.gif new file mode 100755 index 0000000000..b6d50691c0 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/corners-blue.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/corners.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/corners.gif new file mode 100755 index 0000000000..ec2c016db0 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/corners.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/l-blue.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/l-blue.gif new file mode 100755 index 0000000000..29170b6a7d Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/l-blue.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/l.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/l.gif new file mode 100755 index 0000000000..189f0daf4f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/l.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/r-blue.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/r-blue.gif new file mode 100755 index 0000000000..20c889129c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/r-blue.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/r.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/r.gif new file mode 100755 index 0000000000..4b32203f02 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/r.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/tb-blue.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/tb-blue.gif new file mode 100755 index 0000000000..7d65b18d0b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/tb-blue.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/tb.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/tb.gif new file mode 100755 index 0000000000..c4276515ff Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/box/tb.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/arrow.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/arrow.gif new file mode 100755 index 0000000000..e7ee057d5d Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/arrow.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn-arrow.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn-arrow.gif new file mode 100755 index 0000000000..31b79b644c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn-arrow.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn-sprite.gif new file mode 100755 index 0000000000..c040e8204b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn.gif new file mode 100755 index 0000000000..34eeef8d52 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/btn.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-cs.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-cs.gif new file mode 100755 index 0000000000..9be75446cf Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-cs.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-lr.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-lr.gif new file mode 100755 index 0000000000..094b70df2b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-lr.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-tb.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-tb.gif new file mode 100755 index 0000000000..e2bd4ea487 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/group-tb.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-b-noline.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-b-noline.gif new file mode 100755 index 0000000000..dbc5af14af Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-b-noline.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-b.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-b.gif new file mode 100755 index 0000000000..e1c4f54859 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-b.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-bo.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-bo.gif new file mode 100755 index 0000000000..def6af6099 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-bo.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-noline.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-noline.gif new file mode 100755 index 0000000000..f816fae4df Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-noline.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-o.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-o.gif new file mode 100755 index 0000000000..43098269f5 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow-o.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow.gif new file mode 100755 index 0000000000..14d5afed90 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/button/s-arrow.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-add.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-add.gif new file mode 100755 index 0000000000..b22cd1448e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-add.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-no.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-no.gif new file mode 100755 index 0000000000..08d083355f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-no.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-yes.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-yes.gif new file mode 100755 index 0000000000..8aacb307e8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/dd/drop-yes.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/editor/tb-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/editor/tb-sprite.gif new file mode 100755 index 0000000000..d561bae92f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/editor/tb-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/checkbox.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/checkbox.gif new file mode 100755 index 0000000000..28d711aa77 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/checkbox.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/clear-trigger.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/clear-trigger.gif new file mode 100755 index 0000000000..5815ec8855 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/clear-trigger.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/date-trigger.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/date-trigger.gif new file mode 100755 index 0000000000..342eea35e0 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/date-trigger.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/error-tip-corners.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/error-tip-corners.gif new file mode 100755 index 0000000000..6ea4c38387 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/error-tip-corners.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/exclamation.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/exclamation.gif new file mode 100755 index 0000000000..ea31a3060a Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/exclamation.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/radio.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/radio.gif new file mode 100755 index 0000000000..5065247623 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/radio.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/search-trigger.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/search-trigger.gif new file mode 100755 index 0000000000..d2f910d584 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/search-trigger.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/text-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/text-bg.gif new file mode 100755 index 0000000000..8e098bfa6b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/text-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger-square.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger-square.gif new file mode 100755 index 0000000000..16a2a36902 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger-square.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger-tpl.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger-tpl.gif new file mode 100755 index 0000000000..3fc4fbbb6c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger-tpl.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger.gif new file mode 100755 index 0000000000..3d7c46ae8c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/form/trigger.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/gradient-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/gradient-bg.gif new file mode 100755 index 0000000000..8f29c1a669 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/gradient-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/col-move-bottom.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/col-move-bottom.gif new file mode 100755 index 0000000000..dd99e2e2cd Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/col-move-bottom.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/col-move-top.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/col-move-top.gif new file mode 100755 index 0000000000..1f961e8560 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/col-move-top.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/columns.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/columns.gif new file mode 100755 index 0000000000..2d3a82393e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/columns.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/dirty.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/dirty.gif new file mode 100755 index 0000000000..55a0fd79e5 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/dirty.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/done.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/done.gif new file mode 100755 index 0000000000..af2ec9394d Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/done.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/drop-no.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/drop-no.gif new file mode 100755 index 0000000000..9309236da3 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/drop-no.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/drop-yes.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/drop-yes.gif new file mode 100755 index 0000000000..3aba1fca79 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/drop-yes.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-hrow.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-hrow.gif new file mode 100755 index 0000000000..f45ba319ef Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-hrow.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-loading.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-loading.gif new file mode 100755 index 0000000000..bc8383f666 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-loading.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-split.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-split.gif new file mode 100755 index 0000000000..4f402a768d Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid-split.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hd-btn.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hd-btn.gif new file mode 100755 index 0000000000..e4173d5258 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hd-btn.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow-over.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow-over.gif new file mode 100755 index 0000000000..3cac0b38b9 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow-over.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow-over2.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow-over2.gif new file mode 100755 index 0000000000..f443f0df3c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow-over2.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow.gif new file mode 100755 index 0000000000..930688294a Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow2.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow2.gif new file mode 100755 index 0000000000..f4396b8833 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-hrow2.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-rowheader.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-rowheader.gif new file mode 100755 index 0000000000..ef3d6f8640 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-rowheader.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-bg.gif new file mode 100755 index 0000000000..0a26794142 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-bg2.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-bg2.gif new file mode 100755 index 0000000000..13dd76eacc Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-bg2.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-sel-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-sel-bg.gif new file mode 100755 index 0000000000..5ca383d145 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/grid3-special-col-sel-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-by.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-by.gif new file mode 100755 index 0000000000..d6075bba2f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-by.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-collapse.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-collapse.gif new file mode 100755 index 0000000000..fac32c34a8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-collapse.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-expand-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-expand-sprite.gif new file mode 100755 index 0000000000..1bf6c033e8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-expand-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-expand.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-expand.gif new file mode 100755 index 0000000000..383996973f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/group-expand.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hd-pop.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hd-pop.gif new file mode 100755 index 0000000000..251f5898ac Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hd-pop.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-asc.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-asc.gif new file mode 100755 index 0000000000..b648abea61 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-asc.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-desc.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-desc.gif new file mode 100755 index 0000000000..7a4cbb27d4 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-desc.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-lock.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-lock.gif new file mode 100755 index 0000000000..1596126108 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-lock.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-lock.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-lock.png new file mode 100755 index 0000000000..c0f7ca6af4 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-lock.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-unlock.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-unlock.gif new file mode 100755 index 0000000000..af59cf92a4 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-unlock.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-unlock.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-unlock.png new file mode 100755 index 0000000000..4912586b21 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/hmenu-unlock.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/invalid_line.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/invalid_line.gif new file mode 100755 index 0000000000..fb7e0f34d6 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/invalid_line.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/loading.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/loading.gif new file mode 100755 index 0000000000..1714f1632e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/loading.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-first-disabled.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-first-disabled.gif new file mode 100755 index 0000000000..1e02c419f5 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-first-disabled.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-first.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-first.gif new file mode 100755 index 0000000000..60be4bcd3b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-first.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-last-disabled.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-last-disabled.gif new file mode 100755 index 0000000000..869706777c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-last-disabled.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-last.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-last.gif new file mode 100755 index 0000000000..beb4a8302a Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-last.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-next-disabled.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-next-disabled.gif new file mode 100755 index 0000000000..90a7756f6f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-next-disabled.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-next.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-next.gif new file mode 100755 index 0000000000..97db1c2207 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-next.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-prev-disabled.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-prev-disabled.gif new file mode 100755 index 0000000000..37154d6240 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-prev-disabled.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-prev.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-prev.gif new file mode 100755 index 0000000000..d07e61c36a Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/page-prev.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/refresh.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/refresh.gif new file mode 100755 index 0000000000..868b2dc594 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/refresh.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-check-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-check-sprite.gif new file mode 100755 index 0000000000..c230773a45 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-check-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-expand-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-expand-sprite.gif new file mode 100755 index 0000000000..abea9be561 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-expand-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-over.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-over.gif new file mode 100755 index 0000000000..888974dc0a Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-over.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-sel.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-sel.gif new file mode 100755 index 0000000000..98239ea69e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/row-sel.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort-hd.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort-hd.gif new file mode 100755 index 0000000000..488675a479 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort-hd.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort_asc.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort_asc.gif new file mode 100755 index 0000000000..f50ae62fce Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort_asc.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort_desc.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort_desc.gif new file mode 100755 index 0000000000..651e515aa8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/grid/sort_desc.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/collapse.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/collapse.gif new file mode 100755 index 0000000000..55547981b9 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/collapse.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/expand.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/expand.gif new file mode 100755 index 0000000000..3803d3596a Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/expand.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/gradient-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/gradient-bg.gif new file mode 100755 index 0000000000..8f29c1a669 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/gradient-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-bottom.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-bottom.gif new file mode 100755 index 0000000000..14b9d22f79 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-bottom.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-left.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-left.gif new file mode 100755 index 0000000000..9b12f92b85 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-left.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-right.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-right.gif new file mode 100755 index 0000000000..bf54d8cea1 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-right.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-top.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-top.gif new file mode 100755 index 0000000000..24cd21d897 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/mini-top.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/ns-collapse.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/ns-collapse.gif new file mode 100755 index 0000000000..d24e13f935 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/ns-collapse.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/ns-expand.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/ns-expand.gif new file mode 100755 index 0000000000..4a54011bd7 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/ns-expand.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-close.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-close.gif new file mode 100755 index 0000000000..43324ebd38 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-close.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-title-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-title-bg.gif new file mode 100755 index 0000000000..d3b59f8cf3 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-title-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-title-light-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-title-light-bg.gif new file mode 100755 index 0000000000..4272e32092 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/panel-title-light-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/stick.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/stick.gif new file mode 100755 index 0000000000..71a292b499 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/stick.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/stuck.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/stuck.gif new file mode 100755 index 0000000000..200db8b5b5 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/stuck.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/tab-close-on.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/tab-close-on.gif new file mode 100755 index 0000000000..163420322e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/tab-close-on.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/tab-close.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/tab-close.gif new file mode 100755 index 0000000000..ba61c07bda Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/layout/tab-close.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/checked.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/checked.gif new file mode 100755 index 0000000000..fad5893727 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/checked.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/group-checked.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/group-checked.gif new file mode 100755 index 0000000000..eda4fb93f0 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/group-checked.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/item-over-disabled.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/item-over-disabled.gif new file mode 100755 index 0000000000..5e2fa306b0 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/item-over-disabled.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/item-over.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/item-over.gif new file mode 100755 index 0000000000..2b6d5cc76b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/item-over.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/menu-parent.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/menu-parent.gif new file mode 100755 index 0000000000..c956052cb6 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/menu-parent.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/menu.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/menu.gif new file mode 100755 index 0000000000..11f8996c0b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/menu.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/unchecked.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/unchecked.gif new file mode 100755 index 0000000000..43823e52db Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/menu/unchecked.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clear.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clear.gif new file mode 100755 index 0000000000..d997d6568c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clear.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clearfocus.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clearfocus.gif new file mode 100755 index 0000000000..fe15687d5c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clearfocus.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clearinvalid.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clearinvalid.gif new file mode 100755 index 0000000000..c92d897cbe Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/clearinvalid.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/close.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/close.gif new file mode 100755 index 0000000000..2b2f736177 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/close.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expand.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expand.gif new file mode 100755 index 0000000000..3803d3596a Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expand.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expandfocus.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expandfocus.gif new file mode 100755 index 0000000000..94d9a9ce14 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expandfocus.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expandinvalid.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expandinvalid.gif new file mode 100755 index 0000000000..f5cbe47d6b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/multiselect/expandinvalid.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/corners-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/corners-sprite.gif new file mode 100755 index 0000000000..c447500de8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/corners-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/corners-sprite_b.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/corners-sprite_b.gif new file mode 100755 index 0000000000..b509458205 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/corners-sprite_b.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/left-right.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/left-right.gif new file mode 100755 index 0000000000..a6ac2ab8c0 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/left-right.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/light-hd.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/light-hd.gif new file mode 100755 index 0000000000..a0eaa30393 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/light-hd.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprite-tpl.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprite-tpl.gif new file mode 100755 index 0000000000..14a2c9f302 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprite-tpl.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprites.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprites.gif new file mode 100755 index 0000000000..9efb4db41d Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprites.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprites.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprites.png new file mode 100755 index 0000000000..8f93903d0d Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tool-sprites.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tools-sprites-trans.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tools-sprites-trans.gif new file mode 100755 index 0000000000..5c4f9bcd9b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/tools-sprites-trans.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom.gif new file mode 100755 index 0000000000..d395269284 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom.png new file mode 100755 index 0000000000..30e4d96b4f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom_bc.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom_bc.gif new file mode 100755 index 0000000000..1954e3abac Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/top-bottom_bc.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-corners-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-corners-sprite.gif new file mode 100755 index 0000000000..aea5c3131f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-corners-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-left-right.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-left-right.gif new file mode 100755 index 0000000000..b69bffee5f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-left-right.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-top-bottom.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-top-bottom.gif new file mode 100755 index 0000000000..119bbbcd9b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/panel/white-top-bottom.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/progress/progress-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/progress/progress-bg.gif new file mode 100755 index 0000000000..77ad06ce05 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/progress/progress-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/bg.gif new file mode 100755 index 0000000000..2159a4f7ce Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/close.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/close.gif new file mode 100755 index 0000000000..fb3570d1f7 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/close.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-anchor-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-anchor-sprite.gif new file mode 100755 index 0000000000..b21b955869 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-anchor-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-sprite.gif new file mode 100755 index 0000000000..dfe008a661 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-sprite_old.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-sprite_old.gif new file mode 100755 index 0000000000..2d7b7e3941 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/qtip/tip-sprite_old.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/s.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/s.gif new file mode 100755 index 0000000000..1d11fa9ada Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/s.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow-c.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow-c.png new file mode 100755 index 0000000000..4548f9a361 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow-c.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow-lr.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow-lr.png new file mode 100755 index 0000000000..1d629efed0 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow-lr.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow.png new file mode 100755 index 0000000000..2bc4231bbb Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shadow.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/calendar.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/calendar.gif new file mode 100755 index 0000000000..e6ae370d68 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/calendar.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/glass-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/glass-bg.gif new file mode 100755 index 0000000000..beb72caeb8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/glass-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/hd-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/hd-sprite.gif new file mode 100755 index 0000000000..856d56c450 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/hd-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/large-loading.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/large-loading.gif new file mode 100755 index 0000000000..832720bb35 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/large-loading.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/left-btn.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/left-btn.gif new file mode 100755 index 0000000000..efabe993c1 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/left-btn.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/loading-balls.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/loading-balls.gif new file mode 100755 index 0000000000..c88bb179e8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/loading-balls.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/right-btn.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/right-btn.gif new file mode 100755 index 0000000000..f904fd2e58 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/right-btn.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/warning.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/warning.gif new file mode 100755 index 0000000000..806d4bc093 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/shared/warning.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/e-handle-dark.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/e-handle-dark.gif new file mode 100755 index 0000000000..2f865d3267 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/e-handle-dark.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/e-handle.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/e-handle.gif new file mode 100755 index 0000000000..9045775267 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/e-handle.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/ne-handle-dark.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/ne-handle-dark.gif new file mode 100755 index 0000000000..03a196831c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/ne-handle-dark.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/ne-handle.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/ne-handle.gif new file mode 100755 index 0000000000..7b11644a87 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/ne-handle.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/nw-handle-dark.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/nw-handle-dark.gif new file mode 100755 index 0000000000..252635a961 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/nw-handle-dark.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/nw-handle.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/nw-handle.gif new file mode 100755 index 0000000000..2cfd90e134 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/nw-handle.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/s-handle-dark.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/s-handle-dark.gif new file mode 100755 index 0000000000..5861298874 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/s-handle-dark.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/s-handle.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/s-handle.gif new file mode 100755 index 0000000000..3a8b4600fb Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/s-handle.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/se-handle-dark.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/se-handle-dark.gif new file mode 100755 index 0000000000..ce72a8a66d Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/se-handle-dark.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/se-handle.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/se-handle.gif new file mode 100755 index 0000000000..4f8042d98f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/se-handle.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/square.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/square.gif new file mode 100755 index 0000000000..ff4df0ffce Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/square.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/sw-handle-dark.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/sw-handle-dark.gif new file mode 100755 index 0000000000..e8e13b17e1 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/sw-handle-dark.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/sw-handle.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/sw-handle.gif new file mode 100755 index 0000000000..7a90d1b6cb Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/sizer/sw-handle.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-bg.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-bg.png new file mode 100755 index 0000000000..c525c7cd80 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-bg.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-thumb.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-thumb.png new file mode 100755 index 0000000000..883821b45f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-thumb.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-v-bg.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-v-bg.png new file mode 100755 index 0000000000..6d8d4dc25d Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-v-bg.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-v-thumb.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-v-thumb.png new file mode 100755 index 0000000000..bfadcdc6b4 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/slider/slider-v-thumb.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/spinner/spinner-split.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/spinner/spinner-split.gif new file mode 100755 index 0000000000..37de7e4e77 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/spinner/spinner-split.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/spinner/spinner.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/spinner/spinner.gif new file mode 100755 index 0000000000..f28196fd7e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/spinner/spinner.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroll-left.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroll-left.gif new file mode 100755 index 0000000000..830378ec83 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroll-left.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroll-right.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroll-right.gif new file mode 100755 index 0000000000..4d9bf35985 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroll-right.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroller-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroller-bg.gif new file mode 100755 index 0000000000..9e31ddce8b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/scroller-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-inactive-left-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-inactive-left-bg.gif new file mode 100755 index 0000000000..e61a9e4f2b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-inactive-left-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-inactive-right-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-inactive-right-bg.gif new file mode 100755 index 0000000000..b264934264 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-inactive-right-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-left-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-left-bg.gif new file mode 100755 index 0000000000..965ace3024 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-left-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-over-left-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-over-left-bg.gif new file mode 100755 index 0000000000..de8a68eb33 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-over-left-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-over-right-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-over-right-bg.gif new file mode 100755 index 0000000000..09d5af7339 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-over-right-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-right-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-right-bg.gif new file mode 100755 index 0000000000..a6a58735c4 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-btm-right-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-close.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-close.gif new file mode 100755 index 0000000000..663022bab4 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-close.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-bg.gif new file mode 100755 index 0000000000..926703a7ea Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-bg.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-bg.png new file mode 100755 index 0000000000..b9cbd37ce4 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-bg.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-btm-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-btm-bg.gif new file mode 100755 index 0000000000..64e83a738f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tab-strip-btm-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tabs-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tabs-sprite.gif new file mode 100755 index 0000000000..d86491b7ac Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tabs/tabs-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/bg.gif new file mode 100755 index 0000000000..4fa4aa12e7 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-arrow-light.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-arrow-light.gif new file mode 100755 index 0000000000..e048a18ab6 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-arrow-light.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-arrow.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-arrow.gif new file mode 100755 index 0000000000..6a88cf24bc Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-arrow.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-over-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-over-bg.gif new file mode 100755 index 0000000000..b7b1244716 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/btn-over-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/gray-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/gray-bg.gif new file mode 100755 index 0000000000..27d634be1c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/gray-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/more.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/more.gif new file mode 100755 index 0000000000..2e0d186e08 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/more.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-bg.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-bg.gif new file mode 100755 index 0000000000..756a4bf1f2 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-bg.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-btn-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-btn-sprite.gif new file mode 100755 index 0000000000..da88138240 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-btn-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-xl-btn-sprite.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-xl-btn-sprite.gif new file mode 100755 index 0000000000..49dd8d642c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-xl-btn-sprite.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-xl-sep.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-xl-sep.gif new file mode 100755 index 0000000000..5429770cf0 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/toolbar/tb-xl-sep.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/arrows.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/arrows.gif new file mode 100755 index 0000000000..136265b64e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/arrows.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-add.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-add.gif new file mode 100755 index 0000000000..b22cd1448e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-add.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-between.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-between.gif new file mode 100755 index 0000000000..5c6c09d987 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-between.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-no.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-no.gif new file mode 100755 index 0000000000..9d9c6a9ce1 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-no.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-over.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-over.gif new file mode 100755 index 0000000000..30d1ca7107 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-over.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-under.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-under.gif new file mode 100755 index 0000000000..85f66b1e58 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-under.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-yes.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-yes.gif new file mode 100755 index 0000000000..8aacb307e8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/drop-yes.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-minus-nl.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-minus-nl.gif new file mode 100755 index 0000000000..8c5bc5d4d5 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-minus-nl.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-minus.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-minus.gif new file mode 100755 index 0000000000..585051376c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-minus.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-plus-nl.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-plus-nl.gif new file mode 100755 index 0000000000..752b42a3c7 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-plus-nl.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-plus.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-plus.gif new file mode 100755 index 0000000000..ff126359d3 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end-plus.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end.gif new file mode 100755 index 0000000000..f24ddee799 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-end.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-line.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-line.gif new file mode 100755 index 0000000000..75e6da4f8e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-line.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-minus-nl.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-minus-nl.gif new file mode 100755 index 0000000000..928779e923 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-minus-nl.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-minus.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-minus.gif new file mode 100755 index 0000000000..97dcc7110f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-minus.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-plus-nl.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-plus-nl.gif new file mode 100755 index 0000000000..9f7f69880f Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-plus-nl.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-plus.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-plus.gif new file mode 100755 index 0000000000..698de4793c Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow-plus.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow.gif new file mode 100755 index 0000000000..b8f4208389 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/elbow.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/folder-open.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/folder-open.gif new file mode 100755 index 0000000000..56ba737bcc Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/folder-open.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/folder.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/folder.gif new file mode 100755 index 0000000000..20412f7c1b Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/folder.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/leaf.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/leaf.gif new file mode 100755 index 0000000000..445769d3f8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/leaf.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/loading.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/loading.gif new file mode 100755 index 0000000000..1714f1632e Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/loading.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/s.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/s.gif new file mode 100755 index 0000000000..1d11fa9ada Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/tree/s.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-error.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-error.gif new file mode 100755 index 0000000000..397b655ab8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-error.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-info.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-info.gif new file mode 100755 index 0000000000..58281c3067 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-info.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-question.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-question.gif new file mode 100755 index 0000000000..08abd82ae8 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-question.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-warning.gif b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-warning.gif new file mode 100755 index 0000000000..27ff98b4f7 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/icon-warning.gif differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-corners.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-corners.png new file mode 100755 index 0000000000..3826676141 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-corners.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-corners_ie6.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-corners_ie6.png new file mode 100755 index 0000000000..1fdc098ac2 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-corners_ie6.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-right.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-right.png new file mode 100755 index 0000000000..74d6a8b105 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-right.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-right_ie6.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-right_ie6.png new file mode 100755 index 0000000000..5af2b2c508 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/left-right_ie6.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/right-corners.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/right-corners.png new file mode 100755 index 0000000000..1679e5cab2 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/right-corners.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/right-corners_ie6.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/right-corners_ie6.png new file mode 100755 index 0000000000..6e6e82e769 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/right-corners_ie6.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/top-bottom.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/top-bottom.png new file mode 100755 index 0000000000..c2e9ac9017 Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/top-bottom.png differ diff --git a/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/top-bottom_ie6.png b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/top-bottom_ie6.png new file mode 100755 index 0000000000..700e83c9ba Binary files /dev/null and b/scm-webapp/src/main/webapp/resources/extjs/resources/images/tp/window/top-bottom_ie6.png differ diff --git a/scm-webapp/src/main/webapp/resources/js/group/sonia.group.grid.js b/scm-webapp/src/main/webapp/resources/js/group/sonia.group.grid.js index a386e2d115..7ed4599e6b 100644 --- a/scm-webapp/src/main/webapp/resources/js/group/sonia.group.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/group/sonia.group.grid.js @@ -38,6 +38,9 @@ Sonia.group.Grid = Ext.extend(Sonia.rest.Grid, { colTypeText: 'Type', emptyGroupStoreText: 'No group is configured', groupFormTitleText: 'Group Form', + + // parent panel for history + parentPanel: null, initComponent: function(){ var groupStore = new Sonia.rest.JsonStore({ @@ -82,6 +85,9 @@ Sonia.group.Grid = Ext.extend(Sonia.rest.Grid, { Ext.apply(this, Ext.apply(this.initialConfig, config)); Sonia.group.Grid.superclass.initComponent.apply(this, arguments); + + // store grid in parent panel + this.parentPanel.groupGrid = this; }, @@ -116,7 +122,9 @@ Sonia.group.Grid = Ext.extend(Sonia.rest.Grid, { console.debug( group.name + ' selected' ); } - Sonia.History.append(group.name); + if (this.parentPanel){ + this.parentPanel.updateHistory(group); + } Ext.getCmp('groupRmButton').setDisabled(false); Sonia.group.setEditPanel([{ diff --git a/scm-webapp/src/main/webapp/resources/js/group/sonia.group.panel.js b/scm-webapp/src/main/webapp/resources/js/group/sonia.group.panel.js index a529f81a4f..a3e840db3c 100644 --- a/scm-webapp/src/main/webapp/resources/js/group/sonia.group.panel.js +++ b/scm-webapp/src/main/webapp/resources/js/group/sonia.group.panel.js @@ -37,6 +37,9 @@ Sonia.group.Panel = Ext.extend(Sonia.rest.Panel, { removeMsgText: 'Remove Group "{0}"?', errorTitleText: 'Error', errorMsgText: 'Group deletion failed', + + // grid + groupGrid: null, initComponent: function(){ var config = { @@ -49,7 +52,8 @@ Sonia.group.Panel = Ext.extend(Sonia.rest.Panel, { items: [{ id: 'groupGrid', xtype: 'groupGrid', - region: 'center' + region: 'center', + parentPanel: this }, { id: 'groupEditPanel', xtype: 'tabpanel', @@ -71,9 +75,24 @@ Sonia.group.Panel = Ext.extend(Sonia.rest.Panel, { Ext.apply(this, Ext.apply(this.initialConfig, config)); Sonia.group.Panel.superclass.initComponent.apply(this, arguments); }, + + getGrid: function(){ + if (!this.groupGrid){ + if (debug){ + console.debug('could not find group grid, fetch by id'); + } + this.groupGrid = Ext.getCmp('groupGrid'); + } + return this.groupGrid; + }, + + updateHistory: function(group){ + var token = Sonia.History.createToken('groupPanel', group.name); + Sonia.History.add(token); + }, removeGroup: function(){ - var grid = Ext.getCmp('groupGrid'); + var grid = this.getGrid(); var selected = grid.getSelectionModel().getSelected(); if ( selected ){ var item = selected.data; @@ -140,10 +159,36 @@ Sonia.group.Panel = Ext.extend(Sonia.rest.Panel, { }, reload: function(){ - Ext.getCmp('groupGrid').reload(); + this.getGrid().reload(); } }); // register xtype Ext.reg('groupPanel', Sonia.group.Panel); + +// register history handler +Sonia.History.register('groupPanel', { + + onActivate: function(panel){ + var token = null; + var rec = panel.getGrid().getSelectionModel().getSelected(); + if (rec){ + token = Sonia.History.createToken('groupPanel', rec.get('name')); + } else { + token = Sonia.History.createToken('groupPanel'); + } + return token; + }, + + onChange: function(repoId){ + var panel = Ext.getCmp('groups'); + if ( ! panel ){ + main.addGroupsTabPanel(); + panel = Ext.getCmp('groups'); + } + if (repoId){ + panel.getGrid().selectById(repoId); + } + } +}); \ No newline at end of file diff --git a/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js b/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js index f711e65242..1f7158ff7e 100644 --- a/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js +++ b/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js @@ -61,7 +61,7 @@ Ext.apply(Ext.form.VTypes, { // username validator username: function(val){ - return val.match(/^[A-z0-9\.\-_@]+$/); + return val.match(/^[^ ][A-z0-9\.\-_@ ]*[^ ]$/); }, usernameText: 'The username is invalid.' diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewergrid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewergrid.js index 3debc6cbad..75604d0f93 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewergrid.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewergrid.js @@ -140,7 +140,7 @@ Sonia.repository.ChangesetViewerGrid = Ext.extend(Ext.grid.GridPanel, { openDiffViewer: function(revision){ main.addTab({ - id: 'diff-' + this.repository.id + ':' + revision, + id: 'diffPanel|' + this.repository.id + '|' + revision, xtype: 'diffPanel', repository: this.repository, revision: revision, @@ -150,7 +150,7 @@ Sonia.repository.ChangesetViewerGrid = Ext.extend(Ext.grid.GridPanel, { openRepositoryBrowser: function(revision){ main.addTab({ - id: 'repositorybrowser-' + this.repository.id + ':' + revision, + id: 'repositoryBrowser|' + this.repository.id + '|' + revision, xtype: 'repositoryBrowser', repository: this.repository, revision: revision, diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewerpanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewerpanel.js index 759055fdca..8469c89451 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewerpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewerpanel.js @@ -34,35 +34,50 @@ Sonia.repository.ChangesetViewerPanel = Ext.extend(Ext.Panel, { repository: null, start: 0, pageSize: 20, - historyId: null, changesetStore: null, + // parameters for file history view + inline: false, + path: null, + revision: null, + changesetViewerTitleText: 'Commits {0}', initComponent: function(){ - this.historyId = Sonia.History.createToken([ - 'changesetviewer', - this.repository.id, - this.start, - this.pageSize - ]); + if (! this.url){ + this.url = restUrl + 'repositories/' + this.repository.id + '/changesets.json'; + } + + var params = { + start: this.start, + limit: this.pageSize + } + + var baseParams = {}; + + if (this.path){ + baseParams.path = this.path; + } + + if (this.revision){ + baseParams.revision = this.revision; + } this.changesetStore = new Sonia.rest.JsonStore({ id: 'changesetStore', proxy: new Ext.data.HttpProxy({ - url: restUrl + 'repositories/' + this.repository.id + '/changesets.json', + url: this.url, method: 'GET' }), fields: ['id', 'date', 'author', 'description', 'modifications', 'tags', 'branches', 'properties'], root: 'changesets', idProperty: 'id', totalProperty: 'total', - autoLoad: true, - autoDestroy: true, - baseParams: { - start: this.start, - limit: this.pageSize + baseParams: baseParams, + autoLoad: { + params: params }, + autoDestroy: true, listeners: { load: { fn: this.updateHistory, @@ -72,29 +87,39 @@ Sonia.repository.ChangesetViewerPanel = Ext.extend(Ext.Panel, { }); var config = { - title: String.format(this.changesetViewerTitleText, this.repository.name), items: [{ xtype: 'repositoryChangesetViewerGrid', repository: this.repository, store: this.changesetStore - }], - bbar: { + }] + }; + + if ( ! this.inline ){ + config.title = String.format(this.changesetViewerTitleText, this.repository.name) + config.bbar = { xtype: 'paging', store: this.changesetStore, displayInfo: true, pageSize: this.pageSize, prependButtons: true } - }; + } Ext.apply(this, Ext.apply(this.initialConfig, config)); Sonia.repository.ChangesetViewerPanel.superclass.initComponent.apply(this, arguments); }, updateHistory: function(store, records, options){ - var id = Sonia.History.appendWithDepth([options.params.start, options.params.limit], 2); - if (id){ - this.historyId = id; + if ( ! this.inline && options && options.params ){ + this.start = options.params.start; + this.pageSize = options.params.limit; + var token = Sonia.History.createToken( + 'repositoryChangesetViewerPanel', + this.repository.id, + this.start, + this.pageSize + ); + Sonia.History.add(token); } }, @@ -111,36 +136,41 @@ Sonia.repository.ChangesetViewerPanel = Ext.extend(Ext.Panel, { Ext.reg('repositoryChangesetViewerPanel', Sonia.repository.ChangesetViewerPanel); // register history handler -Sonia.History.register('changesetviewer', function(params){ +Sonia.History.register('repositoryChangesetViewerPanel', { - if (params){ - - var id = params[0] + '-changesetViewer'; - var start = Sonia.util.parseInt(params[1], 0); - var pageSize = Sonia.util.parseInt(params[2], 20); - - if (debug){ - console.debug('load changesetviewer for ' + id + ', ' + start + ', ' + pageSize ); + onActivate: function(panel){ + return Sonia.History.createToken( + 'repositoryChangesetViewerPanel', + panel.repository.id, + panel.start, + panel.pageSize + ); + }, + + onChange: function(repoId, start, limit){ + if (start){ + start = parseInt(start); } - - var tab = Ext.getCmp(id); - - if ( tab ){ - main.getMainTabPanel().setActiveTab(id); - tab.loadChangesets(start, pageSize); - } else { - Sonia.repository.get(params[0], function(repository){ - main.addTab({ - id: repository.id + '-changesetViewer', + if (limit){ + limit = parseInt(limit); + } + var id = 'repositoryChangesetViewerPanel|' + repoId; + Sonia.repository.get(repoId, function(repository){ + var panel = Ext.getCmp(id); + if (! panel){ + panel = { + id: id, xtype: 'repositoryChangesetViewerPanel', - repository: repository, + repository : repository, start: start, - pageSize: pageSize, - closable: true - }) - }); - } - + pageSize: limit, + closable: true, + autoScroll: true + } + } else { + panel.loadChangesets(start, limit); + } + main.addTab(panel); + }); } - -}); +}); \ No newline at end of file diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.contentpanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.contentpanel.js index d83827cce6..50bbcd8473 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.contentpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.contentpanel.js @@ -35,6 +35,9 @@ Sonia.repository.ContentPanel = Ext.extend(Ext.Panel, { path: null, contentUrl: null, + // view content/blame/history + view: 'content', + initComponent: function(){ var name = Sonia.util.getName(this.path); this.contentUrl = Sonia.repository.createContentUrl( @@ -44,6 +47,19 @@ Sonia.repository.ContentPanel = Ext.extend(Ext.Panel, { var bottomBar = [this.path]; this.appendRepositoryProperties(bottomBar); + var panel = null; + + switch (this.view){ + case 'blame': + panel = this.createBlamePanel(); + break; + case 'history': + panel = this.createHistoryPanel(); + break; + default: + panel = this.createSyntaxPanel(); + } + var config = { title: name, tbar: [{ @@ -58,34 +74,89 @@ Sonia.repository.ContentPanel = Ext.extend(Ext.Panel, { text: 'Blame', handler: this.openBlamePanel, scope: this + },{ + text: 'History', + handler: this.openHistoryPanel, + scope: this }], bbar: bottomBar, - items: [{ - xtype: 'syntaxHighlighterPanel', - syntax: Sonia.util.getExtension(this.path), - contentUrl: this.contentUrl - }] + items: [panel] } Ext.apply(this, Ext.apply(this.initialConfig, config)); Sonia.repository.ContentPanel.superclass.initComponent.apply(this, arguments); }, - openSyntaxPanel: function(){ - this.openPanel({ + loadPanel: function(view){ + switch (view){ + case 'blame': + this.openBlamePanel(); + break; + case 'history': + this.openHistoryPanel(); + break; + default: + this.openSyntaxPanel(); + } + + }, + + createHistoryPanel: function(){ + return { + xtype: 'repositoryChangesetViewerPanel', + repository: this.repository, + revision: this.revision, + path: this.path, + inline: true, + // TODO find a better way + pageSize: 9999 + } + }, + + openHistoryPanel: function(){ + this.openPanel(this.createHistoryPanel()); + this.view = 'history'; + this.updateHistory(); + }, + + createSyntaxPanel: function(){ + return { xtype: 'syntaxHighlighterPanel', syntax: Sonia.util.getExtension(this.path), contentUrl: this.contentUrl - }); + } }, - openBlamePanel: function(){ - this.openPanel({ + openSyntaxPanel: function(){ + this.openPanel(this.createSyntaxPanel()); + this.view = 'content'; + this.updateHistory(); + }, + + createBlamePanel: function(){ + return { xtype: 'blamePanel', repository: this.repository, revision: this.revision, path: this.path - }); + } + }, + + openBlamePanel: function(){ + this.openPanel(this.createBlamePanel()); + this.view = 'blame'; + this.updateHistory(); + }, + + updateHistory: function(){ + var token = Sonia.History.createToken( + 'contentPanel', + this.repository.id, + this.revision, + this.path, + this.view + ); + Sonia.History.add(token); }, downlaodFile: function(){ @@ -116,5 +187,47 @@ Sonia.repository.ContentPanel = Ext.extend(Ext.Panel, { }); +// register xtype +Ext.reg('contentPanel', Sonia.repository.ContentPanel); -Ext.reg('contentPanel', Sonia.repository.ContentPanel); \ No newline at end of file +// register history handler +Sonia.History.register('contentPanel', { + + onActivate: function(panel){ + return Sonia.History.createToken( + 'contentPanel', + panel.repository.id, + panel.revision, + panel.path, + panel.view + ); + }, + + onChange: function(repoId, revision, path, view){ + if (revision == 'null'){ + revision = null; + } + if (!view || view == 'null'){ + view = 'content'; + } + var id = 'contentPanel|' + repoId + '|' + revision + '|' + path; + Sonia.repository.get(repoId, function(repository){ + var panel = Ext.getCmp(id); + if (! panel){ + panel = { + id: id, + xtype: 'contentPanel', + repository : repository, + revision: revision, + path: path, + view: view, + closable: true, + autoScroll: true + } + } else { + panel.loadPanel(view); + } + main.addTab(panel); + }); + } +}); \ No newline at end of file diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.diffpanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.diffpanel.js index 8bef39d447..3393e43fa3 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.diffpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.diffpanel.js @@ -66,5 +66,35 @@ Sonia.repository.DiffPanel = Ext.extend(Ext.Panel, { }); +// register xtype +Ext.reg('diffPanel', Sonia.repository.DiffPanel); -Ext.reg('diffPanel', Sonia.repository.DiffPanel); \ No newline at end of file +// register history handler +Sonia.History.register('diffPanel', { + + onActivate: function(panel){ + return Sonia.History.createToken( + 'diffPanel', + panel.repository.id, + panel.revision + ); + }, + + onChange: function(repoId, revision){ + var id = 'diffPanel|' + repoId + '|' + revision; + Sonia.repository.get(repoId, function(repository){ + var panel = Ext.getCmp(id); + if (! panel){ + panel = { + id: id, + xtype: 'diffPanel', + repository : repository, + revision: revision, + closable: true, + autoScroll: true + } + } + main.addTab(panel); + }); + } +}); \ No newline at end of file diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.extendedinfopanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.extendedinfopanel.js index 399249817c..0edbd171e2 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.extendedinfopanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.extendedinfopanel.js @@ -95,7 +95,7 @@ Sonia.repository.ExtendedInfoPanel = Ext.extend(Sonia.repository.InfoPanel,{ createRepositoryBrowser: function(){ return { - id: 'repositorybrowser-' + this.item.id + ':_', + id: 'repositoryBrowser|' + this.item.id + '|null', xtype: 'repositoryBrowser', repository: this.item, closable: true diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js index 6bc75e1dd5..a3ca4a2883 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js @@ -44,6 +44,9 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { // TODO find better text mainGroup: 'main', + + // for history + parentPanel: null, initComponent: function(){ @@ -177,6 +180,10 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { Ext.apply(this, Ext.apply(this.initialConfig, config)); Sonia.repository.Grid.superclass.initComponent.apply(this, arguments); + + if (this.parentPanel){ + this.parentPanel.repositoryGrid = this; + } }, convertToGroup: function(v, data){ @@ -263,7 +270,9 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { console.debug( item.name + ' selected' ); } - Sonia.History.append(item.id); + if ( this.parentPanel ){ + this.parentPanel.updateHistory(item); + } var infoPanel = main.getInfoPanel(item.type); infoPanel.item = item; diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.infopanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.infopanel.js index d01def315a..f0d0024da8 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.infopanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.infopanel.js @@ -148,7 +148,7 @@ Sonia.repository.InfoPanel = Ext.extend(Ext.Panel, { createChangesetViewer: function(){ return { - id: this.item.id + '-changesetViewer', + id: 'repositoryChangesetViewerPanel|' + this.item.id, repository: this.item, xtype: 'repositoryChangesetViewerPanel', closable: true, diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.panel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.panel.js index e7c3fc8465..28be95d035 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.panel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.panel.js @@ -38,6 +38,8 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, { removeMsgText: 'Remove Repository "{0}"?', errorTitleText: 'Error', errorMsgText: 'Repository deletion failed', + + repositoryGrid: null, initComponent: function(){ @@ -126,41 +128,56 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, { var config = { tbar: toolbar, items: [{ - id: 'repositoryGrid', - xtype: 'repositoryGrid', - region: 'center' - }, { - id: 'repositoryEditPanel', - xtype: 'tabpanel', - activeTab: 0, - height: 250, - split: true, - border: true, - region: 'south', - items: [{ - bodyCssClass: 'x-panel-mc', - title: this.titleText, - padding: 5, - html: this.emptyText - }] - } - ] + id: 'repositoryGrid', + xtype: 'repositoryGrid', + region: 'center', + parentPanel: this + },{ + id: 'repositoryEditPanel', + xtype: 'tabpanel', + activeTab: 0, + height: 250, + split: true, + border: true, + region: 'south', + items: [{ + bodyCssClass: 'x-panel-mc', + title: this.titleText, + padding: 5, + html: this.emptyText + }] + }] } Ext.apply(this, Ext.apply(this.initialConfig, config)); Sonia.repository.Panel.superclass.initComponent.apply(this, arguments); }, + getGrid: function(){ + if ( ! this.repositoryGrid ){ + if ( debug ){ + console.debug('repository grid not found, retrive by cmp id'); + } + this.repositoryGrid = Ext.getCmp('repositoryGrid'); + } + return this.repositoryGrid; + }, + + updateHistory: function(item){ + var token = Sonia.History.createToken('repositoryPanel', item.id); + Sonia.History.add(token); + }, + filterByType: function(combo, rec){ - Ext.getCmp('repositoryGrid').filter(rec.get('name')); + this.getGrid().filter(rec.get('name')); }, search: function(field){ - Ext.getCmp('repositoryGrid').search(field.getValue()); + this.getGrid().search(field.getValue()); }, removeRepository: function(){ - var grid = Ext.getCmp('repositoryGrid'); + var grid = this.getGrid(); var selected = grid.getSelectionModel().getSelected(); if ( selected ){ var item = selected.data; @@ -227,7 +244,7 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, { }, repositoryCreated: function(item){ - var grid = Ext.getCmp('repositoryGrid'); + var grid = this.getGrid(); this.clearRepositoryFilter(grid); grid.reload(function(){ @@ -243,7 +260,7 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, { console.debug('clear repository filter'); } if (! grid ){ - grid = Ext.getCmp('repositoryGrid'); + grid = this.getGrid(); } Ext.getCmp('repositorySearch').setValue(''); Ext.getCmp('repositoryTypeFilter').setValue(''); @@ -251,10 +268,36 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, { }, reload: function(){ - Ext.getCmp('repositoryGrid').reload(); + this.getGrid().reload(); } }); // register xtype -Ext.reg('repositoryPanel', Sonia.repository.Panel); \ No newline at end of file +Ext.reg('repositoryPanel', Sonia.repository.Panel); + +// register history handler +Sonia.History.register('repositoryPanel', { + + onActivate: function(panel){ + var token = null; + var rec = panel.getGrid().getSelectionModel().getSelected(); + if (rec){ + token = Sonia.History.createToken('repositoryPanel', rec.get('id')); + } else { + token = Sonia.History.createToken('repositoryPanel'); + } + return token; + }, + + onChange: function(repoId){ + var panel = Ext.getCmp('repositories'); + if ( ! panel ){ + main.addRepositoriesTabPanel(); + panel = Ext.getCmp('repositories'); + } + if (repoId){ + panel.getGrid().selectById(repoId); + } + } +}); \ No newline at end of file diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.repositorybrowser.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.repositorybrowser.js index c9c504e666..91a099d1b4 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.repositorybrowser.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.repositorybrowser.js @@ -32,7 +32,6 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, { repository: null, revision: null, - historyId: null, path: null, repositoryBrowserTitleText: 'Source {0}', @@ -50,12 +49,6 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, { console.debug('create new browser for repository ' + this.repository.name + " and revision " + this.revision); } - this.historyId = Sonia.History.createToken([ - 'repositorybrowser', - this.repository.id, - this.revision ? this.revision : '_' - ]); - var browserStore = new Sonia.rest.JsonStore({ proxy: new Ext.data.HttpProxy({ url: restUrl + 'repositories/' + this.repository.id + '/browse.json', @@ -174,22 +167,6 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, { length: 0 })); } - - var historyParams = []; - if ( this.revision ){ - historyParams.push(this.revision) - } else { - historyParams.push('_'); - } - - if ( extra.params.path ){ - historyParams.push(extra.params.path); - } - - var id = Sonia.History.appendWithDepth(historyParams, 2); - if (id){ - this.historyId = id; - } }, onClick: function(e){ @@ -252,9 +229,22 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, { } }); + this.path = path; + this.updateHistory(); + this.renderClickPath(path); }, + updateHistory: function(){ + var token = Sonia.History.createToken( + 'repositoryBrowser', + this.repository.id, + this.revision, + this.path + ); + Sonia.History.add(token); + }, + createFolderButton: function(path, name){ return { xtype: 'button', @@ -319,40 +309,45 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, { // register xtype Ext.reg('repositoryBrowser', Sonia.repository.RepositoryBrowser); + // register history handler -Sonia.History.register('repositorybrowser', function(params){ +Sonia.History.register('repositoryBrowser', { - if (params){ - - var id = 'repositorybrowser-' + params[0] + ':'; - var revision = params[1]; - id += revision; - var path = params[2] ? params[2] : ''; - - if ( revision == '_' ){ + onActivate: function(panel){ + return Sonia.History.createToken( + 'repositoryBrowser', + panel.repository.id, + panel.revision, + panel.path + ); + }, + + onChange: function(repoId, revision, path){ + if (revision == 'null'){ revision = null; } - - if (debug){ - console.debug('load repositorybrowser for ' + id + ', ' + revision + ', ' + path ); + if (path == 'null'){ + path = ''; } - - var tab = Ext.getCmp(id); - - if ( tab ){ - main.getMainTabPanel().setActiveTab(id); - tab.changeDirectory(path); - } else { - Sonia.repository.get(params[0], function(repository){ - main.addTab({ + var id = 'repositoryBrowser|' + repoId + "|" + revision; + Sonia.repository.get(repoId, function(repository){ + var panel = Ext.getCmp(id); + if (! panel){ + panel = { id: id, xtype: 'repositoryBrowser', - repository: repository, + repository : repository, revision: revision, - path: path, - closable: true - }) - }); - } + closable: true, + autoScroll: true + } + if (path){ + panel.path = path; + } + } else { + panel.changeDirectory(path); + } + main.addTab(panel); + }); } }); \ No newline at end of file diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.history.js b/scm-webapp/src/main/webapp/resources/js/sonia.history.js index 731b5fed37..a7b7dc1cd6 100644 --- a/scm-webapp/src/main/webapp/resources/js/sonia.history.js +++ b/scm-webapp/src/main/webapp/resources/js/sonia.history.js @@ -51,16 +51,14 @@ Sonia.History = { } }, - createToken: function(elements){ + createToken: function(){ var token = ''; - if (Ext.isArray(elements)){ - for (var i=0; i() + { + @Override + public boolean accept(String item) + { + return item.startsWith("test"); + } + }); + assertNull(cache.get("test-1")); + assertNull(cache.get("test-2")); + assertNotNull(cache.get("a-1")); + assertNotNull(cache.get("a-2")); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Cache cache; + + /** Field description */ + private CacheManager cm; +}