From 2f13891f8166944636316441a631230fe277ff4f Mon Sep 17 00:00:00 2001 From: Athou Date: Thu, 4 Apr 2013 11:36:24 +0200 Subject: [PATCH] settings page and custom css for users --- pom.xml | 5 + .../commafeed/backend/model/UserSettings.java | 13 + .../commafeed/frontend/model/Settings.java | 9 + .../commafeed/frontend/pages/HomePage.java | 22 + .../references/UserCustomCssReference.java | 39 + .../angularui/AngularUIReference.java | 19 +- .../references/angularui/angular-ui.css | 50 + .../references/angularui/angular-ui.js | 1461 +++++++++++++++++ .../codemirror/CodeMirrorCssReference.java | 29 + .../codemirror/CodeMirrorReference.java | 32 + .../frontend/rest/resources/SettingsREST.java | 2 + src/main/webapp/directives/toolbar.html | 2 +- src/main/webapp/js/controllers.js | 18 + src/main/webapp/js/directives.js | 3 + src/main/webapp/js/main.js | 6 + src/main/webapp/js/services.js | 20 +- src/main/webapp/templates/settings.html | 28 + 17 files changed, 1744 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/commafeed/frontend/references/UserCustomCssReference.java create mode 100644 src/main/java/com/commafeed/frontend/references/angularui/angular-ui.css create mode 100644 src/main/java/com/commafeed/frontend/references/angularui/angular-ui.js create mode 100644 src/main/java/com/commafeed/frontend/references/codemirror/CodeMirrorCssReference.java create mode 100644 src/main/java/com/commafeed/frontend/references/codemirror/CodeMirrorReference.java create mode 100644 src/main/webapp/templates/settings.html diff --git a/pom.xml b/pom.xml index 3834c24d..0a76b27e 100644 --- a/pom.xml +++ b/pom.xml @@ -258,6 +258,11 @@ mousetrap 1.3 + + org.webjars + codemirror + 3.11 + diff --git a/src/main/java/com/commafeed/backend/model/UserSettings.java b/src/main/java/com/commafeed/backend/model/UserSettings.java index aa823e3d..44fba463 100644 --- a/src/main/java/com/commafeed/backend/model/UserSettings.java +++ b/src/main/java/com/commafeed/backend/model/UserSettings.java @@ -5,6 +5,7 @@ import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.JoinColumn; +import javax.persistence.Lob; import javax.persistence.OneToOne; import javax.persistence.Table; @@ -25,6 +26,10 @@ public class UserSettings extends AbstractModel { @Column(nullable = false) private ReadingMode readingMode; + @Lob + @Column(length = Integer.MAX_VALUE) + private String customCss; + public ReadingMode getReadingMode() { return readingMode; } @@ -41,4 +46,12 @@ public class UserSettings extends AbstractModel { this.user = user; } + public String getCustomCss() { + return customCss; + } + + public void setCustomCss(String customCss) { + this.customCss = customCss; + } + } diff --git a/src/main/java/com/commafeed/frontend/model/Settings.java b/src/main/java/com/commafeed/frontend/model/Settings.java index 967ab276..c462483c 100644 --- a/src/main/java/com/commafeed/frontend/model/Settings.java +++ b/src/main/java/com/commafeed/frontend/model/Settings.java @@ -6,6 +6,7 @@ import java.io.Serializable; public class Settings implements Serializable { private String readingMode; + private String customCss; public String getReadingMode() { return readingMode; @@ -15,4 +16,12 @@ public class Settings implements Serializable { this.readingMode = readingMode; } + public String getCustomCss() { + return customCss; + } + + public void setCustomCss(String customCss) { + this.customCss = customCss; + } + } diff --git a/src/main/java/com/commafeed/frontend/pages/HomePage.java b/src/main/java/com/commafeed/frontend/pages/HomePage.java index 8771ea95..7128681d 100644 --- a/src/main/java/com/commafeed/frontend/pages/HomePage.java +++ b/src/main/java/com/commafeed/frontend/pages/HomePage.java @@ -1,17 +1,24 @@ package com.commafeed.frontend.pages; +import javax.inject.Inject; + import org.apache.wicket.markup.head.CssHeaderItem; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptHeaderItem; +import com.commafeed.backend.dao.UserSettingsService; import com.commafeed.backend.model.UserRole.Role; +import com.commafeed.backend.model.UserSettings; +import com.commafeed.frontend.CommaFeedSession; import com.commafeed.frontend.SecurityCheck; +import com.commafeed.frontend.references.UserCustomCssReference; import com.commafeed.frontend.references.angular.AngularReference; import com.commafeed.frontend.references.angular.AngularResourceReference; import com.commafeed.frontend.references.angular.AngularSanitizeReference; import com.commafeed.frontend.references.angularui.AngularUIReference; import com.commafeed.frontend.references.angularuibootstrap.AngularUIBootstrapReference; import com.commafeed.frontend.references.angularuistate.AngularUIStateReference; +import com.commafeed.frontend.references.codemirror.CodeMirrorCssReference; import com.commafeed.frontend.references.csstreeview.CssTreeViewReference; import com.commafeed.frontend.references.mousetrap.MouseTrapReference; import com.commafeed.frontend.references.nggrid.NGGridReference; @@ -24,6 +31,9 @@ import com.commafeed.frontend.references.spinjs.SpinJSReference; @SecurityCheck(Role.USER) public class HomePage extends BasePage { + @Inject + UserSettingsService settingsService; + @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); @@ -39,6 +49,7 @@ public class HomePage extends BasePage { SpinJSReference.renderHead(response); MouseTrapReference.renderHead(response); NGGridReference.renderHead(response); + CodeMirrorCssReference.renderHead(response); CssTreeViewReference.renderHead(response); @@ -48,5 +59,16 @@ public class HomePage extends BasePage { response.render(JavaScriptHeaderItem.forUrl("js/services.js")); response.render(CssHeaderItem.forUrl("css/app.css")); + + response.render(CssHeaderItem + .forReference(new UserCustomCssReference() { + @Override + protected String getCss() { + UserSettings settings = settingsService + .findByUser(CommaFeedSession.get().getUser()); + return settings == null ? null : settings + .getCustomCss(); + } + })); } } diff --git a/src/main/java/com/commafeed/frontend/references/UserCustomCssReference.java b/src/main/java/com/commafeed/frontend/references/UserCustomCssReference.java new file mode 100644 index 00000000..eb5583ad --- /dev/null +++ b/src/main/java/com/commafeed/frontend/references/UserCustomCssReference.java @@ -0,0 +1,39 @@ +package com.commafeed.frontend.references; + +import java.io.IOException; + +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.request.resource.AbstractResource; +import org.apache.wicket.request.resource.IResource; +import org.apache.wicket.request.resource.ResourceReference; + +@SuppressWarnings("serial") +public abstract class UserCustomCssReference extends ResourceReference { + + public UserCustomCssReference() { + super(UserCustomCssReference.class, "custom.css"); + } + + @Override + public IResource getResource() { + return new AbstractResource() { + @Override + protected ResourceResponse newResourceResponse(Attributes attributes) { + ResourceResponse resourceResponse = new ResourceResponse(); + resourceResponse.setContentType("text/css"); + resourceResponse.setTextEncoding("UTF-8"); + resourceResponse.setWriteCallback(new WriteCallback() { + @Override + public void writeData(Attributes attributes) + throws IOException { + attributes.getResponse().write( + StringUtils.trimToEmpty(getCss())); + } + }); + return resourceResponse; + } + }; + } + + protected abstract String getCss(); +} diff --git a/src/main/java/com/commafeed/frontend/references/angularui/AngularUIReference.java b/src/main/java/com/commafeed/frontend/references/angularui/AngularUIReference.java index 757d81c6..54349770 100644 --- a/src/main/java/com/commafeed/frontend/references/angularui/AngularUIReference.java +++ b/src/main/java/com/commafeed/frontend/references/angularui/AngularUIReference.java @@ -2,28 +2,31 @@ package com.commafeed.frontend.references.angularui; import java.util.Arrays; +import org.apache.wicket.markup.head.CssHeaderItem; import org.apache.wicket.markup.head.HeaderItem; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptHeaderItem; +import org.apache.wicket.request.resource.CssResourceReference; +import org.apache.wicket.request.resource.JavaScriptResourceReference; -import com.commafeed.frontend.utils.WicketUtils; +import com.commafeed.frontend.references.angular.AngularReference; -import de.agilecoders.wicket.webjars.request.resource.WebjarsJavaScriptResourceReference; - -public class AngularUIReference extends WebjarsJavaScriptResourceReference { +public class AngularUIReference extends JavaScriptResourceReference { private static final long serialVersionUID = 1L; public static final AngularUIReference INSTANCE = new AngularUIReference(); private AngularUIReference() { - super("/angular-ui/current/angular-ui.js"); + super(AngularUIReference.class, "angular-ui.js"); } + @SuppressWarnings("unchecked") @Override public Iterable getDependencies() { - return Arrays - .asList(WicketUtils - .buildCssWebJarHeaderItem("/angular-ui/current/angular-ui.css")); + return Arrays.asList(JavaScriptHeaderItem + .forReference(AngularReference.INSTANCE), CssHeaderItem + .forReference(new CssResourceReference( + AngularUIReference.class, "angular-ui.css"))); } public static void renderHead(final IHeaderResponse response) { diff --git a/src/main/java/com/commafeed/frontend/references/angularui/angular-ui.css b/src/main/java/com/commafeed/frontend/references/angularui/angular-ui.css new file mode 100644 index 00000000..eb02a8ed --- /dev/null +++ b/src/main/java/com/commafeed/frontend/references/angularui/angular-ui.css @@ -0,0 +1,50 @@ +/** + * import components to builds angular-ui.css + */ + +/* ui-reset */ + +.ui-resetwrap { + position: relative; + display: inline-block; +} + +.ui-reset { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: none; + height: 100%; + cursor: pointer; +} + +.ui-resetwrap:hover .ui-reset { + display: block; +} + +/* ui-currency */ + +.ui-currency-pos { + color: green; +} + +.ui-currency-neg { + color: red; +} + +.ui-currency-zero { + color: blue; +} + +.ui-currency-pos.ui-bignum, +.ui-currency-neg.ui-smallnum { + font-size: 110%; +} + +/* highlight */ + +.ui-match { + background: yellow; +} + diff --git a/src/main/java/com/commafeed/frontend/references/angularui/angular-ui.js b/src/main/java/com/commafeed/frontend/references/angularui/angular-ui.js new file mode 100644 index 00000000..e92b2cfc --- /dev/null +++ b/src/main/java/com/commafeed/frontend/references/angularui/angular-ui.js @@ -0,0 +1,1461 @@ +/** + * AngularUI - The companion suite for AngularJS + * @version v0.4.0 - 2013-02-15 + * @link http://angular-ui.github.com + * @license MIT License, http://www.opensource.org/licenses/MIT + */ + + +angular.module('ui.config', []).value('ui.config', {}); +angular.module('ui.filters', ['ui.config']); +angular.module('ui.directives', ['ui.config']); +angular.module('ui', ['ui.filters', 'ui.directives', 'ui.config']); + +/** + * Animates the injection of new DOM elements by simply creating the DOM with a class and then immediately removing it + * Animations must be done using CSS3 transitions, but provide excellent flexibility + * + * @todo Add proper support for animating out + * @param [options] {mixed} Can be an object with multiple options, or a string with the animation class + * class {string} the CSS class(es) to use. For example, 'ui-hide' might be an excellent alternative class. + * @example
  • {{item}}
  • + */ +angular.module('ui.directives').directive('uiAnimate', ['ui.config', '$timeout', function (uiConfig, $timeout) { + var options = {}; + if (angular.isString(uiConfig.animate)) { + options['class'] = uiConfig.animate; + } else if (uiConfig.animate) { + options = uiConfig.animate; + } + return { + restrict: 'A', // supports using directive as element, attribute and class + link: function ($scope, element, attrs) { + var opts = {}; + if (attrs.uiAnimate) { + opts = $scope.$eval(attrs.uiAnimate); + if (angular.isString(opts)) { + opts = {'class': opts}; + } + } + opts = angular.extend({'class': 'ui-animate'}, options, opts); + + element.addClass(opts['class']); + $timeout(function () { + element.removeClass(opts['class']); + }, 20, false); + } + }; +}]); + + +/* +* AngularJs Fullcalendar Wrapper for the JQuery FullCalendar +* API @ http://arshaw.com/fullcalendar/ +* +* Angular Calendar Directive that takes in the [eventSources] nested array object as the ng-model and watches (eventSources.length + eventSources[i].length) for changes. +* Can also take in multiple event urls as a source object(s) and feed the events per view. +* The calendar will watch any eventSource array and update itself when a delta is created +* An equalsTracker attrs has been added for use cases that would render the overall length tracker the same even though the events have changed to force updates. +* +*/ + +angular.module('ui.directives').directive('uiCalendar',['ui.config', '$parse', function (uiConfig,$parse) { + uiConfig.uiCalendar = uiConfig.uiCalendar || {}; + //returns calendar + return { + require: 'ngModel', + restrict: 'A', + link: function(scope, elm, attrs, $timeout) { + var sources = scope.$eval(attrs.ngModel); + var tracker = 0; + /* returns the length of all source arrays plus the length of eventSource itself */ + var getSources = function () { + var equalsTracker = scope.$eval(attrs.equalsTracker); + tracker = 0; + angular.forEach(sources,function(value,key){ + if(angular.isArray(value)){ + tracker += value.length; + } + }); + if(angular.isNumber(equalsTracker)){ + return tracker + sources.length + equalsTracker; + }else{ + return tracker + sources.length; + } + }; + /* update the calendar with the correct options */ + function update() { + //calendar object exposed on scope + scope.calendar = elm.html(''); + var view = scope.calendar.fullCalendar('getView'); + if(view){ + view = view.name; //setting the default view to be whatever the current view is. This can be overwritten. + } + /* If the calendar has options added then render them */ + var expression, + options = { + defaultView : view, + eventSources: sources + }; + if (attrs.uiCalendar) { + expression = scope.$eval(attrs.uiCalendar); + } else { + expression = {}; + } + angular.extend(options, uiConfig.uiCalendar, expression); + scope.calendar.fullCalendar(options); + } + update(); + /* watches all eventSources */ + scope.$watch(getSources, function( newVal, oldVal ) + { + update(); + }); + } + }; +}]); +/*global angular, CodeMirror, Error*/ +/** + * Binds a CodeMirror widget to a + + + + +
    + + +
    + \ No newline at end of file