tg-prepare 1.1.0__py3-none-any.whl → 2.1.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tg-prepare might be problematic. Click here for more details.

Files changed (70) hide show
  1. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/METADATA +3 -3
  2. tg_prepare-2.1.0b2.dist-info/RECORD +78 -0
  3. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/WHEEL +1 -1
  4. tg_prepare-2.1.0b2.dist-info/projects/.secret_key +1 -0
  5. tgp_backend/__init__.py +3 -4
  6. tgp_backend/config.py +31 -0
  7. tgp_backend/directories.py +6 -8
  8. tgp_backend/nextcloud.py +40 -19
  9. tgp_backend/project.py +172 -45
  10. tgp_backend/session_manager.py +47 -0
  11. tgp_backend/util.py +73 -25
  12. tgp_ui/app.py +43 -335
  13. tgp_ui/routes/__init__.py +0 -0
  14. tgp_ui/routes/collection.py +272 -0
  15. tgp_ui/routes/data.py +228 -0
  16. tgp_ui/routes/project.py +102 -0
  17. tgp_ui/routes/publication.py +129 -0
  18. tgp_ui/routes/tabs.py +34 -0
  19. tgp_ui/routes/views.py +62 -0
  20. tgp_ui/static/css/bootstrap.min.css.map +1 -0
  21. tgp_ui/static/css/navbar.css +92 -0
  22. tgp_ui/static/img/favicon.ico +0 -0
  23. tgp_ui/static/img/textgrid-logo.svg +1 -0
  24. tgp_ui/static/js/collectionManager.js +60 -0
  25. tgp_ui/static/js/fileManager.js +186 -0
  26. tgp_ui/static/js/main.js +32 -485
  27. tgp_ui/static/js/modalManager.js +105 -0
  28. tgp_ui/static/js/navbarManager.js +151 -0
  29. tgp_ui/static/js/projectManager.js +60 -0
  30. tgp_ui/static/js/require.js +5 -0
  31. tgp_ui/static/js/sidebarManager.js +32 -0
  32. tgp_ui/static/js/tabManager.js +79 -0
  33. tgp_ui/templates/details/empty_container.html +16 -0
  34. tgp_ui/templates/details/manage_collection.html +205 -0
  35. tgp_ui/templates/includes/set_session_id_form.html +16 -0
  36. tgp_ui/templates/includes/upload_form.html +131 -0
  37. tgp_ui/templates/layout.html +9 -48
  38. tgp_ui/templates/macros.html +79 -72
  39. tgp_ui/templates/modal/delete_project.html +25 -0
  40. tgp_ui/templates/modal/empty_container.html +9 -0
  41. tgp_ui/templates/modal/file_explorer_content.html +34 -0
  42. tgp_ui/templates/modal/file_explorer_main.html +22 -0
  43. tgp_ui/templates/modal/file_explorer_nextcloud.html +27 -0
  44. tgp_ui/templates/modal/github_modal.html +29 -0
  45. tgp_ui/templates/modal/nextcloud_login.html +48 -0
  46. tgp_ui/templates/modal/tei_explorer.html +58 -0
  47. tgp_ui/templates/modal/xpath_parser.html +52 -0
  48. tgp_ui/templates/project_main.html +36 -0
  49. tgp_ui/templates/project_navbar.html +81 -0
  50. tgp_ui/templates/{projects.html → projects_main.html} +13 -28
  51. tgp_ui/templates/tab_final_upload.html +29 -0
  52. tgp_ui/templates/tabs/check_result.html +90 -0
  53. tgp_ui/templates/tabs/edit_project.html +113 -0
  54. tgp_ui/templates/tabs/empty_container.html +12 -0
  55. tgp_ui/templates/tabs/import_data.html +138 -0
  56. tgp_ui/templates/tabs/manage_collections.html +88 -0
  57. tgp_ui/templates/tabs/select_directories.html +41 -0
  58. tgp_ui/templates/tabs/upload.html +42 -0
  59. tgp_ui/templates/tabs/validate_metadata.html +227 -0
  60. tg_prepare-1.1.0.dist-info/RECORD +0 -39
  61. tgp_ui/templates/collection.html +0 -194
  62. tgp_ui/templates/file_upload.html +0 -24
  63. tgp_ui/templates/nxc_file_tree.html +0 -33
  64. tgp_ui/templates/project.html +0 -26
  65. tgp_ui/templates/storage.html +0 -49
  66. tgp_ui/templates/tei_explorer.html +0 -48
  67. tgp_ui/templates/xpath_parser_modal_content.html +0 -37
  68. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/entry_points.txt +0 -0
  69. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/licenses/LICENSE +0 -0
  70. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2023-2025 TU-Dresden (ZIH)
3
+ # ralf.klammer@tu-dresden.de
4
+ # moritz.wilhelm@tu-dresden.de
5
+
6
+ import logging
7
+
8
+ log = logging.getLogger(__name__)
9
+
10
+
11
+ class SessionManager:
12
+ def __init__(self, session):
13
+ self.session = session
14
+
15
+
16
+ class SessionManagerNextcloud(SessionManager):
17
+
18
+ def save_credentials(self, form_data):
19
+ log.info("Saving credentials to session")
20
+ self.session["nextcloud"] = {
21
+ "username": form_data.get("nextcloud_user"),
22
+ "password": form_data.get("nextcloud_password"),
23
+ "url": form_data.get("nextcloud_url"),
24
+ "folder": form_data.get("nextcloud_folder", ""),
25
+ }
26
+
27
+ def get_credentials(self):
28
+ log.info("Retrieving credentials from session")
29
+ return self.session.get("nextcloud", {})
30
+
31
+ def delete_nextcloud_credentials(self):
32
+ log.info("Deleting credentials from session")
33
+ self.session.pop("nextcloud", None)
34
+
35
+ def request_has_valid_credentials(self, request):
36
+ """
37
+ Check if the request contains valid Nextcloud credentials.
38
+ """
39
+ relevant_form_keys = [
40
+ "nextcloud_url",
41
+ "nextcloud_user",
42
+ "nextcloud_password",
43
+ ]
44
+ relevant_form_values = [
45
+ request.form.get(key) for key in relevant_form_keys
46
+ ]
47
+ return all(relevant_form_values)
tgp_backend/util.py CHANGED
@@ -6,27 +6,21 @@ import logging
6
6
  import os
7
7
  import re
8
8
 
9
- from configparser import ConfigParser
9
+ from collections import defaultdict
10
+
11
+ from .config import get_config_value
10
12
 
11
13
  log = logging.getLogger(__name__)
12
14
 
13
15
 
14
- def config(section, parameter, default=None):
15
- _config = ConfigParser()
16
- _config.read("config.ini")
17
-
18
- if section not in _config:
19
- log.warn("Section: %s not in *.ini -> using default" % section)
20
- return default
21
- config_val = _config[section].get(parameter)
22
- if not config_val:
23
- log.info(
24
- "Parameter: %s not in section: (%s) of *.ini -> using default: %s"
25
- % (parameter, section, default)
26
- )
27
- return default
28
- else:
29
- return config_val
16
+ def config(*args, **kwargs):
17
+ log.warning(
18
+ """
19
+ Using deprecated config function.
20
+ Please use tgp_backend.config.get_config_value instead.
21
+ """
22
+ )
23
+ return get_config_value(*args, **kwargs)
30
24
 
31
25
 
32
26
  def cli_startup(log_level=logging.INFO, log_file=None):
@@ -48,7 +42,9 @@ def get_file_extension(fname):
48
42
  return ""
49
43
 
50
44
 
51
- def list_files_and_folders(path):
45
+ def list_files_and_folders(path, get_selectable=False):
46
+
47
+ selectable_folders = []
52
48
 
53
49
  def recursive_list(dir_path, depth=0):
54
50
  items = []
@@ -58,22 +54,41 @@ def list_files_and_folders(path):
58
54
 
59
55
  if entry.is_dir():
60
56
  children = recursive_list(entry.path, depth=depth + 1)
57
+ contains_xml = any(
58
+ f.get("name", "").endswith(".xml") for f in children
59
+ )
60
+ item = {
61
+ "type": "folder",
62
+ "name": entry.name,
63
+ "depth": depth,
64
+ "path": entry.path,
65
+ "contains_xml": contains_xml,
66
+ "children": {"count": len(children), "list": children},
67
+ }
68
+ items.append(item)
69
+ if contains_xml:
70
+ selectable_folders.append(item)
71
+ else:
61
72
  items.append(
62
73
  {
63
- "type": "folder",
74
+ "type": "file",
64
75
  "name": entry.name,
65
76
  "depth": depth,
66
77
  "path": entry.path,
67
- "children": {"count": len(children), "list": children},
68
78
  }
69
79
  )
70
- else:
71
- items.append(
72
- {"type": "file", "name": entry.name, "depth": depth}
73
- )
74
80
  return items
75
81
 
76
- return recursive_list(path)
82
+ result = recursive_list(path)
83
+ if get_selectable:
84
+ return selectable_folders
85
+ else:
86
+ return result
87
+
88
+
89
+ def get_selectable_folders(path):
90
+
91
+ return list_files_and_folders(path, get_selectable=True)
77
92
 
78
93
 
79
94
  def remove_empty_strings_from_dict(d):
@@ -81,3 +96,36 @@ def remove_empty_strings_from_dict(d):
81
96
  if d[key] == "":
82
97
  d[key] = None
83
98
  return d
99
+
100
+
101
+ def parse_request_data(request, attrib_prefix):
102
+ """
103
+ Processes form data and creates a list of dictionaries
104
+ for the specified attributes.
105
+ """
106
+ grouped_data = defaultdict(lambda: defaultdict(list))
107
+
108
+ # Group data based on prefix
109
+ for key in request.form.keys():
110
+ if key.startswith(attrib_prefix):
111
+ try:
112
+ _, field, data_type = key.split("-")
113
+ grouped_data[field][data_type] = request.form.getlist(key)
114
+ except ValueError:
115
+ log.warning(
116
+ f"Invalid key format: {key}. Expected format: '{attrib_prefix}-field-data_type'."
117
+ )
118
+ continue # Skip invalid keys
119
+
120
+ # Transform grouped data into desired structure
121
+ max_length = max(len(data["xpath"]) for data in grouped_data.values())
122
+ return [
123
+ {
124
+ field: {
125
+ "xpath": data["xpath"][i],
126
+ "value": data["value"][i],
127
+ }
128
+ for field, data in grouped_data.items()
129
+ }
130
+ for i in range(max_length)
131
+ ]
tgp_ui/app.py CHANGED
@@ -7,22 +7,22 @@ import logging
7
7
 
8
8
  import click # type: ignore
9
9
  import os
10
- import shutil
11
10
 
12
- from json import loads
13
- from flask import Flask, render_template, request, redirect, session # type: ignore
14
- from flask import url_for as default_url_for # type: ignore
15
- from flask_json import json_response, FlaskJSON # type: ignore
11
+ from flask import Flask, render_template, session # type: ignore
12
+ from flask_json import FlaskJSON # type: ignore
16
13
 
17
- from tgp_backend.directories import generateList
18
- from tgp_backend.project import Project, TGProject
14
+ from tgp_backend.project import Project
19
15
 
20
16
  from tgp_backend.auth import SecretKeyManager
21
17
  from tgp_backend.nextcloud import Nextcloud
22
- from tgp_backend.util import config
23
- from tgp_backend.util import remove_empty_strings_from_dict
18
+ from tgp_backend.config import LOG_LEVEL, MAIN_PATH, get_config_value
24
19
 
25
- from tg_model.tei import TEIParser # type: ignore
20
+ from .routes.project import project_routes
21
+ from .routes.views import main_views
22
+ from .routes.data import data_routes
23
+ from .routes.tabs import tab_manager
24
+ from .routes.collection import collection_routes
25
+ from .routes.publication import publication_routes
26
26
 
27
27
  log = logging.getLogger(__name__)
28
28
 
@@ -30,44 +30,38 @@ base_params = {
30
30
  "title": "TG Prepare",
31
31
  }
32
32
 
33
- MAIN_PATH = config("main", "path", default="./projects")
34
-
35
33
  app = Flask(__name__)
36
34
  FlaskJSON(app)
37
35
 
38
-
39
36
  secret_manager = SecretKeyManager(MAIN_PATH)
40
37
  app.secret_key = secret_manager.secret_key
41
38
 
42
39
  # Additional security settings, if not in DEBUG mode
43
- app.config.update(SESSION_COOKIE_NAME="tgp_nextcloud_session")
44
- if config("log", "level", default="DEBUG") != "DEBUG":
40
+ app.config.update(SESSION_COOKIE_NAME="tgp_session")
41
+ if LOG_LEVEL != "DEBUG":
45
42
  app.config.update(
46
43
  SESSION_COOKIE_SECURE=True, # Only allow cookies over HTTPS
47
44
  SESSION_COOKIE_HTTPONLY=True, # Prevent JavaScript access to cookies
48
45
  SESSION_COOKIE_SAMESITE="Strict", # Protect against CSRF attacks
49
46
  )
50
47
 
51
- app.jinja_env.globals.update(len=len, round=round)
52
-
53
-
54
- # Function to retrieve the prefix from headers, used for reverse proxy setups
55
- def get_prefix():
56
- return request.headers.get(
57
- "X-Forwarded-Prefix", request.headers.get("X-Script-Name", "")
58
- )
59
-
60
48
 
61
- # Custom implementation of Flask's url_for to include the prefix
62
- def url_for(*args, **kwargs):
63
- """Overrides Flask's url_for globally to include the prefix"""
64
- return get_prefix() + default_url_for(*args, **kwargs)
49
+ app.register_blueprint(main_views)
50
+ app.register_blueprint(project_routes)
51
+ app.register_blueprint(data_routes)
52
+ app.register_blueprint(tab_manager)
53
+ app.register_blueprint(collection_routes)
54
+ app.register_blueprint(publication_routes)
65
55
 
66
56
 
67
- # Context processor to inject the custom url_for into the Jinja2 templates
68
- @app.context_processor
69
- def inject_url_for():
70
- return dict(url_for=url_for)
57
+ def get_textgrid_login_url(instance):
58
+ """
59
+ Returns the TextGrid login URL based on the instance (test or production).
60
+ """
61
+ if instance == "test":
62
+ return "https://test.textgridlab.org/1.0/Shibboleth.sso/Login?target=/1.0/secure/TextGrid-WebAuth.php?authZinstance=test.textgridlab.org"
63
+ else:
64
+ return "https://textgridlab.org/1.0/Shibboleth.sso/Login?target=/1.0/secure/TextGrid-WebAuth.php?authZinstance=textgrid-esx2.gwdg.de"
71
65
 
72
66
 
73
67
  def get_projects():
@@ -79,7 +73,13 @@ def get_projects():
79
73
  return projects
80
74
 
81
75
 
82
- app.jinja_env.globals.update(title="TG Prepare", get_projects=get_projects)
76
+ app.jinja_env.globals.update(
77
+ len=len,
78
+ round=round,
79
+ title="TG Prepare",
80
+ get_projects=get_projects,
81
+ get_textgrid_login_url=get_textgrid_login_url,
82
+ )
83
83
 
84
84
 
85
85
  def _startup():
@@ -90,9 +90,9 @@ def _startup():
90
90
 
91
91
  logging.getLogger("zeep").setLevel(logging.INFO)
92
92
  app.run(
93
- host=config("main", "host", default="0.0.0.0"),
94
- port=config("main", "port", default=8077),
95
- debug=config("log", "level", default="DEBUG") == "DEBUG",
93
+ host=get_config_value("main", "host", default="0.0.0.0"),
94
+ port=get_config_value("main", "port", default=8077),
95
+ debug=get_config_value("log", "level", default="DEBUG") == "DEBUG",
96
96
  )
97
97
 
98
98
 
@@ -103,185 +103,19 @@ def startup(path):
103
103
  _startup()
104
104
 
105
105
 
106
- # *****************
107
- # VIEWS
108
- # *****************
109
- @app.route(
110
- "/xpath_parser_modal/<string:projectname>/<string:title>",
111
- methods=["GET", "POST"],
112
- )
113
- def xpath_parser_modal(projectname=None, title=None):
114
- project = Project(projectname)
115
- collection = project.get_collection(title)
116
- # collection_config = collection["config"]
117
- collection_parser = collection["parser"]
118
-
119
- return render_template(
120
- "xpath_parser_modal_content.html",
121
- # collection=collection_config,
122
- collection_parser=collection_parser,
123
- )
124
-
125
-
126
- @app.route("/new_project", methods=["POST"])
127
- def new_project():
128
- project = Project(request.form.get("projectname"))
129
- project.create()
130
- return redirect(url_for("project", projectname=project.name))
131
-
132
-
133
- @app.route("/upload_files/<string:projectname>", methods=["POST"])
134
- def upload_files(projectname=None):
135
- Project(projectname).file_upload(request.files.getlist("files"))
136
-
137
- return redirect(url_for("project", projectname=projectname))
138
-
139
-
140
- @app.route(
141
- "/collection/<string:projectname>/<string:name>", methods=["GET", "POST"]
142
- )
143
- def collection(projectname, name):
144
- project = Project(projectname)
145
- collection = project.get_collection(name)
146
- return render_template(
147
- "collection.html",
148
- project=project,
149
- collection_title=name,
150
- collection=collection["config"],
151
- )
152
-
153
-
154
- @app.route("/publication/<string:projectname>", methods=["GET", "POST"])
155
- def publication(projectname):
156
- project = Project(projectname)
157
- return render_template(
158
- "publication.html",
159
- project=project,
160
- )
161
-
162
-
163
- @app.route("/project/<string:projectname>", methods=["GET", "POST"])
164
- def project(projectname=None):
165
- params = {
166
- "sub_title": "Project: %s" % projectname,
167
- "sub_description": "",
168
- }
169
- params.update(base_params)
170
-
171
- return render_template(
172
- "project.html",
173
- user=session.get("user", "-"),
174
- current_project=projectname,
175
- project=Project(projectname),
176
- tab=request.args.get("tab"),
177
- **params,
178
- )
179
-
180
-
181
- @app.route("/", methods=["GET"])
182
- @app.route("/project", methods=["GET", "POST"])
183
- @app.route("/projects", methods=["GET", "POST"])
184
- def projects():
185
- params = {
186
- "sub_title": "Projects",
187
- "sub_description": "",
188
- }
189
- params.update(base_params)
190
-
191
- projectname = request.form.get("projectname")
192
- fullpath = f"{MAIN_PATH}/{projectname}"
193
-
194
- if request.method == "POST":
195
- if request.form.get("delete"):
196
- # Delete the project
197
- if fullpath.strip("/") == MAIN_PATH.strip("/"):
198
- log.error(f"Cannot delete main path ({MAIN_PATH})!")
199
- elif os.path.exists(fullpath):
200
- shutil.rmtree(fullpath)
201
- else:
202
- log.warning("Project does not exist!")
203
-
204
- # Get list of all existing projects/directories
205
- projects = []
206
- for sub in os.listdir(MAIN_PATH):
207
- projectpath = "%s/%s" % (MAIN_PATH, sub)
208
- if os.path.isdir(projectpath):
209
- projects.append(Project(sub))
210
- # projects.append({"name": sub, "fullpath": projectpath})
211
-
212
- return render_template("projects.html", projects=projects, **params)
213
-
214
-
215
- @app.route(
216
- "/tei_explorer/<string:projectname>/<string:title>", methods=["GET"]
217
- )
218
- def tei_explorer(projectname, title):
106
+ # Step 9
107
+ @app.route("/tab-final-upload/<string:projectname>", methods=["GET"])
108
+ def tab_final_upload(projectname):
109
+ # Erstelle das Project-Objekt
219
110
  project = Project(projectname)
220
- dir_list_dict, file_list_dict = generateList(
221
- project.get_subproject_inpath(title)
222
- )
223
111
 
112
+ # Übergib das Project-Objekt an das Template
224
113
  return render_template(
225
- "tei_explorer.html",
226
- dir_list=dir_list_dict,
227
- file_list=file_list_dict,
228
- collection_title=title,
229
- project=project,
114
+ "tab_final_upload.html",
115
+ project=project, # Das Project-Objekt wird hier übergeben
230
116
  )
231
117
 
232
118
 
233
- # *****************
234
- # JSON-REQUESTS
235
- # *****************
236
- @app.route("/load_tei_content", methods=["GET"])
237
- def load_tei_content():
238
- path = request.args.get("path")
239
- log.debug("load_tei_content path: %s" % path)
240
- _type = request.args.get("type")
241
- if path is not None:
242
- tei_parser = TEIParser(fullpath=path)
243
- if _type == "header":
244
- return json_response(
245
- value="OK",
246
- content=tei_parser.find(
247
- "//teiHeader", node_as_text=True
248
- ).decode("utf-8"),
249
- )
250
- elif _type == "text":
251
- return json_response(
252
- value="OK",
253
- content=tei_parser.find(".//text", node_as_text=True).decode(
254
- "utf-8"
255
- ),
256
- )
257
- return json_response(value="Unknown type requested!")
258
-
259
-
260
- @app.route(
261
- "/set_configs/<string:projectname>/<string:title>", methods=["POST"]
262
- )
263
- def save_collection(projectname, title):
264
- project = Project(projectname)
265
- collection = project.get_collection(title)
266
- collection_config = collection["config"]
267
- for _attrib in request.form:
268
- attrib = _attrib.replace("[]", "")
269
- if attrib in collection_config.multi_attribs:
270
- value = [
271
- remove_empty_strings_from_dict(loads(v))
272
- for v in request.form.getlist(_attrib)
273
- ]
274
- elif attrib in collection_config.xpath_or_value_attribs:
275
- value = remove_empty_strings_from_dict(
276
- loads(request.form.get(attrib))
277
- )
278
- else:
279
- value = request.form.get(attrib)
280
- setattr(collection_config, attrib, value)
281
- collection_config.save()
282
- return json_response(response="OK")
283
-
284
-
285
119
  @app.route("/nextcloud_tab/", methods=["POST"])
286
120
  def nextcloud_tab():
287
121
  nextcloud = Nextcloud(**session)
@@ -292,131 +126,5 @@ def nextcloud_tab():
292
126
  )
293
127
 
294
128
 
295
- @app.route("/nextcloud_login/", methods=["POST"])
296
- def nextcloud_login():
297
-
298
- data = request.get_json()
299
- login_data = data.get("data", [])
300
-
301
- if Nextcloud(**login_data).test_connection():
302
- for key in login_data:
303
- session[key] = login_data[key]
304
-
305
- return json_response(login_succes=True)
306
-
307
-
308
- @app.route("/nextcloud_logout", methods=["POST"])
309
- def nextcloud_logout():
310
- session.clear()
311
- return json_response(response="OK")
312
-
313
-
314
- @app.route("/nextcloud_download", methods=["POST"])
315
- def nextcloud_download():
316
- data = request.get_json()
317
- projectname = data.get("projectname")
318
- file_paths = data.get("file_paths", [])
319
- nxt = Nextcloud(**session)
320
- nxt.download_nxc_files(file_paths, projectname)
321
-
322
- return json_response(response="OK")
323
-
324
-
325
- @app.route("/clone_git_project/<string:projectname>", methods=["POST"])
326
- def clone_git_project(projectname=None):
327
- Project(projectname).clone_git_project(request.form.get("github_repo"))
328
-
329
- return json_response(response="OK")
330
-
331
-
332
- @app.route(
333
- "/check_xpath/<string:projectname>/<string:collectionname>",
334
- methods=["GET"],
335
- )
336
- def check_xpath(projectname, collectionname):
337
- project = Project(projectname)
338
- collection = project.get_collection(collectionname)
339
- collection_config = collection["config"]
340
-
341
- xpath = request.args.get("xpath")
342
-
343
- results = []
344
-
345
- for file in collection_config.elements:
346
- tei_parser = TEIParser(fullpath=file["fullpath"])
347
- result = tei_parser.find(xpath)
348
- if result is not None:
349
- results.append({"filename": file["filename"], "result": result})
350
-
351
- return json_response(value="OK", results=results)
352
-
353
-
354
- @app.route("/set_configs/<string:projectname>", methods=["POST"])
355
- def set_configs(projectname):
356
- Project(projectname).init_configs(request.form.getlist("tei_directories"))
357
-
358
- return json_response(response="OK")
359
-
360
-
361
- @app.route(
362
- "/publish_project/<string:projectname>/<string:instance>", methods=["POST"]
363
- )
364
- def publish_project(projectname, instance):
365
- TGProject(projectname, instance).publish_tg_project()
366
- return json_response(response="OK")
367
-
368
-
369
- @app.route(
370
- "/save_session_id/<string:projectname>/<string:instance>", methods=["POST"]
371
- )
372
- def save_session_id(projectname, instance):
373
- TGProject(projectname, instance).tg_session_id = request.form.get(
374
- "tg_auth_session_id"
375
- )
376
-
377
- return json_response(response="OK")
378
-
379
-
380
- @app.route(
381
- "/save_tg_project_id/<string:projectname>/<string:instance>",
382
- methods=["POST"],
383
- )
384
- def save_tg_project_id(projectname, instance):
385
- TGProject(projectname, instance).tg_project_id = request.form.get(
386
- "tg_project_id"
387
- )
388
- return json_response(response="OK")
389
-
390
-
391
- @app.route(
392
- "/delete_tg_project_id/<string:projectname>/<string:instance>/<string:tg_project_id>",
393
- methods=["POST"],
394
- )
395
- def delete_tg_project_id(projectname, instance, tg_project_id):
396
- TGProject(projectname, instance).delete_tg_project(tg_project_id)
397
-
398
- return json_response(response="OK")
399
-
400
-
401
- @app.route(
402
- "/get_tg_project_hits/<string:projectname>/<string:instance>/<string:tg_project_id>",
403
- methods=["GET"],
404
- )
405
- def get_tg_project_hits(projectname, instance, tg_project_id):
406
- hits = TGProject(projectname, instance).get_tg_project_hits(tg_project_id)
407
- return json_response(response="OK", hits=hits)
408
-
409
-
410
- @app.route(
411
- "/create_tg_project/<string:projectname>/<string:instance>",
412
- methods=["POST"],
413
- )
414
- def create_tg_project(projectname, instance):
415
- TGProject(projectname, instance).create_tg_project(
416
- request.form.get("tg_projectname")
417
- )
418
- return json_response(response="OK")
419
-
420
-
421
129
  if __name__ == "__main__":
422
130
  startup()
File without changes