mirror of
				https://github.com/dgtlmoon/changedetection.io.git
				synced 2025-10-31 14:47:21 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			openai-int
			...
			UI-eta-tim
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 01dd67b1ad | ||
|   | 316cca0901 | 
| @@ -1,7 +1,5 @@ | ||||
| import flask_login | ||||
| import os | ||||
| import time | ||||
| import timeago | ||||
|  | ||||
| from flask import Blueprint, request, make_response, render_template, redirect, url_for, flash, session | ||||
| from flask_login import current_user | ||||
| @@ -10,7 +8,6 @@ from flask_paginate import Pagination, get_page_parameter | ||||
| from changedetectionio import forms | ||||
| from changedetectionio.store import ChangeDetectionStore | ||||
| from changedetectionio.auth_decorator import login_optionally_required | ||||
| from changedetectionio.strtobool import strtobool | ||||
|  | ||||
| def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMetaData): | ||||
|     watchlist_blueprint = Blueprint('watchlist', __name__, template_folder="templates") | ||||
| @@ -77,7 +74,6 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|         sorted_tags = sorted(datastore.data['settings']['application'].get('tags').items(), key=lambda x: x[1]['title']) | ||||
|         output = render_template( | ||||
|             "watch-overview.html", | ||||
|                                  # Don't link to hosting when we're on the hosting environment | ||||
|                                  active_tag=active_tag, | ||||
|                                  active_tag_uuid=active_tag_uuid, | ||||
|                                  app_rss_token=datastore.data['settings']['application'].get('rss_access_token'), | ||||
| @@ -88,9 +84,10 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|                                  has_proxies=datastore.proxy_list, | ||||
|                                  has_unviewed=datastore.has_unviewed, | ||||
|                                  hosted_sticky=os.getenv("SALTED_PASS", False) == False, | ||||
|                                  now_time_server=time.time(), | ||||
|                                  pagination=pagination, | ||||
|                                  queued_uuids=[q_uuid.item['uuid'] for q_uuid in update_q.queue], | ||||
|                                  search_q=request.args.get('q','').strip(), | ||||
|                                  search_q=request.args.get('q', '').strip(), | ||||
|                                  sort_attribute=request.args.get('sort') if request.args.get('sort') else request.cookies.get('sort'), | ||||
|                                  sort_order=request.args.get('order') if request.args.get('order') else request.cookies.get('order'), | ||||
|                                  system_default_fetcher=datastore.data['settings']['application'].get('fetch_backend'), | ||||
|   | ||||
| @@ -3,7 +3,16 @@ | ||||
| {% from '_helpers.html' import render_simple_field, render_field, render_nolabel_field, sort_by_title %} | ||||
| <script src="{{url_for('static_content', group='js', filename='jquery-3.6.0.min.js')}}"></script> | ||||
| <script src="{{url_for('static_content', group='js', filename='watch-overview.js')}}" defer></script> | ||||
| <script>let nowtimeserver={{ now_time_server }};</script> | ||||
|  | ||||
| <style> | ||||
| .checking-now .last-checked { | ||||
|     background-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1) 100%); | ||||
|     background-size: 0 100%; | ||||
|     background-repeat: no-repeat; | ||||
|     transition: background-size 0.9s ease | ||||
| } | ||||
| </style> | ||||
| <div class="box"> | ||||
|  | ||||
|     <form class="pure-form" action="{{ url_for('ui.ui_views.form_quick_watch_add', tag=active_tag_uuid) }}" method="POST" id="new-watch-form"> | ||||
| @@ -91,8 +100,8 @@ | ||||
|             {% endif %} | ||||
|             {% for watch in (watches|sort(attribute=sort_attribute, reverse=sort_order == 'asc'))|pagination_slice(skip=pagination.skip) %} | ||||
|  | ||||
|                 {% set is_unviewed =  watch.newest_history_key| int > watch.last_viewed and watch.history_n>=2 %} | ||||
|  | ||||
|                 {% set is_unviewed = watch.newest_history_key| int > watch.last_viewed and watch.history_n>=2 %} | ||||
|                 {% set checking_now = is_checking_now(watch) %} | ||||
|             <tr id="{{ watch.uuid }}" | ||||
|                 class="{{ loop.cycle('pure-table-odd', 'pure-table-even') }} processor-{{ watch['processor'] }} | ||||
|                 {% if watch.last_error is defined and watch.last_error != False %}error{% endif %} | ||||
| @@ -100,7 +109,9 @@ | ||||
|                 {% if watch.paused is defined and watch.paused != False %}paused{% endif %} | ||||
|                 {% if is_unviewed %}unviewed{% endif %} | ||||
|                 {% if watch.has_restock_info %} has-restock-info {% if watch['restock']['in_stock'] %}in-stock{% else %}not-in-stock{% endif %} {% else %}no-restock-info{% endif %} | ||||
|                 {% if watch.uuid in queued_uuids %}queued{% endif %}"> | ||||
|                 {% if watch.uuid in queued_uuids %}queued{% endif %} | ||||
|                 {% if checking_now %}checking-now{% endif %} | ||||
|                 "> | ||||
|                 <td class="inline checkbox-uuid" ><input name="uuids"  type="checkbox" value="{{ watch.uuid}} " > <span>{{ loop.index+pagination.skip }}</span></td> | ||||
|                 <td class="inline watch-controls"> | ||||
|                     {% if not watch.paused %} | ||||
| @@ -178,7 +189,14 @@ | ||||
|                     {% endif %} | ||||
|                 </td> | ||||
| {% endif %} | ||||
|                 <td class="last-checked" data-timestamp="{{ watch.last_checked }}">{{watch|format_last_checked_time|safe}}</td> | ||||
|             {#last_checked becomes fetch-start-time#} | ||||
|                 <td class="last-checked" data-timestamp="{{ watch.last_checked }}" {% if checking_now %} data-fetchduration={{ watch.fetch_time }} data-eta_complete="{{ watch.last_checked+watch.fetch_time }}" {% endif %} > | ||||
|                     {% if checking_now %} | ||||
|                         <span class="spinner"></span><span> Checking now</span> | ||||
|                     {% else %} | ||||
|                         {{watch|format_last_checked_time|safe}}</td> | ||||
|                     {% endif %} | ||||
|  | ||||
|                 <td class="last-changed" data-timestamp="{{ watch.last_changed }}">{% if watch.history_n >=2 and watch.last_changed >0 %} | ||||
|                     {{watch.last_changed|format_timestamp_timeago}} | ||||
|                     {% else %} | ||||
|   | ||||
| @@ -123,14 +123,18 @@ def _jinja2_filter_format_number_locale(value: float) -> str: | ||||
|  | ||||
|     return formatted_value | ||||
|  | ||||
| @app.template_global('is_checking_now') | ||||
| def _watch_is_checking_now(watch_obj, format="%Y-%m-%d %H:%M:%S"): | ||||
|     # Worker thread tells us which UUID it is currently processing. | ||||
|     for t in running_update_threads: | ||||
|         if t.current_uuid == watch_obj['uuid']: | ||||
|             return True | ||||
|  | ||||
|  | ||||
| # We use the whole watch object from the store/JSON so we can see if there's some related status in terms of a thread | ||||
| # running or something similar. | ||||
| @app.template_filter('format_last_checked_time') | ||||
| def _jinja2_filter_datetime(watch_obj, format="%Y-%m-%d %H:%M:%S"): | ||||
|     # Worker thread tells us which UUID it is currently processing. | ||||
|     for t in running_update_threads: | ||||
|         if t.current_uuid == watch_obj['uuid']: | ||||
|             return '<span class="spinner"></span><span> Checking now</span>' | ||||
|  | ||||
|     if watch_obj['last_checked'] == 0: | ||||
|         return 'Not yet' | ||||
|   | ||||
| @@ -48,6 +48,8 @@ $(function () { | ||||
|         $('input[type=checkbox]').not(this).prop('checked', this.checked); | ||||
|     }); | ||||
|  | ||||
|     const time_check_step_size_seconds=1; | ||||
|  | ||||
|     // checkboxes - show/hide buttons | ||||
|     $("input[type=checkbox]").click(function (e) { | ||||
|         if ($('input[type=checkbox]:checked').length) { | ||||
| @@ -57,5 +59,30 @@ $(function () { | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     setInterval(function () { | ||||
|         // Background ETA completion for 'checking now' | ||||
|         $(".watch-table .checking-now .last-checked").each(function () { | ||||
|             const eta_complete = parseFloat($(this).data('eta_complete')); | ||||
|             const fetch_duration = parseInt($(this).data('fetchduration')); | ||||
|  | ||||
|             if (eta_complete + 2 > nowtimeserver && fetch_duration > 3) { | ||||
|                 const remaining_seconds = Math.abs(eta_complete) - nowtimeserver - 1; | ||||
|  | ||||
|                 let r = (1.0 - (remaining_seconds / fetch_duration)) * 100; | ||||
|                 if (r < 10) { | ||||
|                     r = 10; | ||||
|                 } | ||||
|                 if (r >= 90) { | ||||
|                     r = 100; | ||||
|                 } | ||||
|                 $(this).css('background-size', `${r}% 100%`); | ||||
|                 //$(this).text(`${r}% remain ${remaining_seconds}`); | ||||
|             } else { | ||||
|                 $(this).css('background-size', `100% 100%`); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         nowtimeserver = nowtimeserver + time_check_step_size_seconds; | ||||
|     }, time_check_step_size_seconds * 1000); | ||||
| }); | ||||
|  | ||||
|   | ||||
| @@ -253,8 +253,9 @@ class update_worker(threading.Thread): | ||||
|                 pass | ||||
|  | ||||
|             else: | ||||
|                 fetch_start_time = time.time() | ||||
|  | ||||
|                 uuid = queued_item_data.item.get('uuid') | ||||
|                 fetch_start_time = round(time.time())  # Also used for a unique history key for now | ||||
|                 self.current_uuid = uuid | ||||
|                 if uuid in list(self.datastore.data['watching'].keys()) and self.datastore.data['watching'][uuid].get('url'): | ||||
|                     changed_detected = False | ||||
| @@ -262,8 +263,10 @@ class update_worker(threading.Thread): | ||||
|                     process_changedetection_results = True | ||||
|                     update_obj = {} | ||||
|  | ||||
|  | ||||
|                     # Clear last errors (move to preflight func?) | ||||
|                     self.datastore.data['watching'][uuid]['browser_steps_last_error_step'] = None | ||||
|                     self.datastore.data['watching'][uuid]['last_checked'] = fetch_start_time | ||||
|  | ||||
|                     watch = self.datastore.data['watching'].get(uuid) | ||||
|  | ||||
| @@ -287,10 +290,6 @@ class update_worker(threading.Thread): | ||||
|  | ||||
|                         update_handler.call_browser() | ||||
|  | ||||
|                         # In reality, the actual time of when the change was detected could be a few seconds after this | ||||
|                         # For example it should include when the page stopped rendering if using a playwright/chrome type fetch | ||||
|                         fetch_start_time = time.time() | ||||
|  | ||||
|                         changed_detected, update_obj, contents = update_handler.run_changedetection(watch=watch) | ||||
|  | ||||
|                         # Re #342 | ||||
| @@ -587,7 +586,6 @@ class update_worker(threading.Thread): | ||||
|                         pass | ||||
|  | ||||
|                     self.datastore.update_watch(uuid=uuid, update_obj={'fetch_time': round(time.time() - fetch_start_time, 3), | ||||
|                                                                        'last_checked': int(fetch_start_time), | ||||
|                                                                        'check_count': count | ||||
|                                                                        }) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user