Commit dc11a23e05d5aae5adf42adbd5e0492bcf499dcd
1 parent
ba5232a0
Exists in
master
Versão inicial do Validador.
Showing
31 changed files
with
516 additions
and
1 deletions
Show diff stats
inicial.txt
... | ... | @@ -1 +0,0 @@ |
1 | -Repositorio validador_sinais Criado |
... | ... | @@ -0,0 +1,62 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +from flask import Flask, send_from_directory | |
3 | +from flask.ext.cors import CORS | |
4 | +from jinja2 import Environment, PackageLoader | |
5 | +from validador import Validador | |
6 | +import os | |
7 | +import pyutil | |
8 | + | |
9 | +app = Flask(__name__) | |
10 | +CORS(app) | |
11 | +controller = None | |
12 | + | |
13 | +@app.route("/<path:path>") | |
14 | +def send_static_files(path): | |
15 | + root_dir = os.path.abspath(os.path.dirname(__file__)) | |
16 | + file_dir = os.path.join(root_dir, "view") | |
17 | + return send_from_directory(file_dir, path) | |
18 | + | |
19 | +@app.route("/update_project") | |
20 | +def update_project(): | |
21 | + try: | |
22 | + return controller.update_project() | |
23 | + except: | |
24 | + pyutil.print_stack_trace() | |
25 | + raise | |
26 | + | |
27 | +@app.route("/create_project") | |
28 | +def create_project(): | |
29 | + try: | |
30 | + return controller.create_project() | |
31 | + except: | |
32 | + pyutil.print_stack_trace() | |
33 | + raise | |
34 | + | |
35 | +@app.route("/finish_task", methods=["POST"]) | |
36 | +def finish_task(): | |
37 | + # TODO read - request.data['upload_session_id'] e request.data['sign_name'] | |
38 | + return | |
39 | + | |
40 | +def read_settings(app): | |
41 | + here = os.path.abspath(__file__) | |
42 | + config_path = os.path.join(os.path.dirname(here), 'settings_local.py') | |
43 | + if os.path.exists(config_path): | |
44 | + app.config.from_pyfile(config_path) | |
45 | + app.config['HOST_ENDPOINT'] = "http://" + app.config['SERVER_HOST'] + ":" + str(app.config['SERVER_PORT']) | |
46 | + | |
47 | +def setup_controller(): | |
48 | + global controller | |
49 | + read_settings(app) | |
50 | + env = Environment(loader=PackageLoader('main', 'view')) | |
51 | + controller = Validador(app.config, env) | |
52 | + | |
53 | +def run(): | |
54 | + setup_controller() | |
55 | + app.run(port=app.config['SERVER_PORT']) | |
56 | + | |
57 | +if __name__ == '__main__': | |
58 | + try: | |
59 | + run() | |
60 | + except: | |
61 | + pyutil.print_stack_trace() | |
62 | + raise | ... | ... |
... | ... | @@ -0,0 +1,68 @@ |
1 | +# -*- coding: UTF-8 -*- | |
2 | + | |
3 | +import datetime | |
4 | +import logging | |
5 | +import os | |
6 | +import shutil | |
7 | +import sys | |
8 | + | |
9 | +# @def funcao para obter data e hora atual do sistema | |
10 | +# @param string formato de data e hora | |
11 | +# @return string retorna data e hora do sistema no momento da chamada | |
12 | +def getTimeStamp(date_fmt="%Y-%m-%d %H:%M:%S.%f"): | |
13 | + if ("%f" in date_fmt): | |
14 | + # [:-3] remove 3 casas decimais dos milisegundos (ms) | |
15 | + return datetime.datetime.now().strftime(date_fmt)[:-3] | |
16 | + else: | |
17 | + return datetime.datetime.now().strftime(date_fmt) | |
18 | + | |
19 | +# @def funcao para gravar log dos eventos em arquivo | |
20 | +# @param string mensagem a ser salva | |
21 | +# @param int indice do tipo de log 0: apenas print, 1: debug, 2: info, 3: warn, 4: error, 5: critical | |
22 | +# @param string caminho completo do arquivo de logs | |
23 | +# @param string formato de tempo utilizado | |
24 | +# @return none | |
25 | +def log(msg="", log_level=2, log_file="events.log"): | |
26 | + dict_level = { | |
27 | + 0: ["Print", None, None], | |
28 | + 1: ["DEBUG", logging.DEBUG, logging.debug], | |
29 | + 2: ["INFO", logging.INFO, logging.info], | |
30 | + 3: ["WARNING", logging.WARN, logging.warn], | |
31 | + 4: ["ERROR", logging.ERROR, logging.error], | |
32 | + 5: ["CRITICAL", logging.CRITICAL, logging.critical] | |
33 | + } | |
34 | + # log_format = "[%(asctime)s.%(msecs).03d] %(levelname)s: <User: %(name)s> <Module: %(module)s> <Function: %(funcName)s>: %(message)s" | |
35 | + log_format = "[%(asctime)s.%(msecs).03d] %(levelname)s: %(message)s" | |
36 | + date_fmt = "%Y-%m-%d %H:%M:%S" | |
37 | + logging.basicConfig(filename=log_file, datefmt=date_fmt, format=log_format, level=dict_level[log_level][1]) | |
38 | + logging.Formatter(fmt="%(asctime)s", datefmt=date_fmt) | |
39 | + log_level %= len(dict_level) | |
40 | + write_mode = dict_level[log_level][2] | |
41 | + print("[%s] %s: %s" % (getTimeStamp(), dict_level[log_level][0], msg)) | |
42 | + if (write_mode != None): | |
43 | + write_mode(msg) | |
44 | + return | |
45 | + | |
46 | +# @def funcao para exibir excecao | |
47 | +# @param string deve ser passado: "__file__" para identificar em qual modulo ocorreu a excecao | |
48 | +# @return int retorna 1 | |
49 | +def print_stack_trace(): | |
50 | + error = "\n File name: %s\n Function name: %s\n Line code: %s\n Type exception: %s\n Message: %s" % ( | |
51 | + os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), | |
52 | + sys.exc_info()[2].tb_frame.f_code.co_name, | |
53 | + sys.exc_info()[2].tb_lineno, | |
54 | + sys.exc_info()[0].__name__, | |
55 | + sys.exc_info()[1] | |
56 | + ) | |
57 | + log(error, 4) | |
58 | + return 1 | |
59 | + | |
60 | +def get_date_now(): | |
61 | + return datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S') | |
62 | + | |
63 | +def is_int(string): | |
64 | + try: | |
65 | + int(string) | |
66 | + return True | |
67 | + except ValueError: | |
68 | + return False | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Corretor Server Configuration | |
3 | +SERVER_HOST = "localhost" | |
4 | +SERVER_PORT = 8001 | |
5 | + | |
6 | +# PyBossa Configuration | |
7 | +PYBOSSA_APP_NAME = "Validador de Sinais" | |
8 | +PYBOSSA_APP_SHORT_NAME = "validador_sinais" | |
9 | +PYBOSSA_APP_DESCRIPTION = "Esse projeto possibilitará que especialistas aprovem sinais gerados pela comunidade." | |
10 | +PYBOSSA_ENDPOINT = "http://localhost:5000" | |
11 | +PYBOSSA_API_KEY = "my-api-key" | |
0 | 12 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,62 @@ |
1 | +from flask import request, make_response | |
2 | +from werkzeug import secure_filename | |
3 | +import pbclient | |
4 | +import os | |
5 | +import pyutil | |
6 | + | |
7 | +class Validador: | |
8 | + | |
9 | + def __init__(self, configuration, template_env): | |
10 | + self.config = configuration | |
11 | + self.env = template_env | |
12 | + self.__setup_pb_client() | |
13 | + | |
14 | + def __setup_pb_client(self): | |
15 | + pbclient.set('endpoint', self.config['PYBOSSA_ENDPOINT']) | |
16 | + pbclient.set('api_key', self.config['PYBOSSA_API_KEY']) | |
17 | + | |
18 | + def __find_project(self, app_short_name): | |
19 | + projects = pbclient.find_project(short_name=app_short_name) | |
20 | + return projects[0] if len(projects) > 0 else None | |
21 | + | |
22 | + def __setup_project(self, project): | |
23 | + self.__create_tasks(project) | |
24 | + self.__update_project_info(project) | |
25 | + | |
26 | + def __create_tasks(self, project): | |
27 | + test_signs = ["ENSINADO", "ENTANTO", "ENTENDIDO"] | |
28 | + for sign in test_signs: | |
29 | + task = dict(sign_name=sign, submission_date=pyutil.get_date_now()) | |
30 | + pbclient.create_task(project.id, task) | |
31 | + | |
32 | + def __update_project_info(self, project): | |
33 | + template = self.env.get_template('template.html') | |
34 | + project.info['task_presenter'] = template.render(server=self.config['HOST_ENDPOINT'], app_shortname=self.config['PYBOSSA_APP_SHORT_NAME']) | |
35 | + project.info['thumbnail'] = self.config['HOST_ENDPOINT'] + "/img/thumbnail.png" | |
36 | + project.info['sched'] = "incremental" | |
37 | + project.allow_anonymous_contributors = False | |
38 | + pbclient.update_project(project) | |
39 | + | |
40 | + def create_project(self): | |
41 | + app_short_name = self.config['PYBOSSA_APP_SHORT_NAME'] | |
42 | + project = self.__find_project(app_short_name) | |
43 | + result_msg = "" | |
44 | + if (project): | |
45 | + result_msg = "The project " + app_short_name + " was already created." | |
46 | + else: | |
47 | + project = pbclient.create_project(self.config['PYBOSSA_APP_NAME'], app_short_name, self.config['PYBOSSA_APP_DESCRIPTION']) | |
48 | + if (project): | |
49 | + self.__setup_project(project) | |
50 | + result_msg = "The project " + app_short_name + " was created." | |
51 | + else: | |
52 | + result_msg = "The project " + app_short_name + " couldn't be created. Check the server log for details." | |
53 | + pyutil.log(result_msg) | |
54 | + return result_msg | |
55 | + | |
56 | + def update_project(self): | |
57 | + app_short_name = self.config['PYBOSSA_APP_SHORT_NAME'] | |
58 | + project = self.__find_project(app_short_name) | |
59 | + self.__update_project_info(project) | |
60 | + result_msg = "The project " + app_short_name + " was updated." | |
61 | + pyutil.log(result_msg) | |
62 | + return result_msg | ... | ... |
... | ... | @@ -0,0 +1,96 @@ |
1 | +@font-face { | |
2 | + font-family: 'Titillium Web'; | |
3 | + src: url('../fonts/TitilliumWeb-SemiBold.ttf') format('truetype'); | |
4 | +} | |
5 | + | |
6 | +.video-body { | |
7 | + height: 50%; | |
8 | + width: 85%; | |
9 | +} | |
10 | + | |
11 | +.video-container { | |
12 | + padding-left: 40px; | |
13 | + padding-right: 0px; | |
14 | +} | |
15 | + | |
16 | +.row { | |
17 | + margin-left: 0%; | |
18 | + margin-right: 0%; | |
19 | +} | |
20 | + | |
21 | +/* Sombras */ | |
22 | +.line-separator, .btn-default { | |
23 | + box-shadow: 2px 2px 2px rgba(215, 217, 221, 1.0); | |
24 | + -webkit-box-shadow: 2px 2px 2px rgba(215, 217, 221, 1.0); | |
25 | + -moz-box-shadow: 2px 2px 2px rgba(215, 217, 221, 1.0); | |
26 | +} | |
27 | + | |
28 | +/* Fontes */ | |
29 | +.btn-default, .finish-task-button, h1, | |
30 | + h2, h3, h4, h5, h6 { | |
31 | + font-family: 'Titillium Web', sans-serif; | |
32 | +} | |
33 | + | |
34 | +/* Header */ | |
35 | +#validador-header { | |
36 | + padding: 1px; | |
37 | + background: rgba(255, 255, 255, 1.0); | |
38 | +} | |
39 | + | |
40 | +/* Body */ | |
41 | +.body-container { | |
42 | + background: rgba(236, 238, 242, 1.0); | |
43 | + padding-bottom: 10px; | |
44 | +} | |
45 | + | |
46 | +/* Linha */ | |
47 | +.line-separator { | |
48 | + height: 2px; | |
49 | + width: 100%; | |
50 | + background-color: rgba(145, 200, 206, 1.0); | |
51 | +} | |
52 | + | |
53 | +/* Texto */ | |
54 | +h1, h2, h3, h4, h5, h6 { | |
55 | + color: rgba(144, 164, 174, 1.0); | |
56 | +} | |
57 | + | |
58 | +h6 { | |
59 | + font-size: 20px; | |
60 | +} | |
61 | + | |
62 | +.btn-default { | |
63 | + background-color: rgba(94, 199, 189, 1.0); | |
64 | +} | |
65 | + | |
66 | +.btn-default { | |
67 | + color: rgba(255, 255, 255, 1.0); | |
68 | +} | |
69 | + | |
70 | +.icon { | |
71 | + width: 50px; | |
72 | + height: 50px; | |
73 | +} | |
74 | + | |
75 | +#finish-task-container { | |
76 | + padding-top: 40px; | |
77 | + padding-right: 40px; | |
78 | +} | |
79 | + | |
80 | +.finish-task-button { | |
81 | + float: right; | |
82 | + padding-bottom: 0px; | |
83 | + padding-left: 25px; | |
84 | + color: rgba(94, 199, 189, 1.0); | |
85 | +} | |
86 | + | |
87 | +.enabled-button:hover { | |
88 | + cursor: pointer; | |
89 | + filter: alpha(opacity = 50); | |
90 | + opacity: 0.5; | |
91 | +} | |
92 | + | |
93 | +.disabled-button { | |
94 | + filter: alpha(opacity = 50); | |
95 | + opacity: 0.5; | |
96 | +} | ... | ... |
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
... | ... | @@ -0,0 +1,17 @@ |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |
3 | +<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="100px" height="100px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" | |
4 | +viewBox="0 0 100 100" | |
5 | + xmlns:xlink="http://www.w3.org/1999/xlink"> | |
6 | + <defs> | |
7 | + <style type="text/css"> | |
8 | + <![CDATA[ | |
9 | + .fil0 {fill:#5EC7BD;fill-rule:nonzero} | |
10 | + ]]> | |
11 | + </style> | |
12 | + </defs> | |
13 | + <g id="finish"> | |
14 | + <metadata id="finish"/> | |
15 | + <path class="fil0" d="M44 79c-4,4 -10,4 -13,0l-20 -20c-2,-2 -3,-4 -3,-6 0,-3 1,-5 3,-7 3,-3 9,-3 13,0l12 12c0,1 2,1 3,0l37 -37c2,-2 5,-3 7,-3l0 0c2,0 5,1 6,3 2,1 3,4 3,6 0,3 -1,5 -3,7l-45 45z"/> | |
16 | + </g> | |
17 | +</svg> | ... | ... |
6.12 KB
... | ... | @@ -0,0 +1,17 @@ |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |
3 | +<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="100px" height="100px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" | |
4 | +viewBox="0 0 100 100" | |
5 | + xmlns:xlink="http://www.w3.org/1999/xlink"> | |
6 | + <defs> | |
7 | + <style type="text/css"> | |
8 | + <![CDATA[ | |
9 | + .fil0 {fill:#5EC7BD;fill-rule:nonzero} | |
10 | + ]]> | |
11 | + </style> | |
12 | + </defs> | |
13 | + <g id="skip"> | |
14 | + <metadata id="skip"/> | |
15 | + <path class="fil0" d="M10 24c1,-1 23,-17 45,0 8,6 12,15 13,26l22 0 -34 34 -34 -34 22 0c0,-1 1,-3 1,-4 -2,-29 -19,-26 -35,-22z"/> | |
16 | + </g> | |
17 | +</svg> | ... | ... |
34.6 KB
... | ... | @@ -0,0 +1,171 @@ |
1 | +<link rel="stylesheet" href="{{ server }}/assets/css/main.css"> | |
2 | + | |
3 | +<div class="row"> | |
4 | + <div id="success" class="alert alert-success" style="display: none;"> | |
5 | + <strong>Parabéns!</strong> <span>Tarefa concluída.</span> | |
6 | + </div> | |
7 | + <div id="finish" class="alert alert-success" style="display: none;"> | |
8 | + <strong>Parabéns!</strong> <span> Você completou todas as | |
9 | + tarefas disponíveis! </span> <br /> | |
10 | + <div class="alert-actions"> | |
11 | + <a class="btn small" href="/">Voltar</a> <a class="btn small" | |
12 | + href="/project">ou, olhar outros projetos.</a> | |
13 | + </div> | |
14 | + </div> | |
15 | +</div> | |
16 | + | |
17 | +<div id="main-container" class="container"> | |
18 | + <div id="validador-header"> | |
19 | + <h2> | |
20 | + A animação do sinal "<span class="sign-label"></span>" está correta? | |
21 | + </h2> | |
22 | + </div> | |
23 | + <div class="line-separator"></div> | |
24 | + <div id="corretor-container" class="row body-container"> | |
25 | + <div id="avatar-container" class="col-sm-6 video-container"> | |
26 | + <div class="row"> | |
27 | + <h6> | |
28 | + ANIMAÇÃO "<span class="sign-label"></span>": | |
29 | + </h6> | |
30 | + </div> | |
31 | + <div class="row"> | |
32 | + <video id="avatar-video" src="" preload="metadata" | |
33 | + class="video-body" autoplay loop controls> | |
34 | + <source type="video/webm"> | |
35 | + </video> | |
36 | + </div> | |
37 | + </div> | |
38 | + <div id="ref-container" class="col-sm-6 video-container"> | |
39 | + <div class="row"> | |
40 | + <h6> | |
41 | + VÍDEO DE REFERÊNCIA “<span class="sign-label"></span>”: | |
42 | + </h6> | |
43 | + </div> | |
44 | + <div class="row"> | |
45 | + <video id="ref-video" src="" preload="metadata" class="video-body" | |
46 | + autoplay loop controls> | |
47 | + <source type="video/webm"> | |
48 | + </video> | |
49 | + </div> | |
50 | + <div id="finish-task-container" class="row"> | |
51 | + <div id="finish-button" class="finish-task-button enabled-button"> | |
52 | + <span id="finish-button-text">SIM</span><img class="icon" | |
53 | + src="{{ server }}/img/finish.svg"></img> | |
54 | + </div> | |
55 | + <div id="no-button" class="finish-task-button enabled-button" | |
56 | + data-toggle="modal" data-target="#feedback-modal"> | |
57 | + NÃO<img class="icon" src="{{ server }}/img/no.png"></img> | |
58 | + </div> | |
59 | + <div id="skip-button" class="finish-task-button enabled-button"> | |
60 | + PULAR<img class="icon" src="{{ server }}/img/skip.svg"></img> | |
61 | + </div> | |
62 | + </div> | |
63 | + </div> | |
64 | + <div id="feedback-modal" class="modal fade" tabindex="-1" | |
65 | + role="dialog" aria-labelledby="myModalLabel"> | |
66 | + <div class="modal-dialog" role="document"> | |
67 | + <div class="modal-content"> | |
68 | + <div class="modal-header"> | |
69 | + <button type="button" class="close" data-dismiss="modal" | |
70 | + aria-label="FECHAR"> | |
71 | + <span aria-hidden="true">×</span> | |
72 | + </button> | |
73 | + <h5 class="modal-title" id="myModalLabel">Feedback da | |
74 | + avaliação</h5> | |
75 | + </div> | |
76 | + <div class="modal-body"> | |
77 | + <h6 style="margin-top: 0px;">O que precisa ser melhorado?</h6> | |
78 | + <div class="radio"> | |
79 | + <input type="radio" name="optradio"> A animação do | |
80 | + avatar. | |
81 | + </div> | |
82 | + <div class="radio"> | |
83 | + <input type="radio" name="optradio">O vídeo de | |
84 | + referência. | |
85 | + </div> | |
86 | + </div> | |
87 | + <div class="modal-footer"> | |
88 | + <button type="button" class="btn btn-default" data-dismiss="modal">FECHAR</button> | |
89 | + <button id="no-finish-button" type="button" | |
90 | + class="btn btn-default disabled" data-dismiss="modal">FINALIZAR</button> | |
91 | + </div> | |
92 | + </div> | |
93 | + </div> | |
94 | + </div> | |
95 | + </div> | |
96 | +</div> | |
97 | + | |
98 | +<script type="text/javascript"> | |
99 | + var base_url = "{{ server }}/videos/"; | |
100 | + var current_task_id = -1; | |
101 | + | |
102 | + function setupButtons(task, deferred) { | |
103 | + $("#finish-button").off("click").on("click", function() { | |
104 | + console.log($(this).text().trim() == "SIM"); | |
105 | + saveAnswer(task, deferred, "APPROVED"); | |
106 | + }); | |
107 | + $("#skip-button").off("click").on("click", function() { | |
108 | + saveAnswer(task, deferred, "SKIPPED"); | |
109 | + }); | |
110 | + $("#no-finish-button").off("click").on("click", function() { | |
111 | + saveAnswer(task, deferred, "DISAPPROVED"); | |
112 | + }); | |
113 | + $("#no-finish-button").addClass("disabled"); | |
114 | + $("#feedback-modal input[name='optradio']").prop("checked", false); | |
115 | + $("#feedback-modal input[name='optradio']").off("click").on("click", | |
116 | + function() { | |
117 | + $("#no-finish-button").removeClass("disabled"); | |
118 | + }); | |
119 | + } | |
120 | + | |
121 | + function createAnswer(task, status) { | |
122 | + var answer = { | |
123 | + "status" : status, | |
124 | + "number_of_approval" : 0 | |
125 | + }; | |
126 | + var last_answer = task.info.last_answer; | |
127 | + var hasLastAnswer = typeof last_answer != "undefined"; | |
128 | + if (hasLastAnswer) { | |
129 | + answer = last_answer; | |
130 | + } | |
131 | + if (status == "APPROVED") { | |
132 | + answer["number_of_approval"] = answer.number_of_approval + 1; | |
133 | + } | |
134 | + return answer; | |
135 | + } | |
136 | + | |
137 | + function saveAnswer(task, deferred, status) { | |
138 | + var answer = createAnswer(task, status); | |
139 | + pybossa.saveTask(task.id, answer).done(function() { | |
140 | + $("#success").fadeIn(500); | |
141 | + $("#main-container").hide(); | |
142 | + setTimeout(function() { | |
143 | + deferred.resolve(); | |
144 | + }, 2000); | |
145 | + }); | |
146 | + } | |
147 | + | |
148 | + function loadTaskInfo(task) { | |
149 | + current_task_id = task.id; | |
150 | + var sign_name = task.info.sign_name; | |
151 | + var avatar_vid_link = base_url + sign_name + "_AVATAR.webm"; | |
152 | + var ref_vid_link = base_url + sign_name + "_REF.webm"; | |
153 | + $(".sign-label").text(sign_name); | |
154 | + $("#avatar-video").attr("src", avatar_vid_link); | |
155 | + $("#ref-video").attr("src", ref_vid_link); | |
156 | + } | |
157 | + | |
158 | + pybossa.presentTask(function(task, deferred) { | |
159 | + if (!$.isEmptyObject(task) && current_task_id != task.id) { | |
160 | + loadTaskInfo(task); | |
161 | + setupButtons(task, deferred); | |
162 | + $("#success").hide(); | |
163 | + $("#main-container").fadeIn(500); | |
164 | + } else { | |
165 | + $("#main-container").hide(); | |
166 | + $("#finish").fadeIn(500); | |
167 | + } | |
168 | + }); | |
169 | + | |
170 | + pybossa.run('{{ app_shortname }}'); | |
171 | +</script> | ... | ... |
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type