diasporadiaries

a platform for writing stories with personal accounts and messages
git clone git://parazyd.org/diasporadiaries.git
Log | Files | Refs | Submodules | README | LICENSE

commit 1d131ae8a95976f26140c25a3e5818c57bc8b54e
parent ce5a75cc96be814d754605cd8c1b95c1bde72490
Author: parazyd <parazyd@dyne.org>
Date:   Tue, 15 Jan 2019 12:32:43 +0100

Initial working code.

Diffstat:
Adiaspora.py | 270+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astatic/css/diaspora.css | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astatic/fonts/librebaskerville.woff2 | 0
Astatic/img/disembark.svg | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astatic/img/embark.svg | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astatic/img/flags | 2++
Astatic/img/slatkisi.png | 0
Astatic/js/summernote-cleaner.js | 179+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/cc.html | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/country.html | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/footer.html | 5+++++
Atemplates/header.html | 15+++++++++++++++
Atemplates/index.html | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/nav.html | 40++++++++++++++++++++++++++++++++++++++++
Atemplates/submit.html | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/submitted.html | 17+++++++++++++++++
Atemplates/view.html | 21+++++++++++++++++++++
Aworld.json | 2++
18 files changed, 1430 insertions(+), 0 deletions(-)

diff --git a/diaspora.py b/diaspora.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 Ivan Jelincic <parazyd@dyne.org> +# +# This file is part of diasporadiaries +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +""" +Main diasporadiaries module +""" +from argparse import ArgumentParser +from random import randint, shuffle +from time import gmtime, strftime, time +import json +import sqlite3 + +from flask import (Flask, render_template, request, Markup) + + +app = Flask(__name__) + + +def initdb(dbpath): + """ + Initializes the sqlite3 database and returns the db context and cursor. + + There are two tables, one which holds users, and the other holds stories. + """ + _dbctx = sqlite3.connect(dbpath, check_same_thread=False) + _db = _dbctx.cursor() + + udbinit = """ + CREATE TABLE IF NOT EXISTS users ( + id integer PRIMARY KEY, + email text NOT NULL, + name text NOT NULL, + password text NOT NULL, + timestamp integer NOT NULL + ); + """ + + sdbinit = """ + CREATE TABLE IF NOT EXISTS stories ( + id integer PRIMARY KEY, + name text NOT NULL, + embark text NOT NULL, + disembark text NOT NULL, + email text, + contact text, + story text NOT NULL, + timestamp integer NOT NULL, + visible integer NOT NULL + ); + """ + + _db.execute(udbinit) + _db.execute(sdbinit) + + return _dbctx, _db + + +def getcountryname(cc): + """ + Returns a country name which matches the given country code. + """ + return countrymap.get(cc, 'Unknown countries') + + +def query_all_where(col, val): + """ + Executes a query where col = val and returns all found rows. + """ + db.execute("SELECT * FROM stories WHERE %s = '%s';" % (col, val)) + return db.fetchall() + + +def query_col(col): + """ + Executes a SELECT query and returns the entire col. + """ + db.execute("SELECT %s FROM stories;" % col) + return db.fetchall() + + +def fillstory(row): + """ + Returns a story dict filled with the given row from the db. + """ + return { + 'id': row[0], + 'name': row[1], + 'embark': row[2], + 'embarkname': getcountryname(row[2]), + 'disembark': row[3], + 'disembarkname': getcountryname(row[3]), + 'email': row[4], + 'contact': row[5], + 'story': row[6], + 'date': strftime('%d.%m.%Y.', gmtime(row[7])), + 'time': strftime('%H:%M UTC', gmtime(row[7])), + 'visible': row[8], + } + + +def getstory(storyid): + """ + Returns a story dict with the given story id. + """ + return fillstory(query_all_where('id', storyid)[0]) + + +def getstories(col, cc): + """ + Returns a list of filled stories for viewing multiple ones in + the /country route. + """ + rows = query_all_where(col, cc) + + stories = [] + for row in rows: + sinstory = fillstory(row) + sinstory['story'] = Markup(sinstory['story']).striptags()[:128] + sinstory['story'] += '...' + stories.append(sinstory) + + return stories[::-1] + + +def getstoriesfiltered(cc, column, param): + """ + Returns a filtered list of filled stories for viewing multiple ones + in the /country route. + """ + stories = getstories(cc, column) + + filtered_stories = [] + for j in stories: + if j['embark'] == param: + filtered_stories.append(j) + + return filtered_stories + + +def makenav(): + """ + Queries the disembark column for filling up the by-country dropdown + navigation. + """ + rows = query_col('disembark') + + havec = [] + for j in rows: + havec.append(j[0]) + + havec = list(set(havec)) + navlist = [] + for j in havec: + navlist.append((j, getcountryname(j))) + + shuffle(navlist) + return navlist + + +@app.route('/') +def main(): + """ + Main route, the homepage. + """ + return render_template('index.html', navlist=makenav()) + + +@app.route('/submit', methods=['GET', 'POST']) +def submit(): + """ + Route for submitting a story. + """ + if request.method == 'POST': + db.execute(""" + INSERT INTO stories VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + """, (None, + request.form['Name'], + request.form['Embark'], + request.form['Disembark'], + request.form['Email'], + request.form['Contact'], + request.form['Story'], + int(time()), + 1)), + dbctx.commit() + + + return render_template('submitted.html', navlist=makenav()) + + return render_template('submit.html', navlist=makenav()) + + +@app.route('/country', methods=['GET']) +def country(): + """ + Route for viewing stories for a specific country. + TODO: If no country is given, it will show a random country. + """ + cc = request.args.get('id') + # TODO: if not cc: + + ccfrom = request.args.get('from') + if ccfrom: + filtered_stories = getstoriesfiltered('disembark', cc, ccfrom) + + stories = getstories('disembark', cc) + clist = [] + for j in stories: + clist.append((j['embark'], j['embarkname'])) + clist = list(set(clist)) + + if not ccfrom: + return render_template('country.html', navlist=makenav(), + country=getcountryname(cc), cc=cc, + stories=stories, filtered_stories=None, + clist=clist) + + return render_template('country.html', navlist=makenav(), + country=getcountryname(cc), cc=cc, + stories=stories, filtered_stories=filtered_stories, + clist=clist) + + +@app.route('/view', methods=['GET']) +def view(): + """ + Route for viewing a single story. + If no story is specified, it will render a random story. + """ + story_id = request.args.get('id', randint(1, len(query_col('id')))) + story = getstory(story_id) + return render_template('view.html', navlist=makenav(), story=story) + + +if __name__ == '__main__': + parser = ArgumentParser() + parser.add_argument('-l', default='0.0.0.0', + help='Address for listening (ex: 127.0.0.1)') + parser.add_argument('-p', default='8000', + help='Port for listening (ex: 8000)') + parser.add_argument('-db', default='stories.db', + help='Path to sqlite database (ex: stories.db)') + parser.add_argument('-d', action='store_true', default=True, + help='Debug mode') + args = parser.parse_args() + + countrymap = {} + with open('world.json') as f: + data = json.load(f) + for i in data: + countrymap[i['alpha2']] = i['name'] + countrymap['xk'] = 'Kosovo' + + dbctx, db = initdb(args.db) + + app.run(host=args.l, port=args.p, threaded=True, debug=args.d) diff --git a/static/css/diaspora.css b/static/css/diaspora.css @@ -0,0 +1,130 @@ +@font-face { + font-family: 'Libre Baskerville'; + font-style: normal; + font-weight: 400; + src: url('/static/fonts/librebaskerville.woff2') format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +html, body { + height: 100%; + font-family: 'Libre Baskerville', serif; + font-style: italic; + font-size: 1.2em; +} + +nav { + font-family: 'Libre Baskerville', serif; + font-style: italic; + margin-bottom: 2em; +} + +.cover { + font-family: 'Libre Baskerville', serif; + font-style: italic; + text-align: justify; + margin-bottom: 4em; + /* padding: 2em 5em; */ +} + +.burger { + display: inline-block; + font-size: 1em; + border: 0; + background: none; + outline: 0; + padding: 0; + cursor: pointer; + /* border-bottom: 4px solid currentColor; */ + /* width: 28px; */ + transition: border-bottom 1s ease-in-out; + -webkit-transition: border-bottom 1s ease-in-out; +} + +.burger:hover { + text-decoration: underline; +} + +.burger::-moz-focus-inner { + border: 0; + padding: 0; +} + +.burger:before { + content: ""; + display: block; + /* border-bottom: 4px solid currentColor; */ + width: 100%; + margin-bottom: 5px; + transition: -webkit-transform 0.5s ease-in-out; + transition: transform 0.5s ease-in-out; + transition: transform 0.5s ease-in-out, -webkit-transform 0.5s ease-in-out; + -webkit-transition: -webkit-transform 0.5s ease-in-out; +} + +.burger:after { + content: ""; + display: block; + /*border-bottom: 4px solid currentColor; */ + width: 100%; + margin-bottom: 5px; + transition: -webkit-transform 0.5s ease-in-out; + transition: transform 0.5s ease-in-out; + transition: transform 0.5s ease-in-out, -webkit-transform 0.5s ease-in-out; + -webkit-transition: -webkit-transform 0.5s ease-in-out; +} + +.burger-check { + display: none; +} + +.burger-check:checked ~ .burger { + /* border-bottom: 4px solid transparent; */ + transition: border-bottom 0.8s ease-in-out; + -webkit-transition: border-bottom 0.8s ease-in-out; +} + +.burger-check:checked ~ .burger:before { + transform: rotate(-405deg) translateY(1px) translateX(-3px); + -webkit-transform: rotate(-405deg) translateY(1px) translateX(-3px); + transition: -webkit-transform 0.5s ease-in-out; + transition: transform 0.5s ease-in-out; + transition: transform 0.5s ease-in-out, -webkit-transform 0.5s ease-in-out; + -webkit-transition: -webkit-transform 0.5s ease-in-out; +} + +.burger-check:checked ~ .burger:after { + transform: rotate(405deg) translateY(-4px) translateX(-5px); + -webkit-transform: rotate(405deg) translateY(-4px) translateX(-5px); + transition: -webkit-transform 0.5s ease-in-out; + transition: transform 0.5s ease-in-out; + transition: transform 0.5s ease-in-out, -webkit-transform 0.5s ease-in-out; + -webkit-transition: -webkit-transform 0.5s ease-in-out; +} + +.readmore { + overflow: hidden; + max-height: 0; + transition: max-height 0.5s ease-in-out; +} + +.burger-check:checked ~ .readmore { + max-height: 300em; + transition: max-height 0.5s ease-in-out; +} + +.note-editable { + text-align: left; + line-height: 2em; +} + +.countrylist-bottom { + margin-top: 2em; + text-align: center; +} + +.countrylist-bottom a { + text-decoration: none; +} + + diff --git a/static/fonts/librebaskerville.woff2 b/static/fonts/librebaskerville.woff2 Binary files differ. diff --git a/static/img/disembark.svg b/static/img/disembark.svg @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="530.000000pt" + height="400.000000pt" + viewBox="0 0 530.000000 400.000000" + preserveAspectRatio="xMidYMid meet" + id="svg3813" + sodipodi:docname="disembark.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <defs + id="defs3817" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1918" + inkscape:window-height="1066" + id="namedview3815" + showgrid="false" + inkscape:zoom="0.82125" + inkscape:cx="416.06453" + inkscape:cy="294.05738" + inkscape:window-x="0" + inkscape:window-y="12" + inkscape:window-maximized="0" + inkscape:current-layer="svg3813" + inkscape:measure-start="154.124,411.41" + inkscape:measure-end="0,0" /> + <metadata + id="metadata3801"> +Created by potrace 1.15, written by Peter Selinger 2001-2017 +<rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> +</rdf:RDF> +</metadata> + <g + transform="matrix(-0.1,0,0,-0.1,530.76131,400)" + id="g3811" + style="fill:#000000;stroke:none"> + <path + d="m 1963,3650 c 3,-8 177,-454 387,-990 210,-536 385,-981 388,-989 5,-12 63,-13 386,-7 209,3 382,8 384,11 5,5 -63,116 -172,280 -202,304 -483,676 -787,1039 -291,349 -597,691 -586,656 z" + id="path3803" + inkscape:connector-curvature="0" /> + <path + d="m 1917,3023 c -189,-373 -357,-772 -482,-1148 -73,-222 -132,-441 -122,-452 6,-5 1438,165 1445,172 4,4 -727,1597 -737,1608 -4,4 -51,-77 -104,-180 z" + id="path3805" + inkscape:connector-curvature="0" /> + <path + d="m 4035,1629 c -77,-11 -1055,-124 -2034,-234 -420,-47 -773,-90 -783,-96 -10,-5 -20,-20 -23,-32 -5,-18 51,-197 125,-404 8,-21 40,-57 88,-96 98,-81 109,-87 174,-87 55,0 64,4 162,75 133,96 332,90 464,-14 68,-54 84,-61 145,-61 47,0 62,5 103,35 93,66 132,86 203,100 121,26 226,-2 343,-90 54,-40 66,-45 113,-45 30,0 64,4 77,9 13,5 72,51 133,101 l 109,92 48,-54 47,-53 164,165 c 173,175 288,312 375,448 65,101 115,205 110,229 -4,22 -52,26 -143,12 z" + id="path3807" + inkscape:connector-curvature="0" /> + <path + d="m 1210,733 c -30,-37 -63,-77 -73,-89 -17,-22 -16,-23 110,-128 88,-74 144,-113 183,-127 144,-54 301,-27 417,72 77,66 155,63 253,-11 77,-59 130,-79 226,-87 99,-8 188,20 278,87 106,77 165,79 259,6 93,-72 146,-90 263,-91 96,0 104,2 168,35 60,31 284,205 285,221 1,4 -31,46 -71,93 -62,76 -73,85 -87,73 -9,-7 -57,-48 -108,-91 -51,-42 -108,-83 -127,-91 -67,-28 -124,-16 -185,37 -88,78 -237,115 -352,88 -68,-16 -99,-32 -172,-86 -95,-71 -159,-71 -250,0 -73,57 -144,86 -225,93 -117,10 -200,-19 -319,-108 -50,-38 -113,-48 -163,-26 -19,8 -84,56 -144,106 -59,50 -109,91 -110,91 0,0 -26,-30 -56,-67 z" + id="path3809" + inkscape:connector-curvature="0" /> + </g> + <g + transform="matrix(0.35984324,0,0,0.39233849,371.17694,106.00928)" + id="g3885"> + <path + inkscape:connector-curvature="0" + d="m 416.848,404.905 c -19.438,0 -29.554,6.069 -38.479,11.425 -7.985,4.791 -14.293,8.575 -28.19,8.575 -13.898,0 -20.206,-3.784 -28.191,-8.575 -8.926,-5.355 -19.042,-11.425 -38.479,-11.425 -19.436,0 -29.553,6.069 -38.478,11.425 -7.985,4.791 -14.292,8.575 -28.189,8.575 -13.896,0 -20.203,-3.784 -28.189,-8.575 -3.874,-2.324 -7.975,-4.782 -12.962,-6.821 l 50.067,-25.088 c 13.838,-1.532 22.175,-6.514 29.557,-10.941 7.987,-4.791 14.296,-8.574 28.193,-8.574 13.897,0 20.205,3.784 28.19,8.575 8.926,5.355 19.043,11.425 38.48,11.425 19.437,0 29.554,-6.069 38.479,-11.425 7.985,-4.791 14.293,-8.575 28.19,-8.575 5.523,0 10,-4.478 10,-10 0,-5.522 -4.477,-10 -10,-10 -19.438,0 -29.554,6.069 -38.479,11.425 -7.985,4.791 -14.293,8.575 -28.19,8.575 -13.898,0 -20.206,-3.784 -28.191,-8.575 -5.816,-3.49 -12.156,-7.271 -21.231,-9.491 l 49.39,-24.749 c 4.939,-2.475 6.936,-8.482 4.461,-13.42 -2.475,-4.939 -8.485,-6.936 -13.42,-4.461 l -68.634,34.392 c 4.052,-13.419 3.866,-27.489 -0.928,-40.767 -5.515,-15.273 -16.549,-27.632 -30.181,-34.692 9.266,-10.24 17.349,-24.501 25.423,-41.503 6.602,-13.872 12.142,-25.923 15.833,-36.717 11.793,4.301 23.75,6.489 35.465,6.489 5.713,0 11.37,-0.519 16.919,-1.563 21.811,-4.107 40.403,-16.126 53.766,-34.758 3.219,-4.488 2.189,-10.735 -2.298,-13.954 -4.49,-3.219 -10.737,-2.188 -13.954,2.298 -19.152,26.706 -52.059,34.906 -85.29,21.855 0.184,-1.898 0.288,-3.766 0.268,-5.594 -0.268,-24.851 -20.429,-37.295 -35.566,-44.492 -12.055,-5.738 -22.341,-8.528 -31.444,-8.528 -16.217,0 -27.791,8.69 -37.587,22.101 -12.42,-6.488 -22.758,-15.344 -29.917,-25.953 -10.105,-14.977 -13.381,-32.565 -9.472,-50.865 1.154,-5.4 -2.289,-10.714 -7.69,-11.868 -5.399,-1.152 -10.715,2.289 -11.868,7.69 -5.072,23.739 -0.766,46.642 12.451,66.23 8.767,12.991 21.176,23.848 35.975,31.819 -4.183,7.76 -8.211,16.237 -12.383,25.024 -16.232,34.099 -20.374,54.965 -14.301,72.025 1.386,3.893 3.292,7.495 5.752,10.852 3.13,5.169 10.505,19.007 14.019,39.623 5.909,34.667 -1.236,71.495 -21.223,109.506 l -95.827,48.018 c -4.938,2.475 -6.935,8.482 -4.461,13.42 1.754,3.501 5.283,5.522 8.948,5.522 1.506,0 3.034,-0.341 4.472,-1.062 l 87.015,-43.603 c 1.806,-0.164 3.718,-0.249 5.707,-0.249 13.896,0 20.202,3.784 28.187,8.575 8.926,5.354 19.042,11.425 38.479,11.425 19.437,0 29.554,-6.069 38.479,-11.425 7.985,-4.791 14.292,-8.575 28.188,-8.575 13.897,0 20.205,3.784 28.19,8.575 8.926,5.355 19.043,11.425 38.48,11.425 19.437,0 29.554,-6.069 38.479,-11.425 7.985,-4.791 14.293,-8.575 28.19,-8.575 5.523,0 10,-4.478 10,-10 0,-5.523 -4.478,-10.001 -10,-10.001 z M 178.136,179.439 c 4.774,-10.056 8.935,-18.554 12.787,-25.606 6.149,2.083 12.56,3.728 19.173,4.885 0.583,0.102 1.162,0.151 1.734,0.151 4.768,0 8.989,-3.422 9.839,-8.279 0.951,-5.44 -2.688,-10.622 -8.128,-11.573 -3.847,-0.673 -7.595,-1.557 -11.251,-2.598 5.671,-6.622 11.347,-9.744 18.275,-9.744 6.064,0 13.538,2.154 22.852,6.589 21.088,10.026 24.074,18.732 24.159,26.648 0.135,12.432 -7.694,29.865 -18.772,53.143 -16.029,33.752 -28.497,47.52 -43.034,47.52 -5.655,0 -12.271,-1.832 -20.226,-5.602 -8.394,-3.977 -14.177,-8.183 -17.738,-12.939 -0.732,-1.153 -1.251,-1.897 -1.477,-2.212 -0.692,-1.182 -1.268,-2.395 -1.715,-3.65 -3.99,-11.209 0.18,-28.702 13.522,-56.733 z m 6.902,109.29 c -0.862,-4.816 -1.905,-9.31 -3.052,-13.471 8.66,3.565 16.483,5.314 23.784,5.314 5.96,0 11.418,-1.112 16.483,-3.209 13.653,2.714 25.465,13.153 30.56,27.264 6.025,16.685 1.667,34.767 -11.94,49.849 l -22.554,11.302 c -0.021,0.011 -0.043,0.021 -0.064,0.032 l -45.329,22.714 c 16.762,-42.123 16.242,-76.729 12.112,-99.795 z" + id="path3881" /> + <path + inkscape:connector-curvature="0" + d="m 260.255,113.496 c 5.65,1.766 11.491,2.66 17.359,2.66 25.507,0 47.763,-16.389 55.382,-40.781 4.616,-14.776 3.2,-30.48 -3.987,-44.22 C 321.811,17.396 309.692,7.272 294.881,2.646 289.26,0.891 283.443,0 277.594,0 252.04,0 229.755,16.375 222.142,40.748 c -9.548,30.565 7.55,63.2 38.113,72.748 z M 241.232,46.711 C 246.223,30.734 260.836,20 277.594,20 c 3.825,0 7.635,0.584 11.324,1.736 9.706,3.032 17.65,9.669 22.369,18.69 4.713,9.01 5.643,19.304 2.619,28.986 -4.997,15.996 -19.581,26.744 -36.292,26.744 -3.844,0 -7.678,-0.589 -11.396,-1.75 -20.037,-6.26 -31.245,-27.655 -24.986,-47.695 z" + id="path3883" /> + </g> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3887" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3889" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3891" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3893" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3895" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3897" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3899" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3901" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3903" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3905" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3907" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3909" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3911" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3913" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,28.711176,-11.798938)" + id="g3915" /> +</svg> diff --git a/static/img/embark.svg b/static/img/embark.svg @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="530.000000pt" + height="400.000000pt" + viewBox="0 0 530.000000 400.000000" + preserveAspectRatio="xMidYMid meet" + id="svg3813" + sodipodi:docname="embark.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + <defs + id="defs3817" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1918" + inkscape:window-height="1066" + id="namedview3815" + showgrid="false" + inkscape:zoom="0.82125" + inkscape:cx="416.06453" + inkscape:cy="294.05738" + inkscape:window-x="0" + inkscape:window-y="12" + inkscape:window-maximized="0" + inkscape:current-layer="svg3813" /> + <metadata + id="metadata3801"> +Created by potrace 1.15, written by Peter Selinger 2001-2017 +<rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> +</rdf:RDF> +</metadata> + <g + transform="translate(0.000000,400.000000) scale(0.100000,-0.100000)" + fill="#000000" + stroke="none" + id="g3811"> + <path + d="M1963 3650 c3 -8 177 -454 387 -990 210 -536 385 -981 388 -989 5 -12 63 -13 386 -7 209 3 382 8 384 11 5 5 -63 116 -172 280 -202 304 -483 676 -787 1039 -291 349 -597 691 -586 656z" + id="path3803" /> + <path + d="M1917 3023 c-189 -373 -357 -772 -482 -1148 -73 -222 -132 -441 -122 -452 6 -5 1438 165 1445 172 4 4 -727 1597 -737 1608 -4 4 -51 -77 -104 -180z" + id="path3805" /> + <path + d="M4035 1629 c-77 -11 -1055 -124 -2034 -234 -420 -47 -773 -90 -783 -96 -10 -5 -20 -20 -23 -32 -5 -18 51 -197 125 -404 8 -21 40 -57 88 -96 98 -81 109 -87 174 -87 55 0 64 4 162 75 133 96 332 90 464 -14 68 -54 84 -61 145 -61 47 0 62 5 103 35 93 66 132 86 203 100 121 26 226 -2 343 -90 54 -40 66 -45 113 -45 30 0 64 4 77 9 13 5 72 51 133 101 l109 92 48 -54 47 -53 164 165 c173 175 288 312 375 448 65 101 115 205 110 229 -4 22 -52 26 -143 12z" + id="path3807" /> + <path + d="M1210 733 c-30 -37 -63 -77 -73 -89 -17 -22 -16 -23 110 -128 88 -74 144 -113 183 -127 144 -54 301 -27 417 72 77 66 155 63 253 -11 77 -59 130 -79 226 -87 99 -8 188 20 278 87 106 77 165 79 259 6 93 -72 146 -90 263 -91 96 0 104 2 168 35 60 31 284 205 285 221 1 4 -31 46 -71 93 -62 76 -73 85 -87 73 -9 -7 -57 -48 -108 -91 -51 -42 -108 -83 -127 -91 -67 -28 -124 -16 -185 37 -88 78 -237 115 -352 88 -68 -16 -99 -32 -172 -86 -95 -71 -159 -71 -250 0 -73 57 -144 86 -225 93 -117 10 -200 -19 -319 -108 -50 -38 -113 -48 -163 -26 -19 8 -84 56 -144 106 -59 50 -109 91 -110 91 0 0 -26 -30 -56 -67z" + id="path3809" /> + </g> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3885"> + <path + inkscape:connector-curvature="0" + d="m 416.848,404.905 c -19.438,0 -29.554,6.069 -38.479,11.425 -7.985,4.791 -14.293,8.575 -28.19,8.575 -13.898,0 -20.206,-3.784 -28.191,-8.575 -8.926,-5.355 -19.042,-11.425 -38.479,-11.425 -19.436,0 -29.553,6.069 -38.478,11.425 -7.985,4.791 -14.292,8.575 -28.189,8.575 -13.896,0 -20.203,-3.784 -28.189,-8.575 -3.874,-2.324 -7.975,-4.782 -12.962,-6.821 l 50.067,-25.088 c 13.838,-1.532 22.175,-6.514 29.557,-10.941 7.987,-4.791 14.296,-8.574 28.193,-8.574 13.897,0 20.205,3.784 28.19,8.575 8.926,5.355 19.043,11.425 38.48,11.425 19.437,0 29.554,-6.069 38.479,-11.425 7.985,-4.791 14.293,-8.575 28.19,-8.575 5.523,0 10,-4.478 10,-10 0,-5.522 -4.477,-10 -10,-10 -19.438,0 -29.554,6.069 -38.479,11.425 -7.985,4.791 -14.293,8.575 -28.19,8.575 -13.898,0 -20.206,-3.784 -28.191,-8.575 -5.816,-3.49 -12.156,-7.271 -21.231,-9.491 l 49.39,-24.749 c 4.939,-2.475 6.936,-8.482 4.461,-13.42 -2.475,-4.939 -8.485,-6.936 -13.42,-4.461 l -68.634,34.392 c 4.052,-13.419 3.866,-27.489 -0.928,-40.767 -5.515,-15.273 -16.549,-27.632 -30.181,-34.692 9.266,-10.24 17.349,-24.501 25.423,-41.503 6.602,-13.872 12.142,-25.923 15.833,-36.717 11.793,4.301 23.75,6.489 35.465,6.489 5.713,0 11.37,-0.519 16.919,-1.563 21.811,-4.107 40.403,-16.126 53.766,-34.758 3.219,-4.488 2.189,-10.735 -2.298,-13.954 -4.49,-3.219 -10.737,-2.188 -13.954,2.298 -19.152,26.706 -52.059,34.906 -85.29,21.855 0.184,-1.898 0.288,-3.766 0.268,-5.594 -0.268,-24.851 -20.429,-37.295 -35.566,-44.492 -12.055,-5.738 -22.341,-8.528 -31.444,-8.528 -16.217,0 -27.791,8.69 -37.587,22.101 -12.42,-6.488 -22.758,-15.344 -29.917,-25.953 -10.105,-14.977 -13.381,-32.565 -9.472,-50.865 1.154,-5.4 -2.289,-10.714 -7.69,-11.868 -5.399,-1.152 -10.715,2.289 -11.868,7.69 -5.072,23.739 -0.766,46.642 12.451,66.23 8.767,12.991 21.176,23.848 35.975,31.819 -4.183,7.76 -8.211,16.237 -12.383,25.024 -16.232,34.099 -20.374,54.965 -14.301,72.025 1.386,3.893 3.292,7.495 5.752,10.852 3.13,5.169 10.505,19.007 14.019,39.623 5.909,34.667 -1.236,71.495 -21.223,109.506 l -95.827,48.018 c -4.938,2.475 -6.935,8.482 -4.461,13.42 1.754,3.501 5.283,5.522 8.948,5.522 1.506,0 3.034,-0.341 4.472,-1.062 l 87.015,-43.603 c 1.806,-0.164 3.718,-0.249 5.707,-0.249 13.896,0 20.202,3.784 28.187,8.575 8.926,5.354 19.042,11.425 38.479,11.425 19.437,0 29.554,-6.069 38.479,-11.425 7.985,-4.791 14.292,-8.575 28.188,-8.575 13.897,0 20.205,3.784 28.19,8.575 8.926,5.355 19.043,11.425 38.48,11.425 19.437,0 29.554,-6.069 38.479,-11.425 7.985,-4.791 14.293,-8.575 28.19,-8.575 5.523,0 10,-4.478 10,-10 0,-5.523 -4.478,-10.001 -10,-10.001 z M 178.136,179.439 c 4.774,-10.056 8.935,-18.554 12.787,-25.606 6.149,2.083 12.56,3.728 19.173,4.885 0.583,0.102 1.162,0.151 1.734,0.151 4.768,0 8.989,-3.422 9.839,-8.279 0.951,-5.44 -2.688,-10.622 -8.128,-11.573 -3.847,-0.673 -7.595,-1.557 -11.251,-2.598 5.671,-6.622 11.347,-9.744 18.275,-9.744 6.064,0 13.538,2.154 22.852,6.589 21.088,10.026 24.074,18.732 24.159,26.648 0.135,12.432 -7.694,29.865 -18.772,53.143 -16.029,33.752 -28.497,47.52 -43.034,47.52 -5.655,0 -12.271,-1.832 -20.226,-5.602 -8.394,-3.977 -14.177,-8.183 -17.738,-12.939 -0.732,-1.153 -1.251,-1.897 -1.477,-2.212 -0.692,-1.182 -1.268,-2.395 -1.715,-3.65 -3.99,-11.209 0.18,-28.702 13.522,-56.733 z m 6.902,109.29 c -0.862,-4.816 -1.905,-9.31 -3.052,-13.471 8.66,3.565 16.483,5.314 23.784,5.314 5.96,0 11.418,-1.112 16.483,-3.209 13.653,2.714 25.465,13.153 30.56,27.264 6.025,16.685 1.667,34.767 -11.94,49.849 l -22.554,11.302 c -0.021,0.011 -0.043,0.021 -0.064,0.032 l -45.329,22.714 c 16.762,-42.123 16.242,-76.729 12.112,-99.795 z" + id="path3881" /> + <path + inkscape:connector-curvature="0" + d="m 260.255,113.496 c 5.65,1.766 11.491,2.66 17.359,2.66 25.507,0 47.763,-16.389 55.382,-40.781 4.616,-14.776 3.2,-30.48 -3.987,-44.22 C 321.811,17.396 309.692,7.272 294.881,2.646 289.26,0.891 283.443,0 277.594,0 252.04,0 229.755,16.375 222.142,40.748 c -9.548,30.565 7.55,63.2 38.113,72.748 z M 241.232,46.711 C 246.223,30.734 260.836,20 277.594,20 c 3.825,0 7.635,0.584 11.324,1.736 9.706,3.032 17.65,9.669 22.369,18.69 4.713,9.01 5.643,19.304 2.619,28.986 -4.997,15.996 -19.581,26.744 -36.292,26.744 -3.844,0 -7.678,-0.589 -11.396,-1.75 -20.037,-6.26 -31.245,-27.655 -24.986,-47.695 z" + id="path3883" /> + </g> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3887" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3889" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3891" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3893" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3895" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3897" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3899" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3901" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3903" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3905" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3907" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3909" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3911" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3913" /> + <g + transform="matrix(0.35984324,0,0,0.39233849,-10.558231,156.23759)" + id="g3915" /> +</svg> diff --git a/static/img/flags b/static/img/flags @@ -0,0 +1 @@ +../../extra/world_countries/flags/64x64+ \ No newline at end of file diff --git a/static/img/slatkisi.png b/static/img/slatkisi.png Binary files differ. diff --git a/static/js/summernote-cleaner.js b/static/js/summernote-cleaner.js @@ -0,0 +1,179 @@ +/* https://github.com/DiemenDesign/summernote-cleaner */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } else if (typeof module === 'object' && module.exports) { + module.exports = factory(require('jquery')); + } else { + factory(window.jQuery); + } +} +(function ($) { + $.extend(true, $.summernote.lang, { + 'en-US': { + cleaner: { + tooltip: 'Cleaner', + not: 'Text has been Cleaned!!!', + limitText: 'Text', + limitHTML: 'HTML' + } + } + }); + $.extend($.summernote.options, { + cleaner: { + action: 'both', // both|button|paste 'button' only cleans via toolbar button, 'paste' only clean when pasting content, both does both options. + newline: '<br>', // Summernote's default is to use '<p><br></p>' + notStyle: 'position:absolute;top:0;left:0;right:0', + icon: '<i class="note-icon"><svg xmlns="http://www.w3.org/2000/svg" id="libre-paintbrush" viewBox="0 0 14 14" width="14" height="14"><path d="m 11.821425,1 q 0.46875,0 0.82031,0.311384 0.35157,0.311384 0.35157,0.780134 0,0.421875 -0.30134,1.01116 -2.22322,4.212054 -3.11384,5.035715 -0.64956,0.609375 -1.45982,0.609375 -0.84375,0 -1.44978,-0.61942 -0.60603,-0.61942 -0.60603,-1.469866 0,-0.857143 0.61608,-1.419643 l 4.27232,-3.877232 Q 11.345985,1 11.821425,1 z m -6.08705,6.924107 q 0.26116,0.508928 0.71317,0.870536 0.45201,0.361607 1.00781,0.508928 l 0.007,0.475447 q 0.0268,1.426339 -0.86719,2.32366 Q 5.700895,13 4.261155,13 q -0.82366,0 -1.45982,-0.311384 -0.63616,-0.311384 -1.0212,-0.853795 -0.38505,-0.54241 -0.57924,-1.225446 -0.1942,-0.683036 -0.1942,-1.473214 0.0469,0.03348 0.27455,0.200893 0.22768,0.16741 0.41518,0.29799 0.1875,0.130581 0.39509,0.24442 0.20759,0.113839 0.30804,0.113839 0.27455,0 0.3683,-0.247767 0.16741,-0.441965 0.38505,-0.753349 0.21763,-0.311383 0.4654,-0.508928 0.24776,-0.197545 0.58928,-0.31808 0.34152,-0.120536 0.68974,-0.170759 0.34821,-0.05022 0.83705,-0.07031 z"/></svg></i>', + keepHtml: true, //Remove all Html formats + keepOnlyTags: [], // If keepHtml is true, remove all tags except these + keepClasses: false, //Remove Classes + badTags: ['style', 'script', 'applet', 'embed', 'noframes', 'noscript', 'html'], //Remove full tags with contents + badAttributes: ['style', 'start'], //Remove attributes from remaining tags + limitChars: 520, // 0|# 0 disables option + limitDisplay: 'both', // none|text|html|both + limitStop: false // true/false + } + }); + $.extend($.summernote.plugins, { + 'cleaner':function (context) { + var self = this, + ui = $.summernote.ui, + $note = context.layoutInfo.note, + $editor = context.layoutInfo.editor, + options = context.options, + lang = options.langInfo; + var cleanText = function (txt, nlO) { + var out = txt; + if (!options.cleaner.keepClasses) { + var sS = /(\n|\r| class=(")?Mso[a-zA-Z]+(")?)/g; + out = txt.replace(sS, ' '); + } + var nL = /(\n)+/g; + out = out.replace(nL, nlO); + if (options.cleaner.keepHtml) { + var cS = new RegExp('<!--(.*?)-->', 'gi'); + out = out.replace(cS, ''); + var tS = new RegExp('<(/)*(meta|link|\\?xml:|st1:|o:|font)(.*?)>', 'gi'); + out = out.replace(tS, ''); + var bT = options.cleaner.badTags; + for (var i = 0; i < bT.length; i++) { + tS = new RegExp('<' + bT[i] + '\\b.*>.*</' + bT[i] + '>', 'gi'); + out = out.replace(tS, ''); + } + var allowedTags = options.cleaner.keepOnlyTags; + if (typeof(allowedTags) == "undefined") allowedTags = []; + if (allowedTags.length > 0) { + allowedTags = (((allowedTags||'') + '').toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); + var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi; + out = out.replace(tags, function($0, $1) { + return allowedTags.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '' + }); + } + var bA = options.cleaner.badAttributes; + for (var ii = 0; ii < bA.length; ii++ ) { + //var aS=new RegExp(' ('+bA[ii]+'="(.*?)")|('+bA[ii]+'=\'(.*?)\')', 'gi'); + var aS = new RegExp(' ' + bA[ii] + '=[\'|"](.*?)[\'|"]', 'gi'); + out = out.replace(aS, ''); + } + } + return out; + }; + if (options.cleaner.action == 'both' || options.cleaner.action == 'button') { + context.memo('button.cleaner', function () { + var button = ui.button({ + contents: options.cleaner.icon, + tooltip: lang.cleaner.tooltip, + container: 'body', + click:function () { + if ($note.summernote('createRange').toString()) + $note.summernote('pasteHTML', $note.summernote('createRange').toString()); + else + $note.summernote('code', cleanText($note.summernote('code'))); + if ($editor.find('.note-status-output').length > 0) + $editor.find('.note-status-output').html('<div class="alert alert-success">' + lang.cleaner.not + '</div>'); + else + $editor.find('.note-editing-area').append('<div class="alert alert-success" style="' + options.cleaner.notStyle + '">' + lang.cleaner.not + '</div>'); + } + }); + return button.render(); + }); + } + this.events = { + 'summernote.init':function () { + if ($editor.find('.note-status-output').length < 1) { + $editor.find('.note-statusbar').prepend('<output class="note-status-output"></output>'); + $("head").append('<style>.note-statusbar .note-status-output{display:block;padding-top:7px;width:100%;font-size:14px;line-height:1.42857143;height:25px;color:#000}.note-statusbar .pull-right{float:right!important}.note-statusbar .note-status-output .text-muted{color:#777}.note-statusbar .note-status-output .text-primary{color:#286090}.note-statusbar .note-status-output .text-success{color:#3c763d}.note-statusbar .note-status-output .text-info{color:#31708f}.note-statusbar .note-status-output .text-warning{color:#8a6d3b}.note-statusbar .note-status-output .text-danger{color:#a94442}.note-statusbar .alert{margin:-7px 0 0 0;padding:2px 10px;border:1px solid transparent;border-radius:0}.note-statusbar .alert .note-icon{margin-right:5px}.note-statusbar .alert-success{color:#3c763d!important;background-color: #dff0d8 !important;border-color:#d6e9c6}.note-statusbar .alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.note-statusbar .alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.note-statusbar .alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}</style>'); + } + if (options.cleaner.limitChars != 0 || options.cleaner.limitDisplay != 'none') { + var textLength = $editor.find(".note-editable").text().replace(/(<([^>]+)>)/ig, "").replace(/( )/, " "); + var codeLength = $editor.find('.note-editable').html(); + var lengthStatus = ''; + if (textLength.length > options.cleaner.limitChars && options.cleaner.limitChars > 0) + lengthStatus += 'text-danger">'; + else + lengthStatus += '">'; + if (options.cleaner.limitDisplay == 'text' || options.cleaner.limitDisplay == 'both') lengthStatus += lang.cleaner.limitText + ': ' + textLength.length; + if (options.cleaner.limitDisplay == 'both') lengthStatus += ' / '; + if (options.cleaner.limitDisplay == 'html' || options.cleaner.limitDisplay == 'both') lengthStatus += lang.cleaner.limitHTML + ': ' + codeLength.length; + $editor.find('.note-status-output').html('<small class="pull-right ' + lengthStatus + '&nbsp;</small>'); + } + }, + 'summernote.keydown':function (we, e) { + if (options.cleaner.limitChars != 0 || options.cleaner.limitDisplay != 'none') { + var textLength = $editor.find(".note-editable").text().replace(/(<([^>]+)>)/ig, "").replace(/( )/, " "); + var codeLength = $editor.find('.note-editable').html(); + var lengthStatus = ''; + if (options.cleaner.limitStop == true && textLength.length >= options.cleaner.limitChars) { + var key = e.keyCode; + allowed_keys = [8, 37, 38, 39, 40, 46] + if ($.inArray(key, allowed_keys) != -1) { + $editor.find('.cleanerLimit').removeClass('text-danger'); + return true; + } else { + $editor.find('.cleanerLimit').addClass('text-danger'); + e.preventDefault(); + e.stopPropagation(); + } + } else { + if (textLength.length > options.cleaner.limitChars && options.cleaner.limitChars > 0) + lengthStatus += 'text-danger">'; + else + lengthStatus += '">'; + if (options.cleaner.limitDisplay == 'text' || options.cleaner.limitDisplay == 'both') + lengthStatus += lang.cleaner.limitText + ': ' + textLength.length; + if (options.cleaner.limitDisplay == 'both') + lengthStatus += ' / '; + if (options.cleaner.limitDisplay == 'html' || options.cleaner.limitDisplay == 'both') + lengthStatus += lang.cleaner.limitHTML + ': ' + codeLength.length; + $editor.find('.note-status-output').html('<small class="cleanerLimit pull-right ' + lengthStatus + '&nbsp;</small>'); + } + } + }, + 'summernote.paste':function (we, e) { + if (options.cleaner.action == 'both' || options.cleaner.action == 'paste') { + e.preventDefault(); + var ua = window.navigator.userAgent; + var msie = ua.indexOf("MSIE "); + msie = msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./); + var ffox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; + if (msie) + var text = window.clipboardData.getData("Text"); + else + var text = e.originalEvent.clipboardData.getData(options.cleaner.keepHtml ? 'Text' : 'text/plain'); + if (text) { + if (msie || ffox) + setTimeout(function(){$note.summernote('pasteHTML', cleanText(text, options.cleaner.newline));}, 1); + else + $note.summernote('pasteHTML', cleanText(text, options.cleaner.newline)); + if ($editor.find('.note-status-output').length > 0) + $editor.find('.note-status-output').html('<div class="summernote-cleanerAlert alert alert-success">' + lang.cleaner.not + '</div>'); + else + $editor.find('.note-resizebar').append('<div class="summernote-cleanerAlert alert alert-success" style="' + options.cleaner.notStyle + '">' + lang.cleaner.not + '</div>'); + } + } + } + } + } + }); +})); diff --git a/templates/cc.html b/templates/cc.html @@ -0,0 +1,253 @@ +<option value="XXX">Select country...</option> +<option value="af">Afghanistan</option> +<option value="ax">Åland Islands</option> +<option value="al">Albania</option> +<option value="dz">Algeria</option> +<option value="as">American Samoa</option> +<option value="ad">Andorra</option> +<option value="ao">Angola</option> +<option value="ai">Anguilla</option> +<option value="aq">Antarctica</option> +<option value="ag">Antigua and Barbuda</option> +<option value="ar">Argentina</option> +<option value="am">Armenia</option> +<option value="aw">Aruba</option> +<option value="au">Australia</option> +<option value="at">Austria</option> +<option value="az">Azerbaijan</option> +<option value="bs">Bahamas</option> +<option value="bh">Bahrain</option> +<option value="bd">Bangladesh</option> +<option value="bb">Barbados</option> +<option value="by">Belarus</option> +<option value="be">Belgium</option> +<option value="bz">Belize</option> +<option value="bj">Benin</option> +<option value="bm">Bermuda</option> +<option value="bt">Bhutan</option> +<option value="bo">Bolivia (Plurinational State of)</option> +<option value="bq">Bonaire, Sint Eustatius and Saba</option> +<option value="ba">Bosnia and Herzegovina</option> +<option value="bw">Botswana</option> +<option value="bv">Bouvet Island</option> +<option value="br">Brazil</option> +<option value="io">British Indian Ocean Territory</option> +<option value="bn">Brunei Darussalam</option> +<option value="bg">Bulgaria</option> +<option value="bf">Burkina Faso</option> +<option value="bi">Burundi</option> +<option value="cv">Cabo Verde</option> +<option value="kh">Cambodia</option> +<option value="cm">Cameroon</option> +<option value="ca">Canada</option> +<option value="ky">Cayman Islands</option> +<option value="cf">Central African Republic</option> +<option value="td">Chad</option> +<option value="cl">Chile</option> +<option value="cn">China</option> +<option value="cx">Christmas Island</option> +<option value="cc">Cocos (Keeling) Islands</option> +<option value="co">Colombia</option> +<option value="km">Comoros</option> +<option value="cg">Congo</option> +<option value="cd">Congo, Democratic Republic of the</option> +<option value="ck">Cook Islands</option> +<option value="cr">Costa Rica</option> +<option value="ci">Côte d'Ivoire</option> +<option value="hr">Croatia</option> +<option value="cu">Cuba</option> +<option value="cw">Curaçao</option> +<option value="cy">Cyprus</option> +<option value="cz">Czechia</option> +<option value="dk">Denmark</option> +<option value="dj">Djibouti</option> +<option value="dm">Dominica</option> +<option value="do">Dominican Republic</option> +<option value="ec">Ecuador</option> +<option value="eg">Egypt</option> +<option value="sv">El Salvador</option> +<option value="gq">Equatorial Guinea</option> +<option value="er">Eritrea</option> +<option value="ee">Estonia</option> +<option value="sz">Eswatini</option> +<option value="et">Ethiopia</option> +<option value="fk">Falkland Islands (Malvinas)</option> +<option value="fo">Faroe Islands</option> +<option value="fj">Fiji</option> +<option value="fi">Finland</option> +<option value="fr">France</option> +<option value="gf">French Guiana</option> +<option value="pf">French Polynesia</option> +<option value="tf">French Southern Territories</option> +<option value="ga">Gabon</option> +<option value="gm">Gambia</option> +<option value="ge">Georgia</option> +<option value="de">Germany</option> +<option value="gh">Ghana</option> +<option value="gi">Gibraltar</option> +<option value="gr">Greece</option> +<option value="gl">Greenland</option> +<option value="gd">Grenada</option> +<option value="gp">Guadeloupe</option> +<option value="gu">Guam</option> +<option value="gt">Guatemala</option> +<option value="gg">Guernsey</option> +<option value="gn">Guinea</option> +<option value="gw">Guinea-Bissau</option> +<option value="gy">Guyana</option> +<option value="ht">Haiti</option> +<option value="hm">Heard Island and McDonald Islands</option> +<option value="va">Holy See</option> +<option value="hn">Honduras</option> +<option value="hk">Hong Kong</option> +<option value="hu">Hungary</option> +<option value="is">Iceland</option> +<option value="in">India</option> +<option value="id">Indonesia</option> +<option value="ir">Iran (Islamic Republic of)</option> +<option value="iq">Iraq</option> +<option value="ie">Ireland</option> +<option value="im">Isle of Man</option> +<option value="il">Israel</option> +<option value="it">Italy</option> +<option value="jm">Jamaica</option> +<option value="jp">Japan</option> +<option value="je">Jersey</option> +<option value="jo">Jordan</option> +<option value="kz">Kazakhstan</option> +<option value="ke">Kenya</option> +<option value="ki">Kiribati</option> +<option value="kp">Korea (Democratic People's Republic of)</option> +<option value="kr">Korea, Republic of</option> +<option value="xk">Kosovo</option> +<option value="kw">Kuwait</option> +<option value="kg">Kyrgyzstan</option> +<option value="la">Lao People's Democratic Republic</option> +<option value="lv">Latvia</option> +<option value="lb">Lebanon</option> +<option value="ls">Lesotho</option> +<option value="lr">Liberia</option> +<option value="ly">Libya</option> +<option value="li">Liechtenstein</option> +<option value="lt">Lithuania</option> +<option value="lu">Luxembourg</option> +<option value="mo">Macao</option> +<option value="mk">Macedonia, the former Yugoslav Republic of</option> +<option value="mg">Madagascar</option> +<option value="mw">Malawi</option> +<option value="my">Malaysia</option> +<option value="mv">Maldives</option> +<option value="ml">Mali</option> +<option value="mt">Malta</option> +<option value="mh">Marshall Islands</option> +<option value="mq">Martinique</option> +<option value="mr">Mauritania</option> +<option value="mu">Mauritius</option> +<option value="yt">Mayotte</option> +<option value="mx">Mexico</option> +<option value="fm">Micronesia (Federated States of)</option> +<option value="md">Moldova, Republic of</option> +<option value="mc">Monaco</option> +<option value="mn">Mongolia</option> +<option value="me">Montenegro</option> +<option value="ms">Montserrat</option> +<option value="ma">Morocco</option> +<option value="mz">Mozambique</option> +<option value="mm">Myanmar</option> +<option value="na">Namibia</option> +<option value="nr">Nauru</option> +<option value="np">Nepal</option> +<option value="nl">Netherlands</option> +<option value="nc">New Caledonia</option> +<option value="nz">New Zealand</option> +<option value="ni">Nicaragua</option> +<option value="ne">Niger</option> +<option value="ng">Nigeria</option> +<option value="nu">Niue</option> +<option value="nf">Norfolk Island</option> +<option value="mp">Northern Mariana Islands</option> +<option value="no">Norway</option> +<option value="nn">Other</option> +<option value="om">Oman</option> +<option value="pk">Pakistan</option> +<option value="pw">Palau</option> +<option value="ps">Palestine, State of</option> +<option value="pa">Panama</option> +<option value="pg">Papua New Guinea</option> +<option value="py">Paraguay</option> +<option value="pe">Peru</option> +<option value="ph">Philippines</option> +<option value="pn">Pitcairn</option> +<option value="pl">Poland</option> +<option value="pt">Portugal</option> +<option value="pr">Puerto Rico</option> +<option value="qa">Qatar</option> +<option value="re">Réunion</option> +<option value="ro">Romania</option> +<option value="ru">Russian Federation</option> +<option value="rw">Rwanda</option> +<option value="bl">Saint Barthélemy</option> +<option value="sh">Saint Helena, Ascension and Tristan da Cunha</option> +<option value="kn">Saint Kitts and Nevis</option> +<option value="lc">Saint Lucia</option> +<option value="mf">Saint Martin (French part)</option> +<option value="pm">Saint Pierre and Miquelon</option> +<option value="vc">Saint Vincent and the Grenadines</option> +<option value="ws">Samoa</option> +<option value="sm">San Marino</option> +<option value="st">Sao Tome and Principe</option> +<option value="sa">Saudi Arabia</option> +<option value="sn">Senegal</option> +<option value="rs">Serbia</option> +<option value="sc">Seychelles</option> +<option value="sl">Sierra Leone</option> +<option value="sg">Singapore</option> +<option value="sx">Sint Maarten (Dutch part)</option> +<option value="sk">Slovakia</option> +<option value="si">Slovenia</option> +<option value="sb">Solomon Islands</option> +<option value="so">Somalia</option> +<option value="za">South Africa</option> +<option value="gs">South Georgia and the South Sandwich Islands</option> +<option value="ss">South Sudan</option> +<option value="es">Spain</option> +<option value="lk">Sri Lanka</option> +<option value="sd">Sudan</option> +<option value="sr">Suriname</option> +<option value="sj">Svalbard and Jan Mayen</option> +<option value="se">Sweden</option> +<option value="ch">Switzerland</option> +<option value="sy">Syrian Arab Republic</option> +<option value="tw">Taiwan, Province of China</option> +<option value="tj">Tajikistan</option> +<option value="tz">Tanzania, United Republic of</option> +<option value="th">Thailand</option> +<option value="tl">Timor-Leste</option> +<option value="tg">Togo</option> +<option value="tk">Tokelau</option> +<option value="to">Tonga</option> +<option value="tt">Trinidad and Tobago</option> +<option value="tn">Tunisia</option> +<option value="tr">Turkey</option> +<option value="tm">Turkmenistan</option> +<option value="tc">Turks and Caicos Islands</option> +<option value="tv">Tuvalu</option> +<option value="ug">Uganda</option> +<option value="ua">Ukraine</option> +<option value="ae">United Arab Emirates</option> +<option value="gb">United Kingdom of Great Britain and Northern Ireland</option> +<option value="us">United States of America</option> +<option value="um">United States Minor Outlying Islands</option> +<option value="uy">Uruguay</option> +<option value="uz">Uzbekistan</option> +<option value="vu">Vanuatu</option> +<option value="ve">Venezuela (Bolivarian Republic of)</option> +<option value="vn">Viet Nam</option> +<option value="vg">Virgin Islands (British)</option> +<option value="vi">Virgin Islands (U.S.)</option> +<option value="wf">Wallis and Futuna</option> +<option value="eh">Western Sahara</option> +<option value="ye">Yemen</option> +<option value="zm">Zambia</option> +<option value="zw">Zimbabwe</option> +<option value="nn">Other</option> diff --git a/templates/country.html b/templates/country.html @@ -0,0 +1,80 @@ +{% include 'header.html' %} + + <title>{{ country }} diaries | Diaspora Diaries</title> + +{% include 'nav.html' %} + + <main role="main" class="container cover"> + + {% if filtered_stories %} + <h1 class="cover-heading">{{ country }} diaries by people from {{ filtered_stories[0]['embarkname'] }}</h1> + {% else %} + <h1 class="cover-heading">{{ country }} diaries</h1> + {% endif %} + + + <div class="album py-5 bg-light"> + <div class="container"> + + {% if filtered_stories %} + {% set stor = filtered_stories %} + {% else %} + {% set stor = stories %} + {% endif %} + + {% for i in stor %} + {% if loop.index % 3 == 1 %} + <div class="row"> + {% endif %} + + <div class="col-md-4"> + <div class="card-body"> + <p class="card-text"> + {{ i['story'] }} + </p> + + <div class="d-flex justify-content-between align-items-center"> + <div class="btn-group"> + <a href="/view?id={{ i['id'] }}" class="btn btn-sm btn-outline-secondary">Read</a> + </div> + + <img style="height: 1em;" src="/static/img/flags/{{ i['embark'] }}.png" alt="{{ i['embarkname'] }}" title="{{ i['embarkname' ]}}"><span class="fa fa-anchor"></span><img style="height: 1em;" src="/static/img/flags/{{ i['disembark'] }}.png" alt="{{ i['disembarkname'] }}" title="{{ i['disembarkname'] }}"> + + <small class="text-muted"> + {{ i['name'] }}<br> + {{ i['date'] }}<br> + {{ i['time'] }} + </small> + </div> + </div> + </div> + + {% if loop.index % 3 == 0 or loop.last %} + </div> + {% if not loop.last %} + <hr style="width: 100%; height: 2px;"> + {% endif %} + {% endif %} + + {% endfor %} + </div> + </div> + + <div class="container"> + <div class="countrylist-bottom"> + <p class="lead">List by country of embarkment:</p> + <a href="/country?id={{ cc }}"> + <img style="height: 2em;" src="/static/img/flags/globe.png" alt="All around the globe" title="All around the globe"> + </a> + {% for j in clist %} + <!-- LIST ONLY FROM J TO I --> + <a href="/country?id={{ cc }}&from={{ j[0] }}"> + <img style="height: 2em;" src="/static/img/flags/{{ j[0] }}.png" alt="{{ j[1] }}" title="{{ j[1] }}"> + </a> + {% endfor %} + </div> + </div> + + </main> + +{% include 'footer.html' %} diff --git a/templates/footer.html b/templates/footer.html @@ -0,0 +1,5 @@ + <footer> + <img src="/static/img/slatkisi.png" width="150"> + </footer> +</body> +</html> diff --git a/templates/header.html b/templates/header.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous"> + + <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> + <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> + + <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous"> + + <link href="/static/css/diaspora.css" rel="stylesheet"> diff --git a/templates/index.html b/templates/index.html @@ -0,0 +1,57 @@ +{% include 'header.html' %} + + <title>Home | Diaspora Diaries</title> + +{% include 'nav.html' %} + + <main role="main" class="container cover"> + + <h1 class="cover-heading">Diaspora Diaries</h1> + + <p>This is a place where everyone that has an experience with living abroad + can write down their story.</p> + + <p class="lead">You can use your knowledge and the situations you have gone + through to help someone with similar problems, everyday frustrations or just + make them feel less alone. You can also write about the reasons and background + of your migration. After all, we are all just human beings in a search for + peace and happiness.</p> + + <p class="lead">Let your fellow humans know that they are surrounded with + others of their kind. Make them feel less scared and lonely.</p> + + <p class="text-center"> + <a href="/submit" class="btn btn-lg btn-secondary">GO AND WRITE DOWN YOUR + STORY!</a> + </p> + + <input class="burger-check" id="burger-check" type="checkbox"> + <label for="burger-check" class="burger">Read more...</label> + + <div class="readmore"> + <p class="lead">In this day and age, there are a lot of people migrating in a + search for a better life. People are changing towns, cities, states and even + continents in their quest for a better surroundings. They are searching for a + place where they can feel more at ease, chase their dreams or simply live + their life.</p> + + <p class="lead">Moving to a place different from the one you were born in, + accustomed to and familiar with is often a difficult and long process that can + be filled with a lot of misunderstandings and dead ends leading to frustration + and overwhelming feeling of loneliness.</p> + + <p class="lead">It is hard to walk through foreign streets, filled with busy + unfamiliar faces, signs, foreign languages, different climate and culture + trying to get your foot in the door and organize your new life. Every + community has its way of doing things, very often not so clearly explained. + It is natural to feel lost and confused.</p> + + <p class="lead">Person changing it’s environment has a fresh and highly + perceptive regard towards new culture and corresponding customs. They can spot + a bizarre rule of conduct from miles ahead. It is strange, it is funny, it is + useful.</p> + + </div> + </main> + +{% include 'footer.html' %} diff --git a/templates/nav.html b/templates/nav.html @@ -0,0 +1,40 @@ +</head> +<body class="text-center"> + + <nav class="navbar navbar-expand-lg navbar-light bg-light"> + <a class="navbar-brand" href="/">Diaspora Diaries</a> + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + + <div class="collapse navbar-collapse" id="navbarSupportedContent"> + <ul class="navbar-nav mr-auto"> + <li class="nav-item "> + <a class="nav-link" href="/">Home</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/submit">Write!</a> + </li> + + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" href="#" id="navbarDowntown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Stories + </a> + <div class="dropdown-menu" aria-labelledby="navbarDropdown"> + {% for i in navlist %} + <a class="dropdown-item" href="/country?id={{ i[0] }}"> + <img width="32" src="/static/img/flags/{{ i[0] }}.png"> {{ i[1]}} + </a> + {% endfor %} + <!-- <a class="dropdown-item" href="#">Country 1</a> + <a class="dropdown-item" href="#">Country 2</a> + <div class="dropdown-divider"></div> + <a class="dropdown-item" href="#">Country 3</a> --> + </div> + </li> + <li class="nav-item"> + <a class="nav-link disabled" href="/contact">Contact</a> + </li> + </ul> + </div> + </nav> diff --git a/templates/submit.html b/templates/submit.html @@ -0,0 +1,98 @@ +{% include 'header.html' %} + + <title>Write | Diaspora Diaries</title> + + <link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.11/summernote-bs4.css" rel="stylesheet"> + <script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.11/summernote-bs4.js"></script> + <script src="/static/js/summernote-cleaner.js"></script> + + <script> + function countryCheck(that, idname) { + if (that.value == "nn") { + document.getElementById(idname).style.display = "inline"; + } else { + document.getElementById(idname).style.display = "none"; + } + } + </script> + +{% include 'nav.html' %} + + <main role="main" class="container"> + + <form action="/submit" method="POST" id="storyform"> + <p class="lead">Name:<br> + <input type="text" name="Name" required placeholder="Name"> + </p> + + <p class="lead">Country of embarkment:<br> + <select name="Embark" form="storyform" onchange="countryCheck(this, 'embarkother');"> + {% include 'cc.html' %} + </select> + <p class="lead"> + <input type="text" name="EmbarkOther" id="embarkother" style="display: none;" placeholder="Type country here"> + </p> + </p> + + <p class="lead">Country of disembarkment:<br> + <select name="Disembark" form="storyform" onchange="countryCheck(this, 'disembarkother');"> + {% include 'cc.html' %} + </select> + <p class="lead"> + <input type="text" name="DisembarkOther" id="disembarkother" style="display: none;" placeholder="Type country here"> + </p> + </p> + + <p class="lead">Email:<br> + <input type="email" name="Email" placeholder="Email"> + </p> + + <p class="lead">Contact info:<br> + <textarea name="Contact" form="storyform"></textarea> + </p> + + <p class="lead">Write your story:<br> + <textarea id="storytext" name="Story" form="storyform" required></textarea> + </p> + + <input type="submit" value="Submit"> + </form> + + </main> + + <script> + $('.summernote').summernote({ + toolbar:[ + ['cleaner',['cleaner']], // The Button + ['style',['style']], + ['font',['bold','underline','clear']], + ['fontname',['fontname']], + ['color',['color']], + ['para',['ul','ol','paragraph']], + ['height',['height']], + ['table',['table']], + ['insert',['media','link','hr']], + ['view',['fullscreen','codeview']], + ['help',['help']] + ], + cleaner:{ + action: 'both', // both|button|paste + newline: '<br>', // Summernote's default is to use '<p><br></p>' + notStyle: 'position:absolute;top:0;left:0;right:0', // Position of Notification + icon: '<i class="note-icon">[Your Button]</i>', + keepHtml: false, // Remove all Html formats + keepOnlyTags: ['<p>', '<br>', '<ul>', '<li>', '<b>', '<strong>','<i>', '<a>'], // If keepHtml is true, remove all tags except these + keepClasses: false, // Remove Classes + badTags: ['style', 'script', 'applet', 'embed', 'noframes', 'noscript', 'html'], // Remove full tags with contents + badAttributes: ['style', 'start'], // Remove attributes from remaining tags + limitChars: false, // 0/false|# 0/false disables option + limitDisplay: 'both', // text|html|both + limitStop: false // true/false + } + }); + + $(document).ready(function() { + $('#storytext').summernote(); + }); + </script> +{% include 'footer.html' %} diff --git a/templates/submitted.html b/templates/submitted.html @@ -0,0 +1,17 @@ +{% include 'header.html' %} + + <title>Submitted | Diaspora Diaries</title> + +{% include 'nav.html' %} + + <main role="main" class="container cover"> + + <h1 class="cover-heading">Story submitted!</h1> + + <p class="lead">Thank you for submitting your story!</p> + + <p class="lead">You can return to the <a href="/">homepage</a> now.</p> + + </main> + +{% include 'footer.html' %} diff --git a/templates/view.html b/templates/view.html @@ -0,0 +1,21 @@ +{% include 'header.html' %} + + <title>{{ story['name'] }} in {{ story['disembarkname'] }} | Diaspora Diaries</title> + +{% include 'nav.html' %} + + <main role="main" class="container cover"> + + <h1 class="cover-heading">{{ story['name'] }} in {{ story['disembarkname'] }}</h1> + + <p>by {{ story['name'] }}, {{ story['date'] }} {{ story['time'] }}</p> + <hr style="width: 100%; height: 2px;"> + + {{ story['story']|safe }} + + <hr style="width: 100%; height: 2px;"> + <a href="/country?id={{ story['disembark'] }}">&lt; back</a> + + </main> + +{% include 'footer.html' %} diff --git a/world.json b/world.json @@ -0,0 +1 @@ +extra/world_countries/data/en/world.json+ \ No newline at end of file