www
This commit is contained in:
parent
893515735a
commit
46a0cc8c0b
51
selection/construct.py
Normal file
51
selection/construct.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import os, json, glob, logging
|
||||||
|
|
||||||
|
ARCH = "archives/"
|
||||||
|
EXP = "selection/"
|
||||||
|
sel = os.path.join(EXP, "tm-selection.js")
|
||||||
|
|
||||||
|
def find(li, url):
|
||||||
|
|
||||||
|
d = os.path.join(ARCH, li)
|
||||||
|
|
||||||
|
if not os.path.isdir(d):
|
||||||
|
logging.warning("Invalid archive path: " + d)
|
||||||
|
return None
|
||||||
|
|
||||||
|
dir_files = [f for f in glob.glob(os.path.join(d, "*.json"))]
|
||||||
|
|
||||||
|
for f in dir_files:
|
||||||
|
with open(f) as fp:
|
||||||
|
dj = json.load(fp)
|
||||||
|
for t in dj['threads']:
|
||||||
|
if t['url'] == url:
|
||||||
|
return t
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def construct():
|
||||||
|
|
||||||
|
dump = {}
|
||||||
|
|
||||||
|
with open(sel) as f:
|
||||||
|
d = json.load(f)
|
||||||
|
|
||||||
|
for k, v in d.items():
|
||||||
|
dump[k] = []
|
||||||
|
for i in v:
|
||||||
|
m = find(i['list'], i['url'])
|
||||||
|
if m is not None:
|
||||||
|
m['list'] = i['list']
|
||||||
|
dump[k].append(m)
|
||||||
|
|
||||||
|
fout = os.path.join(EXP, "tm-selection-dump.js")
|
||||||
|
|
||||||
|
with open(fout, 'w+', encoding='utf-8') as f:
|
||||||
|
json.dump(dump, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
construct()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1201
selection/tm-selection-dump.js
Normal file
1201
selection/tm-selection-dump.js
Normal file
File diff suppressed because one or more lines are too long
15
selection/tm-selection.js
Normal file
15
selection/tm-selection.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"net.art": [
|
||||||
|
{
|
||||||
|
"list": "crumb",
|
||||||
|
"url": "https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind1406&L=new-media-curating&F=&S=&P=15160"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"end2end": [],
|
||||||
|
"new media art": [
|
||||||
|
{
|
||||||
|
"list": "nettime-l",
|
||||||
|
"url": "https://nettime.org/Lists-Archives/nettime-l-0905/msg00038.html"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
3
www-serve
Executable file
3
www-serve
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
source activate listserv
|
||||||
|
gunicorn -w 1 --bind 0.0.0.0:6767 www-serve:app
|
||||||
4
www-serve.py
Normal file
4
www-serve.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from www import app
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(debug=True, use_reloader=False)
|
||||||
5
www/__init__.py
Normal file
5
www/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
from www import routes
|
||||||
57
www/archive.py
Normal file
57
www/archive.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import os, glob, json
|
||||||
|
|
||||||
|
ARCH = "archives/"
|
||||||
|
EXP = "selection/"
|
||||||
|
sel = os.path.join(EXP, "tm-selection.js")
|
||||||
|
|
||||||
|
with open(sel) as f:
|
||||||
|
d = json.load(f)
|
||||||
|
|
||||||
|
def lists():
|
||||||
|
return os.listdir(ARCH)
|
||||||
|
|
||||||
|
def tags():
|
||||||
|
global d
|
||||||
|
return list(d.keys())
|
||||||
|
|
||||||
|
def commit(li, url, tag):
|
||||||
|
global sel
|
||||||
|
|
||||||
|
if tag not in list(d.keys()):
|
||||||
|
print("new tag: " + tag)
|
||||||
|
d[tag] = []
|
||||||
|
|
||||||
|
for i in d[tag]:
|
||||||
|
if i['url'] == url:
|
||||||
|
return False
|
||||||
|
|
||||||
|
d[tag].append({'list': li, 'url': url})
|
||||||
|
|
||||||
|
with open(sel, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(d, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def report():
|
||||||
|
|
||||||
|
re = "Report: \n"
|
||||||
|
for k, v in d.items():
|
||||||
|
lre = {}
|
||||||
|
for i in v:
|
||||||
|
if i['list'] not in lre:
|
||||||
|
lre[i['list']] = 0
|
||||||
|
lre[i['list']] += 1
|
||||||
|
re += "<" + k + ">: " + str(len(v)) + " ("
|
||||||
|
for kk, vv in lre.items():
|
||||||
|
re += kk + ": " + str(vv) + " / "
|
||||||
|
re += ")\n"
|
||||||
|
|
||||||
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
37
www/routes.py
Normal file
37
www/routes.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from flask import render_template, request, jsonify, send_from_directory
|
||||||
|
from www import app
|
||||||
|
import logging
|
||||||
|
from www import archive
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
l = archive.lists()
|
||||||
|
return render_template("index.html", lists=l, tags=archive.tags())
|
||||||
|
|
||||||
|
@app.route('/tags')
|
||||||
|
def tags():
|
||||||
|
return jsonify(result=archive.tags())
|
||||||
|
|
||||||
|
@app.route('/report')
|
||||||
|
def report():
|
||||||
|
return jsonify(report=archive.report())
|
||||||
|
|
||||||
|
# @app.route('/favicon.ico')
|
||||||
|
# def favicon():
|
||||||
|
# return send_from_directory(os.path.join(app.root_path, 'static'),
|
||||||
|
# 'favicon.ico', mimetype='image/vnd.microsoft.icon')
|
||||||
|
|
||||||
|
@app.route('/collect')
|
||||||
|
def collect():
|
||||||
|
url = request.args.get('url')
|
||||||
|
tag = request.args.get('tags')
|
||||||
|
li = request.args.get('list')
|
||||||
|
|
||||||
|
msg = "Added " + url + " to " + tag
|
||||||
|
if not archive.commit(li, url, tag):
|
||||||
|
msg = url + " already exists..."
|
||||||
|
|
||||||
|
return jsonify({ "msg": msg, "report": archive.report()})
|
||||||
|
|
||||||
|
|
||||||
30
www/static/collect.js
Normal file
30
www/static/collect.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
// https://goodies.pixabay.com/jquery/tag-editor/demo.html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$.get("/tags", function(data, status){
|
||||||
|
$('#tags').tagEditor({
|
||||||
|
autocomplete: {
|
||||||
|
delay: 0, // show suggestions immediately
|
||||||
|
position: { collision: 'flip' }, // automatic menu position up/down
|
||||||
|
source: data.result
|
||||||
|
},
|
||||||
|
maxLength: 25,
|
||||||
|
placeholder: 'Enter tags ...'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$.get("/report", function(data, status){
|
||||||
|
$('#report').text(data.report);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#collect').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
args = $(this).serialize();
|
||||||
|
$.get('/collect?'+ args, function(data) {
|
||||||
|
console.log(data);
|
||||||
|
$('#serv').append(data.msg + "<br>");
|
||||||
|
$('#report').text(data.report);
|
||||||
|
});
|
||||||
|
});
|
||||||
4
www/static/jquery-1.11.1.min.js
vendored
Normal file
4
www/static/jquery-1.11.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
12
www/static/jquery-ui-1.10.2.min.js
vendored
Normal file
12
www/static/jquery-ui-1.10.2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
www/static/jquery.caret.min.js
vendored
Executable file
2
www/static/jquery.caret.min.js
vendored
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
// http://code.accursoft.com/caret - 1.3.3
|
||||||
|
!function(e){e.fn.caret=function(e){var t=this[0],n="true"===t.contentEditable;if(0==arguments.length){if(window.getSelection){if(n){t.focus();var o=window.getSelection().getRangeAt(0),r=o.cloneRange();return r.selectNodeContents(t),r.setEnd(o.endContainer,o.endOffset),r.toString().length}return t.selectionStart}if(document.selection){if(t.focus(),n){var o=document.selection.createRange(),r=document.body.createTextRange();return r.moveToElementText(t),r.setEndPoint("EndToEnd",o),r.text.length}var e=0,c=t.createTextRange(),r=document.selection.createRange().duplicate(),a=r.getBookmark();for(c.moveToBookmark(a);0!==c.moveStart("character",-1);)e++;return e}return t.selectionStart?t.selectionStart:0}if(-1==e&&(e=this[n?"text":"val"]().length),window.getSelection)n?(t.focus(),window.getSelection().collapse(t.firstChild,e)):t.setSelectionRange(e,e);else if(document.body.createTextRange)if(n){var c=document.body.createTextRange();c.moveToElementText(t),c.moveStart("character",e),c.collapse(!0),c.select()}else{var c=t.createTextRange();c.move("character",e),c.select()}return n||t.focus(),e}}(jQuery);
|
||||||
45
www/static/jquery.tag-editor.css
Executable file
45
www/static/jquery.tag-editor.css
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
/* surrounding tag container */
|
||||||
|
.tag-editor {
|
||||||
|
list-style-type: none; padding: 0 5px 0 0; margin: 0; overflow: hidden; border: 1px solid #eee; cursor: text;
|
||||||
|
font: normal 14px sans-serif; color: #555; background: #fff; line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* core styles usually need no change */
|
||||||
|
.tag-editor li { display: block; float: left; overflow: hidden; margin: 3px 0; }
|
||||||
|
.tag-editor div { float: left; padding: 0 4px; }
|
||||||
|
.tag-editor .placeholder { padding: 0 8px; color: #bbb; }
|
||||||
|
.tag-editor .tag-editor-spacer { padding: 0; width: 8px; overflow: hidden; color: transparent; background: none; }
|
||||||
|
.tag-editor input {
|
||||||
|
vertical-align: inherit; border: 0; outline: none; padding: 0; margin: 0; cursor: text;
|
||||||
|
font-family: inherit; font-weight: inherit; font-size: inherit; font-style: inherit;
|
||||||
|
box-shadow: none; background: none; color: #444;
|
||||||
|
}
|
||||||
|
/* hide original input field or textarea visually to allow tab navigation */
|
||||||
|
.tag-editor-hidden-src { position: absolute !important; left: -99999px; }
|
||||||
|
/* hide IE10 "clear field" X */
|
||||||
|
.tag-editor ::-ms-clear { display: none; }
|
||||||
|
|
||||||
|
/* tag style */
|
||||||
|
.tag-editor .tag-editor-tag {
|
||||||
|
padding-left: 5px; color: #46799b; background: #e0eaf1; white-space: nowrap;
|
||||||
|
overflow: hidden; cursor: pointer; border-radius: 2px 0 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete icon */
|
||||||
|
.tag-editor .tag-editor-delete { background: #e0eaf1; cursor: pointer; border-radius: 0 2px 2px 0; padding-left: 3px; padding-right: 4px; }
|
||||||
|
.tag-editor .tag-editor-delete i { line-height: 18px; display: inline-block; }
|
||||||
|
.tag-editor .tag-editor-delete i:before { font-size: 16px; color: #8ba7ba; content: "×"; font-style: normal; }
|
||||||
|
.tag-editor .tag-editor-delete:hover i:before { color: #d65454; }
|
||||||
|
.tag-editor .tag-editor-tag.active+.tag-editor-delete, .tag-editor .tag-editor-tag.active+.tag-editor-delete i { visibility: hidden; cursor: text; }
|
||||||
|
|
||||||
|
.tag-editor .tag-editor-tag.active { background: none !important; }
|
||||||
|
|
||||||
|
/* jQuery UI autocomplete - code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css */
|
||||||
|
.ui-autocomplete { position: absolute; top: 0; left: 0; cursor: default; font-size: 14px; }
|
||||||
|
.ui-front { z-index: 9999; }
|
||||||
|
.ui-menu { list-style: none; padding: 1px; margin: 0; display: block; outline: none; }
|
||||||
|
.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.4; min-height: 0; /* support: IE7 */ }
|
||||||
|
.ui-widget-content { border: 1px solid #bbb; background: #fff; color: #555; }
|
||||||
|
.ui-widget-content a { color: #46799b; }
|
||||||
|
.ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { background: #e0eaf1; }
|
||||||
|
.ui-helper-hidden-accessible { display: none; }
|
||||||
3
www/static/jquery.tag-editor.min.js
vendored
Executable file
3
www/static/jquery.tag-editor.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
16
www/static/lestyle.css
Normal file
16
www/static/lestyle.css
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#collect {
|
||||||
|
width: 30em;
|
||||||
|
display: block;
|
||||||
|
border: 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
/*font-size: 1em;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
54
www/templates/index.html
Normal file
54
www/templates/index.html
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>URLCOLLECT</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static',filename='jquery.tag-editor.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static',filename='lestyle.css') }}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form action="/collect" method="get" id="collect">
|
||||||
|
<h2>*************************************GET::</h2>
|
||||||
|
|
||||||
|
<label for="url">url</label>
|
||||||
|
<input type="text" name="url" id="url">
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
{% for l in lists %}
|
||||||
|
{{l}} <input type="radio" name="list" value="{{l}}">
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label for="tags">tags</label>
|
||||||
|
<input type="text" name="tags" id="tags">
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
<label for="tags">existing tags: </label>
|
||||||
|
<pre id="list_tags">
|
||||||
|
{% for t in tags %}
|
||||||
|
{{t}}
|
||||||
|
{% endfor %}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<button type="submit" id="submit">collect!</button>
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
---
|
||||||
|
<br>
|
||||||
|
<pre id="report"></pre>
|
||||||
|
---
|
||||||
|
<br>
|
||||||
|
<pre id="serv"></pre>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
<div id="collected"></div>
|
||||||
|
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
|
||||||
|
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
|
||||||
|
<script src="{{ url_for('static',filename='jquery.caret.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static',filename='jquery.tag-editor.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static',filename='collect.js') }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user