diff --git a/intake/app.py b/intake/app.py index 4d1addf..21df08f 100644 --- a/intake/app.py +++ b/intake/app.py @@ -5,7 +5,7 @@ import time from flask import Flask, render_template, request, jsonify, abort, redirect, url_for -from intake.source import LocalSource +from intake.source import LocalSource, execute_action # Globals app = Flask(__name__) @@ -70,7 +70,7 @@ def source_feed(source_name): if count_arg.isdigit() and page_arg.isdigit(): count = int(count_arg) page = int(page_arg) - sorted_items = sorted_items[count * page:count * page + count] + sorted_items = sorted_items[count * page : count * page + count] return render_template( "feed.jinja2", @@ -126,6 +126,13 @@ def mass_deactivate(): return jsonify({}) +@app.post("/action///") +def action(source_name, item_id, action): + source = LocalSource(intake_data_dir(), source_name) + item = execute_action(source, item_id, action) + return jsonify(item) + + def wsgi(): # init_default_logging() return app diff --git a/intake/source.py b/intake/source.py index 5ac5054..659c377 100755 --- a/intake/source.py +++ b/intake/source.py @@ -75,7 +75,7 @@ class LocalSource: yield json.loads(filepath.read_text(encoding="utf8")) -def read_stdout(process: Popen, output: list): +def _read_stdout(process: Popen, output: list) -> None: """ Read the subprocess's stdout into memory. This prevents the process from blocking when the pipe fills up. @@ -89,7 +89,7 @@ def read_stdout(process: Popen, output: list): break -def read_stderr(process: Popen): +def _read_stderr(process: Popen) -> None: """ Read the subprocess's stderr stream and pass it to logging. This prevents the process from blocking when the pipe fills up. @@ -102,12 +102,12 @@ def read_stderr(process: Popen): break -def execute_source_action( +def _execute_source_action( source: LocalSource, action: str, input: str, timeout: timedelta -): +) -> List[str]: """ Execute the action from a given source. If stdin is specified, pass it - along to the process. + along to the process. Returns lines from stdout. """ # Gather the information necessary to launch the process config = source.get_config() @@ -141,9 +141,9 @@ def execute_source_action( # Kick off monitoring threads output = [] - t_stdout: Thread = Thread(target=read_stdout, args=(process, output), daemon=True) + t_stdout: Thread = Thread(target=_read_stdout, args=(process, output), daemon=True) t_stdout.start() - t_stderr: Thread = Thread(target=read_stderr, args=(process,), daemon=True) + t_stderr: Thread = Thread(target=_read_stderr, args=(process,), daemon=True) t_stderr.start() # Send input to the process, if provided @@ -168,7 +168,7 @@ def execute_source_action( return output -def fetch_items(source: LocalSource, timeout: int = 60): +def fetch_items(source: LocalSource, timeout: int = 60) -> List[dict]: """ Execute the feed source and return the current feed items. Returns a list of feed items on success. @@ -176,7 +176,7 @@ def fetch_items(source: LocalSource, timeout: int = 60): """ items = [] - output = execute_source_action(source, "fetch", None, timedelta(timeout)) + output = _execute_source_action(source, "fetch", None, timedelta(timeout)) for line in output: try: @@ -188,13 +188,17 @@ def fetch_items(source: LocalSource, timeout: int = 60): return items -def execute_action(source: LocalSource, item_id: str, action: str, timeout: int = 60): +def execute_action( + source: LocalSource, item_id: str, action: str, timeout: int = 60 +) -> dict: """ Execute the action for a feed source. """ item = source.get_item(item_id) - output = execute_source_action(source, action, json.dumps(item), timedelta(timeout)) + output = _execute_source_action( + source, action, json.dumps(item), timedelta(timeout) + ) if not output: raise SourceUpdateException("no item") diff --git a/intake/templates/feed.jinja2 b/intake/templates/feed.jinja2 index 0c219ed..7af83cf 100644 --- a/intake/templates/feed.jinja2 +++ b/intake/templates/feed.jinja2 @@ -99,14 +99,13 @@ var mdeactivate = function (items) { location.reload(); }); }; -var callback = function (source, itemid) { - document.getElementById(source + "-" + itemid + "-callback").disabled = true; - fetch('/callback/', { +var doAction = function (source, itemid, action) { + document.getElementById(`${source}-${itemid}-action-${action}`).disabled = true; + fetch(`/action/${source}/${itemid}/${action}`, { method: 'POST', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, - body: JSON.stringify({source: source, itemid: itemid}), }) .then(function (data) { location.reload() @@ -130,15 +129,15 @@ var callback = function (source, itemid) { {% endif %} {# The item title is a clickable if there is body content #} - {% if item.body or item.callback %} + {% if item.body or item.action %}
{{item.title}} {% if item.body %}

{{item.body|safe}}

{% endif %} - {% if item.callback %} -

- {% endif %} + {% for action in item.action %} +

+ {% endfor %}
{% else %} {{item.title}}
diff --git a/tests/demo_basic_callback/increment.py b/tests/demo_basic_callback/increment.py index 56a4239..5954bc0 100755 --- a/tests/demo_basic_callback/increment.py +++ b/tests/demo_basic_callback/increment.py @@ -20,5 +20,6 @@ if args.action == "increment": item = sys.stdin.readline() item = json.loads(item) item["action"]["increment"] += 1 + item["body"] = f"

{item['action']['increment']}

" print(json.dumps(item)) pass