diff --git a/ma-impl.sublime-workspace b/ma-impl.sublime-workspace index 7b33cb727a672a0499b9aaab0160892403b77e9c..61e4ba59e8aa161053ce7c68f1e45f31eb55484c 100644 --- a/ma-impl.sublime-workspace +++ b/ma-impl.sublime-workspace @@ -3,6 +3,10 @@ { "selected_items": [ + [ + "border-top", + "border-top-style" + ], [ "TOMCAT", "TOMCAT_MINOR" @@ -276,34 +280,18 @@ "buffers": [ { - "file": "vipra-ui/app/templates/topics/show/index.hbs", - "settings": - { - "buffer_size": 408, - "line_ending": "Unix" - } - }, - { - "file": "vipra-ui/app/templates/application.hbs", - "settings": - { - "buffer_size": 1378, - "line_ending": "Unix" - } - }, - { - "file": "vipra-ui/app/routes/articles/show.js", + "file": "vipra-ui/app/templates/articles/index.hbs", "settings": { - "buffer_size": 692, + "buffer_size": 385, "line_ending": "Unix" } }, { - "file": "vipra-ui/app/templates/articles/show.hbs", + "file": "vipra-ui/app/routes/articles/index.js", "settings": { - "buffer_size": 699, + "buffer_size": 1232, "line_ending": "Unix" } } @@ -488,26 +476,34 @@ "/home/eike/repos/master/ma-impl", "/home/eike/repos/master/ma-impl/vipra-ui", "/home/eike/repos/master/ma-impl/vipra-ui/app", - "/home/eike/repos/master/ma-impl/vipra-ui/app/helpers", "/home/eike/repos/master/ma-impl/vipra-ui/app/routes", "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/articles", + "/home/eike/repos/master/ma-impl/vipra-ui/app/styles", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/articles", - "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/topics/show" + "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/components" ], "file_history": [ + "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/articles/index.hbs", + "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/articles/index.js", + "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/index.hbs", + "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/application.hbs", + "/home/eike/repos/master/ma-impl/vipra-ui/app/styles/app.scss", + "/home/eike/repos/master/ma-impl/vipra-ui/app/styles/sticky-footer.scss", + "/home/eike/repos/master/ma-impl/vipra-ui/app/controllers/application.js", + "/home/eike/repos/master/ma-impl/vipra-ui/app/components/scroll-top.js", + "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/components/scroll-top.hbs", + "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/articles/show.hbs", + "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/topics/show/index.hbs", + "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/articles/show.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/articles/menu.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/articles/menu.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/words/index.hbs", - "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/articles/show.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/components/items-list.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/helpers/pluralize.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/helpers/uppercase.js", - "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/articles/index.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/words_loading.hbs", - "/home/eike/repos/master/ma-impl/vipra-ui/app/styles/app.scss", - "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/application.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/bower.json", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/topics/index.hbs", "/home/eike/.config/sublime-text-3/Packages/User/Preferences.sublime-settings", @@ -516,7 +512,6 @@ "/home/eike/repos/master/ma-impl/vipra-ui/app/adapters/application.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/articles.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/ember-cli-build.js", - "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/index.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/loading.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/styles/app.css", "/home/eike/Downloads/squares.css", @@ -526,7 +521,6 @@ "/home/eike/repos/master/ma-impl/vipra-ui/app/models/word.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/words/index.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/components/items-list.js", - "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/topics/show/index.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/router.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/words", "/home/eike/repos/master/ma-impl/vipra-ui/app/models/topic.js", @@ -552,7 +546,6 @@ "/home/eike/repos/master/ma-impl/vipra-ui/app/helpers/topic-share.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/components/topic-link.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/topics/edit.hbs", - "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/articles/show.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/templates/articles/edit.hbs", "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/topics/edit.js", "/home/eike/repos/master/ma-impl/vipra-ui/app/routes/articles/edit.js", @@ -619,12 +612,7 @@ "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles.hbs", "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/models/article.js", "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/index.hbs", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/routes/articles/index.js", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/routes/article.js", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles/index.hbs", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles/new.hbs", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/routes/article/show.js", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/article.hbs" + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/routes/articles/index.js" ], "find": { @@ -948,61 +936,29 @@ "groups": [ { - "selected": 2, + "selected": 1, "sheets": [ { "buffer": 0, - "file": "vipra-ui/app/templates/topics/show/index.hbs", + "file": "vipra-ui/app/templates/articles/index.hbs", "semi_transient": false, "settings": { - "buffer_size": 408, + "buffer_size": 385, "regions": { }, "selection": [ [ - 408, - 408 + 385, + 385 ] ], "settings": { - "syntax": "Packages/Handlebars/grammars/Handlebars.tmLanguage", - "tab_size": 2, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 3, - "type": "text" - }, - { - "buffer": 1, - "file": "vipra-ui/app/templates/application.hbs", - "semi_transient": false, - "settings": - { - "buffer_size": 1378, - "regions": - { - }, - "selection": - [ - [ - 1378, - 1378 - ] - ], - "settings": - { - "syntax": "Packages/Handlebars/grammars/Handlebars.tmLanguage", - "tab_size": 2, - "translate_tabs_to_spaces": true + "syntax": "Packages/Handlebars/grammars/Handlebars.tmLanguage" }, "translation.x": 0.0, "translation.y": 0.0, @@ -1012,20 +968,20 @@ "type": "text" }, { - "buffer": 2, - "file": "vipra-ui/app/routes/articles/show.js", + "buffer": 1, + "file": "vipra-ui/app/routes/articles/index.js", "semi_transient": false, "settings": { - "buffer_size": 692, + "buffer_size": 1232, "regions": { }, "selection": [ [ - 692, - 692 + 1212, + 1212 ] ], "settings": @@ -1034,42 +990,12 @@ "tab_size": 2, "translate_tabs_to_spaces": true }, - "translation.x": 0.0, - "translation.y": 0.0, + "translation.x": -0.0, + "translation.y": 663.0, "zoom_level": 1.0 }, "stack_index": 0, "type": "text" - }, - { - "buffer": 3, - "file": "vipra-ui/app/templates/articles/show.hbs", - "semi_transient": true, - "settings": - { - "buffer_size": 699, - "regions": - { - }, - "selection": - [ - [ - 0, - 0 - ] - ], - "settings": - { - "syntax": "Packages/Handlebars/grammars/Handlebars.tmLanguage", - "tab_size": 2, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 2, - "type": "text" } ] } diff --git a/vipra-config/config.properties b/vipra-config/config.properties deleted file mode 100644 index 06623e215e66a3dfaefbdf3baabce5e5aeb14412..0000000000000000000000000000000000000000 --- a/vipra-config/config.properties +++ /dev/null @@ -1,5 +0,0 @@ -db.host=localhost -db.port=27017 -db.name=test - -fb.path=${datadir}/vipra \ No newline at end of file diff --git a/vipra-rest/src/main/java/de/vipra/rest/model/Wrapper.java b/vipra-rest/src/main/java/de/vipra/rest/model/Wrapper.java index d18f8d75db0c9b9240a1b466baa99b99dd3a010f..0d19036bab66a0fd23b113abf92b8fd78e77cae6 100644 --- a/vipra-rest/src/main/java/de/vipra/rest/model/Wrapper.java +++ b/vipra-rest/src/main/java/de/vipra/rest/model/Wrapper.java @@ -12,12 +12,14 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriBuilder; import de.vipra.rest.Messages; +import de.vipra.util.NestedMap; public class Wrapper<T> { private T data; private List<APIError> errors; private Map<String, String> links; + private NestedMap meta; private final APIVersion jsonapi = new APIVersion(); public Wrapper() {} @@ -68,6 +70,20 @@ public class Wrapper<T> { links.put(key, link); } + public NestedMap getMeta() { + return meta; + } + + public void setMeta(NestedMap meta) { + this.meta = meta; + } + + public void addMeta(String key, Object value) { + if (meta == null) + meta = new NestedMap(); + meta.put(key, value); + } + public APIVersion getJsonapi() { return jsonapi; } diff --git a/vipra-rest/src/main/java/de/vipra/rest/resource/ArticleResource.java b/vipra-rest/src/main/java/de/vipra/rest/resource/ArticleResource.java index 9a3ec6a8f6fb8781bd6db59f62f561a50c136bd1..204b2f1b18e550b112e5f168f11a53d28ed85cce 100644 --- a/vipra-rest/src/main/java/de/vipra/rest/resource/ArticleResource.java +++ b/vipra-rest/src/main/java/de/vipra/rest/resource/ArticleResource.java @@ -33,13 +33,12 @@ import de.vipra.rest.model.APIError; import de.vipra.rest.model.Wrapper; import de.vipra.util.Config; import de.vipra.util.MongoUtils; +import de.vipra.util.StringUtils; import de.vipra.util.ex.ConfigException; import de.vipra.util.ex.DatabaseException; import de.vipra.util.model.Article; import de.vipra.util.service.DatabaseService; -import static de.vipra.rest.resource.ResourceHelper.*; - @Path("articles") public class ArticleResource { @@ -74,7 +73,13 @@ public class ArticleResource { return res.badRequest(); try { - List<Article> articles = service.getMultiple(skip, limit, sortBy, getFields(fields)); + List<Article> articles = service.getMultiple(skip, limit, sortBy, StringUtils.getFields(fields)); + + if((skip != null && skip > 0) || (limit != null && limit > 0)) + res.addMeta("total", service.count()); + else + res.addMeta("total", articles.size()); + return res.ok(articles); } catch (Exception e) { res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); @@ -96,7 +101,7 @@ public class ArticleResource { Article article; try { - article = getSingle(id, getFields(fields)); + article = getSingle(id, StringUtils.getFields(fields)); } catch (Exception e) { res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); return res.badRequest(); diff --git a/vipra-rest/src/main/java/de/vipra/rest/resource/ResourceHelper.java b/vipra-rest/src/main/java/de/vipra/rest/resource/ResourceHelper.java deleted file mode 100644 index af609e9719a99a34086abf88ab6f50cc12a28586..0000000000000000000000000000000000000000 --- a/vipra-rest/src/main/java/de/vipra/rest/resource/ResourceHelper.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.vipra.rest.resource; - -public class ResourceHelper { - - public static String[] getFields(String fields) { - if (fields == null) - return null; - fields = fields.trim(); - if (fields.length() == 0) - return null; - return fields.split(","); - } - -} diff --git a/vipra-rest/src/main/java/de/vipra/rest/resource/TopicResource.java b/vipra-rest/src/main/java/de/vipra/rest/resource/TopicResource.java index 20f7c1661ef1a42b0ddbc5c3fe0b08ff0491c169..691dc746606bc19ca3ad87d016eed66449e35766 100644 --- a/vipra-rest/src/main/java/de/vipra/rest/resource/TopicResource.java +++ b/vipra-rest/src/main/java/de/vipra/rest/resource/TopicResource.java @@ -27,13 +27,12 @@ import de.vipra.rest.model.APIError; import de.vipra.rest.model.Wrapper; import de.vipra.util.Config; import de.vipra.util.MongoUtils; +import de.vipra.util.StringUtils; import de.vipra.util.ex.ConfigException; import de.vipra.util.ex.DatabaseException; import de.vipra.util.model.TopicFull; import de.vipra.util.service.DatabaseService; -import static de.vipra.rest.resource.ResourceHelper.*; - @Path("topics") public class TopicResource { @@ -68,7 +67,13 @@ public class TopicResource { return Response.status(Response.Status.BAD_REQUEST).entity(res).build(); try { - List<TopicFull> topics = service.getMultiple(skip, limit, sortBy, getFields(fields)); + List<TopicFull> topics = service.getMultiple(skip, limit, sortBy, StringUtils.getFields(fields)); + + if((skip != null && skip > 0) || (limit != null && limit > 0)) + res.addMeta("total", service.count()); + else + res.addMeta("total", topics.size()); + return res.ok(topics); } catch (Exception e) { res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); @@ -90,7 +95,7 @@ public class TopicResource { TopicFull topic; try { - topic = getSingle(id, getFields(fields)); + topic = getSingle(id, StringUtils.getFields(fields)); } catch (Exception e) { res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); return res.badRequest(); diff --git a/vipra-rest/src/main/java/de/vipra/rest/resource/WordResource.java b/vipra-rest/src/main/java/de/vipra/rest/resource/WordResource.java index fbb002e9131d7ad48f1165cca71eee23793c6e24..191cb3dc357c696ffe61355c72b9f27ae3f57598 100644 --- a/vipra-rest/src/main/java/de/vipra/rest/resource/WordResource.java +++ b/vipra-rest/src/main/java/de/vipra/rest/resource/WordResource.java @@ -24,12 +24,11 @@ import de.vipra.rest.Messages; import de.vipra.rest.model.APIError; import de.vipra.rest.model.Wrapper; import de.vipra.util.Config; +import de.vipra.util.StringUtils; import de.vipra.util.ex.ConfigException; import de.vipra.util.model.Word; import de.vipra.util.service.DatabaseService; -import static de.vipra.rest.resource.ResourceHelper.*; - @Path("words") public class WordResource { @@ -64,7 +63,13 @@ public class WordResource { return res.badRequest(); try { - List<Word> words = service.getMultiple(skip, limit, sortBy, getFields(fields)); + List<Word> words = service.getMultiple(skip, limit, sortBy, StringUtils.getFields(fields)); + + if ((skip != null && skip > 0) || (limit != null && limit > 0)) + res.addMeta("total", service.count()); + else + res.addMeta("total", words.size()); + return res.ok(words); } catch (Exception e) { res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); @@ -86,7 +91,7 @@ public class WordResource { Word word; try { - word = getSingle(id, getFields(fields)); + word = getSingle(id, StringUtils.getFields(fields)); } catch (Exception e) { res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); return res.badRequest(); diff --git a/vipra-rest/src/main/java/de/vipra/rest/serializer/GenericSerializer.java b/vipra-rest/src/main/java/de/vipra/rest/serializer/GenericSerializer.java index fe7cc73cfb0e7e452077fbc7238f06ed211af4a1..d58ca461f7d012de1ff763073c8f93fde8fce972 100644 --- a/vipra-rest/src/main/java/de/vipra/rest/serializer/GenericSerializer.java +++ b/vipra-rest/src/main/java/de/vipra/rest/serializer/GenericSerializer.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; +import de.vipra.util.NestedMap; import de.vipra.util.an.JsonType; import de.vipra.util.an.JsonWrap; import de.vipra.util.model.Model; @@ -74,8 +75,8 @@ public class GenericSerializer<T extends Model<?>> extends JsonSerializer<T> { public void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException { - Map<String, Object> map = new HashMap<>(); - pathAdd(map, "type", typeName); + NestedMap map = new NestedMap(); + map.put("type", typeName); for (Entry<String, Field> entry : allFields) { Object v = null; @@ -86,30 +87,10 @@ public class GenericSerializer<T extends Model<?>> extends JsonSerializer<T> { } if (v != null) - pathAdd(map, entry.getKey(), v); + map.put(entry.getKey(), v); } serializers.defaultSerializeValue(map, gen); } - @SuppressWarnings("unchecked") - private static void pathAdd(Map<String, Object> map, String path, Object value) { - Map<String, Object> current = map; - String[] parts = path.split("\\."); - String name = parts.length > 0 ? parts[parts.length - 1] : path; - - for (int i = 0; i < parts.length - 1; i++) { - Object o = current.get(parts[i]); - if (o == null || !(o instanceof Map)) { - HashMap<String, Object> newMap = new HashMap<>(); - current.put(parts[i], newMap); - current = newMap; - } else { - current = (Map<String, Object>) o; - } - } - - current.put(name, value); - } - } diff --git a/vipra-rest/src/main/resources/config.properties b/vipra-rest/src/main/resources/config.properties index 06623e215e66a3dfaefbdf3baabce5e5aeb14412..ae859d297d92ab50c7cec64fba62b4fab4a3ab11 100644 --- a/vipra-rest/src/main/resources/config.properties +++ b/vipra-rest/src/main/resources/config.properties @@ -1,5 +1,4 @@ db.host=localhost db.port=27017 db.name=test - -fb.path=${datadir}/vipra \ No newline at end of file +fb.path=/home/eike/.local/share/vipra \ No newline at end of file diff --git a/vipra-ui/app/components/scroll-top.js b/vipra-ui/app/components/scroll-top.js new file mode 100644 index 0000000000000000000000000000000000000000..5701f5aa07c52dbc7e01c40c6741d83dc4196a07 --- /dev/null +++ b/vipra-ui/app/components/scroll-top.js @@ -0,0 +1,17 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + tagName: 'a', + attributeBindings: ['href'], + href: '#', + classNames: ['scroll-top'], + + click(e) { + e.preventDefault(); + window.scrollTo(0, 0); + }, + + _text: Ember.computed(function() { + return this.get('text') || 'Top'; + }) +}); diff --git a/vipra-ui/app/routes/articles/index.js b/vipra-ui/app/routes/articles/index.js index 1428ecf3d146a1a1bbee3c8ca4b023c8bb4e2de2..246a6e2ba8445e85688fd335e5d6ba6cb76be112 100644 --- a/vipra-ui/app/routes/articles/index.js +++ b/vipra-ui/app/routes/articles/index.js @@ -31,7 +31,10 @@ var chartOptions = { export default Ember.Route.extend({ model() { return Ember.RSVP.hash({ - articles: this.store.findAll('article'), + articles: this.store.query('article', { + skip: 0, + limit: 100 + }), chartOptions: chartOptions, chartData: chartData }); @@ -58,4 +61,5 @@ export default Ember.Route.extend({ data: data }]; } + }); diff --git a/vipra-ui/app/styles/app.scss b/vipra-ui/app/styles/app.scss index 1e691064b7afc7e32b81667ea8b99ee4dd132937..0c0ea97f1a3d1b833c705f6595572fd9756c7449 100644 --- a/vipra-ui/app/styles/app.scss +++ b/vipra-ui/app/styles/app.scss @@ -1,6 +1,7 @@ body { // for navbar padding-top: 60px; + padding-bottom: 20px; } .word { @@ -19,4 +20,19 @@ body { background: url(/assets/images/squares.gif) no-repeat center center; width: 120px; height: 120px; -} \ No newline at end of file +} + +.navbar-default { + .navbar-nav { + &> .active { + &> a, + &> a:hover, + &> a:focus { + border-bottom: 3px solid; + padding-bottom: 12px; + } + } + } +} + +@import 'sticky-footer' \ No newline at end of file diff --git a/vipra-ui/app/styles/sticky-footer.scss b/vipra-ui/app/styles/sticky-footer.scss new file mode 100644 index 0000000000000000000000000000000000000000..6d26ce5f61744486e7816616afcac95c1dddec3b --- /dev/null +++ b/vipra-ui/app/styles/sticky-footer.scss @@ -0,0 +1,19 @@ +html { + position: relative; + min-height: 100%; +} + +body { + /* Margin bottom by footer height */ + margin-bottom: 60px; +} + +.footer { + position: absolute; + bottom: 0; + width: 100%; + /* Set the fixed height of the footer here */ + height: 50px; + border-top-width: 1px; + border-top-style: solid; +} \ No newline at end of file diff --git a/vipra-ui/app/templates/application.hbs b/vipra-ui/app/templates/application.hbs index 395c3aea15e0d260460c1915d17a09130b9d6c82..16d581722917ac881e1cfabd83edc32d3d20c2a5 100644 --- a/vipra-ui/app/templates/application.hbs +++ b/vipra-ui/app/templates/application.hbs @@ -8,26 +8,28 @@ <span class="icon-bar"></span> <span class="icon-bar"></span> </button> - <a class="navbar-brand" href="#">Vipra</a> + {{link-to 'Vipra' 'index' class='navbar-brand'}} </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="vipra-navbar-collapse-1"> <ul class="nav navbar-nav"> - <li class="dropdown"> - <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Browse <span class="caret"></span></a> - <ul class="dropdown-menu"> - <li>{{#link-to 'articles'}}Articles{{/link-to}}</li> - <li>{{#link-to 'topics'}}Topics{{/link-to}}</li> - <li>{{#link-to 'words'}}Words{{/link-to}}</li> - </ul> - </li> + {{#link-to 'articles' tagName='li'}}{{link-to 'Articles' 'articles'}}{{/link-to}} + {{#link-to 'topics' tagName='li'}}{{link-to 'Topics' 'topics'}}{{/link-to}} + {{#link-to 'words' tagName='li'}}{{link-to 'Words' 'words'}}{{/link-to}} {{outlet 'menu-left'}} + <div id="testi"></div> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> -<div class="container-fluid"> +<div class="container"> {{outlet}} -</div> \ No newline at end of file +</div> + +<footer class="footer navbar-default"> + <div class="container-fluid"> + + </div> +</footer> \ No newline at end of file diff --git a/vipra-ui/app/templates/articles/index.hbs b/vipra-ui/app/templates/articles/index.hbs index 69560732e8eda908f365433252148a359a09aa53..de55f79dc3f647407af28147825a8b1137908a4c 100644 --- a/vipra-ui/app/templates/articles/index.hbs +++ b/vipra-ui/app/templates/articles/index.hbs @@ -2,6 +2,9 @@ {{dynamic-high-charts content=model.chartData chartOptions=model.chartOptions}} +{{model.articles.meta.total}} {{pluralize model.articles.meta.total 'article'}} in total. + +<br> {{debounced-input class='form-control' placeholder='Filter' size='50' value=filter debounce='150'}} <br> diff --git a/vipra-ui/app/templates/articles/show.hbs b/vipra-ui/app/templates/articles/show.hbs index a5cc88755e7f6bf5ebfc4c7121b4d3087b6c266d..b4d7a82fe3ef6df6aeb5ba517e31fc23545331e7 100644 --- a/vipra-ui/app/templates/articles/show.hbs +++ b/vipra-ui/app/templates/articles/show.hbs @@ -6,6 +6,14 @@ <td>Date</td> <td>{{model.article.date}}</td> </tr> + <tr> + <td>Created</td> + <td>{{model.article.created}}</td> + </tr> + <tr> + <td>Last modified</td> + <td>{{model.article.modified}}</td> + </tr> <tr> <td>URL</td> <td><a href="{{model.article.url}}">{{model.article.url}}</a></td> @@ -25,4 +33,7 @@ </tbody> </table> -{{model.article.text}} \ No newline at end of file +{{model.article.text}} + +<br><br> +{{scroll-top}} \ No newline at end of file diff --git a/vipra-ui/app/templates/components/scroll-top.hbs b/vipra-ui/app/templates/components/scroll-top.hbs new file mode 100644 index 0000000000000000000000000000000000000000..04bed982c84513c9e059320f8d89af981483b68f --- /dev/null +++ b/vipra-ui/app/templates/components/scroll-top.hbs @@ -0,0 +1,5 @@ +{{#if hasBlock}} + {{yield}} +{{else}} + {{_text}} +{{/if}} \ No newline at end of file diff --git a/vipra-ui/app/templates/index.hbs b/vipra-ui/app/templates/index.hbs index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9573659386866629832c26ddda352f4ca35f80ef 100644 --- a/vipra-ui/app/templates/index.hbs +++ b/vipra-ui/app/templates/index.hbs @@ -0,0 +1,17 @@ +<div class="container"> + <div class="row"> + <div class="col-md-12"> + <div class="text-center"> + <h1>Vipra</h1> + </div> + <input type="text" class="form-control input-lg" placeholder="Search..."> + </div> + </div> + + <div class="row"> + <div class="col-md-12"> + + </div> + </div> + +</div> \ No newline at end of file diff --git a/vipra-ui/package.json b/vipra-ui/package.json index c6a30adb9bcd26b5f9ae9294744d606d487d019a..d1b51b9f483805111bbac94a84298123f28ed6c5 100644 --- a/vipra-ui/package.json +++ b/vipra-ui/package.json @@ -36,6 +36,7 @@ "ember-data": "1.13.15", "ember-disable-proxy-controllers": "^1.0.1", "ember-export-application-global": "^1.0.4", - "ember-highcharts": "0.3.0" + "ember-highcharts": "0.3.0", + "ember-wormhole": "0.3.4" } } diff --git a/vipra-ui/tests/integration/components/scroll-top-test.js b/vipra-ui/tests/integration/components/scroll-top-test.js new file mode 100644 index 0000000000000000000000000000000000000000..26cf1dc6c8992cc76b547be300f7cbd38e982839 --- /dev/null +++ b/vipra-ui/tests/integration/components/scroll-top-test.js @@ -0,0 +1,25 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('scroll-top', 'Integration | Component | scroll top', { + integration: true +}); + +test('it renders', function(assert) { + + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL + + + this.render(hbs`{{scroll-top}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage:" + EOL + + this.render(hbs` + {{#scroll-top}} + template block text + {{/scroll-top}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/vipra-util/src/main/java/de/vipra/util/NestedMap.java b/vipra-util/src/main/java/de/vipra/util/NestedMap.java new file mode 100644 index 0000000000000000000000000000000000000000..183c0ff65d022437d8bab95735affe96b3f12008 --- /dev/null +++ b/vipra-util/src/main/java/de/vipra/util/NestedMap.java @@ -0,0 +1,45 @@ +package de.vipra.util; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +public class NestedMap { + + private Map<String, Object> map = new HashMap<>(); + + public NestedMap() {} + + @JsonCreator + public NestedMap(Map<String, Object> map) { + this.map = map; + } + + @JsonValue + public Map<String, Object> getMap() { + return map; + } + + @SuppressWarnings("unchecked") + public void put(String key, Object value) { + Map<String, Object> current = map; + String[] parts = key.split("\\."); + String name = parts.length > 0 ? parts[parts.length - 1] : key; + + for (int i = 0; i < parts.length - 1; i++) { + Object o = current.get(parts[i]); + if (o == null || !(o instanceof Map)) { + HashMap<String, Object> newMap = new HashMap<>(); + current.put(parts[i], newMap); + current = newMap; + } else { + current = (Map<String, Object>) o; + } + } + + current.put(name, value); + } + +} diff --git a/vipra-util/src/main/java/de/vipra/util/StringUtils.java b/vipra-util/src/main/java/de/vipra/util/StringUtils.java index adeda301024f9a75363d7a010e84b8f183e6222a..f45f5cc3051d6e9b3c8d562ecc9fa990935f1408 100644 --- a/vipra-util/src/main/java/de/vipra/util/StringUtils.java +++ b/vipra-util/src/main/java/de/vipra/util/StringUtils.java @@ -134,4 +134,13 @@ public class StringUtils { return quantity(qty, singular, singular + "s"); } + public static String[] getFields(String fields) { + if (fields == null) + return null; + fields = fields.trim(); + if (fields.length() == 0) + return null; + return fields.split(","); + } + } diff --git a/vipra-util/src/main/java/de/vipra/util/service/DatabaseService.java b/vipra-util/src/main/java/de/vipra/util/service/DatabaseService.java index 324e978c96d3ddf258f53e207060e1a54e370274..fa4bc3494b6527d10a4b930528ed07245199da04 100644 --- a/vipra-util/src/main/java/de/vipra/util/service/DatabaseService.java +++ b/vipra-util/src/main/java/de/vipra/util/service/DatabaseService.java @@ -58,9 +58,9 @@ public class DatabaseService<T extends Model<?>, U> implements Service<T, U, Dat @Override public List<T> getMultiple(Integer skip, Integer limit, String sortBy, String... fields) { Query<T> q = datastore.createQuery(clazz); - if (skip != null) + if (skip != null && skip > 0) q.offset(skip); - if (limit != null) + if (limit != null && limit > 0) q.limit(limit); if (sortBy != null) q.order(sortBy);