From c9ff3d5495b0229d837fa0ec23486cc7b6b191d0 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Fri, 28 Dec 2012 13:13:14 +0100 Subject: o Listing builds on the person view. --- .../io/trygvis/esper/testing/core/db/BuildDao.java | 31 +- .../esper/testing/util/sql/PageRequest.java | 4 + .../esper/testing/web/AbstractResource.java | 26 - .../io/trygvis/esper/testing/web/CoreResource.java | 132 - .../trygvis/esper/testing/web/JenkinsResource.java | 86 - .../esper/testing/web/JerseyApplication.java | 78 +- .../io/trygvis/esper/testing/web/MagicParam.java | 10 + .../testing/web/resource/AbstractResource.java | 26 + .../esper/testing/web/resource/BadgeJson.java | 21 + .../esper/testing/web/resource/CoreResource.java | 143 + .../testing/web/resource/JenkinsResource.java | 86 + .../esper/testing/web/resource/PersonJson.java | 17 + .../webapp/WEB-INF/tags/common/head-element.tagx | 36 - src/main/webapp/WEB-INF/tags/common/head.tagx | 36 + src/main/webapp/apps/core/CoreResources.js | 17 + src/main/webapp/apps/core/PersonService.js | 9 - src/main/webapp/apps/frontPageApp/frontPageApp.js | 21 +- src/main/webapp/apps/personApp/person.html | 7 + src/main/webapp/apps/personApp/personApp.js | 10 +- .../ng-grid-1.6.0/ng-grid-1.6.0.debug.js | 2393 +++++ .../angular-ui/ng-grid-1.6.0/ng-grid-1.6.0.js | 133 + .../external/angular-ui/ng-grid-1.6.0/ng-grid.css | 456 + .../webapp/external/jquery-1.8.3/jquery-1.8.3.js | 9472 ++++++++++++++++++++ .../external/jquery-1.8.3/jquery-1.8.3.min.js | 2 + src/main/webapp/idea.js | 2 +- src/main/webapp/index.jspx | 6 +- src/main/webapp/jenkins/index.jspx | 4 +- src/main/webapp/login.jspx | 2 +- src/main/webapp/person/person.jspx | 6 +- src/main/webapp/shiro.jspx | 2 +- src/test/resources/jenkins/build/matrixRun-2.xml | 54 + 31 files changed, 13013 insertions(+), 315 deletions(-) delete mode 100644 src/main/java/io/trygvis/esper/testing/web/AbstractResource.java delete mode 100644 src/main/java/io/trygvis/esper/testing/web/CoreResource.java delete mode 100644 src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java create mode 100644 src/main/java/io/trygvis/esper/testing/web/MagicParam.java create mode 100644 src/main/java/io/trygvis/esper/testing/web/resource/AbstractResource.java create mode 100644 src/main/java/io/trygvis/esper/testing/web/resource/BadgeJson.java create mode 100644 src/main/java/io/trygvis/esper/testing/web/resource/CoreResource.java create mode 100644 src/main/java/io/trygvis/esper/testing/web/resource/JenkinsResource.java create mode 100644 src/main/java/io/trygvis/esper/testing/web/resource/PersonJson.java delete mode 100644 src/main/webapp/WEB-INF/tags/common/head-element.tagx create mode 100644 src/main/webapp/WEB-INF/tags/common/head.tagx create mode 100644 src/main/webapp/apps/core/CoreResources.js delete mode 100644 src/main/webapp/apps/core/PersonService.js create mode 100644 src/main/webapp/external/angular-ui/ng-grid-1.6.0/ng-grid-1.6.0.debug.js create mode 100644 src/main/webapp/external/angular-ui/ng-grid-1.6.0/ng-grid-1.6.0.js create mode 100644 src/main/webapp/external/angular-ui/ng-grid-1.6.0/ng-grid.css create mode 100644 src/main/webapp/external/jquery-1.8.3/jquery-1.8.3.js create mode 100644 src/main/webapp/external/jquery-1.8.3/jquery-1.8.3.min.js create mode 100644 src/test/resources/jenkins/build/matrixRun-2.xml diff --git a/src/main/java/io/trygvis/esper/testing/core/db/BuildDao.java b/src/main/java/io/trygvis/esper/testing/core/db/BuildDao.java index 24ecfd3..e498017 100644 --- a/src/main/java/io/trygvis/esper/testing/core/db/BuildDao.java +++ b/src/main/java/io/trygvis/esper/testing/core/db/BuildDao.java @@ -7,7 +7,9 @@ import org.joda.time.*; import java.sql.*; import java.util.*; +import static io.trygvis.esper.testing.Util.toList; import static io.trygvis.esper.testing.util.sql.ResultSetF.*; +import static io.trygvis.esper.testing.util.sql.SqlOption.fromRs; import static java.lang.System.*; public class BuildDao { @@ -59,7 +61,34 @@ public class BuildDao { try (PreparedStatement s = c.prepareStatement("SELECT person FROM build_participant WHERE build=?")) { int i = 1; s.setString(i, build.toString()); - return Util.toList(s, getUuid); + return toList(s, getUuid); + } + } + + public SqlOption selectBuild(UUID uuid) throws SQLException { + try (PreparedStatement s = c.prepareStatement("SELECT " + BUILD + " FROM build WHERE uuid=?")) { + int i = 1; + s.setString(i, uuid.toString()); + return fromRs(s.executeQuery()).map(build); + } + } + + public List selectBuildsByPerson(UUID person, PageRequest page) throws SQLException { + try (PreparedStatement s = c.prepareStatement("SELECT " + BUILD + " FROM build b, build_participant bp WHERE bp.person=? AND b.uuid = bp.build ORDER BY created_date LIMIT ? OFFSET ?")) { + int i = 1; + s.setString(i++, person.toString()); + s.setInt(i++, page.count.orSome(10)); + s.setInt(i, page.startIndex.orSome(0)); + return toList(s, build); + } + } + + public List selectBuilds(PageRequest page) throws SQLException { + try (PreparedStatement s = c.prepareStatement("SELECT " + BUILD + " FROM build ORDER BY created_date LIMIT ? OFFSET ?")) { + int i = 1; + s.setInt(i++, page.count.orSome(10)); + s.setInt(i, page.startIndex.orSome(0)); + return toList(s, build); } } } diff --git a/src/main/java/io/trygvis/esper/testing/util/sql/PageRequest.java b/src/main/java/io/trygvis/esper/testing/util/sql/PageRequest.java index 91a00f8..824291c 100644 --- a/src/main/java/io/trygvis/esper/testing/util/sql/PageRequest.java +++ b/src/main/java/io/trygvis/esper/testing/util/sql/PageRequest.java @@ -15,6 +15,10 @@ public class PageRequest { this.count = count; } + public String toString() { + return "PageRequest{startIndex=" + startIndex + ", count=" + count + '}'; + } + public static PageRequest pageReq(HttpServletRequest req) { return new PageRequest( fromNull(req.getParameter("startIndex")).bind(Util.parseInt), diff --git a/src/main/java/io/trygvis/esper/testing/web/AbstractResource.java b/src/main/java/io/trygvis/esper/testing/web/AbstractResource.java deleted file mode 100644 index c811a2f..0000000 --- a/src/main/java/io/trygvis/esper/testing/web/AbstractResource.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.trygvis.esper.testing.web; - -import fj.data.*; -import io.trygvis.esper.testing.*; - -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import java.sql.*; - -public class AbstractResource { - protected final DatabaseAccess da; - - public AbstractResource(DatabaseAccess da) { - this.da = da; - } - - public T get(DatabaseAccess.DaosCallback> callback) throws SQLException { - Option server = da.inTransaction(callback); - - if(server.isNone()) { - throw new WebApplicationException(Response.Status.NOT_FOUND); - } - - return server.some(); - } -} diff --git a/src/main/java/io/trygvis/esper/testing/web/CoreResource.java b/src/main/java/io/trygvis/esper/testing/web/CoreResource.java deleted file mode 100644 index f2fb12a..0000000 --- a/src/main/java/io/trygvis/esper/testing/web/CoreResource.java +++ /dev/null @@ -1,132 +0,0 @@ -package io.trygvis.esper.testing.web; - -import fj.data.*; -import io.trygvis.esper.testing.*; -import io.trygvis.esper.testing.core.badge.*; -import io.trygvis.esper.testing.core.db.*; -import io.trygvis.esper.testing.util.sql.*; - -import javax.servlet.http.*; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import java.sql.*; -import java.util.*; -import java.util.List; - -import static io.trygvis.esper.testing.util.sql.PageRequest.*; -import static io.trygvis.esper.testing.web.JenkinsResource.*; - -@Path("/resource/core") -@Produces(MediaType.APPLICATION_JSON) -public class CoreResource extends AbstractResource { - - private final BadgeService badgeService; - - public CoreResource(DatabaseAccess da, BadgeService badgeService) { - super(da); - this.badgeService = badgeService; - } - - @GET - @Path("/person") - public List getPersons(@Context final HttpServletRequest req) throws Exception { - final PageRequest pageRequest = pageReq(req); - - return da.inTransaction(new DatabaseAccess.DaosCallback>() { - public List run(Daos daos) throws SQLException { - List list = new ArrayList<>(); - for (PersonDto person : daos.personDao.selectPerson(pageRequest)) { - list.add(getPersonJson(daos, person)); - } - return list; - } - }); - } - - /** - * This is wrong, but Angular's $resource is a bit dumb. - */ - @GET - @Path("/person-count") - public int getPersonCount() throws Exception { - return da.inTransaction(new DatabaseAccess.DaosCallback() { - public Integer run(Daos daos) throws SQLException { - return daos.personDao.selectPersonCount(); - } - }); - } - - @GET - @Path("/person/{uuid}") - public PersonJson getPerson(@PathParam("uuid") final String s) throws Exception { - final UUID uuid = parseUuid(s); - - return get(new DatabaseAccess.DaosCallback>() { - public Option run(Daos daos) throws SQLException { - SqlOption o = daos.personDao.selectPerson(uuid); - if (o.isNone()) { - return Option.none(); - } - - return Option.some(getPersonJson(daos, o.get())); - } - }); - } - - private PersonJson getPersonJson(Daos daos, PersonDto person) throws SQLException { - List badges = new ArrayList<>(); - - for (PersonBadgeDto badge : daos.personDao.selectBadges(person.uuid)) { - badges.add(new BadgeJson(badge.type.name(), badge.level, badge.count, 100, 100)); - } - - List badgesInProgress = new ArrayList<>(); - - for (PersonBadgeProgressDto badgeProgressDto : daos.personDao.selectBadgeProgresses(person.uuid)) { - UnbreakableBadgeProgress progress = badgeService.unbreakable(badgeProgressDto); - badgesInProgress.add(new BadgeJson(progress.type.name(), progress.progressingAgainstLevel(), 0, - progress.progression(), progress.goal())); - } - - return new PersonJson( - person.uuid, - person.name, - badges, - badgesInProgress - ); - } - - public static class PersonJson { - public final UUID uuid; - public final String name; - public final List badges; - public final List badgesInProgress; - - public PersonJson(UUID uuid, String name, List badges, List badgesInProgress) { - this.uuid = uuid; - this.name = name; - this.badges = badges; - this.badgesInProgress = badgesInProgress; - } - } - - public static class BadgeJson { - public final String name; - public final int level; - - /** - * Number of times this badge has been received. - */ - public final int count; - public final int progress; - public final int goal; - - public BadgeJson(String name, int level, int count, int progress, int goal) { - this.name = name; - this.level = level; - this.count = count; - this.progress = progress; - this.goal = goal; - } - } -} diff --git a/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java b/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java deleted file mode 100644 index bd925b6..0000000 --- a/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java +++ /dev/null @@ -1,86 +0,0 @@ -package io.trygvis.esper.testing.web; - -import fj.data.*; -import io.trygvis.esper.testing.*; -import io.trygvis.esper.testing.jenkins.*; -import org.joda.time.*; - -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import java.net.*; -import java.sql.*; -import java.util.*; -import java.util.List; - -import static fj.data.Option.*; - -@Path("/resource/jenkins") -public class JenkinsResource extends AbstractResource { - - public JenkinsResource(DatabaseAccess da) { - super(da); - } - - @GET - @Path("/server") - @Produces(MediaType.APPLICATION_JSON) - public List getServers() throws Exception { - return da.inTransaction(new DatabaseAccess.DaosCallback>() { - public List run(Daos daos) throws SQLException { - List list = new ArrayList<>(); - for (JenkinsServerDto server : daos.jenkinsDao.selectServers(false)) { - list.add(getJenkinsServerJson(daos, server)); - } - return list; - } - }); - } - - @GET - @Path("/server/{uuid}") - @Produces(MediaType.APPLICATION_JSON) - public JenkinsServerJson getServer(@PathParam("uuid") String s) throws Exception { - final UUID uuid = parseUuid(s); - - return get(new DatabaseAccess.DaosCallback>() { - public Option run(final Daos daos) throws SQLException { - Option o = daos.jenkinsDao.selectServer(uuid); - - if (o.isNone()) { - return Option.none(); - } - - return some(getJenkinsServerJson(daos, o.some())); - } - }); - } - - private JenkinsServerJson getJenkinsServerJson(Daos daos, JenkinsServerDto server) throws SQLException { - int count = daos.jenkinsDao.selectJobCountForServer(server.uuid); - return new JenkinsServerJson(server.uuid, server.createdDate, server.url, server.enabled, count); - } - - public static UUID parseUuid(String s) { - try { - return UUID.fromString(s); - } catch (IllegalArgumentException e) { - throw new WebApplicationException(Response.Status.BAD_REQUEST); - } - } -} - -class JenkinsServerJson { - public final UUID uuid; - public final DateTime createdDate; - public final URI url; - public final boolean enabled; - public final int jobCount; - - JenkinsServerJson(UUID uuid, DateTime createdDate, URI url, boolean enabled, int jobCount) { - this.uuid = uuid; - this.createdDate = createdDate; - this.url = url; - this.enabled = enabled; - this.jobCount = jobCount; - } -} diff --git a/src/main/java/io/trygvis/esper/testing/web/JerseyApplication.java b/src/main/java/io/trygvis/esper/testing/web/JerseyApplication.java index eded64c..46964a0 100644 --- a/src/main/java/io/trygvis/esper/testing/web/JerseyApplication.java +++ b/src/main/java/io/trygvis/esper/testing/web/JerseyApplication.java @@ -1,11 +1,23 @@ package io.trygvis.esper.testing.web; +import com.sun.jersey.api.core.*; +import com.sun.jersey.core.spi.component.*; +import com.sun.jersey.server.impl.inject.*; +import com.sun.jersey.spi.inject.*; import io.trygvis.esper.testing.*; import io.trygvis.esper.testing.core.badge.*; +import io.trygvis.esper.testing.util.sql.*; +import io.trygvis.esper.testing.web.resource.*; +import javax.ws.rs.*; import javax.ws.rs.core.*; +import javax.ws.rs.ext.*; +import java.lang.reflect.*; import java.util.*; +import static fj.data.Option.*; +import static io.trygvis.esper.testing.Util.parseInt; + public class JerseyApplication extends Application { private final HashSet singletons; @@ -16,12 +28,74 @@ public class JerseyApplication extends Application { BadgeService badgeService = new BadgeService(); singletons = new HashSet(Arrays.asList( - new CoreResource(da, badgeService), - new JenkinsResource(da) + new CoreResource(da, badgeService), + new JenkinsResource(da) )); } + public Set> getClasses() { + return new HashSet<>(Arrays.>asList(ResourceParamInjector.class)); + } + public Set getSingletons() { return singletons; } + + @Provider + public static class ResourceParamInjector implements InjectableProvider { + + private final ResourceContext rc; + + public ResourceParamInjector(@Context ResourceContext rc) { + this.rc = rc; + } + + public ComponentScope getScope() { + return ComponentScope.PerRequest; + } + + public Injectable getInjectable(final ComponentContext ic, final MagicParam a, Type type) { + if (PageRequest.class.equals(type)) { + return new AbstractHttpContextInjectable() { + public Object getValue(HttpContext hc) { + MultivaluedMap queryParameters = hc.getRequest().getQueryParameters(); + + return new PageRequest( + fromNull(queryParameters.getFirst("startIndex")).bind(parseInt), + fromNull(queryParameters.getFirst("count")).bind(parseInt)); + } + }; + } else if (UUID.class.equals(type)) { + + return new AbstractHttpContextInjectable() { + public Object getValue(HttpContext hc) { + + if (a.query().length() > 0) { + return parse(hc.getRequest().getQueryParameters().getFirst(a.query())); + } else { + MultivaluedMap pathParameters = hc.getUriInfo().getPathParameters(); + + for (Map.Entry> entry : pathParameters.entrySet()) { + if ("uuid".equals(entry.getKey())) { + return parse(entry.getValue().get(0)); + } + } + } + + throw new RuntimeException("@MagicParam used with UUID argument with no {uuid} path variable."); + } + + private UUID parse(String s) { + try { + return UUID.fromString(s); + } catch (IllegalArgumentException e) { + throw new WebApplicationException(400); + } + } + }; + } + + return null; + } + } } diff --git a/src/main/java/io/trygvis/esper/testing/web/MagicParam.java b/src/main/java/io/trygvis/esper/testing/web/MagicParam.java new file mode 100644 index 0000000..1eb3bb0 --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/web/MagicParam.java @@ -0,0 +1,10 @@ +package io.trygvis.esper.testing.web; + +import java.lang.annotation.*; + +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface MagicParam { + String query() default ""; +} diff --git a/src/main/java/io/trygvis/esper/testing/web/resource/AbstractResource.java b/src/main/java/io/trygvis/esper/testing/web/resource/AbstractResource.java new file mode 100644 index 0000000..cddec2c --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/web/resource/AbstractResource.java @@ -0,0 +1,26 @@ +package io.trygvis.esper.testing.web.resource; + +import fj.data.*; +import io.trygvis.esper.testing.*; + +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import java.sql.*; + +public class AbstractResource { + protected final DatabaseAccess da; + + public AbstractResource(DatabaseAccess da) { + this.da = da; + } + + public T get(DatabaseAccess.DaosCallback> callback) throws SQLException { + Option server = da.inTransaction(callback); + + if(server.isNone()) { + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + + return server.some(); + } +} diff --git a/src/main/java/io/trygvis/esper/testing/web/resource/BadgeJson.java b/src/main/java/io/trygvis/esper/testing/web/resource/BadgeJson.java new file mode 100644 index 0000000..65f541a --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/web/resource/BadgeJson.java @@ -0,0 +1,21 @@ +package io.trygvis.esper.testing.web.resource; + +public class BadgeJson { + public final String name; + public final int level; + + /** + * Number of times this badge has been received. + */ + public final int count; + public final int progress; + public final int goal; + + public BadgeJson(String name, int level, int count, int progress, int goal) { + this.name = name; + this.level = level; + this.count = count; + this.progress = progress; + this.goal = goal; + } +} diff --git a/src/main/java/io/trygvis/esper/testing/web/resource/CoreResource.java b/src/main/java/io/trygvis/esper/testing/web/resource/CoreResource.java new file mode 100644 index 0000000..98b32bb --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/web/resource/CoreResource.java @@ -0,0 +1,143 @@ +package io.trygvis.esper.testing.web.resource; + +import fj.data.*; +import io.trygvis.esper.testing.*; +import io.trygvis.esper.testing.core.badge.*; +import io.trygvis.esper.testing.core.db.*; +import io.trygvis.esper.testing.util.sql.*; +import io.trygvis.esper.testing.web.*; + +import javax.servlet.http.*; +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import java.sql.*; +import java.util.*; +import java.util.List; + +import static io.trygvis.esper.testing.util.sql.PageRequest.*; + +@Path("/resource/core") +@Produces(MediaType.APPLICATION_JSON) +public class CoreResource extends AbstractResource { + + private final BadgeService badgeService; + + public CoreResource(DatabaseAccess da, BadgeService badgeService) { + super(da); + this.badgeService = badgeService; + } + + // ----------------------------------------------------------------------- + // Person + // ----------------------------------------------------------------------- + + @GET + @Path("/person") + public List getPersons(@Context final HttpServletRequest req) throws Exception { + final PageRequest pageRequest = pageReq(req); + + return da.inTransaction(new DatabaseAccess.DaosCallback>() { + public List run(Daos daos) throws SQLException { + List list = new ArrayList<>(); + for (PersonDto person : daos.personDao.selectPerson(pageRequest)) { + list.add(getPersonJson(daos, person)); + } + return list; + } + }); + } + + @GET + @Path("/person/{uuid}") + public PersonJson getPerson(@PathParam("uuid") final String s) throws Exception { + final UUID uuid = JenkinsResource.parseUuid(s); + + return get(new DatabaseAccess.DaosCallback>() { + public Option run(Daos daos) throws SQLException { + SqlOption o = daos.personDao.selectPerson(uuid); + if (o.isNone()) { + return Option.none(); + } + + return Option.some(getPersonJson(daos, o.get())); + } + }); + } + + private PersonJson getPersonJson(Daos daos, PersonDto person) throws SQLException { + List badges = new ArrayList<>(); + + for (PersonBadgeDto badge : daos.personDao.selectBadges(person.uuid)) { + badges.add(new BadgeJson(badge.type.name(), badge.level, badge.count, 100, 100)); + } + + List badgesInProgress = new ArrayList<>(); + + for (PersonBadgeProgressDto badgeProgressDto : daos.personDao.selectBadgeProgresses(person.uuid)) { + UnbreakableBadgeProgress progress = badgeService.unbreakable(badgeProgressDto); + badgesInProgress.add(new BadgeJson(progress.type.name(), progress.progressingAgainstLevel(), 0, + progress.progression(), progress.goal())); + } + + return new PersonJson( + person.uuid, + person.name, + badges, + badgesInProgress + ); + } + + // ----------------------------------------------------------------------- + // Build + // ----------------------------------------------------------------------- + + @GET + @Path("/build") + public List getBuilds(@MagicParam final PageRequest page, @MagicParam(query = "person") final UUID person) throws Exception { + return da.inTransaction(new DatabaseAccess.DaosCallback>() { + public List run(Daos daos) throws SQLException { + List buildDtos; + + if(person != null) { + buildDtos = daos.buildDao.selectBuildsByPerson(person, page); + } + else { + buildDtos = daos.buildDao.selectBuilds(page); + } + + List list = new ArrayList<>(); + for (BuildDto build : buildDtos) { + list.add(getBuildJson(daos, build)); + } + return list; + } + }); + } + + @GET + @Path("/build/{uuid}") + public BuildJson getBuild(@MagicParam final UUID uuid) throws Exception { + return get(new DatabaseAccess.DaosCallback>() { + public Option run(Daos daos) throws SQLException { + SqlOption o = daos.buildDao.selectBuild(uuid); + if (o.isNone()) { + return Option.none(); + } + + return Option.some(getBuildJson(daos, o.get())); + } + }); + } + + private BuildJson getBuildJson(Daos daos, BuildDto build) { + return new BuildJson(build.uuid); + } + + public static class BuildJson { + public final UUID uuid; + + public BuildJson(UUID uuid) { + this.uuid = uuid; + } + } +} diff --git a/src/main/java/io/trygvis/esper/testing/web/resource/JenkinsResource.java b/src/main/java/io/trygvis/esper/testing/web/resource/JenkinsResource.java new file mode 100644 index 0000000..284d90e --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/web/resource/JenkinsResource.java @@ -0,0 +1,86 @@ +package io.trygvis.esper.testing.web.resource; + +import fj.data.*; +import io.trygvis.esper.testing.*; +import io.trygvis.esper.testing.jenkins.*; +import org.joda.time.*; + +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import java.net.*; +import java.sql.*; +import java.util.*; +import java.util.List; + +import static fj.data.Option.*; + +@Path("/resource/jenkins") +public class JenkinsResource extends AbstractResource { + + public JenkinsResource(DatabaseAccess da) { + super(da); + } + + @GET + @Path("/server") + @Produces(MediaType.APPLICATION_JSON) + public List getServers() throws Exception { + return da.inTransaction(new DatabaseAccess.DaosCallback>() { + public List run(Daos daos) throws SQLException { + List list = new ArrayList<>(); + for (JenkinsServerDto server : daos.jenkinsDao.selectServers(false)) { + list.add(getJenkinsServerJson(daos, server)); + } + return list; + } + }); + } + + @GET + @Path("/server/{uuid}") + @Produces(MediaType.APPLICATION_JSON) + public JenkinsServerJson getServer(@PathParam("uuid") String s) throws Exception { + final UUID uuid = parseUuid(s); + + return get(new DatabaseAccess.DaosCallback>() { + public Option run(final Daos daos) throws SQLException { + Option o = daos.jenkinsDao.selectServer(uuid); + + if (o.isNone()) { + return Option.none(); + } + + return some(getJenkinsServerJson(daos, o.some())); + } + }); + } + + private JenkinsServerJson getJenkinsServerJson(Daos daos, JenkinsServerDto server) throws SQLException { + int count = daos.jenkinsDao.selectJobCountForServer(server.uuid); + return new JenkinsServerJson(server.uuid, server.createdDate, server.url, server.enabled, count); + } + + public static UUID parseUuid(String s) { + try { + return UUID.fromString(s); + } catch (IllegalArgumentException e) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + } +} + +class JenkinsServerJson { + public final UUID uuid; + public final DateTime createdDate; + public final URI url; + public final boolean enabled; + public final int jobCount; + + JenkinsServerJson(UUID uuid, DateTime createdDate, URI url, boolean enabled, int jobCount) { + this.uuid = uuid; + this.createdDate = createdDate; + this.url = url; + this.enabled = enabled; + this.jobCount = jobCount; + } +} diff --git a/src/main/java/io/trygvis/esper/testing/web/resource/PersonJson.java b/src/main/java/io/trygvis/esper/testing/web/resource/PersonJson.java new file mode 100644 index 0000000..e8008e3 --- /dev/null +++ b/src/main/java/io/trygvis/esper/testing/web/resource/PersonJson.java @@ -0,0 +1,17 @@ +package io.trygvis.esper.testing.web.resource; + +import java.util.*; + +public class PersonJson { + public final UUID uuid; + public final String name; + public final List badges; + public final List badgesInProgress; + + public PersonJson(UUID uuid, String name, List badges, List badgesInProgress) { + this.uuid = uuid; + this.name = name; + this.badges = badges; + this.badgesInProgress = badgesInProgress; + } +} diff --git a/src/main/webapp/WEB-INF/tags/common/head-element.tagx b/src/main/webapp/WEB-INF/tags/common/head-element.tagx deleted file mode 100644 index bb8804c..0000000 --- a/src/main/webapp/WEB-INF/tags/common/head-element.tagx +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - <c:if test="${not empty title }">${title } - </c:if>Yeah - - - - - - - - - - - - - - - diff --git a/src/main/webapp/WEB-INF/tags/common/head.tagx b/src/main/webapp/WEB-INF/tags/common/head.tagx new file mode 100644 index 0000000..2384b20 --- /dev/null +++ b/src/main/webapp/WEB-INF/tags/common/head.tagx @@ -0,0 +1,36 @@ + + + + + + + + + <c:if test="${not empty title }">${title } - </c:if>Yeah + + + + + + + + + + + + + + + diff --git a/src/main/webapp/apps/core/CoreResources.js b/src/main/webapp/apps/core/CoreResources.js new file mode 100644 index 0000000..96d4b24 --- /dev/null +++ b/src/main/webapp/apps/core/CoreResources.js @@ -0,0 +1,17 @@ +'use strict'; + +function Person($resource) { + return $resource('/resource/core/person/:uuid', {uuid: '@uuid'}); +} + +angular. + module('person', ['ngResource']). + factory('Person', Person); + +function Build($resource) { + return $resource('/resource/core/build/:uuid', {uuid: '@uuid'}); +} + +angular. + module('build', ['ngResource']). + factory('Build', Build); diff --git a/src/main/webapp/apps/core/PersonService.js b/src/main/webapp/apps/core/PersonService.js deleted file mode 100644 index 75265a8..0000000 --- a/src/main/webapp/apps/core/PersonService.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -function PersonService($resource) { - return $resource('/resource/core/person/:uuid', {uuid: '@uuid'}); -} - -angular. - module('personService', ['ngResource']). - factory('PersonService', PersonService); diff --git a/src/main/webapp/apps/frontPageApp/frontPageApp.js b/src/main/webapp/apps/frontPageApp/frontPageApp.js index d92a163..c4fa0cc 100644 --- a/src/main/webapp/apps/frontPageApp/frontPageApp.js +++ b/src/main/webapp/apps/frontPageApp/frontPageApp.js @@ -1,11 +1,11 @@ 'use strict'; -var frontPageApp = angular.module('frontPageApp', ['ngGrid', 'personService']).config(function ($routeProvider, $locationProvider) { +var frontPageApp = angular.module('frontPageApp', ['ngGrid', 'person']).config(function ($routeProvider, $locationProvider) { $routeProvider. when('/', {controller: FrontPageCtrl, templateUrl: '/apps/frontPageApp/frontPage.html?noCache=' + noCache}); }); -function FrontPageCtrl($scope, $http, PersonService) { +function FrontPageCtrl($scope, $http, Person) { $scope.persons = []; $scope.pagingOptions = { @@ -19,6 +19,8 @@ function FrontPageCtrl($scope, $http, PersonService) { data: 'persons', displayFooter: true, enablePaging: true, + enableRowReordering: false, + enableColumnReordering: false, showFilter: false, showColumnMenu: false, canSelectRows: false, @@ -41,7 +43,8 @@ function FrontPageCtrl($scope, $http, PersonService) { $scope.setPagingData = function(data, page, pageSize){ // $scope.persons = data.slice((page - 1) * pageSize, page * pageSize); $scope.persons = data; - $scope.personsGridOptions.totalServerItems = data.length; +// $scope.personsGridOptions.totalServerItems = data.length; + window.x = $scope.personsGridOptions; if (!$scope.$$phase) { $scope.$apply(); } @@ -50,7 +53,7 @@ function FrontPageCtrl($scope, $http, PersonService) { $scope.getPagedDataAsync = function (pageSize, page/*, searchText*/) { setTimeout(function () { - PersonService.query({startIndex: page * pageSize, count: pageSize}, function (persons) { + Person.query({startIndex: page * pageSize, count: pageSize}, function (persons) { $scope.setPagingData(persons, page, pageSize); }); }, 100); @@ -60,9 +63,9 @@ function FrontPageCtrl($scope, $http, PersonService) { $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage); }, true); - $http.get('/resource/core/person-count').success(function(count) { - $scope.pagingOptions.totalServerItems = count; - - $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage); - }); +// $http.get('/resource/core/person-count').success(function(count) { +// $scope.pagingOptions.totalServerItems = count; +// +// $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage); +// }); } diff --git a/src/main/webapp/apps/personApp/person.html b/src/main/webapp/apps/personApp/person.html index 4189f20..2c0c3e7 100644 --- a/src/main/webapp/apps/personApp/person.html +++ b/src/main/webapp/apps/personApp/person.html @@ -14,4 +14,11 @@ {{badge.name}} progress: {{badge.progress}} of {{badge.goal}}

+

Builds

+
    +
  • + {{build.uuid}} +
  • +
+ diff --git a/src/main/webapp/apps/personApp/personApp.js b/src/main/webapp/apps/personApp/personApp.js index 59f5a7d..8323c45 100644 --- a/src/main/webapp/apps/personApp/personApp.js +++ b/src/main/webapp/apps/personApp/personApp.js @@ -1,12 +1,16 @@ 'use strict'; -var personApp = angular.module('personApp', ['personService']).config(function ($routeProvider, $locationProvider) { +var personApp = angular.module('personApp', ['person', 'build']).config(function ($routeProvider, $locationProvider) { $routeProvider. when('/', {controller: PersonCtrl, templateUrl: '/apps/personApp/person.html?noCache=' + noCache}); }); -function PersonCtrl($scope, $location, PersonService) { - PersonService.get({uuid: uuid}, function (person) { +function PersonCtrl($scope, $location, Person, Build) { + Person.get({uuid: uuid}, function (person) { $scope.person = person; }); + + Build.query({person: uuid}, function (builds) { + $scope.builds = builds; + }); } diff --git a/src/main/webapp/external/angular-ui/ng-grid-1.6.0/ng-grid-1.6.0.debug.js b/src/main/webapp/external/angular-ui/ng-grid-1.6.0/ng-grid-1.6.0.debug.js new file mode 100644 index 0000000..636fcf1 --- /dev/null +++ b/src/main/webapp/external/angular-ui/ng-grid-1.6.0/ng-grid-1.6.0.debug.js @@ -0,0 +1,2393 @@ +/*********************************************** + * ng-grid JavaScript Library + * Authors: https://github.com/angular-ui/ng-grid/blob/master/README.md + * License: MIT (http://www.opensource.org/licenses/mit-license.php) + * Compiled At: 12/27/2012 16:39:37 + ***********************************************/ + +(function(window) { + 'use strict'; + + /*********************************************** + * FILE: ..\src\namespace.js + ***********************************************/ + if (!window.ng) { + window.ng = {}; + } + window.ngGrid = {}; + window.ngGrid.i18n = {}; + var ngGridServices = angular.module('ngGrid.services', []); + var ngGridDirectives = angular.module('ngGrid.directives', []); + var ngGridFilters = angular.module('ngGrid.filters', []); +// Declare app level module which depends on filters, and services + + /*********************************************** + * FILE: ..\src\constants.js + ***********************************************/ + var SELECTED_PROP = '__ng_selected__'; +// the # of rows we want to add to the top and bottom of the rendered grid rows + var EXCESS_ROWS = 8; + var SCROLL_THRESHOLD = 6; + var ASC = "asc"; +// constant for sorting direction + var DESC = "desc"; +// constant for sorting direction + var NG_FIELD = '_ng_field_'; + var NG_DEPTH = '_ng_depth_'; + var NG_HIDDEN = '_ng_hidden_'; + var NG_COLUMN = '_ng_column_'; + var CUSTOM_FILTERS = /CUSTOM_FILTERS/g; + var TEMPLATE_REGEXP = /<.+>/; + + /*********************************************** + * FILE: ..\src\navigation.js + ***********************************************/ +//set event binding on the grid so we can select using the up/down keys + ng.moveSelectionHandler = function($scope, grid, evt) { + // null checks + if (grid === null || grid === undefined) { + return true; + } + if (grid.config.selectedItems === undefined) { + return true; + } + var charCode = evt.which || evt.keyCode; + // detect which direction for arrow keys to navigate the grid + var offset = (charCode == 38 ? -1 : (charCode == 40 ? 1 : null)); + if (!offset) { + return true; + } + var items = $scope.renderedRows; + var index = items.indexOf(grid.selectionService.lastClickedRow) + offset; + if (index < 0 || index >= items.length) { + return true; + } + grid.selectionService.ChangeSelection(items[index], evt); + if (index > items.length - EXCESS_ROWS) { + grid.$viewport.scrollTop(grid.$viewport.scrollTop() + (grid.config.rowHeight * 2)); + } else if (index < EXCESS_ROWS) { + grid.$viewport.scrollTop(grid.$viewport.scrollTop() - (grid.config.rowHeight * 2)); + } + if (!$scope.$$phase) { + $scope.$parent.$digest(); + } + return false; + }; + + /*********************************************** + * FILE: ..\src\utils.js + ***********************************************/ + if (!String.prototype.trim) { + String.prototype.trim = function() { + return this.replace(/^\s+|\s+$/g, ''); + }; + } + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(elt /*, from*/) { + var len = this.length >>> 0; + var from = Number(arguments[1]) || 0; + from = (from < 0) ? Math.ceil(from) : Math.floor(from); + if (from < 0) { + from += len; + } + for (; from < len; from++) { + if (from in this && this[from] === elt) { + return from; + } + } + return -1; + }; + } + if (!Array.prototype.filter) { + Array.prototype.filter = function(fun /*, thisp */) { + "use strict"; + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") { + throw new TypeError(); + } + var res = []; + var thisp = arguments[1]; + for (var i = 0; i < len; i++) { + if (i in t) { + var val = t[i]; // in case fun mutates this + if (fun.call(thisp, val, i, t)) { + res.push(val); + } + } + } + return res; + }; + } + ng.utils = { + visualLength: function(node) { + var elem = document.getElementById('testDataLength'); + if (!elem) { + elem = document.createElement('SPAN'); + elem.id = "testDataLength"; + elem.style.visibility = "hidden"; + document.body.appendChild(elem); + } + $(elem).css('font', $(node).css('font')); + elem.innerHTML = $(node).text(); + return elem.offsetWidth; + }, + forIn: function(obj, action) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + action(obj[prop], prop); + } + } + }, + evalProperty: function(entity, path) { + var propPath = path.split('.'), i = 0; + var tempProp = entity[propPath[i]], links = propPath.length; + i++; + while (tempProp && i < links) { + tempProp = tempProp[propPath[i]]; + i++; + } + return tempProp; + }, + endsWith: function(str, suffix) { + if (!str || !suffix || typeof str != "string") { + return false; + } + return str.indexOf(suffix, str.length - suffix.length) !== -1; + }, + isNullOrUndefined: function(obj) { + if (obj === undefined || obj === null) { + return true; + } + return false; + }, + getElementsByClassName: function(cl) { + var retnode = []; + var myclass = new RegExp('\\b' + cl + '\\b'); + var elem = document.getElementsByTagName('*'); + for (var i = 0; i < elem.length; i++) { + var classes = elem[i].className; + if (myclass.test(classes)) { + retnode.push(elem[i]); + } + } + return retnode; + }, + newId: (function() { + var seedId = new Date().getTime(); + return function() { + return seedId += 1; + }; + })(), + seti18n: function($scope, language) { + var $langPack = window.ngGrid.i18n[language]; + for (var label in $langPack) { + $scope.i18n[label] = $langPack[label]; + } + }, + + // we copy KO's ie detection here bc it isn't exported in the min versions of KO + // Detect IE versions for workarounds (uses IE conditionals, not UA string, for robustness) + ieVersion: (function() { + var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i'); + // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment + while (div.innerHTML = '', + iElems[0]); + return version > 4 ? version : undefined; + })() + }; + + $.extend(ng.utils, { + isIe6: (function() { + return ng.utils.ieVersion === 6; + })(), + isIe7: (function() { + return ng.utils.ieVersion === 7; + })(), + isIe: (function() { + return ng.utils.ieVersion !== undefined; + })() + }); + + /*********************************************** + * FILE: ..\src\filters\ngColumns.js + ***********************************************/ + ngGridFilters.filter('ngColumns', function() { + return function(input) { + return input.filter(function(col) { + return !col.isAggCol; + }); + }; + }); + + /*********************************************** + * FILE: ..\src\filters\checkmark.js + ***********************************************/ + ngGridFilters.filter('checkmark', function() { + return function(input) { + return input ? '\u2714' : '\u2718'; + }; + }); + + /*********************************************** + * FILE: ..\src\services\SortService.js + ***********************************************/ + ngGridServices.factory('SortService', function() { + var sortService = {}; + sortService.colSortFnCache = {}; // cache of sorting functions. Once we create them, we don't want to keep re-doing it + sortService.dateRE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; // nasty regex for date parsing + // this takes an piece of data from the cell and tries to determine its type and what sorting + // function to use for it + // @item - the cell data + sortService.guessSortFn = function(item) { + var sortFn, // sorting function that is guessed + itemType, // the typeof item + dateParts, // for date parsing + month, // for date parsing + day; // for date parsing + + if (item === undefined || item === null || item === '') { + return null; + } + itemType = typeof(item); + //check for numbers and booleans + switch (itemType) { + case "number": + sortFn = sortService.sortNumber; + break; + case "boolean": + sortFn = sortService.sortBool; + break; + default: + sortFn = undefined; + break; + } + //if we found one, return it + if (sortFn) { + return sortFn; + } + //check if the item is a valid Date + if (Object.prototype.toString.call(item) === '[object Date]') { + return sortService.sortDate; + } + // if we aren't left with a string, return a basic sorting function... + if (itemType !== "string") { + return sortService.basicSort; + } + // now lets string check.. + //check if the item data is a valid number + if (item.match(/^-?[�$�]?[\d,.]+%?$/)) { + return sortService.sortNumberStr; + } + // check for a date: dd/mm/yyyy or dd/mm/yy + // can have / or . or - as separator + // can be mm/dd as well + dateParts = item.match(sortService.dateRE); + if (dateParts) { + // looks like a date + month = parseInt(dateParts[1], 10); + day = parseInt(dateParts[2], 10); + if (month > 12) { + // definitely dd/mm + return sortService.sortDDMMStr; + } else if (day > 12) { + return sortService.sortMMDDStr; + } else { + // looks like a date, but we can't tell which, so assume that it's MM/DD + return sortService.sortMMDDStr; + } + } + //finally just sort the normal string... + return sortService.sortAlpha; + }; + //#region Sorting Functions + sortService.basicSort = function(a, b) { + if (a == b) { + return 0; + } + if (a < b) { + return -1; + } + return 1; + }; + sortService.sortNumber = function(a, b) { + return a - b; + }; + sortService.sortNumberStr = function(a, b) { + var numA, numB, badA = false, badB = false; + numA = parseFloat(a.replace(/[^0-9.-]/g, '')); + if (isNaN(numA)) { + badA = true; + } + numB = parseFloat(b.replace(/[^0-9.-]/g, '')); + if (isNaN(numB)) { + badB = true; + } + // we want bad ones to get pushed to the bottom... which effectively is "greater than" + if (badA && badB) { + return 0; + } + if (badA) { + return 1; + } + if (badB) { + return -1; + } + return numA - numB; + }; + sortService.sortAlpha = function(a, b) { + var strA = a.toLowerCase(), + strB = b.toLowerCase(); + return strA == strB ? 0 : (strA < strB ? -1 : 1); + }; + sortService.sortDate = function(a, b) { + var timeA = a.getTime(), + timeB = b.getTime(); + return timeA == timeB ? 0 : (timeA < timeB ? -1 : 1); + }; + sortService.sortBool = function(a, b) { + if (a && b) { + return 0; + } + if (!a && !b) { + return 0; + } else { + return a ? 1 : -1; + } + }; + sortService.sortDDMMStr = function(a, b) { + var dateA, dateB, mtch, m, d, y; + mtch = a.match(sortService.dateRE); + y = mtch[3]; + m = mtch[2]; + d = mtch[1]; + if (m.length == 1) { + m = '0' + m; + } + if (d.length == 1) { + d = '0' + d; + } + dateA = y + m + d; + mtch = b.match(sortService.dateRE); + y = mtch[3]; + m = mtch[2]; + d = mtch[1]; + if (m.length == 1) { + m = '0' + m; + } + if (d.length == 1) { + d = '0' + d; + } + dateB = y + m + d; + if (dateA == dateB) { + return 0; + } + if (dateA < dateB) { + return -1; + } + return 1; + }; + sortService.sortMMDDStr = function(a, b) { + var dateA, dateB, mtch, m, d, y; + mtch = a.match(sortService.dateRE); + y = mtch[3]; + d = mtch[2]; + m = mtch[1]; + if (m.length == 1) { + m = '0' + m; + } + if (d.length == 1) { + d = '0' + d; + } + dateA = y + m + d; + mtch = b.match(sortService.dateRE); + y = mtch[3]; + d = mtch[2]; + m = mtch[1]; + if (m.length == 1) { + m = '0' + m; + } + if (d.length == 1) { + d = '0' + d; + } + dateB = y + m + d; + if (dateA == dateB) { + return 0; + } + if (dateA < dateB) { + return -1; + } + return 1; + }; + //#endregion + // the core sorting logic trigger + sortService.sortData = function(data /*datasource*/, sortInfo) { + // first make sure we are even supposed to do work + if (!data || !sortInfo) { + return; + } + // grab the metadata for the rest of the logic + var col = sortInfo.column, + direction = sortInfo.direction, + sortFn, + item; + + //see if we already figured out what to use to sort the column + if (sortService.colSortFnCache[col.field]) { + sortFn = sortService.colSortFnCache[col.field]; + } else if (col.sortingAlgorithm != undefined) { + sortFn = col.sortingAlgorithm; + sortService.colSortFnCache[col.field] = col.sortingAlgorithm; + } else { // try and guess what sort function to use + item = data[0]; + if (!item) { + return; + } + sortFn = sortService.guessSortFn(item[col.field]); + //cache it + if (sortFn) { + sortService.colSortFnCache[col.field] = sortFn; + } else { + // we assign the alpha sort because anything that is null/undefined will never get passed to + // the actual sorting function. It will get caught in our null check and returned to be sorted + // down to the bottom + sortFn = sortService.sortAlpha; + } + } + //now actually sort the data + data.sort(function(itemA, itemB) { + var propA = ng.utils.evalProperty(itemA, col.field); + var propB = ng.utils.evalProperty(itemB, col.field); + // we want to force nulls and such to the bottom when we sort... which effectively is "greater than" + if (!propB && !propA) { + return 0; + } else if (!propA) { + return 1; + } else if (!propB) { + return -1; + } + //made it this far, we don't have to worry about null & undefined + if (direction === ASC) { + return sortFn(propA, propB); + } else { + return 0 - sortFn(propA, propB); + } + }); + return; + }; + sortService.Sort = function(sortInfo, data) { + if (sortService.isSorting) { + return; + } + sortService.isSorting = true; + sortService.sortData(data, sortInfo); + sortService.isSorting = false; + }; + return sortService; + }); + + /*********************************************** + * FILE: ..\src\services\DomUtilityService.js + ***********************************************/ + ngGridServices.factory('DomUtilityService', function() { + var domUtilityService = {}; + var getWidths = function() { + var $testContainer = $('
'); + $testContainer.appendTo('body'); + // 1. Run all the following measurements on startup! + //measure Scroll Bars + $testContainer.height(100).width(100).css("position", "absolute").css("overflow", "scroll"); + $testContainer.append('
'); + domUtilityService.ScrollH = ($testContainer.height() - $testContainer[0].clientHeight); + domUtilityService.ScrollW = ($testContainer.width() - $testContainer[0].clientWidth); + $testContainer.empty(); + //clear styles + $testContainer.attr('style', ''); + //measure letter sizes using a pretty typical font size and fat font-family + $testContainer.append('M'); + domUtilityService.LetterW = $testContainer.children().first().width(); + $testContainer.remove(); + }; + domUtilityService.eventStorage = {}; + domUtilityService.AssignGridContainers = function(rootEl, grid) { + grid.$root = $(rootEl); + //Headers + grid.$topPanel = grid.$root.find(".ngTopPanel"); + grid.$groupPanel = grid.$root.find(".ngGroupPanel"); + grid.$headerContainer = grid.$topPanel.find(".ngHeaderContainer"); + grid.$headerScroller = grid.$topPanel.find(".ngHeaderScroller"); + grid.$headers = grid.$headerScroller.children(); + //Viewport + grid.$viewport = grid.$root.find(".ngViewport"); + //Canvas + grid.$canvas = grid.$viewport.find(".ngCanvas"); + //Footers + grid.$footerPanel = grid.$root.find(".ngFooterPanel"); + domUtilityService.UpdateGridLayout(grid); + }; + domUtilityService.UpdateGridLayout = function(grid) { + //catch this so we can return the viewer to their original scroll after the resize! + var scrollTop = grid.$viewport.scrollTop(); + grid.elementDims.rootMaxW = grid.$root.width(); + grid.elementDims.rootMaxH = grid.$root.height(); + //check to see if anything has changed + grid.refreshDomSizes(); + grid.adjustScrollTop(scrollTop, true); //ensure that the user stays scrolled where they were + }; + domUtilityService.numberOfGrids = 0; + domUtilityService.BuildStyles = function($scope, grid, digest) { + var rowHeight = grid.config.rowHeight, + $style = grid.$styleSheet, + gridId = grid.gridId, + css, + cols = $scope.visibleColumns(), + sumWidth = 0; + + if (!$style) { + $style = $('#' + gridId); + if (!$style[0]) { + $style = $("