mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-03 20:02:47 +00:00 
			
		
		
		
	Add admin view on foreign jobs.
This commit is contained in:
		@@ -1,9 +1,11 @@
 | 
			
		||||
from flask import current_app, request
 | 
			
		||||
from flask_login import current_user, login_required
 | 
			
		||||
from ..decorators import admin_required
 | 
			
		||||
from .. import db, socketio
 | 
			
		||||
from ..models import User
 | 
			
		||||
import json
 | 
			
		||||
import jsonpatch
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
@@ -28,6 +30,26 @@ def connect():
 | 
			
		||||
                                   request.sid)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@socketio.on('connect_admin')
 | 
			
		||||
@login_required
 | 
			
		||||
@admin_required
 | 
			
		||||
def connect_admin(selected_user_id):
 | 
			
		||||
    '''
 | 
			
		||||
    ' The Socket.IO module creates a session id (sid) on each request. The
 | 
			
		||||
    ' initiating admin is automatically placed in a room with that sid, which
 | 
			
		||||
    ' will be used for further information exchange generated by a background
 | 
			
		||||
    ' task associated with the sid. Admin will be placed in that room on emiting
 | 
			
		||||
    ' "conncect_admin".
 | 
			
		||||
    '''
 | 
			
		||||
    logger = logging.getLogger(__name__)
 | 
			
		||||
    logger.warning('Admin emitted "connect_admin".')
 | 
			
		||||
    logger.warning('Selected user id is: {}'.format(selected_user_id))
 | 
			
		||||
    socketio.start_background_task(background_task_foreign,
 | 
			
		||||
                                   current_app._get_current_object(),
 | 
			
		||||
                                   selected_user_id,
 | 
			
		||||
                                   request.sid)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@socketio.on('disconnect')
 | 
			
		||||
@login_required
 | 
			
		||||
def disconnect():
 | 
			
		||||
@@ -51,9 +73,13 @@ def background_task(app, user_id, session_id):
 | 
			
		||||
    '''
 | 
			
		||||
    with app.app_context():
 | 
			
		||||
        user = db.session.query(User).filter_by(id=user_id).first()
 | 
			
		||||
        logging.getLogger(__name__)
 | 
			
		||||
        logging.warning('User object is: {}'.format(user))
 | 
			
		||||
        ''' Get current values from the database. '''
 | 
			
		||||
        corpora = user.corpora_as_dict()
 | 
			
		||||
        logging.warning('Corpora are: {}'.format(corpora))
 | 
			
		||||
        jobs = user.jobs_as_dict()
 | 
			
		||||
        logging.warning('Jobs are: {}'.format(jobs))
 | 
			
		||||
        ''' Send initial values. '''
 | 
			
		||||
        socketio.emit('init-corpora',
 | 
			
		||||
                      json.dumps(corpora),
 | 
			
		||||
@@ -83,3 +109,54 @@ def background_task(app, user_id, session_id):
 | 
			
		||||
            jobs = new_jobs
 | 
			
		||||
            socketio.sleep(3)
 | 
			
		||||
    disconnected.remove(session_id)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def background_task_foreign(app, user_id, session_id):
 | 
			
		||||
    '''
 | 
			
		||||
    ' Sends initial corpus and job lists to the client. Afterwards it checks
 | 
			
		||||
    ' every 3 seconds if changes to the initial values appeared. If changes are
 | 
			
		||||
    ' detected, a RFC 6902 compliant JSON patch gets send.
 | 
			
		||||
    '
 | 
			
		||||
    ' NOTE: The initial values are send as a init-* events.
 | 
			
		||||
    '       The JSON patches are send as update-* events.
 | 
			
		||||
    '
 | 
			
		||||
    '       > where '*' is either 'corpora' or 'jobs'
 | 
			
		||||
    '''
 | 
			
		||||
    with app.app_context():
 | 
			
		||||
        user = db.session.query(User).filter_by(id=user_id).first()
 | 
			
		||||
        logging.getLogger(__name__)
 | 
			
		||||
        logging.warning('User object is: {}'.format(user))
 | 
			
		||||
        ''' Get current values from the database. '''
 | 
			
		||||
        corpora = user.corpora_as_dict()
 | 
			
		||||
        logging.warning('Corpora are: {}'.format(corpora))
 | 
			
		||||
        jobs = user.jobs_as_dict()
 | 
			
		||||
        logging.warning('Jobs are: {}'.format(jobs))
 | 
			
		||||
        ''' Send initial values. '''
 | 
			
		||||
        socketio.emit('init-foreign-corpora',
 | 
			
		||||
                      json.dumps(corpora),
 | 
			
		||||
                      room=session_id)
 | 
			
		||||
        socketio.emit('init-foreign-jobs',
 | 
			
		||||
                      json.dumps(jobs),
 | 
			
		||||
                      room=session_id)
 | 
			
		||||
        ''' TODO: Implement maximum runtime for this loop. '''
 | 
			
		||||
        while session_id not in disconnected:
 | 
			
		||||
            ''' Get current values from the database '''
 | 
			
		||||
            new_corpora = user.corpora_as_dict()
 | 
			
		||||
            new_jobs = user.jobs_as_dict()
 | 
			
		||||
            ''' Compute JSON patches. '''
 | 
			
		||||
            corpus_patch = jsonpatch.JsonPatch.from_diff(corpora, new_corpora)
 | 
			
		||||
            jobs_patch = jsonpatch.JsonPatch.from_diff(jobs, new_jobs)
 | 
			
		||||
            ''' In case there are patches, send them to the user. '''
 | 
			
		||||
            if corpus_patch:
 | 
			
		||||
                socketio.emit('update-foreign-corpora',
 | 
			
		||||
                              corpus_patch.to_string(),
 | 
			
		||||
                              room=session_id)
 | 
			
		||||
            if jobs_patch:
 | 
			
		||||
                socketio.emit('update-foreign-jobs',
 | 
			
		||||
                              jobs_patch.to_string(),
 | 
			
		||||
                              room=session_id)
 | 
			
		||||
            ''' Set new values as references for the next iteration. '''
 | 
			
		||||
            corpora = new_corpora
 | 
			
		||||
            jobs = new_jobs
 | 
			
		||||
            socketio.sleep(3)
 | 
			
		||||
    disconnected.remove(session_id)
 | 
			
		||||
 
 | 
			
		||||
@@ -21,50 +21,41 @@
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
  var selected_user_id = {{selected_user.id|tojson|safe}}
 | 
			
		||||
  socket.emit('connect_admin', selected_user_id);
 | 
			
		||||
</script>
 | 
			
		||||
<div class="col s12 m6">
 | 
			
		||||
  <div class="card large">
 | 
			
		||||
    <div class="card-content">
 | 
			
		||||
      <span class="card-title">User Jobs</span>
 | 
			
		||||
      <div id="users">
 | 
			
		||||
        <div class="input-field">
 | 
			
		||||
          <i class="material-icons prefix">search</i>
 | 
			
		||||
          <input id="search-corpus" class="search" type="text"></input>
 | 
			
		||||
          <label for="search-corpus">Search jobs</label>
 | 
			
		||||
  <div id="job-list">
 | 
			
		||||
    <div class="card">
 | 
			
		||||
      <div class="card-content">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
          <div class="col s12">
 | 
			
		||||
            <div class="input-field">
 | 
			
		||||
              <i class="material-icons prefix">search</i>
 | 
			
		||||
              <input id="search-job" class="search" type="text"></input>
 | 
			
		||||
              <label for="search-job">Search job</label>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="col s12">
 | 
			
		||||
            <ul class="pagination"></ul>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="collection list">
 | 
			
		||||
          {% for job in selected_user.jobs.all() %}
 | 
			
		||||
            {% if job.service == 'nlp' %}
 | 
			
		||||
              {% set service_color = 'blue' %}
 | 
			
		||||
              {% set service_icon = 'format_textdirection_l_to_r' %}
 | 
			
		||||
            {% elif job.service =='ocr' %}
 | 
			
		||||
              {% set service_color = 'green' %}
 | 
			
		||||
              {% set service_icon = 'find_in_page' %}
 | 
			
		||||
            {% else %}
 | 
			
		||||
              {% set service_color = 'red' %}
 | 
			
		||||
              {% set service_icon = 'help' %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
            {% if job.status == 'pending' %}
 | 
			
		||||
              {% set badge_color = 'amber' %}
 | 
			
		||||
            {% elif job.status =='running' %}
 | 
			
		||||
              {% set badge_color = 'indigo' %}
 | 
			
		||||
            {% elif job.status =='complete' %}
 | 
			
		||||
              {% set badge_color = 'teal' %}
 | 
			
		||||
            {% else %}
 | 
			
		||||
              {% set badge_color = 'red' %}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
            <a href="{{ url_for('main.job', job_id=job.id) }}" class="collection-item avatar">
 | 
			
		||||
                <i class="material-icons circle {{ service_color }}">{{ service_icon }}</i>
 | 
			
		||||
                <span class="new badge {{ badge_color }}" data-badge-caption="">{{ job.status }}</span>
 | 
			
		||||
                <span class="title">{{ job.title }}</span>
 | 
			
		||||
                <p>{{ job.description }}</p>
 | 
			
		||||
            </a>
 | 
			
		||||
          {% endfor %}
 | 
			
		||||
        </div>
 | 
			
		||||
        <ul class="pagination"></ul>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="collection list"></div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
<script>
 | 
			
		||||
  var jobList = new JobList("job-list", {
 | 
			
		||||
    item: '<div><span class="title"></span><span class="description"></span></div>',
 | 
			
		||||
    page: 4,
 | 
			
		||||
    pagination: true,
 | 
			
		||||
    valueNames: ["description", "title", {data: ["id"]}]
 | 
			
		||||
  });
 | 
			
		||||
  jobList.on("filterComplete", List.updatePagination);
 | 
			
		||||
  jobList.on("searchComplete", List.updatePagination);
 | 
			
		||||
</script>
 | 
			
		||||
<div class="col s12">
 | 
			
		||||
  <div class="card large">
 | 
			
		||||
    <div class="card-content">
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@
 | 
			
		||||
      var jobsSubscribers = [];
 | 
			
		||||
      var socket = io();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      socket.on('init-corpora', function(msg) {
 | 
			
		||||
        var subscriber;
 | 
			
		||||
 | 
			
		||||
@@ -64,6 +65,46 @@
 | 
			
		||||
        console.log(msg);
 | 
			
		||||
      });
 | 
			
		||||
    </script>
 | 
			
		||||
    <script>
 | 
			
		||||
      var foreignCorpora;
 | 
			
		||||
      var foreignCorporaSubscribers = [];
 | 
			
		||||
      var foreignJobs;
 | 
			
		||||
      var foreignJobsSubscribers = [];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      socket.on('init-foreign-corpora', function(msg) {
 | 
			
		||||
        var subscriber;
 | 
			
		||||
 | 
			
		||||
        foreignCorpora = JSON.parse(msg);
 | 
			
		||||
        for (subscriber of foreignCorporaSubscribers) {subscriber._init();}
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      socket.on('init-foreign-jobs', function(msg) {
 | 
			
		||||
        var subscriber;
 | 
			
		||||
 | 
			
		||||
        foreignJobs = JSON.parse(msg);
 | 
			
		||||
        for (subscriber of foreignJobsSubscribers) {subscriber._init();}
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      socket.on('update-foreign-corpora', function(msg) {
 | 
			
		||||
        var patch, patchedCorpora, subscriber;
 | 
			
		||||
 | 
			
		||||
        patch = JSON.parse(msg);
 | 
			
		||||
        foreignCorpora = jsonpatch.apply_patch(foreignCorpora, patch);
 | 
			
		||||
        for (subscriber of foreignCorporaSubscribers) {subscriber._update(patch);}
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      socket.on('update-foreign-jobs', function(msg) {
 | 
			
		||||
        var patch, patchedJobs, subscriber;
 | 
			
		||||
 | 
			
		||||
        patch = JSON.parse(msg);
 | 
			
		||||
        foreignJobs = jsonpatch.apply_patch(foreignJobs, patch);
 | 
			
		||||
        for (subscriber of foreignJobsSubscribers) {subscriber._update(patch);}
 | 
			
		||||
      });
 | 
			
		||||
    </script>
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user