From a9551fb608dcbdca0479a82a1f475047363a0cd9 Mon Sep 17 00:00:00 2001 From: Eike Cochu <eike@cochu.com> Date: Sat, 19 Dec 2015 19:08:13 +0100 Subject: [PATCH] extracted some common classes into vipra-util added project reference from vipra-rest to vipra-util turned vipra-ui into an eclipse project for consistency added basic functionality in ui for displaying, filtering articles added highcharts example in ui added favicon madness in ui uodated elasticsearch version in vm provision --- ma-impl.sublime-workspace | 67 ++++++++--- vipra-cmd/.classpath | 1 + vipra-cmd/.project | 7 -- .../main/java/de/vipra/cmd/Configuration.java | 41 ------- .../src/main/java/de/vipra/cmd/Main.java | 13 +- .../src/main/java/de/vipra/cmd/MongoDB.java | 45 ------- .../de/vipra/cmd/option/ImportOption.java | 21 +++- .../src/main/resources}/config.properties | 0 vipra-rest/.classpath | 5 +- vipra-rest/.project | 8 +- .../.settings/org.eclipse.jdt.core.prefs | 6 +- .../org.eclipse.wst.common.component | 3 + ....eclipse.wst.common.project.facet.core.xml | 2 +- vipra-rest/pom.xml | 13 +- .../main/java/de/vipra/rest/Application.java | 2 + .../java/de/vipra/rest/Configuration.java | 50 -------- .../src/main/java/de/vipra/rest/MongoDB.java | 45 ------- .../src/main/java/de/vipra/rest/PATCH.java | 17 +++ .../rest/provider/ObjectMapperProvider.java | 13 +- .../rest/provider/PatchReaderInterceptor.java | 113 ++++++++++++++++++ .../vipra/rest/resource/ArticleResource.java | 20 ++-- .../rest/serializer/ArticleDeserializer.java | 43 ------- .../rest/serializer/ArticleSerializer.java | 40 ------- .../java/de/vipra/rest/serializer/Helper.java | 61 ---------- .../src/main/resources/config.properties | 3 + vipra-rest/src/main/resources/log4j2.xml | 3 +- vipra-rest/src/main/webapp/WEB-INF/web.xml | 2 +- vipra-rest/src/main/webapp/index.jsp | 1 - vipra-ui/.ember-cli | 3 +- vipra-ui/.project | 11 ++ vipra-ui/app/adapters/application.js | 4 +- vipra-ui/app/components/article-list.js | 15 +++ vipra-ui/app/components/debounced-input.js | 14 +++ .../app/components/dynamic-high-charts.js | 15 +++ vipra-ui/app/components/text-marker.js | 18 +++ vipra-ui/app/index.html | 22 +++- vipra-ui/app/models/article.js | 2 +- vipra-ui/app/router.js | 6 +- vipra-ui/app/routes/articles.js | 7 -- vipra-ui/app/routes/articles/list.js | 61 ++++++++++ .../app/routes/{index.js => not-found.js} | 0 vipra-ui/app/templates/articles.hbs | 6 +- vipra-ui/app/templates/articles/list.hbs | 7 ++ vipra-ui/app/templates/articles/new.hbs | 1 + vipra-ui/app/templates/articles/show.hbs | 10 ++ .../app/templates/components/article-list.hbs | 5 + .../templates/components/debounced-input.hbs | 1 + .../components/dynamic-high-charts.hbs | 1 + .../app/templates/components/text-marker.hbs | 1 + vipra-ui/app/templates/index.hbs | 4 +- vipra-ui/app/templates/loading.hbs | 1 + vipra-ui/app/templates/not-found.hbs | 3 + vipra-ui/package.json | 3 +- vipra-ui/public/android-chrome-144x144.png | Bin 0 -> 7703 bytes vipra-ui/public/android-chrome-192x192.png | Bin 0 -> 10711 bytes vipra-ui/public/android-chrome-36x36.png | Bin 0 -> 1410 bytes vipra-ui/public/android-chrome-48x48.png | Bin 0 -> 1942 bytes vipra-ui/public/android-chrome-72x72.png | Bin 0 -> 2999 bytes vipra-ui/public/android-chrome-96x96.png | Bin 0 -> 4704 bytes vipra-ui/public/apple-touch-icon-114x114.png | Bin 0 -> 1818 bytes vipra-ui/public/apple-touch-icon-120x120.png | Bin 0 -> 1895 bytes vipra-ui/public/apple-touch-icon-144x144.png | Bin 0 -> 2304 bytes vipra-ui/public/apple-touch-icon-152x152.png | Bin 0 -> 2362 bytes vipra-ui/public/apple-touch-icon-180x180.png | Bin 0 -> 2826 bytes vipra-ui/public/apple-touch-icon-57x57.png | Bin 0 -> 989 bytes vipra-ui/public/apple-touch-icon-60x60.png | Bin 0 -> 1025 bytes vipra-ui/public/apple-touch-icon-72x72.png | Bin 0 -> 1189 bytes vipra-ui/public/apple-touch-icon-76x76.png | Bin 0 -> 1227 bytes .../public/apple-touch-icon-precomposed.png | Bin 0 -> 4249 bytes vipra-ui/public/apple-touch-icon.png | Bin 0 -> 2826 bytes vipra-ui/public/browserconfig.xml | 12 ++ vipra-ui/public/favicon-16x16.png | Bin 0 -> 673 bytes vipra-ui/public/favicon-194x194.png | Bin 0 -> 7280 bytes vipra-ui/public/favicon-32x32.png | Bin 0 -> 1124 bytes vipra-ui/public/favicon-96x96.png | Bin 0 -> 3394 bytes vipra-ui/public/favicon.ico | Bin 0 -> 15086 bytes vipra-ui/public/manifest.json | 41 +++++++ vipra-ui/public/mstile-144x144.png | Bin 0 -> 4665 bytes vipra-ui/public/mstile-150x150.png | Bin 0 -> 4592 bytes vipra-ui/public/mstile-310x150.png | Bin 0 -> 4923 bytes vipra-ui/public/mstile-310x310.png | Bin 0 -> 10210 bytes vipra-ui/public/mstile-70x70.png | Bin 0 -> 3220 bytes vipra-ui/public/safari-pinned-tab.svg | 36 ++++++ .../components/article-list-test.js | 25 ++++ .../components/debounced-input-test.js | 25 ++++ .../components/dynamic-high-charts-test.js | 25 ++++ .../components/text-marker-test.js | 25 ++++ .../tests/unit/controllers/articles-test.js | 12 ++ .../{articles-test.js => article-test.js} | 2 +- vipra-ui/tests/unit/routes/not-found-test.js | 11 ++ vipra-util/.classpath | 17 +++ vipra-util/.gitignore | 2 + vipra-util/.project | 36 ++++++ .../.settings/org.eclipse.jdt.core.prefs | 12 ++ .../.settings/org.eclipse.m2e.core.prefs | 4 + .../org.eclipse.wst.common.component | 6 + ....eclipse.wst.common.project.facet.core.xml | 7 ++ vipra-util/pom.xml | 52 ++++++++ vipra-util/src/main/java/META-INF/MANIFEST.MF | 3 + .../src/main/java/de/vipra/util/Config.java | 50 ++++++++ .../java/de/vipra/util/ConfigException.java | 11 ++ .../src/main/java/de/vipra/util/Mongo.java | 48 ++++++++ .../src/main/resources/config.properties | 3 + vipra-util/src/main/resources/log4j2.xml | 14 +++ vm/bootstrap.sh | 2 +- 105 files changed, 929 insertions(+), 418 deletions(-) delete mode 100644 vipra-cmd/src/main/java/de/vipra/cmd/Configuration.java delete mode 100644 vipra-cmd/src/main/java/de/vipra/cmd/MongoDB.java rename {vipra-config => vipra-cmd/src/main/resources}/config.properties (100%) delete mode 100644 vipra-rest/src/main/java/de/vipra/rest/Configuration.java delete mode 100644 vipra-rest/src/main/java/de/vipra/rest/MongoDB.java create mode 100644 vipra-rest/src/main/java/de/vipra/rest/PATCH.java create mode 100644 vipra-rest/src/main/java/de/vipra/rest/provider/PatchReaderInterceptor.java delete mode 100644 vipra-rest/src/main/java/de/vipra/rest/serializer/ArticleDeserializer.java delete mode 100644 vipra-rest/src/main/java/de/vipra/rest/serializer/ArticleSerializer.java delete mode 100644 vipra-rest/src/main/java/de/vipra/rest/serializer/Helper.java create mode 100644 vipra-rest/src/main/resources/config.properties delete mode 100644 vipra-rest/src/main/webapp/index.jsp create mode 100644 vipra-ui/.project create mode 100644 vipra-ui/app/components/article-list.js create mode 100644 vipra-ui/app/components/debounced-input.js create mode 100644 vipra-ui/app/components/dynamic-high-charts.js create mode 100644 vipra-ui/app/components/text-marker.js delete mode 100644 vipra-ui/app/routes/articles.js create mode 100644 vipra-ui/app/routes/articles/list.js rename vipra-ui/app/routes/{index.js => not-found.js} (100%) create mode 100644 vipra-ui/app/templates/articles/list.hbs create mode 100644 vipra-ui/app/templates/articles/new.hbs create mode 100644 vipra-ui/app/templates/articles/show.hbs create mode 100644 vipra-ui/app/templates/components/article-list.hbs create mode 100644 vipra-ui/app/templates/components/debounced-input.hbs create mode 100644 vipra-ui/app/templates/components/dynamic-high-charts.hbs create mode 100644 vipra-ui/app/templates/components/text-marker.hbs create mode 100644 vipra-ui/app/templates/loading.hbs create mode 100644 vipra-ui/app/templates/not-found.hbs create mode 100644 vipra-ui/public/android-chrome-144x144.png create mode 100644 vipra-ui/public/android-chrome-192x192.png create mode 100644 vipra-ui/public/android-chrome-36x36.png create mode 100644 vipra-ui/public/android-chrome-48x48.png create mode 100644 vipra-ui/public/android-chrome-72x72.png create mode 100644 vipra-ui/public/android-chrome-96x96.png create mode 100644 vipra-ui/public/apple-touch-icon-114x114.png create mode 100644 vipra-ui/public/apple-touch-icon-120x120.png create mode 100644 vipra-ui/public/apple-touch-icon-144x144.png create mode 100644 vipra-ui/public/apple-touch-icon-152x152.png create mode 100644 vipra-ui/public/apple-touch-icon-180x180.png create mode 100644 vipra-ui/public/apple-touch-icon-57x57.png create mode 100644 vipra-ui/public/apple-touch-icon-60x60.png create mode 100644 vipra-ui/public/apple-touch-icon-72x72.png create mode 100644 vipra-ui/public/apple-touch-icon-76x76.png create mode 100644 vipra-ui/public/apple-touch-icon-precomposed.png create mode 100644 vipra-ui/public/apple-touch-icon.png create mode 100644 vipra-ui/public/browserconfig.xml create mode 100644 vipra-ui/public/favicon-16x16.png create mode 100644 vipra-ui/public/favicon-194x194.png create mode 100644 vipra-ui/public/favicon-32x32.png create mode 100644 vipra-ui/public/favicon-96x96.png create mode 100644 vipra-ui/public/favicon.ico create mode 100644 vipra-ui/public/manifest.json create mode 100644 vipra-ui/public/mstile-144x144.png create mode 100644 vipra-ui/public/mstile-150x150.png create mode 100644 vipra-ui/public/mstile-310x150.png create mode 100644 vipra-ui/public/mstile-310x310.png create mode 100644 vipra-ui/public/mstile-70x70.png create mode 100644 vipra-ui/public/safari-pinned-tab.svg create mode 100644 vipra-ui/tests/integration/components/article-list-test.js create mode 100644 vipra-ui/tests/integration/components/debounced-input-test.js create mode 100644 vipra-ui/tests/integration/components/dynamic-high-charts-test.js create mode 100644 vipra-ui/tests/integration/components/text-marker-test.js create mode 100644 vipra-ui/tests/unit/controllers/articles-test.js rename vipra-ui/tests/unit/routes/{articles-test.js => article-test.js} (80%) create mode 100644 vipra-ui/tests/unit/routes/not-found-test.js create mode 100644 vipra-util/.classpath create mode 100644 vipra-util/.gitignore create mode 100644 vipra-util/.project create mode 100644 vipra-util/.settings/org.eclipse.jdt.core.prefs create mode 100644 vipra-util/.settings/org.eclipse.m2e.core.prefs create mode 100644 vipra-util/.settings/org.eclipse.wst.common.component create mode 100644 vipra-util/.settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 vipra-util/pom.xml create mode 100644 vipra-util/src/main/java/META-INF/MANIFEST.MF create mode 100644 vipra-util/src/main/java/de/vipra/util/Config.java create mode 100644 vipra-util/src/main/java/de/vipra/util/ConfigException.java create mode 100644 vipra-util/src/main/java/de/vipra/util/Mongo.java create mode 100644 vipra-util/src/main/resources/config.properties create mode 100644 vipra-util/src/main/resources/log4j2.xml diff --git a/ma-impl.sublime-workspace b/ma-impl.sublime-workspace index 12a293e2..01b7a763 100644 --- a/ma-impl.sublime-workspace +++ b/ma-impl.sublime-workspace @@ -279,18 +279,18 @@ "build_varint": "", "command_palette": { - "height": 375.0, - "last_filter": "close", + "height": 231.0, + "last_filter": "insta", "selected_items": [ - [ - "close", - "Project: Close" - ], [ "insta", "Package Control: Install Package" ], + [ + "close", + "Project: Close" + ], [ "synr", "Set Syntax: R" @@ -450,23 +450,54 @@ "expanded_folders": [ "/home/eike/Repositories/fu/ss15/ma/impl", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui" + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/components", + "/home/eike/Repositories/fu/ss15/ma/impl/vm" ], "file_history": [ - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/bower.json", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/bower_components/ember/ember.js", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/routes/articles.js", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/package.json", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/components/article-list.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/components/text-marker.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/components/debounced-input.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/components/dynamic-high-charts.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/components/text-marker.hbs", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/components/article-list.hbs", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles/list.hbs", + "/home/eike/Repositories/fu/ss15/ma/impl/vm/bootstrap.sh", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/adapters/application.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/routes/articles/list.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles/show.hbs", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/components/filter-text.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vm/webapps/test/index.html", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/controllers/articles/list.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/router.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/index.html", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/components/search-box.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/loading.hbs", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/not-found.hbs", "/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/router.js", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/adapters/application.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.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles.show.hbs", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/routes/articles.show.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/articles/test.hbs", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/.ember-cli", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/bower_components/ember-data/ember-data.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/bower_components/ember/ember.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/application.hbs", "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/serializers/application.js", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/bower.json", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/bower_components/ember/.bower.json", + "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/package.json", "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/app.js", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/application.hbs", - "/home/eike/Repositories/fu/ss15/ma/impl/vipra-ui/app/templates/index.hbs", - "/home/eike/Repositories/fu/ss15/ma/impl/vm/bootstrap.sh", "/home/eike/Repositories/fu/ss15/ma/doc/thesis/thesis.tex", "/home/eike/Repositories/fu/ss15/ma/impl/Vagrantfile", "/home/eike/Repositories/fu/ss15/ma/impl/tmbs-processor-backend/src/main/scala/de/cochu/tmbs/processor/MongoDBTest.scala", @@ -583,6 +614,7 @@ "case_sensitive": false, "find_history": [ + "json-api", "\"id\":.*?\\n ", "\"id\":.*?\\n", "\"_id\":", @@ -709,8 +741,7 @@ "!important", "images", "url(\"../images/", - "fa-var", - "account.name" + "fa-var" ], "highlight": true, "in_selection": false, diff --git a/vipra-cmd/.classpath b/vipra-cmd/.classpath index 91251671..1d99666b 100644 --- a/vipra-cmd/.classpath +++ b/vipra-cmd/.classpath @@ -15,5 +15,6 @@ <attribute name="owner.project.facets" value="java"/> </attributes> </classpathentry> + <classpathentry combineaccessrules="false" kind="src" path="/vipra-util"/> <classpathentry kind="output" path="target/classes"/> </classpath> diff --git a/vipra-cmd/.project b/vipra-cmd/.project index 7457abc9..42d5a8ab 100644 --- a/vipra-cmd/.project +++ b/vipra-cmd/.project @@ -33,11 +33,4 @@ <nature>org.eclipse.m2e.core.maven2Nature</nature> <nature>org.eclipse.wst.common.project.facet.core.nature</nature> </natures> - <linkedResources> - <link> - <name>src/main/resources/config.properties</name> - <type>1</type> - <locationURI>PARENT-1-PROJECT_LOC/vipra-config/config.properties</locationURI> - </link> - </linkedResources> </projectDescription> diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/Configuration.java b/vipra-cmd/src/main/java/de/vipra/cmd/Configuration.java deleted file mode 100644 index c3077699..00000000 --- a/vipra-cmd/src/main/java/de/vipra/cmd/Configuration.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.vipra.cmd; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -public class Configuration extends Properties { - - private static final long serialVersionUID = 1L; - - public static final String DEFAULT_HOST = "localhost"; - public static final int DEFAULT_PORT = 27017; - public static final String DEFAULT_DB = "test"; - - public Configuration() { - this(Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties")); - } - - public Configuration(InputStream in) { - try { - load(in); - } catch (IOException e) {} - } - - public String getString(String key, String defaultValue) { - return getProperty(key, defaultValue); - } - - public int getInt(String key, int defaultValue) { - try { - return Integer.parseInt(getProperty(key, Integer.toString(defaultValue))); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public boolean getBool(String key, boolean defaultValue) { - return Boolean.parseBoolean(getProperty(key, Boolean.toString(defaultValue))); - } - -} diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/Main.java b/vipra-cmd/src/main/java/de/vipra/cmd/Main.java index 34ea6ee6..287f10cc 100644 --- a/vipra-cmd/src/main/java/de/vipra/cmd/Main.java +++ b/vipra-cmd/src/main/java/de/vipra/cmd/Main.java @@ -1,15 +1,22 @@ package de.vipra.cmd; +import java.io.IOException; + import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.ParseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import de.vipra.cmd.option.ImportOption; +import de.vipra.util.ConfigException; public class Main { - public static void main(String[] args) { + public static final Logger log = LoggerFactory.getLogger(Main.class); + + public static void main(String[] args) throws IOException, ConfigException { CommandLineParser parser = new DefaultParser(); CmdOptions options = new CmdOptions(); try { @@ -25,7 +32,9 @@ public class Main { } } catch (ParseException e) { options.printHelp(); - } catch (ExecutionException e) {} + } catch (ExecutionException e) { + log.error(e.getMessage()); + } } } diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/MongoDB.java b/vipra-cmd/src/main/java/de/vipra/cmd/MongoDB.java deleted file mode 100644 index 9025c1bd..00000000 --- a/vipra-cmd/src/main/java/de/vipra/cmd/MongoDB.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.vipra.cmd; - -import com.mongodb.MongoClient; -import com.mongodb.client.MongoDatabase; - -public class MongoDB { - - private static MongoDB mongo; - - private final MongoClient client; - private final MongoDatabase db; - - private MongoDB(Configuration config) { - String host = config.getString("db.host", Configuration.DEFAULT_HOST); - Integer port = config.getInt("db.port", Configuration.DEFAULT_PORT); - String databaseName = config.getString("db.name", Configuration.DEFAULT_DB); - - client = new MongoClient(host, port); - db = client.getDatabase(databaseName); - } - - public MongoClient getClient() { - return client; - } - - public MongoDatabase getDatabase() { - return db; - } - - public static MongoDB getInstance() { - if (mongo == null) { - Configuration config = new Configuration(); - mongo = new MongoDB(config); - } - return mongo; - } - - public static MongoDB getInstance(Configuration config) { - if (mongo == null) { - mongo = new MongoDB(config); - } - return mongo; - } - -} diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportOption.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportOption.java index 25b02a08..e8a61d32 100644 --- a/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportOption.java +++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportOption.java @@ -12,15 +12,24 @@ import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import de.vipra.cmd.ExecutionException; -import de.vipra.cmd.MongoDB; +import de.vipra.util.Config; +import de.vipra.util.ConfigException; +import de.vipra.util.Mongo; public class ImportOption { private ArrayList<File> files = new ArrayList<>(); private JSONParser parser = new JSONParser(); - private MongoDB mongo = MongoDB.getInstance(); + private Config config; + private Mongo mongo; public ImportOption(String[] paths) throws ExecutionException { + try { + config = new Config(); + mongo = Mongo.getInstance(config); + } catch (IOException | ConfigException e) { + throw new ExecutionException(e.getMessage()); + } addPaths(paths); } @@ -70,14 +79,18 @@ public class ImportOption { } private void importArticle(JSONObject obj) { - + // 1. add article to mongodb + // 2. add article to file database + // 4. topic modeling + // 3. index article via elasticsearch, include topics } public void doImport() { for (File file : files) { try { importFile(file); - } catch (Exception e) {} + } catch (Exception e) { + } } } diff --git a/vipra-config/config.properties b/vipra-cmd/src/main/resources/config.properties similarity index 100% rename from vipra-config/config.properties rename to vipra-cmd/src/main/resources/config.properties diff --git a/vipra-rest/.classpath b/vipra-rest/.classpath index 6acf3eee..d8728319 100644 --- a/vipra-rest/.classpath +++ b/vipra-rest/.classpath @@ -28,10 +28,11 @@ <attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/> </attributes> </classpathentry> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"> <attributes> - <attribute name="maven.pomderived" value="true"/> + <attribute name="owner.project.facets" value="java"/> </attributes> </classpathentry> + <classpathentry combineaccessrules="false" kind="src" path="/vipra-util"/> <classpathentry kind="output" path="target/classes"/> </classpath> diff --git a/vipra-rest/.project b/vipra-rest/.project index e9151f1e..e24244ea 100644 --- a/vipra-rest/.project +++ b/vipra-rest/.project @@ -4,6 +4,7 @@ <comment></comment> <projects> <project>vipra-cmd</project> + <project>vipra-util</project> </projects> <buildSpec> <buildCommand> @@ -40,11 +41,4 @@ <nature>org.eclipse.wst.common.project.facet.core.nature</nature> <nature>org.eclipse.wst.jsdt.core.jsNature</nature> </natures> - <linkedResources> - <link> - <name>src/main/resources/config.properties</name> - <type>1</type> - <locationURI>PARENT-1-PROJECT_LOC/vipra-config/config.properties</locationURI> - </link> - </linkedResources> </projectDescription> diff --git a/vipra-rest/.settings/org.eclipse.jdt.core.prefs b/vipra-rest/.settings/org.eclipse.jdt.core.prefs index c07c252b..7677f45f 100644 --- a/vipra-rest/.settings/org.eclipse.jdt.core.prefs +++ b/vipra-rest/.settings/org.eclipse.jdt.core.prefs @@ -1,16 +1,16 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.source=1.7 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 diff --git a/vipra-rest/.settings/org.eclipse.wst.common.component b/vipra-rest/.settings/org.eclipse.wst.common.component index bfc7ecd2..df9f1cfb 100644 --- a/vipra-rest/.settings/org.eclipse.wst.common.component +++ b/vipra-rest/.settings/org.eclipse.wst.common.component @@ -4,6 +4,9 @@ <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/> + <dependent-module archiveName="vipra-util.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/vipra-util/vipra-util"> + <dependency-type>uses</dependency-type> + </dependent-module> <property name="java-output-path" value="/vipra-rest/target/classes"/> <property name="context-root" value="vipra-rest"/> </wb-module> diff --git a/vipra-rest/.settings/org.eclipse.wst.common.project.facet.core.xml b/vipra-rest/.settings/org.eclipse.wst.common.project.facet.core.xml index d59fb58d..98434174 100644 --- a/vipra-rest/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/vipra-rest/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -4,5 +4,5 @@ <installed facet="wst.jsdt.web" version="1.0"/> <installed facet="jst.jaxrs" version="2.0"/> <installed facet="jst.web" version="3.1"/> - <installed facet="java" version="1.8"/> + <installed facet="java" version="1.7"/> </faceted-project> diff --git a/vipra-rest/pom.xml b/vipra-rest/pom.xml index 804ffc36..a7b384aa 100644 --- a/vipra-rest/pom.xml +++ b/vipra-rest/pom.xml @@ -12,8 +12,8 @@ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <maven.compiler.target>1.8</maven.compiler.target> - <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.7</maven.compiler.target> + <maven.compiler.source>1.7</maven.compiler.source> <jerseyVersion>2.22.1</jerseyVersion> <jettyVersion>9.3.6.v20151106</jettyVersion> <servletVersion>3.1.0</servletVersion> @@ -29,7 +29,7 @@ </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> - <!--<artifactId>jersey-media-moxy</artifactId>--> + <!--<artifactId>jersey-media-moxy</artifactId> --> <artifactId>jersey-media-json-jackson</artifactId> <version>${jerseyVersion}</version> </dependency> @@ -43,6 +43,11 @@ <artifactId>jersey-test-framework-provider-simple</artifactId> <version>${jerseyVersion}</version> </dependency> + <dependency> + <groupId>com.github.fge</groupId> + <artifactId>json-patch</artifactId> + <version>1.9</version> + </dependency> <!-- Servlet API --> <dependency> @@ -50,7 +55,7 @@ <artifactId>javax.servlet-api</artifactId> <version>${servletVersion}</version> </dependency> - + <!-- Logging --> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/vipra-rest/src/main/java/de/vipra/rest/Application.java b/vipra-rest/src/main/java/de/vipra/rest/Application.java index 632b4c8f..3a105f81 100644 --- a/vipra-rest/src/main/java/de/vipra/rest/Application.java +++ b/vipra-rest/src/main/java/de/vipra/rest/Application.java @@ -6,6 +6,7 @@ import org.glassfish.jersey.server.ResourceConfig; import de.vipra.rest.provider.APIRequestFilter; import de.vipra.rest.provider.CORSResponseFilter; import de.vipra.rest.provider.ObjectMapperProvider; +import de.vipra.rest.provider.PatchReaderInterceptor; public class Application extends ResourceConfig { @@ -15,6 +16,7 @@ public class Application extends ResourceConfig { register(CORSResponseFilter.class); register(ObjectMapperProvider.class); register(APIRequestFilter.class); + register(PatchReaderInterceptor.class); } } diff --git a/vipra-rest/src/main/java/de/vipra/rest/Configuration.java b/vipra-rest/src/main/java/de/vipra/rest/Configuration.java deleted file mode 100644 index 30b9795d..00000000 --- a/vipra-rest/src/main/java/de/vipra/rest/Configuration.java +++ /dev/null @@ -1,50 +0,0 @@ -package de.vipra.rest; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Configuration extends Properties { - - public static final Logger log = LoggerFactory.getLogger(Configuration.class); - - private static final long serialVersionUID = 1L; - - public static final String DEFAULT_HOST = "localhost"; - public static final int DEFAULT_PORT = 27017; - public static final String DEFAULT_DB = "test"; - - public Configuration() { - this(Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties")); - } - - public Configuration(InputStream in) { - if (in == null) { - log.error("configuration file stream not found"); - } else { - try { - load(in); - } catch (IOException e) {} - } - } - - public String getString(String key, String defaultValue) { - return getProperty(key, defaultValue); - } - - public int getInt(String key, int defaultValue) { - try { - return Integer.parseInt(getProperty(key, Integer.toString(defaultValue))); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public boolean getBool(String key, boolean defaultValue) { - return Boolean.parseBoolean(getProperty(key, Boolean.toString(defaultValue))); - } - -} diff --git a/vipra-rest/src/main/java/de/vipra/rest/MongoDB.java b/vipra-rest/src/main/java/de/vipra/rest/MongoDB.java deleted file mode 100644 index e219cf39..00000000 --- a/vipra-rest/src/main/java/de/vipra/rest/MongoDB.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.vipra.rest; - -import com.mongodb.MongoClient; -import com.mongodb.client.MongoDatabase; - -public class MongoDB { - - private static MongoDB mongo; - - private final MongoClient client; - private final MongoDatabase db; - - private MongoDB(Configuration config) { - String host = config.getString("db.host", Configuration.DEFAULT_HOST); - Integer port = config.getInt("db.port", Configuration.DEFAULT_PORT); - String databaseName = config.getString("db.name", Configuration.DEFAULT_DB); - - client = new MongoClient(host, port); - db = client.getDatabase(databaseName); - } - - public MongoClient getClient() { - return client; - } - - public MongoDatabase getDatabase() { - return db; - } - - public static MongoDB getInstance() { - if (mongo == null) { - Configuration config = new Configuration(); - mongo = new MongoDB(config); - } - return mongo; - } - - public static MongoDB getInstance(Configuration config) { - if (mongo == null) { - mongo = new MongoDB(config); - } - return mongo; - } - -} diff --git a/vipra-rest/src/main/java/de/vipra/rest/PATCH.java b/vipra-rest/src/main/java/de/vipra/rest/PATCH.java new file mode 100644 index 00000000..78b80504 --- /dev/null +++ b/vipra-rest/src/main/java/de/vipra/rest/PATCH.java @@ -0,0 +1,17 @@ +package de.vipra.rest; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.ws.rs.HttpMethod; +import javax.ws.rs.NameBinding; + +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@HttpMethod("PATCH") +@Documented +@NameBinding +public @interface PATCH {} \ No newline at end of file diff --git a/vipra-rest/src/main/java/de/vipra/rest/provider/ObjectMapperProvider.java b/vipra-rest/src/main/java/de/vipra/rest/provider/ObjectMapperProvider.java index b818a5f9..7678b4b0 100644 --- a/vipra-rest/src/main/java/de/vipra/rest/provider/ObjectMapperProvider.java +++ b/vipra-rest/src/main/java/de/vipra/rest/provider/ObjectMapperProvider.java @@ -1,5 +1,7 @@ package de.vipra.rest.provider; +import java.text.SimpleDateFormat; + import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; @@ -9,11 +11,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.module.SimpleModule; - -import de.vipra.rest.model.Article; -import de.vipra.rest.serializer.ArticleDeserializer; -import de.vipra.rest.serializer.ArticleSerializer; @Provider public class ObjectMapperProvider implements ContextResolver<ObjectMapper> { @@ -32,14 +29,10 @@ public class ObjectMapperProvider implements ContextResolver<ObjectMapper> { } public static ObjectMapper createDefaultMapper() { - SimpleModule module = new SimpleModule(); - module.addSerializer(Article.class, new ArticleSerializer()); - module.addDeserializer(Article.class, new ArticleDeserializer()); - final ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.setSerializationInclusion(Include.NON_NULL); - mapper.registerModule(module); + mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")); return mapper; } diff --git a/vipra-rest/src/main/java/de/vipra/rest/provider/PatchReaderInterceptor.java b/vipra-rest/src/main/java/de/vipra/rest/provider/PatchReaderInterceptor.java new file mode 100644 index 00000000..ea7f7242 --- /dev/null +++ b/vipra-rest/src/main/java/de/vipra/rest/provider/PatchReaderInterceptor.java @@ -0,0 +1,113 @@ +package de.vipra.rest.provider; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import com.github.fge.jsonpatch.JsonPatch; +import com.github.fge.jsonpatch.JsonPatchException; + +import de.vipra.rest.PATCH; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import javax.ws.rs.GET; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; + +import org.glassfish.jersey.message.MessageBodyWorkers; + +@Provider +@PATCH +public class PatchReaderInterceptor implements ReaderInterceptor { + private UriInfo info; + private MessageBodyWorkers workers; + + @Context + public void setInfo(UriInfo info) { + this.info = info; + } + + @Context + public void setWorkers(MessageBodyWorkers workers) { + this.workers = workers; + } + + @Override + public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) + throws IOException, WebApplicationException { + + // Get the resource we are being called on, + // and find the GET method + Object resource = info.getMatchedResources().get(0); + + Method found = null; + for (Method next : resource.getClass().getMethods()) { + if (next.getAnnotation(GET.class) != null) { + found = next; + break; + } + } + + if (found != null) { + + // Invoke the get method to get the state we are trying to patch + // + Object bean; + try { + bean = found.invoke(resource); + } catch (Exception e) { + throw new WebApplicationException(e); + } + + // Convert this object to a an aray of bytes + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + MessageBodyWriter<? super Object> bodyWriter = workers.getMessageBodyWriter(Object.class, bean.getClass(), + new Annotation[0], MediaType.APPLICATION_JSON_TYPE); + + bodyWriter.writeTo(bean, bean.getClass(), bean.getClass(), new Annotation[0], + MediaType.APPLICATION_JSON_TYPE, new MultivaluedHashMap<String, Object>(), baos); + + // Use the Jackson 2.x classes to convert both the incoming patch + // and the current state of the object into a JsonNode / JsonPatch + ObjectMapper mapper = new ObjectMapper(); + JsonNode serverState = mapper.readValue(baos.toByteArray(), JsonNode.class); + JsonNode patchAsNode = mapper.readValue(readerInterceptorContext.getInputStream(), JsonNode.class); + JsonPatch patch = JsonPatch.fromJson(patchAsNode); + + try { + // Apply the patch + JsonNode result = patch.apply(serverState); + + // Stream the result & modify the stream on the + // readerInterceptor + ByteArrayOutputStream resultAsByteArray = new ByteArrayOutputStream(); + mapper.writeValue(resultAsByteArray, result); + readerInterceptorContext.setInputStream(new ByteArrayInputStream(resultAsByteArray.toByteArray())); + + // Pass control back to the Jersey code + return readerInterceptorContext.proceed(); + + } catch (JsonPatchException e) { + throw new WebApplicationException( + Response.serverError().type("text/plain").entity(e.getMessage()).build()); + } + + } else { + throw new IllegalArgumentException("No matching GET method on resource"); + } + + } +} 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 605a80ea..cc353378 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 @@ -1,6 +1,6 @@ package de.vipra.rest.resource; -import java.io.InputStream; +import java.io.IOException; import java.util.ArrayList; import javax.servlet.ServletContext; @@ -19,13 +19,14 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import de.vipra.rest.APIMediaType; -import de.vipra.rest.Configuration; import de.vipra.rest.Messages; -import de.vipra.rest.MongoDB; import de.vipra.rest.model.APIError; import de.vipra.rest.model.Article; import de.vipra.rest.model.ResponseWrapper; import de.vipra.rest.service.ArticleService; +import de.vipra.util.Config; +import de.vipra.util.ConfigException; +import de.vipra.util.Mongo; @Path("articles") public class ArticleResource { @@ -35,10 +36,9 @@ public class ArticleResource { final ArticleService service; - public ArticleResource(@Context ServletContext servletContext) { - InputStream is = servletContext.getResourceAsStream("config.properties"); - Configuration config = new Configuration(is); - MongoDB mongo = MongoDB.getInstance(config); + public ArticleResource(@Context ServletContext servletContext) throws ConfigException, IOException { + Config config = new Config(); + Mongo mongo = Mongo.getInstance(config); service = new ArticleService(mongo.getDatabase()); } @@ -88,7 +88,8 @@ public class ArticleResource { @Path("{id}") public Response deleteArticle(@PathParam("id") String id) { long deleted = service.deleteArticle(id); - switch (Math.toIntExact(deleted)) { + int del = deleted > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) deleted; + switch (del) { case 0: ResponseWrapper<Article> res = new ResponseWrapper<>(); res.addError(new APIError(Response.Status.NOT_FOUND, "Article not found", @@ -107,8 +108,9 @@ public class ArticleResource { @Path("{id}") public Response updateArticle(@PathParam("id") String id, Article article) { long updated = service.updateArticle(uri.getAbsolutePath(), article); + int upd = updated > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) updated; ResponseWrapper<Article> res = new ResponseWrapper<>(); - switch (Math.toIntExact(updated)) { + switch (upd) { case 0: res.addError(new APIError(Response.Status.NOT_FOUND, "Article not found", String.format(Messages.NOT_FOUND, "article", id))); diff --git a/vipra-rest/src/main/java/de/vipra/rest/serializer/ArticleDeserializer.java b/vipra-rest/src/main/java/de/vipra/rest/serializer/ArticleDeserializer.java deleted file mode 100644 index 54152e0b..00000000 --- a/vipra-rest/src/main/java/de/vipra/rest/serializer/ArticleDeserializer.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.vipra.rest.serializer; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import de.vipra.rest.model.Article; - -import static de.vipra.rest.serializer.Helper.*; - -public class ArticleDeserializer extends JsonDeserializer<Article> { - - @Override - public Article deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - Article article = null; - - JsonNode node = p.readValueAsTree(); - if (node != null) { - article = new Article(); - if (node.has("id")) - article.setId(getString(node, "id")); - - if (node.has("attributes")) { - JsonNode attrs = node.get("attributes"); - if (attrs.has("title")) - article.setTitle(getString(attrs, "title")); - if (attrs.has("text")) - article.setText(getString(attrs, "text")); - if (attrs.has("url")) - article.setUrl(getString(attrs, "url")); - if (attrs.has("date")) - article.setDate(stringToDate(getString(attrs, "date"))); - } - } - - return article; - } - -} diff --git a/vipra-rest/src/main/java/de/vipra/rest/serializer/ArticleSerializer.java b/vipra-rest/src/main/java/de/vipra/rest/serializer/ArticleSerializer.java deleted file mode 100644 index b5ce97f9..00000000 --- a/vipra-rest/src/main/java/de/vipra/rest/serializer/ArticleSerializer.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.vipra.rest.serializer; - -import de.vipra.rest.model.Article; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -import static de.vipra.rest.serializer.Helper.*; - -public class ArticleSerializer extends JsonSerializer<Article> { - - @Override - public void serialize(Article value, JsonGenerator gen, SerializerProvider serializers) - throws IOException, JsonProcessingException { - gen.writeStartObject(); - gen.writeStringField("id", value.getId()); - gen.writeStringField("type", value.getType()); - - if (value.getLinks() != null) - gen.writeObjectField("links", value.getLinks()); - - gen.writeObjectFieldStart("attributes"); - if (value.getTitle() != null) - gen.writeStringField("title", value.getTitle()); - if (value.getText() != null) - gen.writeStringField("text", value.getText()); - if (value.getUrl() != null) - gen.writeStringField("url", value.getUrl()); - if (value.getDate() != null) - gen.writeStringField("date", dateToString(value.getDate())); - gen.writeEndObject(); - - gen.writeEndObject(); - } - -} diff --git a/vipra-rest/src/main/java/de/vipra/rest/serializer/Helper.java b/vipra-rest/src/main/java/de/vipra/rest/serializer/Helper.java deleted file mode 100644 index 09dd2d5d..00000000 --- a/vipra-rest/src/main/java/de/vipra/rest/serializer/Helper.java +++ /dev/null @@ -1,61 +0,0 @@ -package de.vipra.rest.serializer; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import com.fasterxml.jackson.databind.JsonNode; - -public class Helper { - - public static <T> T get(JsonNode node, String name, T defaultValue, Class<T> type) { - if (node == null) { - return defaultValue; - } - node = node.get(name); - if (node == null) { - return defaultValue; - } - switch (type.getSimpleName()) { - case "String": - return type.cast(node.asText()); - case "Integer": - return type.cast(node.asInt()); - case "Long": - return type.cast(node.asLong()); - } - return null; - } - - public static String getString(JsonNode node, String name, String defaultValue) { - return get(node, name, defaultValue, String.class); - } - - public static String getString(JsonNode node, String name) { - return getString(node, name, null); - } - - public static long getLong(JsonNode node, String name, long defaultValue) { - return get(node, name, defaultValue, Long.class); - } - - public static long getLong(JsonNode node, String name) { - return getLong(node, name, 0L); - } - - public static String dateToString(Date date) { - DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - return df.format(date); - } - - public static Date stringToDate(String source) { - DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - try { - return df.parse(source); - } catch (ParseException e) { - return null; - } - } - -} diff --git a/vipra-rest/src/main/resources/config.properties b/vipra-rest/src/main/resources/config.properties new file mode 100644 index 00000000..07030840 --- /dev/null +++ b/vipra-rest/src/main/resources/config.properties @@ -0,0 +1,3 @@ +db.host=localhost +db.port=27017 +db.name=test \ No newline at end of file diff --git a/vipra-rest/src/main/resources/log4j2.xml b/vipra-rest/src/main/resources/log4j2.xml index 8abf1b19..87133400 100644 --- a/vipra-rest/src/main/resources/log4j2.xml +++ b/vipra-rest/src/main/resources/log4j2.xml @@ -6,8 +6,9 @@ </Console> </Appenders> <Loggers> - <Root level="all"> + <Root level="ALL"> <AppenderRef ref="Console" /> </Root> + <Logger name="org.mongodb" level="INFO"/> </Loggers> </Configuration> \ No newline at end of file diff --git a/vipra-rest/src/main/webapp/WEB-INF/web.xml b/vipra-rest/src/main/webapp/WEB-INF/web.xml index dc73bea3..3cfd9841 100644 --- a/vipra-rest/src/main/webapp/WEB-INF/web.xml +++ b/vipra-rest/src/main/webapp/WEB-INF/web.xml @@ -13,6 +13,6 @@ </servlet> <servlet-mapping> <servlet-name>jersey</servlet-name> - <url-pattern>/rest/*</url-pattern> + <url-pattern>/*</url-pattern> </servlet-mapping> </web-app> \ No newline at end of file diff --git a/vipra-rest/src/main/webapp/index.jsp b/vipra-rest/src/main/webapp/index.jsp deleted file mode 100644 index d4fb745c..00000000 --- a/vipra-rest/src/main/webapp/index.jsp +++ /dev/null @@ -1 +0,0 @@ -<jsp:forward page="rest/application.wadl"/> \ No newline at end of file diff --git a/vipra-ui/.ember-cli b/vipra-ui/.ember-cli index 4d87e572..ee64cfed 100644 --- a/vipra-ui/.ember-cli +++ b/vipra-ui/.ember-cli @@ -5,6 +5,5 @@ Setting `disableAnalytics` to true will prevent any data from being sent. */ - "disableAnalytics": false, - "liveReload": false + "disableAnalytics": false } diff --git a/vipra-ui/.project b/vipra-ui/.project new file mode 100644 index 00000000..6f683a49 --- /dev/null +++ b/vipra-ui/.project @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>vipra-ui</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + </buildSpec> + <natures> + </natures> +</projectDescription> diff --git a/vipra-ui/app/adapters/application.js b/vipra-ui/app/adapters/application.js index dff62265..701dadac 100644 --- a/vipra-ui/app/adapters/application.js +++ b/vipra-ui/app/adapters/application.js @@ -1,6 +1,6 @@ import DS from 'ember-data'; export default DS.JSONAPIAdapter.extend({ - host: 'http://localhost:8080', - namespace: 'vipra-rest/rest' + host: `http://${window.location.hostname}:8000`, + namespace: 'vipra-rest' }); diff --git a/vipra-ui/app/components/article-list.js b/vipra-ui/app/components/article-list.js new file mode 100644 index 00000000..afa75e43 --- /dev/null +++ b/vipra-ui/app/components/article-list.js @@ -0,0 +1,15 @@ +import Ember from 'ember'; + + export default Ember.Component.extend({ + + filteredArticles: Ember.computed('articles', 'filter', function() { + var keyword = this.get('filter'); + var filtered = this.get('articles'); + if (keyword) { + keyword = keyword.toLowerCase().trim(); + filtered = this.get('articles').filter((item) => item.get('title').toLowerCase().includes(keyword)); + } + return filtered; + }) + + }); diff --git a/vipra-ui/app/components/debounced-input.js b/vipra-ui/app/components/debounced-input.js new file mode 100644 index 00000000..5eee646f --- /dev/null +++ b/vipra-ui/app/components/debounced-input.js @@ -0,0 +1,14 @@ +import Ember from 'ember'; + +export default Ember.TextField.extend({ + debounce: 500, + fireAtStart: false, + + _elementValueDidChange() { + Ember.run.debounce(this, this._setValue, this.debounce, this.fireAtStart); + }, + + _setValue() { + this.set('value', this.$().val()); + } +}); diff --git a/vipra-ui/app/components/dynamic-high-charts.js b/vipra-ui/app/components/dynamic-high-charts.js new file mode 100644 index 00000000..730778b1 --- /dev/null +++ b/vipra-ui/app/components/dynamic-high-charts.js @@ -0,0 +1,15 @@ +import Ember from 'ember'; +import EmberHighChartsComponent from 'ember-highcharts/components/high-charts'; + +export default EmberHighChartsComponent.extend({ + + redrawChart: function() { + // add redraw logic here. ex: + var chart = this.get('chart'); + var seriesName = this.get('content')[0].name; + chart.series[0].update({ name: seriesName, data: this.get('content')[0].data }, false); + chart.setTitle(null, { text: seriesName }, false); + chart.redraw(); + }.observes('content.@each.isLoaded') + +}); diff --git a/vipra-ui/app/components/text-marker.js b/vipra-ui/app/components/text-marker.js new file mode 100644 index 00000000..0e0518bb --- /dev/null +++ b/vipra-ui/app/components/text-marker.js @@ -0,0 +1,18 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + + setup: function() { + this.updateTextMarker(); + }.on('init'), + + updateTextMarker: function() { + var text = this.get('text'); + var mark = this.get('mark'); + if(mark) { + text = text.replace(new RegExp(mark, 'ig'), '<b>$&</b>'); + } + this.set('marked', text); + }.observes('text', 'mark') + +}); diff --git a/vipra-ui/app/index.html b/vipra-ui/app/index.html index 5262fdc4..42eed3eb 100644 --- a/vipra-ui/app/index.html +++ b/vipra-ui/app/index.html @@ -3,10 +3,30 @@ <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <title>VipraUi</title> + <title>Vipra</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png"> + <link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png"> + <link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png"> + <link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png"> + <link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png"> + <link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png"> + <link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png"> + <link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png"> + <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png"> + <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32"> + <link rel="icon" type="image/png" href="/favicon-194x194.png" sizes="194x194"> + <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96"> + <link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192"> + <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16"> + <link rel="manifest" href="/manifest.json"> + <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5"> + <meta name="msapplication-TileColor" content="#da532c"> + <meta name="msapplication-TileImage" content="/mstile-144x144.png"> + <meta name="theme-color" content="#ffffff"> + {{content-for 'head'}} <link rel="stylesheet" href="assets/vendor.css"> diff --git a/vipra-ui/app/models/article.js b/vipra-ui/app/models/article.js index 064292d2..0d054ad3 100644 --- a/vipra-ui/app/models/article.js +++ b/vipra-ui/app/models/article.js @@ -4,5 +4,5 @@ export default DS.Model.extend({ title: DS.attr(), text: DS.attr(), url: DS.attr(), - date: DS.attr() + date: DS.attr('date') }); diff --git a/vipra-ui/app/router.js b/vipra-ui/app/router.js index 3bf38c00..0a0fb705 100644 --- a/vipra-ui/app/router.js +++ b/vipra-ui/app/router.js @@ -6,7 +6,11 @@ const Router = Ember.Router.extend({ }); Router.map(function() { - this.route('articles'); + this.route('articles', function() { + this.route('list', { path: '/' }); + this.route('show', { path: '/:article_id' }); + }); + this.route('not-found', { path: '/*:' }); }); export default Router; diff --git a/vipra-ui/app/routes/articles.js b/vipra-ui/app/routes/articles.js deleted file mode 100644 index 2009e33b..00000000 --- a/vipra-ui/app/routes/articles.js +++ /dev/null @@ -1,7 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Route.extend({ - model() { - return this.store.findAll('article'); - } -}); diff --git a/vipra-ui/app/routes/articles/list.js b/vipra-ui/app/routes/articles/list.js new file mode 100644 index 00000000..81b69808 --- /dev/null +++ b/vipra-ui/app/routes/articles/list.js @@ -0,0 +1,61 @@ +import Ember from 'ember'; + +var chartData = []; +var chartOptions = { + chart: { + zoomType: 'x' + }, + title: { + text: 'Articles per month' + }, + legend: { + enabled: false + }, + xAxis: { + type: 'datetime', + title: { + text: 'Dates' + } + }, + yAxis: { + title: { + text: 'Articles' + } + }, + tooltip: { + headerFormat: '', + pointFormat: '{point.x:%b %Y}: {point.y} article(s)' + } +}; + +export default Ember.Route.extend({ + model() { + return Ember.RSVP.hash({ + articles: this.store.findAll('article'), + chartOptions: chartOptions, + chartData: chartData + }); + }, + + afterModel(model) { + var count = {}; + model.articles.forEach(article => { + var date = article.get('date') + var month = date.getMonth()+1; + var dstr = date.getFullYear() + '-' + (month < 10 ? '0' + month : month); + if(count.hasOwnProperty(dstr)) { + count[dstr][1] += 1; + } else { + count[dstr] = [Date.UTC(date.getFullYear(), month), 1]; + } + }); + var data = []; + for(var key in count) { + data.push(count[key]); + } + model.chartData = [{ + name: 'Articles', + data: data + }]; + } +}); diff --git a/vipra-ui/app/routes/index.js b/vipra-ui/app/routes/not-found.js similarity index 100% rename from vipra-ui/app/routes/index.js rename to vipra-ui/app/routes/not-found.js diff --git a/vipra-ui/app/templates/articles.hbs b/vipra-ui/app/templates/articles.hbs index 35225d4a..c42a140e 100644 --- a/vipra-ui/app/templates/articles.hbs +++ b/vipra-ui/app/templates/articles.hbs @@ -1,5 +1,5 @@ <h1>Articles</h1> +{{#link-to 'articles.list'}}All{{/link-to}} +<hr> -{{#each model as |article|}} - <p>{{article.title}}</p> -{{/each}} \ No newline at end of file +{{outlet}} \ No newline at end of file diff --git a/vipra-ui/app/templates/articles/list.hbs b/vipra-ui/app/templates/articles/list.hbs new file mode 100644 index 00000000..08f7ccb6 --- /dev/null +++ b/vipra-ui/app/templates/articles/list.hbs @@ -0,0 +1,7 @@ +{{dynamic-high-charts content=model.chartData chartOptions=model.chartOptions}} + +<h2>Found articles</h2> + +{{debounced-input placeholder='Filter' size='50' valueBinding='filter' debounce='150'}} + +{{article-list articles=model.articles filter=filter}} \ No newline at end of file diff --git a/vipra-ui/app/templates/articles/new.hbs b/vipra-ui/app/templates/articles/new.hbs new file mode 100644 index 00000000..c1318fdd --- /dev/null +++ b/vipra-ui/app/templates/articles/new.hbs @@ -0,0 +1 @@ +<h2>New article</h2> \ No newline at end of file diff --git a/vipra-ui/app/templates/articles/show.hbs b/vipra-ui/app/templates/articles/show.hbs new file mode 100644 index 00000000..a93a42bd --- /dev/null +++ b/vipra-ui/app/templates/articles/show.hbs @@ -0,0 +1,10 @@ +<h2>{{model.title}}</h2> + +<dl> + <dt>Date</dt> + <dd>{{model.date}}</dd> + <dt>URL</dt> + <dd><a href="{{model.url}}">{{model.url}}</a></dd> +</dl> + +{{model.text}} \ No newline at end of file diff --git a/vipra-ui/app/templates/components/article-list.hbs b/vipra-ui/app/templates/components/article-list.hbs new file mode 100644 index 00000000..8d3269ff --- /dev/null +++ b/vipra-ui/app/templates/components/article-list.hbs @@ -0,0 +1,5 @@ +<ol> + {{#each filteredArticles as |article|}} + <li>{{#link-to 'articles.show' article.id}}{{text-marker text=article.title mark=filter}}{{/link-to}}</li> + {{/each}} +</ol> \ No newline at end of file diff --git a/vipra-ui/app/templates/components/debounced-input.hbs b/vipra-ui/app/templates/components/debounced-input.hbs new file mode 100644 index 00000000..889d9eea --- /dev/null +++ b/vipra-ui/app/templates/components/debounced-input.hbs @@ -0,0 +1 @@ +{{yield}} diff --git a/vipra-ui/app/templates/components/dynamic-high-charts.hbs b/vipra-ui/app/templates/components/dynamic-high-charts.hbs new file mode 100644 index 00000000..889d9eea --- /dev/null +++ b/vipra-ui/app/templates/components/dynamic-high-charts.hbs @@ -0,0 +1 @@ +{{yield}} diff --git a/vipra-ui/app/templates/components/text-marker.hbs b/vipra-ui/app/templates/components/text-marker.hbs new file mode 100644 index 00000000..5fb15880 --- /dev/null +++ b/vipra-ui/app/templates/components/text-marker.hbs @@ -0,0 +1 @@ +{{{marked}}} \ No newline at end of file diff --git a/vipra-ui/app/templates/index.hbs b/vipra-ui/app/templates/index.hbs index 2f733f8f..51b28c7a 100644 --- a/vipra-ui/app/templates/index.hbs +++ b/vipra-ui/app/templates/index.hbs @@ -1,3 +1 @@ -<h1>Vipra</h1> - -{{#link-to 'articles'}}Browse articles{{/link-to}} \ No newline at end of file +<h1>Vipra</h1> \ No newline at end of file diff --git a/vipra-ui/app/templates/loading.hbs b/vipra-ui/app/templates/loading.hbs new file mode 100644 index 00000000..37d70925 --- /dev/null +++ b/vipra-ui/app/templates/loading.hbs @@ -0,0 +1 @@ +Loading... \ No newline at end of file diff --git a/vipra-ui/app/templates/not-found.hbs b/vipra-ui/app/templates/not-found.hbs new file mode 100644 index 00000000..4ca64b93 --- /dev/null +++ b/vipra-ui/app/templates/not-found.hbs @@ -0,0 +1,3 @@ +<h1>404 - Not found</h1> + +<p>The requested resource was not found on this server</p> \ No newline at end of file diff --git a/vipra-ui/package.json b/vipra-ui/package.json index 24ae137d..fa584f24 100644 --- a/vipra-ui/package.json +++ b/vipra-ui/package.json @@ -34,6 +34,7 @@ "ember-cli-uglify": "^1.2.0", "ember-data": "1.13.15", "ember-disable-proxy-controllers": "^1.0.1", - "ember-export-application-global": "^1.0.4" + "ember-export-application-global": "^1.0.4", + "ember-highcharts": "0.2.1" } } diff --git a/vipra-ui/public/android-chrome-144x144.png b/vipra-ui/public/android-chrome-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..a75a06d5e6943aee4c175213f6cf98b03fa3f85c GIT binary patch literal 7703 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 Q3=9kmp00i_>zopr08&e>YXATM literal 0 HcmV?d00001 diff --git a/vipra-ui/public/android-chrome-192x192.png b/vipra-ui/public/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..38a70604dcb27a9ee3fbf79d71360c5d1bb30def GIT binary patch literal 10711 zcmeAS@N?(olHy`uVBq!ia0y~yU^oE694rhB3_q?e>0w}CU`coMb!1@J*w6hZk(Ggg zK_S^A$d`ekN{xY`p@o6r7Xt%B!wUw6QUeBtR|yOZRx=nF#0%!^3bbKhU|>q}c6VX; z-`;;_KLY~;dx@v7EBk#OL2+Xvb(@GM3=A4Io-U3d6}R5jW==>6pL(zS{=Dk9vEJdK z`HQwL*xDM_=Gef%%VhZJfI)IX8>7|%;bw-#Ge7X$_-EKx&{BWnA;<rMcG-s?nvP0r zQP?JE(EM%d#dXuF)~<VZYuB_jckciD^Z4%fd$lvoS8rNnym_^IsnMz{ul7ZL{q*~t z?e{yy=b7G|=zDXbFUCYs{5Rt*#o&v}6&{u!`cwa>xN4()<(d1f|BG%oPk$n$p3ud5 z<3HEF&Ht}!#QhMh`JPnIy};TeW)q9g(dSl)aZI1*8YnY$D)7hU-ThyEckx3Z6$Lh1 z?%fQGEKDxX&NB*LR8M_a{_xU!zaQ%6ZX8P&7OTW0v9vr8R+#gWi8c01{L_@B>#fq> zl^uIyn1AGSrKCQy=p^+<0d_N;Ajg?gT2dd*vCuxBX}t3D%SAbd8kwip^$TBgl+sgV zlK2q$;P3P&Uaj{Y?Wnu3>(tHXeO0w_QbH}fbxYW%zgXfS)++f@_Uqa!C+E4YWs^3W zW2Mw|chOsw7$p{;jl1lc;+j}adaUW0zTWKK^O(o)z7<I~-IL*(tHXKxiSn)d>i(x; ztgHJvJT$jXZSihkNPEVuAfV{b#KE~~sjly|JR`dYF^~Bi^DeLd>=9|9X+OJW)%&wC za$-7dZ4+9)1#URYnZXd>!XYU%W$VAE(%JG`^9$P*OCN|=FHw>St)Kh%_`=DX__)Pn zZWKJ+GP@<$_drO>OBXHo!l_F?UbXJMU%dW{kZc`8c!a=wum2T4o~BG($7;Q0`UN?m zZMuwxA6Vm`Iuu?#`uAsbPyg;}#j@9)9*$LtA0M0ue#zvsOKef>!zRre%UFCiO6#%8 zzxuQ9&+=aXox*qPvx271^R_kkRI*7zc_Htq3~8Z&<rOs_rvCZxXnEHB;_tD0)YU{^ zn(zE?`E653tK-!`>1zkKDJz(LSM>;3AT@JydC0#j`}Qf{e!HwiXJtRnzxfL@Ul^>c zeKL7ND%UniMv;FWA6Hy>#=oZK<ew$e?|tI`+94hBfq|pLeOp~rgSwpW-|ZidZ(-t@ zA-<1qn<!)OLCx#tW}++HzMXj=x_l1v>>9s*izHtiZ`YM7Q<toY5avCorWfP?#U*^B zsr%;3W!KK#%2a=<c~9-7Lg>@<=KrPFIbRqgwoSV@P2+|ei_g)o`?zu|lOC>q_P%=M zwfeRMkIJum%;ra2_>>iRiM4xc#0&LhT<0do9QAo^S-Zh(5q~tZ->K}on?4;`JoCTN z&+L^v%xY`au3nVu#IX41%RBCm&gf>}-?l#gBd6`gMd#F)ZB7s3_UfGRz*6WDOUINf zPN5X_z_<GE*S%Tm8&MnAZOt2b`QP_<|0l*a@ilMkHuF5VO+lf>KEQU?Oxt4rpXcvx z47;Z*@haxm+&dq?G)1&>PL}E_JJagG?-#?Aa$?`orz@-S3pW*1=FY!6%m3sw`P*OT zm(6wPeaGJSf3}(PK{JJhn-wcxY4XndyXoK2u#o-`582n1w&uFx3lBGViaI?wxN)WZ z<y5^0j^hj6IUBe{S505>=2U##o?8;xsk$BOzyAH*DIU;#?j76O;DU>s9S7GtxF(f; zzf*h6R@&;iO{MAQsQ;^HMh3a^T9rtYez2DLQ7IDeUMOWgL&k*(2GwEw&-h<f$EGg! zSD171UwiF-7169&d6SyDeH>)}NC|oWe*S-I>2bI7s!uns=h-)9p0lXwm4NPp=Zlq& zKU6SOZ+{>ARdk}iBa_r5j~h3qYKP^oe0w)Tb;8p#^>@B6h;YmOED{sKB=x{wPcG)q zy3*Ib{8dAY*Yn#>p6kdO>eaw+|5~qD@<(Hp#*No!b{GXMaQJwgVUmYZ=2xBA?Nzf4 zH~pLE!1eO~p7)F^TcqwzxEuDpY2D5(6-6CK9>(uT`gs4=_BHJGg~H3->WseaFl#qm zv#^1wOJku=Cr4PL?7X06{d=bu-k0^7%_^;?^UKw|_~MB(OZ|8BS-x1iyvO8qz{xk2 z?gcZyK9f~)-)77hd~jj+q56NDTI-YVZ+UlkT9y3#3X|%lHGw}KKbZX`MJm$nPeuE$ zijEF}_Po3Q?1Z9%i?%-BVwC>m&An2!_N4gem0#qP^{N|p8nTM_HmrPcX0?NJR_gmd z-{0K6R@uCKu4HY+7s*V?Y>k9o#`_#|lXbrI&YJ((__b3=ja1GqwKoO2H;?$OOY^^F zP*!=im-*_hZF{bj&pA@}-AyD$g=yKJ6>RrET$!NNH}ALhYv;4i#Wxn|``FE}meZQY z@aKf4*e+(X7TE)d?>YJ&aPXP3t={3=QJ}K-dC!I@>C)M=kI$+t&D~b6R`%hrnMy<6 zzI}`<6jy%t|KD2Z|2fxBhu_BRA9pF^zE_%ydc1i4xCIL*EN*L3SgWu=b<T8m0p+Hp zjiFv&tP3xB-`W|q|L*;qRTZ9}wO-G?qa^&U)%kT$K_G{Ph^4HF%APYT?N|QIEZ!X- zCs&v8MKiJW+&>|$6_+0GKO5J5g;Ab0jaC2u|G$Ezs}?5Ox_F&T+?L6{F3fBGwaeEE zHotuI^bGSM?Uha|xXf?#=rb`c{5E}|lXKOt<fFf5S<k*&ocurk!_$DTQvw}LZGK#D z_D@>SZs`1FKO?Wo47RTu0;FoV1a6BnDaq{EG|@Ks)UgQTH+N#U{(B-AnjV@|%(ctU zVa4Cn`p<Lsr#;QTb8*=R|Nj3AzH5BC^6X=1zvS%Sg)f--``-uh{;~Pz-Q;oIA()Fv zicj!L{<(<{Uv-szTcau=e3mcc-Mm@1zt2i&UnO|9ylI_qfkx4;l^#>upZ`0xZ{f{| zw_lF%7aiC9qdMiajb87)xjXXRTVG{WExR&bK6Y-z-OWZjt+Fg6nN_OtjU%K)CUN&$ z23Isqo@;EI>@Up4^4s>9&wEL;j-@yKE<Bz5L1gvc$#L&)grAPjFT1$nTu=S{TehxK zR^0oZzhKX<o$}#ULMq;ovRdyA^~%5P6n-agDUONDrQ*riGxy~x=B-;O=C|6=-12Lv zVlPk8i^AXOcKfQ*jW>tXq<{IhaPfz`!mt0VTX%0$+dB68f9mJ%1^s=T=D*-f|KHem z63q3wbAIcw|0#GU-MQ5E>FhJJ=d9i%s2{jLv}*g5|EUkNcZ&WBKH;YJIx+v0{9~h2 z9k<Mz%>QwRNA7N}?|m#2^Q-9H{go3d?>s3l{XOe8yH69-T8mBJ((~-=XH1c=+weUj z<2%dd`B#5C)|5OrKSgmppWgjd^=I~7l+Icgbyr*K@J=OL^DPSPwh3Gx1n!I4R5W-T zt4~{c+Whm^j*l0M_21Ob*sDAH(V9lRcZ^qleLU<Vbi$`T?!U?X8Nyl4{Ji$(XUwho z^Gx*O*IpO%&qpr(IFla!{<{79xXv?Gea0WJ98m5oDw%q(YkymH!e<7DlHkuz4XY>o zHoJLGckc|H4cDR`zkemgxbUm8lOxm0pRYgN|FUV%#3L_%etj1&SpQmA`P1fVo<B|{ zh5bivefX08sXq7K>)yOAi&{V5{BQS5>g&fHXB{Hjo7!B|ZcYn7#eRq9eQe(Tr{DIw zC@pT>ELtAS%KFN^Eh{zr{{`8H{NDSv{WerIvVQ$g{mh&21v6e2zt^ulx^H6jgyNQ2 z5dz$gW<`jcTGAHuYU{!4kNTRzRPXT0FsS{tVPfg9J^p3>ng52@9UZ^yepa{n_salY z!HQs&b#1#`7>ZwOJGv&l3w!MRXX2+rC;X>;zH<5Gq4!2AY}2Q|`t+_<e`fuIuO@Xx zm5y`$=6Rk|zc!^S<3JlHbLf=hX(DFD_1@*o^O?9Oma4p~+GsWJzlQ(Eoqx0EOV<SR z`svMCyQ5lLp~!ai)qRiBf27AdzW-nOPNhp@QIFQuzlCSdOSGitMg5*un|znOe97mN z+l%s_ozqfHYTqZrEynZWN_A9yPj)0<wIXXE!%UAQ7vo<|-l|>k-XMSW?%MbIhqSBL z*YTFLHtd?c{>abUYn=Z~T&b*lKG?nZuB`T>MD1BqE&r}OW&Ws8_{g;LPvTzGEAMn# zv^#P3$B)tmFA~os_S{?>@ZeC|p=YVNi7%c%KPGc--ZRzH`{S$a5?j>!cbQ&TD|+C? z|E&0zm;aoot4#c1sMsHrQDJt-KX*mc`7hJ6;`?$R&9j+Zopk+l)VyPEGYlk|WL|}B zd$chpy643g(M7yWbL}SI`S12|<)2ua<}14rAAZ|wzx15*!aClP*$k|=e$HO|dWZ9z zJNcWI2QE9lF73nW3tE3K*XPw73|{=5>**Qe!~M&}7am?9D0J}ej9!iJhC!auaf}bk z-W-a*%C>5Pf^g~&^Q)_SJo%zKKi&Oxd6wL~j^ykG+-Vti{w91o=YRA4!`{n%{q`!l zf%Ww<zlERunX~4bf4%d6rA5+F{+70Xn(y|nKCQ91MQH21Chh9~hwd#1?+M&;fz`z% zc=438w?q_AZFALn|5WkSw})%*?EG+x<AYN27H$@qq%`{=Zga8!EK!d&l6Y)y{1$7y zKmY&4%Zju9axVV<<$C0g&bd{IpBnc)Uefa5X>&aH^+wTP*Idul34Lh}1xnL}mOiqp z?l6uiyz?);<;2uObJ(}ZExWtuO8Yz!`zKE;9t-93?>ls-B=CDEhyC7N--DL__xR7m zyno*BqyOG7PY*aC_34DN|9Sq@UELCA;tsfR#};H=eE8zfv8G0;RVz-cuI=Zx%HL9X z`BQ3u;^pX0iSoJPZuRT?q|HCKaa6q*4w`o^X7kE#{`2;2wtA|1xIFZ?+`Z2$_Vh4) z>bbm2=$OY9W_h-W+cnQ#X=YcqNe&5+s|c-bH@_gOu}5A@#6#e(_QC~cJj~4!g?1@i z+4|jbcct?c;lKF-b8`cfFZS+~RaxPo6BGES?fUUU_W$^u1XEX)eQBH0*;f6iY*|G6 z?2X*gY9&_!rd}&Le`VbR7XiV)-%d5J)JlmExY4`gFpGhvxKN6A=-#>Cr8}oqhn;IT zzMf_?)#pjT()yRL&ozFqO*?=7*ndZj1xL>Oda+EWtL<IF!rl))4-PbSO08P)ZT~i_ z+=3pS>iU1Dt|)~%o%wfht*C-i+a|NjLjUehIrmp5PUt*qTeZ^TOx>+L$~E1yD{KB3 zE_675M(~f`9gaWiro?{A;OKt&p5;~6x7MZ1y{qnePs=}c`AgE3M(H_hR{jjkNgvtD z8_ZR{W+ipz&1(E8>9OIj+Ozd*{(R2(?7L^%@4!r6*H?yJY4x|gIoIeflqym(z4AHh z-(s8S6Fc^q%vkBb)tq9p;4sS((Fu!Rntw2>-8kd7F0aA*`Tv~?>NZ?nJ-=AJsobOc zFu$tU%8QYGXaDIn$#>=R-rP{bWwiNLbSfX?IhT(PX?>i$3>RdzJF4`%mBqd@ESqy~ z?!phz8-=xs>t^h}_`}0s-i*EW@2&m#V?WkDRyt6B<Nk~0wKp34R^1HmxM^|8d)oR& zCd(M+8A@~26}&7%z1U;#ot-$lDpsrYmHNBy%bzWusd-O&=bWwK?(^JQZ~bb#`lKZM z>y>2bb&SkbU+xrUPBcHW=a`S<GD9yDyOqr>EmQq6?j^tVifh;&acWQK@;au@J?__M zZD*_36k(U2{P|&~xkvx!2V2kXy1(SewFXw^sv=M8W702urnTP`Whkj)osc0H?fKd0 zo<OFat+?A)^IP^pBL3QSI##yoac}Iqw3zqTI@X>2)+s(~G253Xw~yq>Jo*;)&44j! zZX6>6cS>bPJ<H`j?V}SKD%MDEojdKj)WtvX(iJfp*AMPb-Jd3XH2GQsr*g5EMgg1V z*3(IXRWJT<ap*mI`YLaGzwrUDc^q@uzJ3UPU;psgi*FItd*7>^<uZ<_e|dE7|Munx z&h}Z0)3O5RJ?`D|&06a#`^Ad4d21L1g;Z*rzTRh7ni7<*$;emSlH`B><*nR<!9vR4 z_XH$9*zYmTUzpRzS<GkUqB#$F3*EA8W1|?)i0L@Ar1XBy>t6D?GnH%q;aEnmx<hsn zJ=4yA+vhv^)3yl$w-OVLb982OW<E0EEBdwC`R;Az8JDEDr4?_!x3qHUnJf1a?|a@A zU%Fc9>e9UvBbKtQ-g-6r>p71VElf;0xqVlpj#sX{C86r@Vj7o_f`ifIJ+ce|&kreR zPPb%aQCq=sbBERr6Q!zOXFrr>?_Me2mA`{OqBC{j3CRT!hwpA_I&>jY`FOXi@-`#+ zv<g$TsE!F)meutiravlr<};&b@7ibf$_MQdR<jmP{rtYkRz~i~pZzZ$9Cp$2Feuhj z=j)L0ny0DNV5Q!|vGdk@9`?mgi#x9t9NxD>J$~O2BVE_nM}iF1;>AMm=4l@~*I3M@ zwrf`Z{mYlWvm9F;A^r8x)WvgzzitpYxNY{|_GUg7ll46}9&zQ*x$XQ=eAm(@4h|Oe z!>heiLzZe)`%72PXAqoZ`Gi&c$GRfDmiu>)acP`cKZR?L`j?=GVm*B87?y2hYGgR* z`MFMbWmlE+q|7x5OKl}ycqM6g`>1xjUEZLyFxx@rvys3Z74CZVaEAwZpEx}})lCi% z_C5DESHxX$$KHqit2K}AYI*Zk!zXHfgqjS~9+t^ld)BQ~s9VUL#APOa&fu#C*DtkY z5sA&KwykZs`K{?(t)J#Ji+ioyGZpmP)Xfq<aa6wVy(4~PQr4E5ZM)A|Z)^TxnYu2a zaDE_*bm(<f?Gx*-oK$VFXbH9F?SEbA!!*bF)uB_{U-B{hinK{8HcvFX!p*R2Gt-4N zb#3lHE?R$a-f={5TJwL=X-mCqwkF*^_3Qj|*9XjZ3*4C*1b;|&E;@cbn6J+`?0xd1 zNCtsVH|J|DwVMC(+mr_<ZNeYzlz$yta+k}0`;PNkyPTX$3O1-)Y)I(aqxbLat+(qY z)n@+KzA<N`x5E#X1@D%v+04?i+0i6pS?-_trtU&N-+x~Jy`;lApGTIt(KVlO+nksy zrkvc5Z^T@l9r1Db`#)SC9xyufx;M-&c=BVK$iBn-BZU|(CO9M<USMf_`?r7?2V-H- zp3C;7LFKy6ZB-sij0$c2cFbFAz`ji(!Ia~Zf<i%}Bh!o0a+|!8-&~B059j}D)k-ca zQ8l^P%pI<EDDO{f-la1~&bL0Swy{w7&?w&UVNr7R-KLK!pXv+q9XwR)x?au^6<NJn zVS495$wiWT6D3u(cqgU>CSE&sV&Pl$h3cm#=H|()*&?K`dE;d<!`B`S)rE(Cx?hz^ zP-dy&)a>|Fy?Ddax8>Yn`d2!WGWpgEbgIwo|6OG5;_yPYJ^$kB)VMi3EX6irOB`pE zyI-$9nEm_k`6=gDesk?}No&y7Kf3x?S)K5=2ZyGXX3i8|&y{^<D(ka0lL;Gi9BO|* zeao|7-=s2HzQi)~woAD9<9loTgbu`96!f0=oOh%9>YZP>EJTiYB>YR;?G-E07jgS= zZ?o2NvB#08?nW^3$ymJ7*(e=b^e!RQ#P;x=iPs$W%vH>vu)=HQi<4~I-}mlVv+n4t zUF8+RX?iOsZ(efC;(%}Hw~L!5T@jk4H2bgWZI2rneYSfTKh25i6pwq|Ci+Bp!;!s9 z#J;SyY3-cyQ=QR%$)hEQSGPUMTz+$g+Jen28@8tBu3a$aDetCx!SB+Oj_L)jJm0Dj zf0FyK;Hu7<ziR&W2^Ltq3)|4Sa_$4!g>xnzO7&s-tm^G3(#Cny>(%w5@`kBja$>i> zUiXI4BtpNosaoRlsrTHkZwU!Z@GcWq*rK#ykJ-udZIk^~uf1CRuPmK^L*hZN^IkE* zS9Yv3iI~5wAd@qgKeUNuX@%`}ndP&qW*>PJWu4E;$l<)rckKn0;w+_lUfq<yaQBBo zlQbl~4UIzc#AP;4unfH4x^*#&Oq%zB=nV-e_a5wea^({H92OCekFTCh?>h2qKTqmU zt~y(WrzL4(X|)-t*UtpZFeq04@jUVKucyob8m!Z07!!=EL{=Q-FX9&3wetEBuRZTo zF7S$qsOm~|PCX*MNAcZ*Te1N+{~Yx8;dH%QaAoOVw(Y`wJEm1nKFRi#;eXg-?{^vX ztOri~otDnYxRrmMpTXA>J;lVT1E&HOJbV8@?%;yGlWk9*e*02`u_t|gSkMd0m2)2T zmK>Y@u7yo?jb>@)T1KHQ4`S!8scVt$NlJ|qS+y~XA!Jvew$g$F4T|E%`ky9USGZ!g z&q#9BLhoZ@v${?_|1CSg{@I&{y_3&>-Fx%G_hbJb$krdzICZ><aqs)of0+kn#{6Ru zN{rp=ouu6-ni94^S9V3+oZoliejPnhbmOb0*!7EvOf#h8j{86I*IyR@=-#VIuhgHd zPr7np=|(n>C3Sb6T-tk%C4a(}EB~3+re$5dpH=S6dUUnd%fIKnPw#Pj_u*CgS)DDv zio|Y*Ch6V?%_ugPl7HIovv-Q^=_lWgKeF1jnSF!w#+kEy|4*~Oup{{!->SA1j=O5F zJG}X^)JdEF>HZVDS=p9MZCpO{mRRY+sdpn88M1jJnf1LY-%SYl$h~^9hr?c#ZI4zg zn9}v+j_tGGKMn_-|2}6?qv@P4x84Z~-0QE5E4*{{hx41$;`=gE7Y1@|d+TQ)`m^p& zQ<Hg^-SPeRrk>-sJ2_=>uE+YfVGpluxH?69UgiH!d-E3EjQA^TT(0QJpL*!qk_B@A z4&694Wp}srm9us;XRp&<Cp?)?*ueFG-I_P6E|)*sf8za)N8QtPYE$3ss^Z!<x#iaV z_Xp-0RHyAvxqCu>wcq<HrLfzp6*p{J%yJ~Hi|4BMoPE`Av-8USmRmkPeLrHZ%cQ(x zx6hc1+^!K-nP5}wzd0}9$cw+BMUBz?)>HVx{QE0CLsagbSy|ov-Sk^^rbv0n`K57T zJrUMtrtOj~jd~SzQFY?1eT#p*O`EUz_t6jk78@>&#Zr}xj~1HADlg#s*D~9-GXLf5 zxP0$?wQv7cO{jL>a&Q~_{ud%g9)wSD$okfHb$?;`XLs-J<oo{fj!IqTJj?p(c3Npi z1KST{_5YDCqjeAQGc?t@-aNBc*Xp7a1K-vQi}w}><^NRPT5$DJ`P|b#7k65III&JV z^ZWY*_6IE2%3B!t{?u>K{K4q3ZT-5C-+dEL<bCtp;UQws`$FT-bAG+L?Um{`&TJO$ z=USbpe&7OY;QueO3JJy^gw+f0h5mSJurT8Kl&qb?i}n|`8ZZAX;xp0t<G)m?pzi7V zHP`p8ylFk<W#|9ZXD_A+)w#E*O}v|{zJT+O?VgQC&hFj$oiq4Sxv8OP=<8pb=GyAr zdL#A1jI~rZH&kW9to>CV<8Qyu{>E3B`=#;T;w_@dra|_xFI0D0{@A?U=bxLVn)oT^ zu=vUHD{fq$e&vXvs@HFI2lMh~tIff#Oe<&Jp0@va%;h(-M`V6{JaIWu`BGGf;5_lH zJ7G+(9)7>1ZoirDkG}7}y>r}sSFPZFTDbh?L!WKyba}nrtK1Z-u;W~ES;b(LdV~GT zlx6Qv{oh)>;AVBl?An?~>4&ry*X8{CcDszpVspLh4`cl|l_7E8X1`s*TDW!7{*~2E z1$yga^5&mhr*z_AlE(`X*5D@sx9d*4zddUW-<*FzFYWTfKYw2uKkLuJnti5UFNZPh zIJLa<uK%4g#gqFry0`ppWz^pJYU=9Wm72U?cz3ThpL%*`@gnIUhy7Lydn7*GoOg8P z(dNzHum9s%`Ru)q%-k9UL+R`zyB$l9n+b04{4sxSO+@69v!}8zBp&wFw{**`-^};6 z;d=7DFbRe9pwKkY04ct$fwD)_?08LE+FGX0{deQk_cgb#d1qeq^Q*D9jlJGh)x71_ zHh~S9KjeeNCNB3~{zA=l&zVK3uYb=9W;nWUSIvqbKV1*G$ydaWg~V%c20xjw{_{<} zuSOv%6C(EHJkwwG|B!6-dBYWc{x$a1O=U)_k8o+PDQ?Seo}67g&HvfWlkHPjt-P}g z9y&I)iEMiD@z=S!il=$zJMZNyr#=<m`#<}MuHueI&&<}|ipdIIb4WJB_i)0u)l2{V z><{1nU{8AOnk&J(<zG~`Z=3Xa_QbY#&%e%l*2KA@{r<^0QS$%TU%t^_#3XBG(-APi zh0XFy)!xnWG5c<xT=U<$HS(?dUw;0%oWI*PMuwMOZJ$;9V@Cbdw_KVRa>JW=T+g4o z8})Bbsd2~}?OPu|vTst~&}MVFW7pDiY~mgV)E?I7eR5a)Q}<bxU5=%`+nLSw#m6e~ zJlp#Iy%TRA67^rf&;Mu5|2YfV|9+}aS@Zp2@^6l{Pmbm6-g@Rx@6+>9@4uVP;QKHs zzvsV!ZLjIBb*taJz3!I%vFTgG*_(e2e|UfVCw{S8VY7<f^|Jg8Tpic*?*{#w`==q& zFO1dR$hbp2NqGP3?_5GovS-WU?{+NQxKc6jM(I1}?(d=dAMGh$ywm^98Sd)38FLOw zab5Y6Q~7Q4<^{YTw%h#X)>wSZV#S|5LZY1sq6?N++<aqu^>kE)m4C#9d7gIH{uiAu z%2D00h3TudqEWK4)SsF9k|&?m9=&gB|0w36s@b2n0;~4+_x}xwJ0ul*HB_qZYEjt# zX`DAq{_tyYmwsU1JpZTWzqFpXFRzj}my4}0pBgr=HKcX&r_Cpq7rR%7cZj~8B{j7r z)w}un-QeF3u21^ec}ejx^SQ0>0<z6pKYe=O-yW~<Zx-K!`zfj4b%hSJ*4G~1Ecoxh zb@|;7+}JF?ERe6g+Ie~YW%uYhmHv=c$(Nx|Q{TQlvoptW%L}gzouWwgI^94So%iPJ zw&fM@?_yrNY@M)qVa|``d*3f;NP6-0rpcdZm4wUF&R2b4pU~lWIz8oLw_R=0Gyc=& zRkQbR-sTxNLv-2F;7?n&EYMr28adtf=n}u&9Y?1591U8t<X%4Ct;gT&($`zR<gK`s zwn0Gq=JMnJ0%Kh!ZVO&>&2`__9FF|P23_fSGC%mM7w!*S;(I>$#DeWshM%XNdLNT; zqQN(7#Uv)piCilWs7-q=baL{7%1r&Yse4T(&D+Jw5|dl?A-s9L@PC!~MZ8b9MFgZ@ z-l}wqx87h%ow|a+shczPujq-?IeaoYvF5qO?XHg2dC%MCUlE)6?rWg`Y~2#m8!C)% z+xNfQ<=hq|WAWSc@8Q_qo7sUZ%0I7Ncx<cgalviNnH6&E(OT*|G?}&~{M^D;KjF~= z2kkdj)$<F*<?8~~r_J4G(HM2)(z4(4<tk!z7WhPagdgfS-!|iUpTGsS-TN*7eA%|r zqUPJ}W9qXG#LLzx)z-aCc)4KeYdy{*m(r@{$ydZiF7<W!>o@JI?v?E!G0UIwUlIdp zGcr->UTl2d(C(!D-0rEd`=u&n``U~CpQ`o_k7ADAFkzcQ)4I9uY%i6EM7pZhgdYC3 zyDZ~X-o|Z#-7H%!f5_qbf8xwv--r7Ae`~&Q@VweHd3EjTaFO+9W#-+R^162v*;Vd& zzIC2(kYMO7hb>Y~`HOV#+C(WWkp3X<cHV6M-=_!NkI&=YyS!<C^o^N^=55tp&Az6w z^qs&qwRsU?>Bjlr_sxw_v3p_q%a-YX)APF1ECmn#`@Ec;yP+nkb-&4v#}}7()}Kr~ zxOASfC}+lnFZUkJyOg@sbM^hZR{~dY%4~}W5)V?}eEc$ZlBCtzD5)*{R}br@<-ShY z{7|`^^WX2@-Lnt<Kk*_srPpdhEtATttzY7`LX5-Z^!%@=ol&%YzH;_GS(~J8(Ms33 z{%2FpsZC>*&-wo}+Unn)_4{iNw1#iJ-O$i?Q2vS7Hm3iRQ+Tt#Fdc8=7D`#_-1<tG zL6l3x-*ofVf3GGOrhJRG&Aa5g!-!?Q;o$?yayChvZ2^-{ed^jY$6|hj*OQ}KIuZtn z7lIzLZ7n&o;fTYU2XWS3T<g3Ks6EWT`(aJ{|H-~Q=RZ9-yx4zIjl`3Mhuco8xc|_f zTBjMH@cZa|o153xOqseVsO*%V)hg|3A(tPqmNJghvyyyQX^8Gry6VDgwnm}#g8oW} z{XVOT)@-N^h(36~p`q{QU!6b7>HjyW{^-7P|53ny&9C=@52Uiy?Ef{*CEL&~_H~oL zRH$+3%E!0XpMK4pdr4n=PvN$g8vS2aZ(Bbn?Q(O(algGhe~wPv{9U>{pW}a&#G~|9 z&vPGV>vT5hwbu(BPMVR#&0<l)%c9-LdT;ISS2@MHm({crF7Mj^wyd7{k57-}qw*b0 zb6*R-5&YqpTQ-g1!fL7gs?&rQALNYJoBP#gnx8t?$s*1dY=5LB=JgjmESF?j#O?Ym zFPuYD@KAV(w#=R0jjInV-F%1hzsTLCm2+A5b28qMIREa}U;ci(t$KehUOv8FT-l0a z@$X9AAcy){(!W=63%t<z;>+<u=+A4(d9M$gcQOo>4-@LIQP?;${{F(n>khhbl&{(A zvHak3fdeX!HVB^E$=$ZUboYMOA3IHs94dQ#ApLto2g|?k@CDBW4m9rn+xEPw?EkWd z&jkeecVy*dRQvwB{j}@tna75b59T)SH{D%-`9pDM#*da5Ca0YiOFtbxzS`UIp2prq zrS<hP|ISL!6Tf1b`IqPS+Y56WY&%?M21o@hx4T)ld;jeZ`TQN%#l0Ake`{QrVDoq3 zrS03r(ypfMzQ0$*VUIv!xWkMl`})v_(SJT^$8P)m|KwqR&JNM|D_Va~$Cv9p=6$#6 z?ti@od4Z(aOL;_3{@lHW|5MwsN!?MMpKmtqXZ;u|AUu1f{OX!(kB_Jbn}3cuz3cy> zxBtpH|L8FObDh8KkK^pie-%w^nk{~um7M4M_TR?k2e#MTQ~mH;bn~Cj>p3{R)`tH# zc;Bb+^;66I2&tvhwsF-L*Z+6+eR%)e-Jsh#2e}roZ@8+R<M&tk?UNtMuadks?=Rh5 z&tAu1$LN!j_B0^b)qJ7Rm+vQw=jcq}HnI7*?%H3)T?|V66Ov-?t}vM7{`<Z|=d$=~ zSL^R?{H-7IM^wN{aZcN>^dsl?DT!oyWKCh+l>B|W=OR%Bhn71Le<L)O`Yk@ylGH96 zQ1<3una2jEjIK@B1JoRJv?`^P#a=gVP5!>!ooTZ13Bi1pb7CcGMmfq)jW^l-N%n8O zDpK}<U0|icudE#XM<>lXQ}4Aom^S`@$J-Zc{o%Mu-3z59LG}M%r+oF<w2;MZO?`=W zS$*b<hZALgSPGp9n{`3o<jU7_<E4LnCb$dKGi*5NDmAI~;>^;A^0i%W4xAU9->~6w zcg?!QmWW+9eJ&Q*Z{u;B60tll<vah+<Lf|X2sk)@70Ne%$Mo!K@%FZZ>w|PeCR_{B z?wPx{p8en2P7WENjA^^NS{6^q%UU6%6#e+n?3JQYGi6wgv3*eIPEOx{`OdrhjrFx3 zIXQ$~MYn&DTm8`F&9`gc9#mNIU(0_o{hG%!^>ekye;nca6D=xeAu@+CMWZPvYpS%= z!;*IG>!GJRT~GQ?{QSJ`(8)Qwzy67zRc^BRclm?+5r0GlN}WTlM15Rfd&T0yYva7r z@u5C5j!d1~axYjSeoyJY^Iq|#d>@?Wmp#b$RoQTsjrT>?zW39)e^*T9-n-=M?rU$K z+C(buQm?FytH12DTHv(xhwW-g1s%C3bRGSsooaqIPffA5Y5FI&JBj%xPMe%xcXQ_7 zwcY#KS!S<h;GCq8<^6Q;w*%AapYZ*eEik`9V^>@QL*T}xPfs=W?vgeA*|>CJyZihj zxA^{mg6QK^0fDv5ih-ijS6AQZ)k-t_x8u@-!^!?i=R?llZ>*0MWL(vvq~FiLG)YIJ zc&p&<a^si(KmClgm#S=A^Y*~~T^$Uu%=-*(hI9tK+OjgrInLX(wPS8g_V@d|dk!5~ z|Ng-KjTe-!FZ^Yr#V=>$`rcMk=cc6kZpYTx@R{%HbN(z}X`J}?hQj)C_J6!BOw}p@ z&ih(C=N$2ye_mE}dd$VEHZvFZ*(_Xk_KU6Ix5<sykEBXjiioVg*SMdxbGgRRQ|*ea zB9}ardzVbs?3>OP@-52Q@0dQfv(HAI^(yC<_&-@T)n?U}8R0X-u6CZ1e0yO3x+7nA zvx_(MCh*?akg%X_NyNLe-}f=AzWMZe{@lOy-&em1IW)=5EyB8n{U7gALvN#Z@4uW@ zQq2gIkSwYwe1B-Et1eGe=yEn@w+P42v7$-4OCLVvbZ?9bTBG1op!hi2OD|S2Y|S3- z=nEO_|HN9RYs&v<b9p7p)pf|_`Xq-d%J<Y2R~TN}78LhhEHi9PbD__XxWM-8{vd%6 zsZOrg1onT|mR9bZ^~>meAZJfU!-_{9YnGkk`?2=)FVW4fP9JhPsy|D7&yB|V;7|V< z&v1E|eOEFwW?*1YEpd$~Nl7e8wMs5ZO)N=eFfuSS)ipHIH8c+~GPW``v@$i&HZZg@ zFvt*GFabqFZhlH;S|x4`l0FhT3=9n6RUr{2L5bxG1x5L3nK`KnC6xuK3Yi5Z$qWn? za~^-<;V2B#&^YCP`i$q(AO>b-ZoOn~VP#?O$s)|c3N8&Mhf|o9H-{*kzH#NmkuyhR ij<BC@@L1rb$M8yAu;i1I=~M;=1_n=8KbLh*2~7b1()?Ed literal 0 HcmV?d00001 diff --git a/vipra-ui/public/android-chrome-36x36.png b/vipra-ui/public/android-chrome-36x36.png new file mode 100644 index 0000000000000000000000000000000000000000..fa55583e69edd38b9b9dc4b344610ce40f076014 GIT binary patch literal 1410 zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm^UmUKs7M+SzC{oH>NSs54@ z6p}rHd>I(3)EF2VS{N99F)%PRykKA`HDF+PmB7GYHG_dcykO3*KpO@I2Bsu$cNd2L z?fqx=GcYi)mw5WRvft+s6gM{9XUZAJz`&yJ>EamTas2JI=nR=q3HA^FXIgHae$#u_ z?K~eTO<vB8zRJEXni5Vcq_#FG1b%e9IGvR>K1X2X*GpYNxtbXoYhO3t5RZP@%(yyY z#iONRSKd0mH51QVs<v^r=jPda&(@y%n7G-q%y_oR`?}9&)9?RD-}l*&`A__7(a85L z9FCdH3~_fB)i?*VG{o>fV}GN#uY3Ce*5)%4x*tjY{~o=0szhXW;ES)Z&kSz!ntM)C z3EVl|{G&k0!#yP_uU&6Oc}{%gbISPdn$m{r7w11+-&9!dWs*B<{rNJ@>NUSTyY_AU znKE~u&%`XAC8zagw0A1?Z<+TsHQ@jgyTe1RoLRRP?>V#g((1eO59tIZiMs8%mEI$; z`dM#ZV0hKB+Qt8$1w7LG7OlX3cd40=hWQt}YxDmtE?hPJI0HjdvA(eBuedn<{w;Hz z_3F;QX}`9>KsUDNwZQ^~?vmTvKe_L5tWRCG?TgQ%WVv7GnV%W#-SBipwqo6UyEi}g z*zU3v`xR}L(A<2G?Xyq%t~YkC&tGuS?+*2JQJBep_^ssE^Zu;8;<od1tzVyYY~<ta z_@vRydbR$vG1vB=EE$HAl}*G`tWU17XDeRVpR#REGn=T@84c}yw=|kr&&n%%mgz51 za+xc(FzWPSm52UKH?5C)7cu@SDi`ZM_(ip4$=$7CN{!VI)VQu5ILS1(g|qsrM}wzS zh=;%`6()v@EhqQxda*gWubL+!fls~A_laDDcX@eJP2{8}zBj9G@N)lS(rLG0IBEJp z?bG`xfz`SfPTQ>c!muIXP$whH()RYF5)mJNXla}}m{_^LIgdw`xw~3sM#_Z>p<Ul+ zAH7)Ub0qPy<)n@5Y4i2IE?Kmh>BXDiZwz|{{w<tRAu6IM@Gr}Ie=ozuv)3Q>H@LN2 zJu}t)Y^{oH&$Tntg(imfSlnAF_x$d^#SV4)MPKIL3SPTYv{rZ-)64WVe>qOPFP(RU zX^RH4R+_GpLQnZB^&fmcoBNDQlXq4YZ~r^vmhtgmuXE?RHS-sJeU|XB;jfV46Xo3H zM|n&(Jo*ycZeqQs{g(e^rsZ>(RgV6;=^W-X*HNx+%Lla?UzX4EfA=T!ghO=PswGX9 z2Y2sjxAN<ZygRSvo{dINJAd}<Pqp95#G1I<4786um7iVr{jQVTty2dTQ~AGs6iW8B zN#Ca($GgAsxT%4k==`9=Di=SbJ+-;Gz_B&Z&SJ@tp4`iQAKw|N$=$kd)5av>62PJG zAYntop_bU6q6@p{EZKYh-L%s)j$NO9d_prHTac7*fx+|lQJh7a*<W6N8^0zc>ez&4 zHnFD;DJ%a5K5vX{($G1fRbH&V?AOz&0tc4rpFO@_*7=^C$oiIVrv2+v@|L?Wyii>* zBSd<Q<G$EGOFt%5&bqxi=z7ctWd?HwW>yiiQ#$LF8HMgFP}s2G@EwideVe*<*L}LZ zDef<OREV1TG@AxL1_lPz64!{5l*E!$tK_28#FA77BLhQIT|*;XL-P<LV=GfbD-%m? z14AnV14HGfcTqIt=BH$)RpQp*P#2rXz`zh*6%tVrlvu7%P?VpRnUkteQdy9ykXcZY z%)n4F=kX^Vj>0evjZ^-o&v-r!VqjM0)=TCVRu=Z2EW#|T;L>1nIE7hxbBMy}8&^&o mIdeqj2>a;<j|E<O46nomOFlW7PGw+VVDNPHb6Mw<&;$Su!fby4 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/android-chrome-48x48.png b/vipra-ui/public/android-chrome-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..053cc4ed735d16d23ca7f7bfc06b8b419c5da221 GIT binary patch literal 1942 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 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/android-chrome-72x72.png b/vipra-ui/public/android-chrome-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..98c240493437e4f97f0c6e08d10ab1c174d792f2 GIT binary patch literal 2999 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 GgeCy>0=1q1 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/android-chrome-96x96.png b/vipra-ui/public/android-chrome-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..2d2202ca6ba65fba1402708be385110c13ca4606 GIT binary patch literal 4704 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 TC)2463=9mOu6{1-oD!M<ks_o; literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-114x114.png b/vipra-ui/public/apple-touch-icon-114x114.png new file mode 100644 index 0000000000000000000000000000000000000000..bc2a612c2e7e6a66e1f82d42722943a90e00e25f GIT binary patch literal 1818 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 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-120x120.png b/vipra-ui/public/apple-touch-icon-120x120.png new file mode 100644 index 0000000000000000000000000000000000000000..fdaabce77f0024103256d92f819694892752aa5a GIT binary patch literal 1895 zcmeAS@N?(olHy`uVBq!ia0y~yV5k6L4h9AW1{wZLJ_ZH`mUKs7M+SzC{oH>NSs54@ z6p}rHd>I(3)EF2VS{N99F)%PRykKA`HDF+PmB7GYHG_dcykO3*KpO@I2Bsu$cNd2L z?fqx=GcYi)mw5WRvft+s6gM_FX=HhVfq{+3)5S3)<KEj_zk`L{Wf%(nFIRP7Vs9~* zHEhXZwC0IeDk7+%6ufj%(&>^p+Y%P0IxI0N$!hdl(xJKRD`S|{GOx;zxhowiH9koQ zGCOrlSp4%{tlWg^H-$0Q=k9!0?|<{|d0zhg=j(d^YnH9tz_l8N_9t#g{uFk0<CY37 zjeynWDO0!e-Foq#Ax{4H#)^JDhDvAQnUR@WHF<8YT`pvD!rsYf|7@koH@S!U?sID% z5te#<RC4Kqi<=DOH3QsR0}tAj%1yYH7|v7{<NImG$D7Y*<=>O8x^Vw;V7b!KVD4L! zg{}F|&%eBpUo1XJ?t7)l^P2eFUDK8Zzq2Zrn0F#w%k)5m^`>XvSHDe5)KGSxeXXTy zA`icO!l~YsRfq0Yyp4_Y$zCocYt7N0W}s`neExnlajB#NrP##>jJ;dt?>%2~?X!MM zkY)9E<MTO>-e0`*V5v|{Ldxsxi7m<QGroVkeeS@y?jLVmXPSq8es$->g~w~ljjE?) z-hOP&6uo%Ch7V=)xwb^E=9gZ)GUN2MEt}66&wnEAx#Ym-$bgU!s_#GB<)2IWwPo2= z{jU;r=WngHW-x!)Ww-UwzOp})-u>#fTl~i9^m^}qC#wr@`^}!l>o4^&diIx)1J4(F zY+nCuz3RMW-sTUa*G}h+KM<N;7Vjs@wqQrq!paQB@3xPHXMQ+ir?ITyX6?-O3kMk= z&fL!3KhM|bVc80cS9;Z7UnRG6&Ff6r_}Fgh$(?G7ZL+Na9&)!gy*TDD#a?~ZOR+Pd zyW}E2c<6kYRrc+bqfOOw`HwzkHk;}-x&Lvh9kvZVbM$qPNS5NsQ1*gj-jW8jVqF@E z$NL;@t@e3Mdg~uC*@f>!!}NlsJC85-a``HhT0N0Ve}yZXjUa#SuK7D7ZuD=O-nq&0 zW68Hpo*#7_dy>k2NG}LrPTW`3z<;tq_d+-ShW<>aDD6Z$<Gjg655#P8HhRz05>ek) zRoX6EwJDCRhVwyCS&NQy^>fb8yiS|>rZGO2T-5W^Jhtgxtjd}18ZxuC@<^CZGJbP( z>fNh;hido_ryTNSkWb&aRdUfq=0*Hf&K*2Ecpu2HCuZfBupUYZX1gQ%L`$L6(dZ7B z`5Z0gIuXWlJ1xn7Oy$m!A7pfPH0@flYjr#0zbLjhC!T9N8mQfCntFg&@`IbMTuHoV zi}k`>)gs>FBO64+-U%`<IXN>zzxB56qgOmfKGaA}`8d_2!i3SN(D%4d*vzRF6aRz= z^&H<_ac-Xj-}l!GMJ`oJ9KXE%<CRT%{ADuDL6bPHO?$Usf1}L8Ijf^Jqi0wfyjfJV z(RQafTcT@^UChHj6J?g&HuMqH%~llqG~xZd<lP3jeMx=Qlm4rn-VoMn-o3n1O)Tif z%QC@V3A0p~a}QaY9X2@szQy1*+r!OUA3bMzS31Y>_Oa;=JZY~h^EWfje<|8M@0``y zGlAFB_ZV9Up0Ud>y5Ht{{>ru!)!WQnACy%7DRpM5zRUYO_1Th38G^4ugHz80W*w8L zmtwkcy!5TGwB$@J`RCTW5ifmGqY`%o?Cm%_J7#*#%$2SwKc;;aZnztDWS*A1l$chS z$h}9q{v~*(a9xvF&9*(~?wrflxo#Z(bfAA3%W2W(zcJx8?|*U#O$@zkn^wFdZ10y} zpWZB3X`(sduWP*erYGW!JMUDxJrO>*G1J{|&fhO37Y{BmIG@gWw%RsHyDo9Y<)iW{ zD*}#4Gq$;XTsu|a%==>{cPypOoz0q*t<GU*!+G#eUWxkNjkn?_F8Ugr{As<9aP2eU zhPl^UV!|(cwl%Hve3(;x=|$4z^E2cozbpEY7%1MJ{Ow_GaB^(yVSfAnhTA-LwTm>J zyz`b_e$AHC?Aq@>9XPey=0oYx*t{M3j)l{O>t?RrbDDGe;f9oeYfoDe`S-oFh+>>B z+&0&}@BA@m&gsH!mHV6$rwg|Q-v2G@C^=oY&A9Nq;|?c1bsqVulC;!VzZ*QiFS2Z2 zUAgw2fyR@fL*1+kT2sR3oL@SnXlMJGg)aA>_9*F{SGl<N_UmJ@;fJ2i?r;Bev$n(R z`93AR_gqKP^g1qPEGoJ!CX#sn#(%5jhqTtf(4M(J#1-vs-ao#RPo9B+LAAs+q9i4; zB-JXpC^fMpmBGls&{WsZNY~Ij#K_pn)X>VrLfgR5%D`ZH$h%Aw4Y~O#nQ4`{H9X@C zyUM`85MC7$Q4*9`u24{vpO%@Es!&o{kgAYbP?F5RP%-E6CmxQ%Fb$1U{-@7)J`G}E zR_4}A<`z~K_MR-lEUe(tU~)KxS$T7a!s#1VP8>ONMCJ(l=?0GlUV03##05(}Ihjrc O)u5iPelF{r5}E*ZxLhCr literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-144x144.png b/vipra-ui/public/apple-touch-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..1d46bf72898e7a1d57e584e33166b4ab93ad1913 GIT binary patch literal 2304 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 bUV03##05(}IhjrcHEldy{an^LB{Ts5Lm~x| literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-152x152.png b/vipra-ui/public/apple-touch-icon-152x152.png new file mode 100644 index 0000000000000000000000000000000000000000..cf4fe5c4d8e00ade403c398bf6354c66dcb6f419 GIT binary patch literal 2362 zcmeAS@N?(olHy`uVBq!ia0y~yV3+~I91IK$47Mxl|1vNzu%tWsIx;Y9?C1WI$jZRL zppfhl<jcTNrN+R}(89p*i-Ccm;RORjsR0ASs{{rHs~HRo;stYd1==t$Ffb)~ySp&_ zZ|^^|pMimay~NYkmHj@Cpt!NYNh8Y>3=Hh|JzX3_DsH`<{X1CLUFN{w`Fe_+6IO(5 zS>fogc<D9{E}kt5(zZm+h;nCYS<pDEE9f|TNsIie2=9sQiz2e(BP84U-iB~Ttl^jA z<UiXeaOmrfySrl)%D0!tyqocD-~OkYexH3_wtszX3hzd*)ZSYRQZv|=HD)Hjs2i_D zczu{J9|)U$f@fR9_wp-ZscPy+BzX!sPtJ7RD*N|G)2#%@_qP6dlRVoux}<xZ`g-Rx zTPVw6`8k_rZs<t5Rr%`R7O#ZhwXA79?q^zagS8qS=H7Jkap<|3yW>#8!FkPUiaJ?t zZ*5;}Q)8a-{!N=fv3c}nKI>KI=BzA|Ik#!n;h4n3k@JfZYAdU*Ex6Ga|F*XCeDnHe zAI0~E_iv7Mn*V*aQ$nM3wA219-PcmlW|0Rst_#ZUsLl3v;N0+%yGQ?3`BnbH836?= z^2D3d_E`wm8tk84cr5p;a*eM0t4WgIOMWlreYU=%(O&F*h0=ryF*ff<iH~P+v22>! z;JZ6>-Ii~W51(z$U1>5iy231+L2L)Z^T6;Q;!*v_Sq&;A^v}2pu93V|>%&=8@M&H{ za?U<M+YNRS>OG+ob<`~6FFOCtWA2fvy~y<W>A{byqN2>t@RVKK+4V;Byi#fM8>9Gy z8B3d3vm184ka_r6w4%haURYx4tPa_~sv90h{@bG|`X+paJon)^n+wG@6aD&r=_`N# zB6eucPX(!jf6WfRzZula6s?P|$?!O(WmWl1D*W$P3*IkVKZiLA9gK2FGTXkn{q-|G zt;A_}qz+XsU&-qd6}<XS!sOovyr*w`q!s7g#vglY>GCGi>p7Y)=GtmnM{pawzoNd- zef^v##-~p%*SO0b?64qnqBPI{f|-?%{WjHjymipd?5KL6$Z8X&#`(ss<LAqTRZ0Qg zZOeP^2a5JAVHV!2ZycezLGW6`*2ya*|GtoV)!61$dC)C)%C#pGY;6_)8j4o#@u<vN z8gk=U3hQg8jf>_K?su@v{4Sdm!gAX2$css$Yi0#WRrgn3a6Wc5xTB2!Y4wMq<xg1- zZ`Pb^Ju^k*#}pq%k3uDtdvm8uk~tR@#&qL>n%8sAG`0UeM>beZ^lDPqQ1zUnx{PIm zUcipHWVslgViuR3Y&~z5^&}j)s_V1V+&3(3>7ws5f9cq4ooHh4AmDb}%kzJw4G-sD zjB48+nALZJU2H=$&zU8YtqmhCO~^2{Six-cg!%Ahjb8VeCwI3b{yvgpz{n}bxOIO` z!sFcz6{&I)f`51ZSnHD^`1&ccv@a)r@4>|q&&1BV&SA^bl)qu%QT+VH`9|h7{7O$` zH0C~GuHI=Xle3WLa{Xqh18xoTt7ot~FMl2H$uPNAt5)H(rRs(jPJ@4?pBf*|oN}yR z)j}y+tk&&bfg$^}DV9n8BGdNCuL!(1oxew8vB@%??)N9BB?^?<O%mi$E4=bHov+hL z=zm{S$g6ehdER7av8HD|{}t!8aL2@|@b)E_?V`lIG*t8LCkgUgV|}miUfE4Z{=|-( z>r+{jR~<-ta(rsTUjc8;mCtfEG(DZ2&04%OK(P0zbj*ikHj^)ipR!k2f730MwK<w) z7u(B(@DitHJ<c`KIji2tO}$hZ=ysoVw$|M{zF}K<RVz=dYfxTavvd2x4zUeee1!M2 zEqsz+P?ntWEK`{`hbtvvO_HD2drS2fd&`~54DPc#Y>m7k#;?1*p;M}|KUbykXV=TK zHMbjn-21C=E8%w~Kl{>#)*S|C?DV#Mx3E$2c=0S(jj`u!>&rPx*LPJ|+HCq6^G;cM z7WXAdoBShR=6yWyc>5f~e{G8nW~}>~HzCwuvip%459KPZCl;@F@ZOkUa{bo&rnO=g zY3Dev+<W}AV9yy}Ctug5jXOGidVhHP^_%0Cd(34OCl7vTebBeo!oW=2anH(S{I7G% z1(e?2$(2wy*y~;K&9$+$c%oRa=j2E&mhV>WS}%4h{|aiEx?5ty(ioLU)7pIZ>DOL7 zef>JuW3h72!PZTS6_|1?#b5pv*ZuPT<^AlMbEU1%Dj(-P<MOT1og}`v+4Yf9$Imcr z;he84r`q@H?=La=7o6(#;!<FcaMUArw(c{ov$k+2d&X2nUOs$L@`j3q@vjXlb!_#% z?6q4iUbwV@>)27#`xyrhx$f69-F_pq_+L%$Y76tywe$YQHl_1?{2p*{$IgoNK5g9_ zH$;DU*5hHIs8@T??%?UkZD*cc_pn!EIuovPpfo4xm7CrB8%LklS}QVf^YS!y|7j`T zy{(vMw&B^I+^15_CMIOWEMakfw`;QyuXmb(;pw}ULcQ8&PsDU@dLaK|&l`<1Hxlpe zQN6h>z5eCXbBy&RdX3$Wno5e-*B(9}&-43F@ultNEeBKzPAW4ctSaPeSb6*?zuJ+d z-E!jkGiJrqBm^H1dGd&H_HUo{O5*$x%OidD@;02b+4?7t;f-2o`7yH<M~?D_`7l}> z(l6IOew5cuwolb2q`O<XXV%Fz8??MU_3{j~+GG>-w~9P{#J2cc)eZB2DInIhjhzdF zty_2QIC$WywE5n9L9@E0*UY@7w=sr2Wiu~Vabfe%151~0eRupa<DdRb7OtNJxFl*B zW2eu^z5iQmnTa_6joFu$o_2ovY@&FNg!K|7@qAY6X9@pvjqcfYt}#88aKz`doRqHF zbF)M9w@zVF=E%RiP}l8DitR0{g&NoXKj(h~t4$$wYZh|`q<;Mye()dbpGCR{EUSe! zFfcHvmbgZgq$HN4S|t~yCYGc!7#SFv>KYp98k&a~8C#heTA5gA8yH#{7)%d&mx-bw zH$NpatrE9}XPjYI85kJCt3o15f)dLW3X1a6GILTDN-7Id6*3D-k{K8(<~;ty!%-Nf zp>fLp^cl~mK@7~w+<M8}!pg$llSP<?6<iuj4yQ0HZw^s7edEfBBWI4t9AQ7*;IY6< ZkKvWLV96&Z)2X0Fk*BMl%Q~loCIEz`Eo}e* literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-180x180.png b/vipra-ui/public/apple-touch-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..9349bc3006cbeae993227c4247526a2f5331bca3 GIT binary patch literal 2826 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 OBiGZ_&t;ucLK6TTxKRiI literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-57x57.png b/vipra-ui/public/apple-touch-icon-57x57.png new file mode 100644 index 0000000000000000000000000000000000000000..404609005a57d079d934aeafb60e9f41c777303d GIT binary patch literal 989 zcmeAS@N?(olHy`uVBq!ia0y~yV6X&X4h9AWhLy#4A{iJMSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7?_g0-CY>| zxA&jf&%nUIUgGKN%6^|mP~6zyq><$b1_q`kPZ!4!kK=Ezz0Vd(lwm0Nzx@5(mv<jN zyR~N8(Nu%LsH3M87C$toN)&szdeWskD;!p&-jM!nDCQfcuT+&-$vc_%+M2V679CXB zTC)A;;?FO)Meeq#zH(1w%lp~SEBD?1{o%lOZvN#?^-`;Jf8O^<%=)n*&e^E#;Dgy- z(wlyitmtm&Rj9seoV5DWUr8~JzZ<!)=d<2nw`QnX_cUtq9?p(^7k^&eTDx_^jvdS% z)w@K0CYfjK?Vg=pc+IiN^lpsWcgOQTs)CQCCMr+;e%WA3w%X^i7jss4%|7~JCG$F` zwaImpc4(PR{H|f7P#Y}u+PM1Nu{s`=_Y8kc;?jOS^a$IPk`n%5vyJ_3;XC&?d@@|x z=i!}ke)B8+pRZJ3_&!=v!FNV-rT3k`zq}Sr-qAVP(s<5vvG;|J7k4@rFsY00O5|C% z{%>OHNnW-&J;tvzoHX;IBDolvCkOHhyJzIpM@4cmHcqzjJ-%e-9$js3bBE^1#a0~) zjy+_w_0y9~Tw)lr^&o@aH2<d3oeN`b@Ex}3JhY(Kbc*APs?MqM76oF`PwZzN&`U@? z$d=PA7g}?`#?eBv;wr-(pW0o&9Jtph`EkX0RY&npv(j?=l2Fxd5Y&{jLF5{fxaP@A z@k~|*A2^h+CrXAMx_iLtXO#V_o9<ykJ%KF~O*MG$YT917wK!buXZZQ!wqm>i&7Lh2 z?Gr1fT)koOvQs@XOj&ozQ$M-HB|Jt`{C`N4y}5cZD{c16Hz{rxJ+Hohcq{Ftsr=ko z=esx_E)hyf4qg|N$9?Ka?yOAqQ%eME-a5=wxmjTypjP_iaM=Q%T?Z^Ce%QFyX{HY^ z!%?9v^-E1P=BJ;!=~%Q-EdS5<e@nJKxj*SXqk-H;oz0DMYZ(|AR7+eVN>UO_QmvAU zQWHy38H@}JO?3^8bPdfzjEt>J4XsQpv<(cc3=F1+yvsz<kei>9nO2Eg!!ypXs|*Yb z;Z-3KB|(Yh3I#>^X_+~x3MG{VsS23|CCLm76>}bc;^8O^)6h8OfBKB)(;x<BWp2G> zZee9%@5v&}!U`@8CWlj)l{bedoW618#E~;cWR9?(Ztz&(rN{6}T(IPmlj&4YzV&qV Kb6Mw<&;$UXIG-K> literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-60x60.png b/vipra-ui/public/apple-touch-icon-60x60.png new file mode 100644 index 0000000000000000000000000000000000000000..69090a0b6c4948749effbb3fe956c3caf72b6154 GIT binary patch literal 1025 zcmeAS@N?(olHy`uVBq!ia0y~yV6XvU4h9AW2Kni2>lhdqSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0zn2bC3(BMF#K=t zKeL~Kfq}im)7O>#K98WdvB60r%M%O?Ov^l7978;gzrA+WU)WKCt>EAC<=i1RlrHtw zEJ-pHFck6L;$SKuIx9g*MIc!4w#yW`3kq>AmL4W-LPCb8+6_fi6k=>7ZY}XJ+^ECl zbn~r+X~6ckMsM4=+3%h9d45uV?#;P#@A4FNoU%A}{6|4W^}_3MHBG0**1XdUl)g8! zM56SD_PuXWR~n|@u5ifDd$Hqrj-CJR$ggphv41u)8EorkKfFc1^_kq1R|-6Bmk+<^ znt0Vj|7e~2A3f%xUx!{M<Qx7tzW;ICl8Zu5c-(>>i*gsSFRIu6?Oyec{abhtQ=*mX zw7U<g$}*4NPqj+k{q(lHyy=2CpH^|!E3Fy7S1u~j*zozkly_drKCjl;6Mr3MO9p2f z*nODW>YMWTfo051m6W%S&h{R8p~y2i$7bd6;#)SR`s%L5Y&&lJ;QX{tKq<=RWZ(*+ zFtc|JmAw;|F1q=|qsSp4X(i{?lKMTmv4NcL6}mgir3*8=*Zn!x=JlejuQQc>)e7$Q z?jeV6U)X&84(H@sJ&Q&2Tm+^06^>Uk#A!Fr?X~~>!j{4Rh3G^rvDJw`S7trslX!k} z#uw$!OS3j89N0LQsk(B??~r5WvJZ}PO8?G!S$K0&%{8yunHhHzljrjuVl6o5viEnB z-wWx)q%3Z?8q)_+kJ9(Odl+cpI>REXUHM5iZ-AXh7jM4rm0}GkWuHCinad~5`#jCv z_<sH0n}0T%R7{oo9eTN?GdWC7uc48-$amW5u+N^qZW-<p{+@Hp@!MI=D`&q%|JWNI zS{8YIk;@E=bJs4tRy}7|Y-S#l|9&>dsTPC6Nq@tOB7&;Tgg5L;ox-&KhG~@QJC}WC ztB){MZHZKUw!<(ttkZvS^tF_!JG`e~|9fxp{C%O1u4Y?Z_?z*4dG_OXpI^l~rkAi? z+UEZ4^G6AJ#XsVg*uQSP%&Revfq_A_#5JNMC9x#cD!C{%u_Tqj$iUE4*U(7U&^*M* z*viz<%EUt3z|hLTV0y^AOcV{d`6-!cmAExL;|#mXz`zh*6%tVrlvu7%P?VpRnUkte zQdy9ykXcZY%)n4F=kX^Vj>0evjZ^-o&v-r!VqjM0)=TCVRu=Z2EW#|T;L>1nIE7hx sbBMy}8&^&oIdeqj2>a;<j|E<O46nomOFlW7P6g#{Pgg&ebxsLQ06+_|ApigX literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-72x72.png b/vipra-ui/public/apple-touch-icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..7e41b0928a7ca05b405ed7bce68b8e2099de6e03 GIT binary patch literal 1189 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84h9AWhJv;?vl$o|SkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7?_g0-CY>| zxA&jf&%nUIUgGKN%6^|mP~6zyq><$b1_ov?PZ!6Kh{JEMzx5Vzlwtqyd;Y%N-(Q3- zpZ6qqL781kx`(8MhUzyLySWn=YCPrUb`?}K){cK7EIF}LKPOl@z=xMt{@kP;IlNn~ z^UG)3Zi%^T{d^lo(`@toJO7@oyD@Y2%(+)R>sP)|3SjASsORFG&z?88&v@gp7iT7| z`<c6Tf<f$igT(DGCTqq0zreCH|M*FU<V{C!>8y#_8aG$ua9hhlou7t5vHd$=?!5W& zUexlLf9&q<6IFYXy`8ab^WD{l&aqCE-<QMM6MFwpQ;n{e!p7$Cm@j-*p8np~4mBKc z4|I5Ur17=(Qk@yAbgMcxGyn9qj;*r)a%l7HA8}_7-SFeBJjZaZmErTpdn*^G-M+B? z%J(3Jx+bx#<OKPt+R^;NYgu!h-<y5=(${m@RA2UqAG6d^2X`OV<a@O@9ktgemjtLY zA6FOJTl(zRSLVp~p$qQ#Gw04_pY_BmKV<E#SrXe6GW*zmCAfbP>5Si0WSdoakMpmv z)Qb78^K5qcpJjf<`>Nr!$%WVjvsnJCw!80jlyBzY^3Y*_qWRoYSNLl5p5CTjrcdIH zFO>@ww;A40a69b4m@D2il|9{ZuewKfrM1K?buG4Co+4uAO<QJcJm|vcY2FZ~8S>C) z!(|8E25%nLQbtRY3kw);)^ND5VadDX;N7{QudN}>|In8nwp(heH(9yduliE3=7Phe z2EmWUj+_5jKIn5{T|05_>8HHY-d<78>*AC0WYD?mIBD`phq(@{y(*{kueO-4I+?m@ zZn~bgi9q3vM?4CyzELW(=j8@0YD_u4_1wgJs$bs7t0&s98{8MqSkU0S?D6Ufg;S=h zccgFa-1AQ7?C;80jdq<CB}M@sO_Tqe>$x>2&rjWb(ha})E{uQ6RQ72UXl+Uh-}cq+ zeSN@W@xu%`dg>k`7vh#TxlXz)aX?}kr;FLr(A>{gWuMJ?@S{<ivu!T3wDjcr55r<D zb~(!iebn8XQzj}Jqm%n$_T7;Gv-use{1$Z7&9}euZ^_~kK3%Vl%WpIm-YhxWCsZ_1 zxXsO-^Qhw0wHE`OboBDFOQu{fOsT*6LSrHK1@jMwyk@ewa~2*?JfY`x`H_a=M)ePj z%<ezV?c>xeXmy`)W7EtJbN_z{HeqsIP|x<4rBrpzlZ`b62@DJjswJ)wB`Jv|saDBF zsfi`23`Pcqrn-hkx`yT<M#fgAhE^sP+6IPJ1_skZ-esa_$jwj5OsmAL;TdPxRR#uz z@T!oAlAy$Lg@U5|w9K4Tg_6pGRE5lfl4J&kiaC!z@o*G|X=t4CKYhmYX%GXmGPhnb zx3IFX_hb=fVFi~4lfx;@%9}$JPT#n4;>ejJGDp}?H+U@Y(qnifE?Dx($#g2H{PA@4 Kb6Mw<&;$UEhwwE3 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-76x76.png b/vipra-ui/public/apple-touch-icon-76x76.png new file mode 100644 index 0000000000000000000000000000000000000000..29d14b903247e28ff96f6ea34bf3a38d50f5482e GIT binary patch literal 1227 zcmeAS@N?(olHy`uVBq!ia0y~yVDJH94h9AWhDU$+zB4c|u%tWsIx;Y9?C1WI$jZRL zppfhl<jcTNrN+R}(89p*i-Ccm;RORjsR0ASs{{rHs~HRo;stYd1==t$Ffb)~ySp&_ zZ|^^|pMimay~NYkmHj@Cpt!NYNh8Y>3=GT#o-U3d5r^O2I2{}mD8W$hZ~1$>v+l2) z47a9DX$ejGapL(hgG+O_e%L4=ackMz34(=ZmcCe#GwakEHFjsg^i3CfH6+AaZd*>c zcD4E=gP*bKoU?n2_Z@yOckXrF0-^OAS8zozYA4i-cmI@W-sLs#nRaP2U%ZaI&Yp}_ zi4WEom@Zpdur8uzYq!6#iTCpSAA0^a>N)jWM69pcK6}~vv^BH1+*Hi___yK%dvZk> zR&W2^8ZX*(e_cA`3bXucH>!kRxh*zUS;=E59hiH$YT69($R5ptm39eE!k3<$<+`2E z{NPM_@N|n#mGer+AImuWt`m!>5&3#r#+U!<^3H#0hmTe2SoJ+i)bZ<EyP&dW(yQ>K zvk|ARn%Up^C2M2GIAyI+@<Tla->f}#K4DY%E1T3O^}Wep*mY>hjM?mEYN@@&Z?ikS z3)Q**C@G57^AyOh?|h<?ZZ#oOAdAu9=m~@UQX1C#D#LFUD%?Kg=Xh4!C}$qqR{2=g z<fF45J)WUy#Iv?rZcn@2G+W;j+Xbo^*g6arN*`#-kNY6E)J%*)S5WK{qs2wj#5LSn zTML;&gc1*0AJ}oxw8+1H(UoIo8QfcHSF?)gfABcHIC!a<woX8b?e4knB0qhe79{*> z-b2ILg2v(|X`(I?^L$^6&X`(ac2uw-PI0m7mr3i4KZ@RBw3gf`yM_5pip0Iy!IB#_ zxvtDkk+3u6S;!N1!l5p!<DF7MtfYas)p;=&r#IEi2ktf`Sv2_F^1C$I%%<ma_rVQ8 z6%2c?Pj@xqi8f*FG1Zdpi@LDbjpM%G4Xur(3sjCuP2_af(U_UJw_?tUDQh21=Ugwg z*OI+lzqOn_V84m9lHjyWY8R*fXfU~OM$U7Q`(~+_-*GC3&gll;$#I|mn5XYRrI<*8 zL_n6q*1Qgv8}idCvV5OczOtL0eRA`YO<z|Q)`c1Al>b>}6uq%i`hdB}QiraG5?XUD z?INa~%?=HZI+JnXZoKRK=UYmq7CwxqyA={1osoHD+w(T-tzWml+B)}e@$Dlwx2<XQ z4zl2R$I9QjWJOF!i&$V_>|)iUEXH&DRgXUN{<LYy3`UJ;xoINWZM)W2Mg;Y+y-k#x zCK7!3ta)Wb&>P8yf4Ld&EBmI2d|nuD{&bg>mHX>Mi)z<;zJ2=W<D50!w@;dfxQf1f zzSuJI|DXNrtZN$nuD{{GF7A|_%Ly3~1_lPz64!{5l*E!$tK_28#FA77BLhQIT|*;X zL-P<LV=GfbD-#QC14AnVgXtmfGEp?-=BH$)RpQq0j5F*i0|P^NRY*ihP-3}4K~a8M zW=^U?No7H*LS{ipG6O@!oX4MdI10lwG*0=SKI8c`h=Ey|TQ8YgSXtP6vIw)Vf=h$R x;S^@&%^?b>Z(KQX<jfJ7BkZReJQjHAF}xBNEcxVQIu%q(dAj<!taD0e0szB?{g(g$ literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon-precomposed.png b/vipra-ui/public/apple-touch-icon-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..4d110e9874af7700780f80bfeec4a287fa6d49b1 GIT binary patch literal 4249 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 AJOBUy literal 0 HcmV?d00001 diff --git a/vipra-ui/public/apple-touch-icon.png b/vipra-ui/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9349bc3006cbeae993227c4247526a2f5331bca3 GIT binary patch literal 2826 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 OBiGZ_&t;ucLK6TTxKRiI literal 0 HcmV?d00001 diff --git a/vipra-ui/public/browserconfig.xml b/vipra-ui/public/browserconfig.xml new file mode 100644 index 00000000..65380f38 --- /dev/null +++ b/vipra-ui/public/browserconfig.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<browserconfig> + <msapplication> + <tile> + <square70x70logo src="/mstile-70x70.png"/> + <square150x150logo src="/mstile-150x150.png"/> + <square310x310logo src="/mstile-310x310.png"/> + <wide310x150logo src="/mstile-310x150.png"/> + <TileColor>#da532c</TileColor> + </tile> + </msapplication> +</browserconfig> diff --git a/vipra-ui/public/favicon-16x16.png b/vipra-ui/public/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..2142db750ebddec14220299d9b135ef67c086a8a GIT binary patch literal 673 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4i*LmhONKMUokK+u%tWsIx;Y9?C1WI$jZRL zppfhl<jcTNrN+R}(89p*i-Ccm;RORjsR0ASs{{rHs~HRo;stYd1==t$Ffb)~ySp&_ zZ|^^|pMimav%n*=n1O*?7=#%aX3ddcU|?V`@$_|Nzt1BmZfv;ElrxTjfzi;@#W6(V zeCl~y?`TGewui4(*s~2-vSNEKxf(PFOz`>3-LzSXon3R$=4}CmB_G)%xc+|NcDz$s z5Wph-)Z&JtO@~DU3ww9l0%rq0%WDh1SJ|IG{F_av>q2JCe3`u5AI}!4Wn7RyvvZr$ zv><~eSEty&tWxmbU0J;^>zZ;|#^LJ4WljJ8YVJMuC41BRGqy%`7XIpg#peJ0;&yM+ z>J?QhV*^6JYEHfLBP?vq>Be>rnM0j1FJ?}WP1Uc6`mub?gH>hXru*)${Ufr%!bnHh zWSTKs?y|`_fu7UXG}mnPjboRb%$0V?<@_(zZA-2v1@|;fDp!kb>5SWucOZVbT1w!? z+?%Qk`_ptHj5CgG@#qeVSuLQb@$Oe#G_O$X>i_p0G@e^%NSf(>@)ExF>2|OFqF+zE z<rv#eL<on;KkQ>*U{Eb_jVMV;EJ?LWE=o--No6oHFf`RQG}1LR4>2;fGBva^vD7v& zv@$R-RDOCFMMG|WN@iLmZVe7~v55=}4B=HF5hX#1<q8Ew`DvLssR|{P1*r;|1trN0 z3>9-8f8yaN4Aam!<$wB&=hGktW@T=@WNu+)VeiQz%)$yT4JL<En3Xq&D4f1=<;0OQ kM`Vt$pKkD2;HAg#N?fqylauLG1_lNOPgg&ebxsLQ09h0C!T<mO literal 0 HcmV?d00001 diff --git a/vipra-ui/public/favicon-194x194.png b/vipra-ui/public/favicon-194x194.png new file mode 100644 index 0000000000000000000000000000000000000000..21aebd21587c3e1e8ead181661abfd5c63b7520f GIT binary patch literal 7280 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 My85}Sb4q9e04ZZxYybcN literal 0 HcmV?d00001 diff --git a/vipra-ui/public/favicon-32x32.png b/vipra-ui/public/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..5f02b4eddf4ea6a56bfcd19c8b61a406f99d9129 GIT binary patch literal 1124 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4i*LmhMUEk>KPaqSkfJR9T^xl_H+M9WCckk zdj$D1FjT2AFf_C<F#KX*U}$*3z))(y!0;-8fx&791A}<MoLzx73=9lRN#5=*4FB8v z&+KPlVBjq9h%9Dc;1&j9Muu5)Bp4VN*h@TpUD@yR2#OmU?la|#V_;zV;_2cT;&FWL zmH3RSsWQhuUjJ;Jo_Fe>BWtC?X70IhKFR3`WlJxdY3kagx%<U2*GVsQI?hB!XzOcf ziC<CJeM0)R+JvAs;f>nNe^YNy664ZlRX5E(x3tve`JY_{zP9Ps&i3W}=fD50v^#(J z`%gCGj8>cCEmeoKx=kJ|3huk{d`C>&|CHDna_7CABJwsLzq9hiB+e_VgeAZBzFT6i z^6?B?<SLuzyxeoHuRcG)&?IWn*{E{s$GX)qz01u{1U*e%@BRB!JDcdE*VdY6<34TK zqbI*ZYPxg^tLN_6Ph~F(TUA=3c#ruUx$g7qRzmxhvlpMcuH1Av^J8b#?b6e#iYD#4 zRyL2zos}gfp0s|}WxDBP`8oHcoRhR>>ud<`Zz_q%-(Gp|`nvc3yJj@WRqJjzIVWJ+ zg3$GI-2X~wZi`-TY$?=LSb6TZ?1XPAA=@rK<J-%osdqVV_u-`$hLarkzWY@1QgoF~ zgELoSX`dK>ytaP0hK0(;RaX|=t3Ad$@k(Z)g4eR+$r42u7X>x%eB~qI+?=(4<q|_- zDR16GA?ZCY%g(Lwn!ZL~x_rIcBhL8qhs;))hRsU2v!Tj&OGrxe0?+2lOWDF}``cX> zE^?gUa*M@1?!g24WabyF0(H=K#8zY%`zl;7{0HL_V+X)7)!?)%#}wJd2X-&	 zdnPQ|WISj7lAI4~Hrq|}p88<@t1pvnqt^1(zdrxO{nX>@Exq@SnEj6Ze=c%W?$wt| zp4V#TZ#5N@I@gmnY2wORK3<!*=L(km3@OZ7;PdGAoGte_CzZU|B>McztIwyOcw}En zTidgFSB;{%=_RkiEkDi(ZCq;3bJc3AQvI)M>z*9pbuN{%$=<&7-p7eY<+fdN`YJU2 z&#M*9Y)`r-x3<ju_~h<~{6$fDeO8|fZZ6db|8Us1e^%JzsWU&ETtBDyVCzgNrB92l zYdzYmk#c^;rzwlKw+rt)uF1T;TUhei6UVDze*6CDK5Tj8W*uvoveC_Y@AGK|K{FZa zBNKNPT9^KQey!ji^Hpw15vx#>Tm}XP)e_f;l9a@fRIB8o)Wnih1|tJQQ(Z$NT|@H_ zBV#L5Ln{+YZ39Cq0|P_lr*}~_<mRVjrd8tB;7}Kv$iTo5UKJ8i5|mi3P*9YgmYI{P zP*Pcts*qVwlFYzRG3W6o9*)8=4UJR&r_Xpk4Pszc=GIH*7FHJao-D#Ftl-jMayW%q vd2@)u=^Iy09657D<_P=g29E_^dJM0`1xr3TnNDS3U|{fc^>bP0l+XkKZnEs| literal 0 HcmV?d00001 diff --git a/vipra-ui/public/favicon-96x96.png b/vipra-ui/public/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..db921e4ed2dcd5d09ed8c3feda59dbecdb4f6493 GIT binary patch literal 3394 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 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/favicon.ico b/vipra-ui/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5732db6037b1f85a34fb650544f2c844313a2855 GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/manifest.json b/vipra-ui/public/manifest.json new file mode 100644 index 00000000..fd248ba8 --- /dev/null +++ b/vipra-ui/public/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "Vipra", + "icons": [ + { + "src": "\/android-chrome-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": 0.75 + }, + { + "src": "\/android-chrome-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": 1 + }, + { + "src": "\/android-chrome-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": 1.5 + }, + { + "src": "\/android-chrome-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": 2 + }, + { + "src": "\/android-chrome-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": 3 + }, + { + "src": "\/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": 4 + } + ] +} diff --git a/vipra-ui/public/mstile-144x144.png b/vipra-ui/public/mstile-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..f8bbf5181ec917852ccc7d485261c378ccbc7585 GIT binary patch literal 4665 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 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/mstile-150x150.png b/vipra-ui/public/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..695de5e588f6771411672a7ab77d11ff9f7b19c0 GIT binary patch literal 4592 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 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/mstile-310x150.png b/vipra-ui/public/mstile-310x150.png new file mode 100644 index 0000000000000000000000000000000000000000..31d0d95b73f37cb775eaa1fbe11152400f961d5f GIT binary patch literal 4923 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 O0>;zT&t;ucLK6UsLk{%- literal 0 HcmV?d00001 diff --git a/vipra-ui/public/mstile-310x310.png b/vipra-ui/public/mstile-310x310.png new file mode 100644 index 0000000000000000000000000000000000000000..632930e827817f36965e2402748adef9b9311d96 GIT binary patch literal 10210 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 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/mstile-70x70.png b/vipra-ui/public/mstile-70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..e6ece63cb1b9caa78fc2cebb370e07d9f2e5db04 GIT binary patch literal 3220 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 literal 0 HcmV?d00001 diff --git a/vipra-ui/public/safari-pinned-tab.svg b/vipra-ui/public/safari-pinned-tab.svg new file mode 100644 index 00000000..93d972a5 --- /dev/null +++ b/vipra-ui/public/safari-pinned-tab.svg @@ -0,0 +1,36 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" + "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> +<svg version="1.0" xmlns="http://www.w3.org/2000/svg" + width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000" + preserveAspectRatio="xMidYMid meet"> +<metadata> +Created by potrace 1.11, written by Peter Selinger 2001-2013 +</metadata> +<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)" +fill="#000000" stroke="none"> +<path d="M3010 5110 c-129 -17 -159 -22 -240 -40 -112 -26 -104 -24 -196 -55 +-184 -63 -388 -173 -539 -289 -82 -64 -103 -83 -202 -183 -298 -302 -477 -668 +-537 -1098 -14 -100 -15 -399 -1 -495 28 -199 96 -426 177 -586 l31 -61 -691 +-692 c-559 -559 -700 -705 -731 -759 -167 -282 -60 -647 233 -791 188 -93 409 +-76 576 42 14 10 337 329 718 709 l692 691 98 -46 c170 -80 379 -140 569 -165 +73 -9 367 -9 453 0 266 28 570 135 800 281 169 107 372 290 487 437 213 274 +356 613 399 945 9 72 11 387 3 458 -39 336 -165 653 -374 938 -63 87 -237 269 +-320 336 -155 126 -414 270 -586 327 -107 35 -259 72 -359 86 -97 14 -377 20 +-460 10z m455 -333 c391 -73 703 -251 961 -552 127 -147 236 -347 298 -544 58 +-185 75 -314 71 -526 -4 -161 -6 -176 -36 -305 -43 -185 -95 -316 -188 -472 +-233 -392 -621 -661 -1085 -754 -101 -20 -394 -26 -506 -11 -237 33 -509 142 +-709 285 -122 86 -288 252 -373 372 -121 171 -223 403 -262 596 -8 43 -18 93 +-21 109 -21 104 -8 467 20 554 3 11 8 31 10 43 3 13 15 59 29 103 147 483 534 +879 1016 1039 58 19 116 37 130 40 14 2 50 10 80 16 30 6 80 13 110 17 30 3 +57 7 58 9 10 8 329 -7 397 -19z m-1730 -2814 c70 -85 212 -223 279 -271 20 +-14 36 -28 36 -32 0 -10 -1285 -1295 -1325 -1326 -45 -34 -120 -54 -183 -49 +-100 7 -191 72 -235 165 -31 65 -29 168 4 235 19 38 177 203 680 707 360 361 +659 657 664 657 6 0 42 -39 80 -86z"/> +<path d="M2995 4299 c-351 -67 -642 -288 -800 -607 -39 -80 -80 -197 -89 -256 +-4 -21 -8 -42 -11 -46 -3 -4 -8 -55 -11 -113 -6 -104 -6 -106 19 -131 45 -45 +119 -27 131 32 3 15 8 59 11 99 17 273 178 553 408 712 78 53 219 119 293 136 +10 2 37 9 59 14 45 10 130 20 188 21 72 0 110 74 67 130 -17 23 -26 25 -97 26 +-43 0 -118 -7 -168 -17z"/> +</g> +</svg> diff --git a/vipra-ui/tests/integration/components/article-list-test.js b/vipra-ui/tests/integration/components/article-list-test.js new file mode 100644 index 00000000..bcc52965 --- /dev/null +++ b/vipra-ui/tests/integration/components/article-list-test.js @@ -0,0 +1,25 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('article-list', 'Integration | Component | article list', { + 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`{{article-list}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage:" + EOL + + this.render(hbs` + {{#article-list}} + template block text + {{/article-list}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/vipra-ui/tests/integration/components/debounced-input-test.js b/vipra-ui/tests/integration/components/debounced-input-test.js new file mode 100644 index 00000000..323028be --- /dev/null +++ b/vipra-ui/tests/integration/components/debounced-input-test.js @@ -0,0 +1,25 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('debounced-input', 'Integration | Component | debounced input', { + 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`{{debounced-input}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage:" + EOL + + this.render(hbs` + {{#debounced-input}} + template block text + {{/debounced-input}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/vipra-ui/tests/integration/components/dynamic-high-charts-test.js b/vipra-ui/tests/integration/components/dynamic-high-charts-test.js new file mode 100644 index 00000000..07810b85 --- /dev/null +++ b/vipra-ui/tests/integration/components/dynamic-high-charts-test.js @@ -0,0 +1,25 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('dynamic-high-charts', 'Integration | Component | dynamic high charts', { + 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`{{dynamic-high-charts}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage:" + EOL + + this.render(hbs` + {{#dynamic-high-charts}} + template block text + {{/dynamic-high-charts}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/vipra-ui/tests/integration/components/text-marker-test.js b/vipra-ui/tests/integration/components/text-marker-test.js new file mode 100644 index 00000000..1af17c61 --- /dev/null +++ b/vipra-ui/tests/integration/components/text-marker-test.js @@ -0,0 +1,25 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('text-marker', 'Integration | Component | text marker', { + 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`{{text-marker}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage:" + EOL + + this.render(hbs` + {{#text-marker}} + template block text + {{/text-marker}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/vipra-ui/tests/unit/controllers/articles-test.js b/vipra-ui/tests/unit/controllers/articles-test.js new file mode 100644 index 00000000..2f09e3a9 --- /dev/null +++ b/vipra-ui/tests/unit/controllers/articles-test.js @@ -0,0 +1,12 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('controller:articles', 'Unit | Controller | articles', { + // Specify the other units that are required for this test. + // needs: ['controller:foo'] +}); + +// Replace this with your real tests. +test('it exists', function(assert) { + let controller = this.subject(); + assert.ok(controller); +}); diff --git a/vipra-ui/tests/unit/routes/articles-test.js b/vipra-ui/tests/unit/routes/article-test.js similarity index 80% rename from vipra-ui/tests/unit/routes/articles-test.js rename to vipra-ui/tests/unit/routes/article-test.js index 14d8ec84..a9185964 100644 --- a/vipra-ui/tests/unit/routes/articles-test.js +++ b/vipra-ui/tests/unit/routes/article-test.js @@ -1,6 +1,6 @@ import { moduleFor, test } from 'ember-qunit'; -moduleFor('route:articles', 'Unit | Route | articles', { +moduleFor('route:article', 'Unit | Route | article', { // Specify the other units that are required for this test. // needs: ['controller:foo'] }); diff --git a/vipra-ui/tests/unit/routes/not-found-test.js b/vipra-ui/tests/unit/routes/not-found-test.js new file mode 100644 index 00000000..2375b9bb --- /dev/null +++ b/vipra-ui/tests/unit/routes/not-found-test.js @@ -0,0 +1,11 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:not-found', 'Unit | Route | not found', { + // Specify the other units that are required for this test. + // needs: ['controller:foo'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +}); diff --git a/vipra-util/.classpath b/vipra-util/.classpath new file mode 100644 index 00000000..d38d831c --- /dev/null +++ b/vipra-util/.classpath @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src/main/java"/> + <classpathentry kind="src" path="src/main/resources"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/> + <classpathentry kind="output" path="target/classes"/> +</classpath> diff --git a/vipra-util/.gitignore b/vipra-util/.gitignore new file mode 100644 index 00000000..09e3bc9b --- /dev/null +++ b/vipra-util/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/vipra-util/.project b/vipra-util/.project new file mode 100644 index 00000000..7e5c99aa --- /dev/null +++ b/vipra-util/.project @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>vipra-util</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.wst.common.project.facet.core.builder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.m2e.core.maven2Builder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.wst.validation.validationbuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jem.workbench.JavaEMFNature</nature> + <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature> + <nature>org.eclipse.m2e.core.maven2Nature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + <nature>org.eclipse.wst.common.project.facet.core.nature</nature> + </natures> +</projectDescription> diff --git a/vipra-util/.settings/org.eclipse.jdt.core.prefs b/vipra-util/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..107056a3 --- /dev/null +++ b/vipra-util/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/vipra-util/.settings/org.eclipse.m2e.core.prefs b/vipra-util/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 00000000..f897a7f1 --- /dev/null +++ b/vipra-util/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/vipra-util/.settings/org.eclipse.wst.common.component b/vipra-util/.settings/org.eclipse.wst.common.component new file mode 100644 index 00000000..217de769 --- /dev/null +++ b/vipra-util/.settings/org.eclipse.wst.common.component @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0"> + <wb-module deploy-name="vipra-util"> + <wb-resource deploy-path="/" source-path="/src/main/java"/> + <wb-resource deploy-path="/" source-path="/src/main/resources"/> + </wb-module> +</project-modules> diff --git a/vipra-util/.settings/org.eclipse.wst.common.project.facet.core.xml b/vipra-util/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 00000000..926884d9 --- /dev/null +++ b/vipra-util/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<faceted-project> + <fixed facet="jst.utility"/> + <fixed facet="java"/> + <installed facet="java" version="1.6"/> + <installed facet="jst.utility" version="1.0"/> +</faceted-project> diff --git a/vipra-util/pom.xml b/vipra-util/pom.xml new file mode 100644 index 00000000..039cebdc --- /dev/null +++ b/vipra-util/pom.xml @@ -0,0 +1,52 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>de.vipra</groupId> + <artifactId>vipra-util</artifactId> + <version>0.0.1-SNAPSHOT</version> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <log4jVersion>2.4.1</log4jVersion> + </properties> + + <dependencies> + <!-- Logging --> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + <version>${log4jVersion}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>${log4jVersion}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + <version>${log4jVersion}</version> + </dependency> + + <!-- MongoDB Database Adapter --> + <dependency> + <groupId>org.mongodb</groupId> + <artifactId>mongodb-driver</artifactId> + <version>3.0.4</version> + </dependency> + </dependencies> + + <build> + <sourceDirectory>src</sourceDirectory> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.3</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/vipra-util/src/main/java/META-INF/MANIFEST.MF b/vipra-util/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 00000000..5e949512 --- /dev/null +++ b/vipra-util/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/vipra-util/src/main/java/de/vipra/util/Config.java b/vipra-util/src/main/java/de/vipra/util/Config.java new file mode 100644 index 00000000..f1001355 --- /dev/null +++ b/vipra-util/src/main/java/de/vipra/util/Config.java @@ -0,0 +1,50 @@ +package de.vipra.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Config { + + public static final Logger log = LoggerFactory.getLogger(Config.class); + + private final Properties props = new Properties(); + + public Config() throws IOException, ConfigException { + this(Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties")); + + } + + public Config(InputStream is) throws IOException, ConfigException { + if (is == null) { + log.error("config file input stream is null"); + throw new ConfigException("config file input stream is null"); + } else { + props.load(is); + } + } + + public String getString(String key) { + return getString(key, null); + } + + public String getString(String key, String defaultValue) { + return props.getProperty(key, defaultValue); + } + + public Integer getInt(String key) { + return getInt(key, null); + } + + public Integer getInt(String key, Integer defaultValue) { + try { + return Integer.parseInt(props.getProperty(key)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + +} diff --git a/vipra-util/src/main/java/de/vipra/util/ConfigException.java b/vipra-util/src/main/java/de/vipra/util/ConfigException.java new file mode 100644 index 00000000..d6404572 --- /dev/null +++ b/vipra-util/src/main/java/de/vipra/util/ConfigException.java @@ -0,0 +1,11 @@ +package de.vipra.util; + +public class ConfigException extends Exception { + + private static final long serialVersionUID = 1L; + + public ConfigException(String string) { + super(string); + } + +} \ No newline at end of file diff --git a/vipra-util/src/main/java/de/vipra/util/Mongo.java b/vipra-util/src/main/java/de/vipra/util/Mongo.java new file mode 100644 index 00000000..73628bd0 --- /dev/null +++ b/vipra-util/src/main/java/de/vipra/util/Mongo.java @@ -0,0 +1,48 @@ +package de.vipra.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mongodb.MongoClient; +import com.mongodb.client.MongoDatabase; +import de.vipra.util.Config; + +public class Mongo { + + public static final Logger log = LoggerFactory.getLogger(Mongo.class); + + private static Mongo instance; + + private final MongoClient client; + private final MongoDatabase database; + + private Mongo(Config config) throws ConfigException { + String host = config.getString("db.host"); + Integer port = config.getInt("db.port"); + String databaseName = config.getString("db.name"); + + if (host == null || port == null || databaseName == null) { + log.error("host/port/dbname missing in configuration"); + throw new ConfigException("host/port/dbname missing in configuration"); + } + + client = new MongoClient(host, port); + database = client.getDatabase(databaseName); + } + + public MongoClient getClient() { + return client; + } + + public MongoDatabase getDatabase() { + return database; + } + + public static Mongo getInstance(Config config) throws ConfigException { + if (instance == null) { + instance = new Mongo(config); + } + return instance; + } + +} diff --git a/vipra-util/src/main/resources/config.properties b/vipra-util/src/main/resources/config.properties new file mode 100644 index 00000000..07030840 --- /dev/null +++ b/vipra-util/src/main/resources/config.properties @@ -0,0 +1,3 @@ +db.host=localhost +db.port=27017 +db.name=test \ No newline at end of file diff --git a/vipra-util/src/main/resources/log4j2.xml b/vipra-util/src/main/resources/log4j2.xml new file mode 100644 index 00000000..87133400 --- /dev/null +++ b/vipra-util/src/main/resources/log4j2.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <Console name="Console" target="SYSTEM_OUT"> + <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n" /> + </Console> + </Appenders> + <Loggers> + <Root level="ALL"> + <AppenderRef ref="Console" /> + </Root> + <Logger name="org.mongodb" level="INFO"/> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/vm/bootstrap.sh b/vm/bootstrap.sh index 5535f49a..0b238ae4 100644 --- a/vm/bootstrap.sh +++ b/vm/bootstrap.sh @@ -96,7 +96,7 @@ mvn -DskipTests -X clean -f ./mahout install # ----------------------------------------------------------------------------- # install elasticsearch -wget https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/deb/elasticsearch/2.1.0/elasticsearch-2.1.0.deb +wget https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/deb/elasticsearch/2.1.1/elasticsearch-2.1.1.deb gdebi -n elasticsearch-2.1.0.deb rm elasticsearch-2.1.0.deb service start elasticsearch -- GitLab