ecmind-blue-studio 1.0.0a1__tar.gz

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.
Files changed (229) hide show
  1. ecmind_blue_studio-1.0.0a1/LICENSE +21 -0
  2. ecmind_blue_studio-1.0.0a1/PKG-INFO +233 -0
  3. ecmind_blue_studio-1.0.0a1/README.md +213 -0
  4. ecmind_blue_studio-1.0.0a1/pyproject.toml +61 -0
  5. ecmind_blue_studio-1.0.0a1/pyproject.toml.orig +51 -0
  6. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/__init__.py +3 -0
  7. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/__main__.py +18 -0
  8. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/compat.py +132 -0
  9. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/config.py +60 -0
  10. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/deps.py +62 -0
  11. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/errors.py +95 -0
  12. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/i18n.py +72 -0
  13. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/locales/de.json +417 -0
  14. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/locales/en.json +417 -0
  15. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/main.py +222 -0
  16. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/__init__.py +167 -0
  17. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/ast.py +411 -0
  18. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/bindings.py +236 -0
  19. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/completion.py +1381 -0
  20. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/errors.py +177 -0
  21. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/executor.py +364 -0
  22. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/formatter.py +278 -0
  23. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/formatting.py +51 -0
  24. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/keywords.py +181 -0
  25. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/lexer.py +408 -0
  26. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/parser.py +1366 -0
  27. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/planner.py +327 -0
  28. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/resolver.py +1449 -0
  29. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/security.py +792 -0
  30. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/snapshot.py +348 -0
  31. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/span.py +20 -0
  32. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/sql_completion.py +247 -0
  33. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/statement_templates.py +162 -0
  34. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/tokens.py +43 -0
  35. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/querylang/variables.py +140 -0
  36. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/rendering.py +53 -0
  37. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/__init__.py +0 -0
  38. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/auth.py +81 -0
  39. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/definition.py +83 -0
  40. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/files.py +124 -0
  41. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/health.py +47 -0
  42. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/icons.py +19 -0
  43. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/jobcalls.py +71 -0
  44. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/objects.py +318 -0
  45. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/pages.py +78 -0
  46. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/query.py +472 -0
  47. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/routers/settings.py +55 -0
  48. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/__init__.py +0 -0
  49. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/auth.py +84 -0
  50. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/commands.py +629 -0
  51. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/db_schema.py +79 -0
  52. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/definition_view.py +467 -0
  53. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/definitions.py +100 -0
  54. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/exports.py +211 -0
  55. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/groups.py +34 -0
  56. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/jobcalls.py +430 -0
  57. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/parent_hints.py +126 -0
  58. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/queries.py +1029 -0
  59. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/roles.py +51 -0
  60. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/security_admin.py +681 -0
  61. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/security_names.py +65 -0
  62. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/startup_checks.py +50 -0
  63. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/user_settings.py +84 -0
  64. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/services/visible_types.py +117 -0
  65. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/sessions.py +149 -0
  66. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/app.css +918 -0
  67. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/icons/favicon-blue.svg +1 -0
  68. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/icons/favicon-green.svg +1 -0
  69. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/icons/favicon-yellow.svg +1 -0
  70. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/app.js +322 -0
  71. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/attachments.js +70 -0
  72. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/definition.js +243 -0
  73. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/ecmql.js +206 -0
  74. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/editor.js +481 -0
  75. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/i18n.js +14 -0
  76. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/jobcalls.js +688 -0
  77. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/output.js +170 -0
  78. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/saved.js +124 -0
  79. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/settings.js +58 -0
  80. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/splitter.js +86 -0
  81. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/js/tabs.js +334 -0
  82. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/bootstrap/bootstrap.bundle.min.js +7 -0
  83. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  84. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  85. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-cyrillic-500-italic-Cljvy9n8.woff2 +0 -0
  86. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-cyrillic-500-italic-Cxw8XFib.woff +0 -0
  87. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
  88. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
  89. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-cyrillic-700-normal-BWTpRfYl.woff2 +0 -0
  90. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-cyrillic-700-normal-CEoEElIJ.woff +0 -0
  91. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  92. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  93. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-greek-500-italic-BOoFGiPg.woff2 +0 -0
  94. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-greek-500-italic-DNb4joLt.woff +0 -0
  95. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
  96. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
  97. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-greek-700-normal-C6CZE3T8.woff2 +0 -0
  98. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-greek-700-normal-DEigVDxa.woff +0 -0
  99. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  100. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  101. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-500-italic-BAmfUVTg.woff2 +0 -0
  102. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-500-italic-DMxVtl1n.woff +0 -0
  103. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  104. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  105. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
  106. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
  107. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  108. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  109. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-ext-500-italic-BfTxQ-NC.woff +0 -0
  110. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-ext-500-italic-gNibIUfK.woff2 +0 -0
  111. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
  112. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
  113. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-ext-700-normal-CZipNAKV.woff2 +0 -0
  114. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-latin-ext-700-normal-CxPITLHs.woff +0 -0
  115. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  116. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-vietnamese-500-italic-BPh13p40.woff2 +0 -0
  117. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-vietnamese-500-italic-BkKfFY3r.woff +0 -0
  118. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
  119. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/jetbrains-mono-vietnamese-700-normal-BDLVIk2r.woff +0 -0
  120. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-400-italic-BUPR0S1h.woff2 +0 -0
  121. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-400-italic-DGpcSWlQ.woff +0 -0
  122. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-400-normal-DvjyhnTk.woff2 +0 -0
  123. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-400-normal-XMp_Qeuo.woff +0 -0
  124. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-600-normal-BuMhxFId.woff2 +0 -0
  125. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-600-normal-C5LXWJm_.woff +0 -0
  126. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-700-normal-Db4W_Rwa.woff2 +0 -0
  127. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-700-normal-FWckWEfO.woff +0 -0
  128. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-ext-400-italic-DTxbCGjE.woff2 +0 -0
  129. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-ext-400-italic-j4MbU4yU.woff +0 -0
  130. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-ext-400-normal-B28g4zcY.woff2 +0 -0
  131. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-ext-400-normal-CtkCLoLZ.woff +0 -0
  132. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-ext-600-normal-CivhzOCV.woff2 +0 -0
  133. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-ext-600-normal-DX5V8c14.woff +0 -0
  134. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-ext-700-normal-BWp9aGB1.woff2 +0 -0
  135. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-cyrillic-ext-700-normal-hbT5P32v.woff +0 -0
  136. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-greek-400-italic-BuH7C3yF.woff +0 -0
  137. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-greek-400-italic-CilYwb5U.woff2 +0 -0
  138. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-greek-400-normal-BKm6CSmU.woff2 +0 -0
  139. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-greek-400-normal-yVf9KAAO.woff +0 -0
  140. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-greek-600-normal-CkCBI2Km.woff2 +0 -0
  141. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-greek-600-normal-Xt_394w2.woff +0 -0
  142. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-greek-700-normal-YcFp24oM.woff2 +0 -0
  143. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-greek-700-normal-bcfTBw-h.woff +0 -0
  144. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-hebrew-400-italic-CXPP0jOX.woff2 +0 -0
  145. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-hebrew-400-italic-D5O-QnBO.woff +0 -0
  146. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-hebrew-400-normal-C3uFZKNA.woff2 +0 -0
  147. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-hebrew-400-normal-Cowz_U6T.woff +0 -0
  148. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-hebrew-600-normal-CQztwT7q.woff2 +0 -0
  149. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-hebrew-600-normal-D7z6DfF6.woff +0 -0
  150. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-hebrew-700-normal-CZc_Q6SQ.woff +0 -0
  151. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-hebrew-700-normal-DnAL3HC_.woff2 +0 -0
  152. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-400-italic-BEURUQpT.woff +0 -0
  153. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-400-italic-oaOkCnEp.woff2 +0 -0
  154. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-400-normal-Bk63H6sG.woff2 +0 -0
  155. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-400-normal-DKniycaP.woff +0 -0
  156. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-600-normal-C3dWW5mx.woff +0 -0
  157. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-600-normal-Cp4N6AwT.woff2 +0 -0
  158. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-700-normal-CZCQA30i.woff +0 -0
  159. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-700-normal-CceUhp2e.woff2 +0 -0
  160. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-ext-400-italic-7zHzNkY4.woff +0 -0
  161. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-ext-400-italic-BF0ugEcP.woff2 +0 -0
  162. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-ext-400-normal-BfzJ9CTS.woff +0 -0
  163. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-ext-400-normal-URAvo6nN.woff2 +0 -0
  164. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-ext-600-normal-CXDaa6Q7.woff2 +0 -0
  165. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-ext-600-normal-YZ6Vktkr.woff +0 -0
  166. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-ext-700-normal-DatbY7Hl.woff2 +0 -0
  167. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-latin-ext-700-normal-IE4yTLg1.woff +0 -0
  168. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-math-400-italic-BsO0csMs.woff2 +0 -0
  169. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-math-400-italic-CAApjVH7.woff +0 -0
  170. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-math-400-normal-C76BUjK0.woff2 +0 -0
  171. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-math-400-normal-Cs0GbA_j.woff +0 -0
  172. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-math-600-normal-CWMKYWAo.woff +0 -0
  173. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-math-600-normal-DQ8cZjrd.woff2 +0 -0
  174. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-math-700-normal-B7X9EnEK.woff +0 -0
  175. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-math-700-normal-EYnC2qGX.woff2 +0 -0
  176. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-symbols-400-italic-0Ch9q1R9.woff2 +0 -0
  177. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-symbols-400-italic-DdEf8Kfy.woff +0 -0
  178. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-symbols-400-normal-B5VgOMNH.woff +0 -0
  179. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-symbols-400-normal-OZvd8qMe.woff2 +0 -0
  180. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-symbols-600-normal-BiWokiHG.woff +0 -0
  181. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-symbols-600-normal-DgwZOEXg.woff2 +0 -0
  182. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-symbols-700-normal-DNvDgxgv.woff +0 -0
  183. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-symbols-700-normal-DfXrtqu8.woff2 +0 -0
  184. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-vietnamese-400-italic-B-vHoAQ6.woff +0 -0
  185. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-vietnamese-400-italic-BLoWRDoa.woff2 +0 -0
  186. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-vietnamese-400-normal-DCU23d-J.woff +0 -0
  187. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-vietnamese-400-normal-Dqpvjuft.woff2 +0 -0
  188. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-vietnamese-600-normal-CVI-Ycr6.woff +0 -0
  189. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-vietnamese-600-normal-cWHhjaNO.woff2 +0 -0
  190. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-vietnamese-700-normal-BwQSBZ9d.woff +0 -0
  191. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/assets/open-sans-vietnamese-700-normal-C0rmKuKj.woff2 +0 -0
  192. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/ecmind-css/ecmind.css +2 -0
  193. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/htmx/htmx.min.js +1 -0
  194. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  195. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/monaco/vs/base/worker/workerMain.js +31 -0
  196. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/monaco/vs/editor/editor.main.css +8 -0
  197. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/monaco/vs/editor/editor.main.js +798 -0
  198. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/monaco/vs/loader.js +11 -0
  199. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/monaco/vs/nls.messages.de.js +21 -0
  200. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/phosphor/fill/Phosphor-Fill.ttf +0 -0
  201. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/phosphor/fill/Phosphor-Fill.woff +0 -0
  202. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/phosphor/fill/Phosphor-Fill.woff2 +0 -0
  203. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/phosphor/fill/style.css +4627 -0
  204. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/phosphor/regular/Phosphor.ttf +0 -0
  205. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/phosphor/regular/Phosphor.woff +0 -0
  206. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/phosphor/regular/Phosphor.woff2 +0 -0
  207. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/static/vendor/phosphor/regular/style.css +4627 -0
  208. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/app.html +286 -0
  209. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/base.html +50 -0
  210. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/login.html +32 -0
  211. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/batch_result.html +38 -0
  212. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/batch_row.html +42 -0
  213. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/batch_shell.html +18 -0
  214. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/count_result.html +20 -0
  215. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/definition.html +167 -0
  216. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/definition_field.html +101 -0
  217. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/details.html +133 -0
  218. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/dml_result.html +54 -0
  219. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/history.html +25 -0
  220. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/jobcalls.html +94 -0
  221. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/result_error.html +15 -0
  222. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/result_section.html +116 -0
  223. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/result_tabs.html +33 -0
  224. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/result_text.html +22 -0
  225. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/security_dml_result.html +42 -0
  226. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/security_result.html +74 -0
  227. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/settings_dialog.html +69 -0
  228. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/sql_result.html +33 -0
  229. ecmind_blue_studio-1.0.0a1/src/ecmind_blue_studio/templates/partials/table_field.html +29 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ECMind GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.4
2
+ Name: ecmind-blue-studio
3
+ Version: 1.0.0a1
4
+ Summary: ECMind blue Studio, admin interface for the ecmind-blue-client
5
+ Author: ECMind GmbH
6
+ Author-email: ECMind GmbH <info@ecmind.ch>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Requires-Dist: fastapi
10
+ Requires-Dist: uvicorn
11
+ Requires-Dist: jinja2
12
+ Requires-Dist: pydantic-settings
13
+ Requires-Dist: itsdangerous
14
+ Requires-Dist: python-multipart
15
+ Requires-Dist: ecmind-blue-client==1.0.0
16
+ Requires-Python: >=3.13
17
+ Project-URL: Homepage, https://ecmind.ch/
18
+ Project-URL: Repository, https://gitlab.ecmind.ch/open/ecmind_blue_studio
19
+ Description-Content-Type: text/markdown
20
+
21
+ # ECMind blue Studio
22
+
23
+ A admin interface for the DMS enaio(r) (OPTIMAL SYSTEMS GmbH), exposing the
24
+ ecmind-blue-client features.
25
+ Query folders, registers and documents with a simple query language in a Monaco
26
+ editor, inspect results and download files. Works fully offline against your
27
+ DMS infrastructure; all frontend assets are vendored.
28
+
29
+ ## Features (work in progress)
30
+
31
+ - Browser-like vertical tabs, each with a query editor and a result view
32
+ - Object definition explorer: every cabinet, type and index field with its full
33
+ configuration, a filter over all of it, prefilled statements per object type
34
+ and the native asobjdef.xml as download
35
+ - Job call monitor: the live server job stream with filters per server, job,
36
+ computer, application and user, and the full parameters of a single call with
37
+ base64 payloads decoded
38
+ - Simple query language for folders, registers and documents with subqueries,
39
+ Klausel-style conditions, code completion and diagnostics
40
+ - Security statements for users, groups, roles, membership and the rights export
41
+ - Result tables per object type with file download
42
+ - ECMind theme with Green/Yellow/Blue brands, automatic light/dark mode
43
+ - English/German localization with automatic detection
44
+
45
+ ## Requirements
46
+
47
+ - Python >= 3.13 and [uv](https://docs.astral.sh/uv/)
48
+ - A DMS application server (default: 127.0.0.1:4000)
49
+ - A technical account with the system role "Kontextwechsel" (switch context)
50
+
51
+ ## Setup
52
+
53
+ ```
54
+ uv sync
55
+ copy .env.example .env
56
+ # edit .env: servers, technical account, session secret
57
+ ```
58
+
59
+ ## Run
60
+
61
+ ```
62
+ uv run uvicorn ecmind_blue_studio.main:app --reload --host 127.0.0.1 --port 8099
63
+ ```
64
+
65
+ Then open http://127.0.0.1:8099 and log in with a DMS user.
66
+
67
+ ## Object definition
68
+
69
+ The first tab cannot be closed and shows what the DMS server knows about its
70
+ own data model: cabinets with their folders, registers and documents, the index
71
+ mask fields of every type with data type, database column and names in the
72
+ configured languages, and the complete configuration of a single field. The
73
+ filter box searches all of it at once, six buttons per object type open a
74
+ prefilled `select`, `count`, `insert`, `update`, `upsert` or `delete` statement
75
+ in a new tab, and the download button hands out the native `asobjdef.xml`.
76
+
77
+ It needs the system role "DMS: Supervisor" (18) or "Editor: Starten" (11);
78
+ without one of them the tab is not shown.
79
+
80
+ ## Job calls
81
+
82
+ The second fixed tab shows the live job stream of the configured servers, the
83
+ same feed the Enterprise Manager displays. Press Listen and every finished job
84
+ appears as one line with its timestamp, computer, user, job name, application
85
+ and file counts; a green check for success, a red warning for a failure, and
86
+ optionally a blue play line when the job starts. Filter by server, by job (a
87
+ popup over every namespace the server offers), by computer, application or user,
88
+ or reduce the stream to failures only. Clicking a line shows the call the way
89
+ the Enterprise Manager prints it, with base64 payloads decoded and XML indented.
90
+
91
+ It needs the system role "DMS: Supervisor" (18) or "Administrator: Starten" (1).
92
+ The monitor runs on the technical connection, which is why the roles are checked
93
+ on the server and not only in the browser. Job parameters are shown unmasked.
94
+
95
+ ## Query language
96
+
97
+ Each tab has a Monaco editor with completion, hover and live diagnostics for a
98
+ simple query language (see [SPECS.md](SPECS.md) section 4). Ctrl+Enter runs the
99
+ query, Shift+Alt+F formats it, Alt+N opens a tab and Alt+W closes it. Internal
100
+ field names work without brackets:
101
+
102
+ ```
103
+ select document Invoice, DeliveryNote where Status = 'open' order by InvoiceDate desc limit 100
104
+ select document Invoice in (register Correspondence where Subject = 'Dunning*') where InvoiceNo != ''
105
+ select document Invoice where Clerk = #USER# and InvoiceDate >= #DATE#-1y6m
106
+ select document Invoice columns InvoiceNo, Amount, folder.CompanyName
107
+ select document Invoice columns InvoiceNo, {OBJECT_FILESIZE}, {OBJECT_MODIFYTIME}, {OBJECT_DOCPAGECOUNT}
108
+ count document Invoice where Status = 'open'
109
+ ```
110
+
111
+ System fields (`OBJECT_ID`, `OBJECT_LINKS`, `OBJECT_FILESIZE`, `OBJECT_COUNT`,
112
+ `OBJECT_MODIFYUSER` and more, see SPECS.md) work in `where`, `order by` and
113
+ `columns`; document-only fields are rejected on folder and register queries
114
+ with a live editor marker.
115
+
116
+ The editor also flags object types the signed-in user cannot see, and completion
117
+ notes them in its list. The DMS answers a query on such a type with an empty result
118
+ and no error at all, so the hint is shown before the run. It stays a warning and
119
+ never blocks the query: a type you can see may return no rows as well.
120
+
121
+ Data statements update, create and delete objects, always with the rights of the
122
+ signed-in user:
123
+
124
+ ```
125
+ update document Invoice 4711 set Status = 'paid'
126
+ update document Invoice 4711, 4712 set Status = 'paid'
127
+ delete document Invoice 6524, 6522 purge
128
+ insert document Invoice into 55 set InvoiceNo = 'R-9' file 'scan.pdf'
129
+ upsert document Invoice into 55 set InvoiceNo = 'R-9', Amount = 12.5 search InvoiceNo
130
+ variant 4711 set Status = 'draft' file 'v2.pdf'
131
+ delete document Invoice where Status = 'void' purge
132
+ insert document Invoice into 55 set InvoiceNo = 'R-9', Positions = (Article = 'A-100', Qty = 5), (Article = 'B-200', Qty = 3)
133
+ update document Invoice 4711 set Positions = (Article = 'A-100', Qty = 7) replacetables
134
+ ```
135
+
136
+ A single `insert`, `update` or `variant` shows what it wrote: the objects are
137
+ read back from the server and rendered as a result table below the
138
+ confirmation, with the usual row actions. A large `update` (more objects than
139
+ one result page) and statement batches keep the plain confirmation, because
140
+ reading every object back costs a roundtrip each.
141
+
142
+ Table fields take a comma separated list of rows, each row a list of
143
+ `Column = value` pairs. On update and upsert the statement has to say whether
144
+ the rows replace the table (`replacetables`) or extend it (`appendtables`) -
145
+ the mode belongs to the whole statement, so replacing one table and appending
146
+ to another needs two statements. The table popup in a result row carries an
147
+ "Edit table" button that opens a new tab with exactly such a statement, filled
148
+ with the rows currently stored.
149
+
150
+ Files referenced by `file '...'` are attached to the tab with the paperclip
151
+ button; `file #BROWSE#` instead opens the file dialog every time the statement
152
+ `update` and `delete` also take a list of object ids, and every listed object
153
+ gets its own copy of the file; a failing object does not stop the others, and
154
+ the result lists what was written and what failed. On an id based update the
155
+ `set` clause is optional, so
156
+ `update document Invoice 6523 file 'scan.pdf'` replaces only the file and
157
+ `update document Invoice 6523 file #NULL#` only removes it. Prefilled
158
+ document statements (edit button, object definition page) end with
159
+ `file #BROWSE#` as a reminder; delete the line for metadata-only changes.
160
+ File content can also be written inline, with an optional extension
161
+ after the closing quotes so the DMS knows the file type: `file '''<data>
162
+ </data>'''.xml` stores the text, `file b64'''iVBOR...'''.png` decodes base64
163
+ (line breaks and spaces are ignored), and `file #NULL#` removes the document
164
+ file on an update. Without an extension, text becomes a txt and base64 a bin
165
+ file:
166
+
167
+ ```
168
+ insert document Invoice into 5693
169
+ set InvoiceNo = 'R-9'
170
+ file b64'''
171
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAARCAYAAADUryzE...
172
+ '''.png;
173
+ select document Invoice
174
+ ```
175
+
176
+ Security statements administer the DMS users, groups and roles in the same
177
+ language, again with the rights of the signed-in user, so the server enforces
178
+ the role for configuring the security system:
179
+
180
+ ```
181
+ select user where locked = false order by username limit 100
182
+ select user where group = 'Sales'
183
+ select group where user = #USER#
184
+ insert user KOL set display_name = 'Roland Koller', password = 'Start.2026', change_pwd = true
185
+ add user KOL to group Sales
186
+ export security group Sales, Marketing
187
+ ```
188
+
189
+ `select user KOL` shows one account with every attribute, `count group` the
190
+ number alone, and `delete user KOL forward to MEY` hands the portfolios and
191
+ mails over before the account goes. User and group rows carry the same edit
192
+ button as DMS rows: it opens a new tab with an `update user` or `update group`
193
+ statement holding the current values. The password is never part of it, and
194
+ never part of a result or a log.
195
+
196
+ Results render as a table by default or as JSON, JSONL, XML, CSV, TSV or TSV
197
+ quoted, `sql` results included. Every text format opens in an editable editor, so
198
+ the output can be trimmed before copy or download hands it to the next step.
199
+ TSV sanitizes tabs and line breaks inside values to keep one record per line,
200
+ TSV quoted keeps them and quotes like CSV instead. Every result
201
+ row offers details (metadata, variants and versions), an edit button that opens
202
+ a prefilled update statement, and file download.
203
+
204
+ Statement batches (separated by `;`) stream their results statement by
205
+ statement, report the executed command and the upsert action per row, and can
206
+ be cancelled mid run; the stop button in the toolbar also aborts long running
207
+ queries. A query starting with a comment line names its tab, the question
208
+ button in the toolbar lists all keyboard shortcuts, the info button next to it
209
+ opens the about dialog, and the tab rail shows the connected DMS servers
210
+ above the user menu.
211
+
212
+ ## Tests
213
+
214
+ ```
215
+ uv run pytest # unit and endpoint tests
216
+ $env:EBS_LIVE_TESTS = "1"; uv run pytest -m live # against a local DMS (PowerShell)
217
+ ```
218
+
219
+ ## Documentation
220
+
221
+ - [SPECS.md](SPECS.md) - full specification and decision log
222
+ - [TODO.md](TODO.md) - backlog
223
+ - [CHANGELOG.md](CHANGELOG.md) - notable changes
224
+
225
+ ## License
226
+
227
+ MIT, see [LICENSE](LICENSE). Bundled third-party libraries, fonts, icons and tools are
228
+ acknowledged in [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).
229
+
230
+ The MIT license covers this software only and grants no rights to the DMS itself. Operators must
231
+ make sure their use of the DMS is covered by their own license agreement with the DMS vendor or
232
+ reseller. See the DMS licensing section of
233
+ [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).
@@ -0,0 +1,213 @@
1
+ # ECMind blue Studio
2
+
3
+ A admin interface for the DMS enaio(r) (OPTIMAL SYSTEMS GmbH), exposing the
4
+ ecmind-blue-client features.
5
+ Query folders, registers and documents with a simple query language in a Monaco
6
+ editor, inspect results and download files. Works fully offline against your
7
+ DMS infrastructure; all frontend assets are vendored.
8
+
9
+ ## Features (work in progress)
10
+
11
+ - Browser-like vertical tabs, each with a query editor and a result view
12
+ - Object definition explorer: every cabinet, type and index field with its full
13
+ configuration, a filter over all of it, prefilled statements per object type
14
+ and the native asobjdef.xml as download
15
+ - Job call monitor: the live server job stream with filters per server, job,
16
+ computer, application and user, and the full parameters of a single call with
17
+ base64 payloads decoded
18
+ - Simple query language for folders, registers and documents with subqueries,
19
+ Klausel-style conditions, code completion and diagnostics
20
+ - Security statements for users, groups, roles, membership and the rights export
21
+ - Result tables per object type with file download
22
+ - ECMind theme with Green/Yellow/Blue brands, automatic light/dark mode
23
+ - English/German localization with automatic detection
24
+
25
+ ## Requirements
26
+
27
+ - Python >= 3.13 and [uv](https://docs.astral.sh/uv/)
28
+ - A DMS application server (default: 127.0.0.1:4000)
29
+ - A technical account with the system role "Kontextwechsel" (switch context)
30
+
31
+ ## Setup
32
+
33
+ ```
34
+ uv sync
35
+ copy .env.example .env
36
+ # edit .env: servers, technical account, session secret
37
+ ```
38
+
39
+ ## Run
40
+
41
+ ```
42
+ uv run uvicorn ecmind_blue_studio.main:app --reload --host 127.0.0.1 --port 8099
43
+ ```
44
+
45
+ Then open http://127.0.0.1:8099 and log in with a DMS user.
46
+
47
+ ## Object definition
48
+
49
+ The first tab cannot be closed and shows what the DMS server knows about its
50
+ own data model: cabinets with their folders, registers and documents, the index
51
+ mask fields of every type with data type, database column and names in the
52
+ configured languages, and the complete configuration of a single field. The
53
+ filter box searches all of it at once, six buttons per object type open a
54
+ prefilled `select`, `count`, `insert`, `update`, `upsert` or `delete` statement
55
+ in a new tab, and the download button hands out the native `asobjdef.xml`.
56
+
57
+ It needs the system role "DMS: Supervisor" (18) or "Editor: Starten" (11);
58
+ without one of them the tab is not shown.
59
+
60
+ ## Job calls
61
+
62
+ The second fixed tab shows the live job stream of the configured servers, the
63
+ same feed the Enterprise Manager displays. Press Listen and every finished job
64
+ appears as one line with its timestamp, computer, user, job name, application
65
+ and file counts; a green check for success, a red warning for a failure, and
66
+ optionally a blue play line when the job starts. Filter by server, by job (a
67
+ popup over every namespace the server offers), by computer, application or user,
68
+ or reduce the stream to failures only. Clicking a line shows the call the way
69
+ the Enterprise Manager prints it, with base64 payloads decoded and XML indented.
70
+
71
+ It needs the system role "DMS: Supervisor" (18) or "Administrator: Starten" (1).
72
+ The monitor runs on the technical connection, which is why the roles are checked
73
+ on the server and not only in the browser. Job parameters are shown unmasked.
74
+
75
+ ## Query language
76
+
77
+ Each tab has a Monaco editor with completion, hover and live diagnostics for a
78
+ simple query language (see [SPECS.md](SPECS.md) section 4). Ctrl+Enter runs the
79
+ query, Shift+Alt+F formats it, Alt+N opens a tab and Alt+W closes it. Internal
80
+ field names work without brackets:
81
+
82
+ ```
83
+ select document Invoice, DeliveryNote where Status = 'open' order by InvoiceDate desc limit 100
84
+ select document Invoice in (register Correspondence where Subject = 'Dunning*') where InvoiceNo != ''
85
+ select document Invoice where Clerk = #USER# and InvoiceDate >= #DATE#-1y6m
86
+ select document Invoice columns InvoiceNo, Amount, folder.CompanyName
87
+ select document Invoice columns InvoiceNo, {OBJECT_FILESIZE}, {OBJECT_MODIFYTIME}, {OBJECT_DOCPAGECOUNT}
88
+ count document Invoice where Status = 'open'
89
+ ```
90
+
91
+ System fields (`OBJECT_ID`, `OBJECT_LINKS`, `OBJECT_FILESIZE`, `OBJECT_COUNT`,
92
+ `OBJECT_MODIFYUSER` and more, see SPECS.md) work in `where`, `order by` and
93
+ `columns`; document-only fields are rejected on folder and register queries
94
+ with a live editor marker.
95
+
96
+ The editor also flags object types the signed-in user cannot see, and completion
97
+ notes them in its list. The DMS answers a query on such a type with an empty result
98
+ and no error at all, so the hint is shown before the run. It stays a warning and
99
+ never blocks the query: a type you can see may return no rows as well.
100
+
101
+ Data statements update, create and delete objects, always with the rights of the
102
+ signed-in user:
103
+
104
+ ```
105
+ update document Invoice 4711 set Status = 'paid'
106
+ update document Invoice 4711, 4712 set Status = 'paid'
107
+ delete document Invoice 6524, 6522 purge
108
+ insert document Invoice into 55 set InvoiceNo = 'R-9' file 'scan.pdf'
109
+ upsert document Invoice into 55 set InvoiceNo = 'R-9', Amount = 12.5 search InvoiceNo
110
+ variant 4711 set Status = 'draft' file 'v2.pdf'
111
+ delete document Invoice where Status = 'void' purge
112
+ insert document Invoice into 55 set InvoiceNo = 'R-9', Positions = (Article = 'A-100', Qty = 5), (Article = 'B-200', Qty = 3)
113
+ update document Invoice 4711 set Positions = (Article = 'A-100', Qty = 7) replacetables
114
+ ```
115
+
116
+ A single `insert`, `update` or `variant` shows what it wrote: the objects are
117
+ read back from the server and rendered as a result table below the
118
+ confirmation, with the usual row actions. A large `update` (more objects than
119
+ one result page) and statement batches keep the plain confirmation, because
120
+ reading every object back costs a roundtrip each.
121
+
122
+ Table fields take a comma separated list of rows, each row a list of
123
+ `Column = value` pairs. On update and upsert the statement has to say whether
124
+ the rows replace the table (`replacetables`) or extend it (`appendtables`) -
125
+ the mode belongs to the whole statement, so replacing one table and appending
126
+ to another needs two statements. The table popup in a result row carries an
127
+ "Edit table" button that opens a new tab with exactly such a statement, filled
128
+ with the rows currently stored.
129
+
130
+ Files referenced by `file '...'` are attached to the tab with the paperclip
131
+ button; `file #BROWSE#` instead opens the file dialog every time the statement
132
+ `update` and `delete` also take a list of object ids, and every listed object
133
+ gets its own copy of the file; a failing object does not stop the others, and
134
+ the result lists what was written and what failed. On an id based update the
135
+ `set` clause is optional, so
136
+ `update document Invoice 6523 file 'scan.pdf'` replaces only the file and
137
+ `update document Invoice 6523 file #NULL#` only removes it. Prefilled
138
+ document statements (edit button, object definition page) end with
139
+ `file #BROWSE#` as a reminder; delete the line for metadata-only changes.
140
+ File content can also be written inline, with an optional extension
141
+ after the closing quotes so the DMS knows the file type: `file '''<data>
142
+ </data>'''.xml` stores the text, `file b64'''iVBOR...'''.png` decodes base64
143
+ (line breaks and spaces are ignored), and `file #NULL#` removes the document
144
+ file on an update. Without an extension, text becomes a txt and base64 a bin
145
+ file:
146
+
147
+ ```
148
+ insert document Invoice into 5693
149
+ set InvoiceNo = 'R-9'
150
+ file b64'''
151
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAARCAYAAADUryzE...
152
+ '''.png;
153
+ select document Invoice
154
+ ```
155
+
156
+ Security statements administer the DMS users, groups and roles in the same
157
+ language, again with the rights of the signed-in user, so the server enforces
158
+ the role for configuring the security system:
159
+
160
+ ```
161
+ select user where locked = false order by username limit 100
162
+ select user where group = 'Sales'
163
+ select group where user = #USER#
164
+ insert user KOL set display_name = 'Roland Koller', password = 'Start.2026', change_pwd = true
165
+ add user KOL to group Sales
166
+ export security group Sales, Marketing
167
+ ```
168
+
169
+ `select user KOL` shows one account with every attribute, `count group` the
170
+ number alone, and `delete user KOL forward to MEY` hands the portfolios and
171
+ mails over before the account goes. User and group rows carry the same edit
172
+ button as DMS rows: it opens a new tab with an `update user` or `update group`
173
+ statement holding the current values. The password is never part of it, and
174
+ never part of a result or a log.
175
+
176
+ Results render as a table by default or as JSON, JSONL, XML, CSV, TSV or TSV
177
+ quoted, `sql` results included. Every text format opens in an editable editor, so
178
+ the output can be trimmed before copy or download hands it to the next step.
179
+ TSV sanitizes tabs and line breaks inside values to keep one record per line,
180
+ TSV quoted keeps them and quotes like CSV instead. Every result
181
+ row offers details (metadata, variants and versions), an edit button that opens
182
+ a prefilled update statement, and file download.
183
+
184
+ Statement batches (separated by `;`) stream their results statement by
185
+ statement, report the executed command and the upsert action per row, and can
186
+ be cancelled mid run; the stop button in the toolbar also aborts long running
187
+ queries. A query starting with a comment line names its tab, the question
188
+ button in the toolbar lists all keyboard shortcuts, the info button next to it
189
+ opens the about dialog, and the tab rail shows the connected DMS servers
190
+ above the user menu.
191
+
192
+ ## Tests
193
+
194
+ ```
195
+ uv run pytest # unit and endpoint tests
196
+ $env:EBS_LIVE_TESTS = "1"; uv run pytest -m live # against a local DMS (PowerShell)
197
+ ```
198
+
199
+ ## Documentation
200
+
201
+ - [SPECS.md](SPECS.md) - full specification and decision log
202
+ - [TODO.md](TODO.md) - backlog
203
+ - [CHANGELOG.md](CHANGELOG.md) - notable changes
204
+
205
+ ## License
206
+
207
+ MIT, see [LICENSE](LICENSE). Bundled third-party libraries, fonts, icons and tools are
208
+ acknowledged in [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).
209
+
210
+ The MIT license covers this software only and grants no rights to the DMS itself. Operators must
211
+ make sure their use of the DMS is covered by their own license agreement with the DMS vendor or
212
+ reseller. See the DMS licensing section of
213
+ [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).
@@ -0,0 +1,61 @@
1
+ [project]
2
+ name = "ecmind-blue-studio"
3
+ version = "1.0.0a1"
4
+ description = "ECMind blue Studio, admin interface for the ecmind-blue-client"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ dependencies = [
10
+ "fastapi",
11
+ "uvicorn",
12
+ "jinja2",
13
+ "pydantic-settings",
14
+ "itsdangerous",
15
+ "python-multipart",
16
+ "ecmind-blue-client==1.0.0",
17
+ ]
18
+
19
+ [[project.authors]]
20
+ name = "ECMind GmbH"
21
+ email = "info@ecmind.ch"
22
+
23
+ [project.urls]
24
+ Homepage = "https://ecmind.ch/"
25
+ Repository = "https://gitlab.ecmind.ch/open/ecmind_blue_studio"
26
+
27
+ [project.scripts]
28
+ ecmind-blue-studio = "ecmind_blue_studio.__main__:main"
29
+
30
+ [dependency-groups]
31
+ dev = [
32
+ "pytest",
33
+ "pytest-asyncio",
34
+ "pytest-cov",
35
+ "httpx",
36
+ "ruff",
37
+ ]
38
+
39
+ [build-system]
40
+ requires = ["uv_build>=0.11,<0.13"]
41
+ build-backend = "uv_build"
42
+
43
+ [tool.pytest.ini_options]
44
+ markers = ["live: needs a local DMS instance"]
45
+ addopts = "-m 'not live'"
46
+ asyncio_mode = "auto"
47
+
48
+ [tool.ruff]
49
+ line-length = 120
50
+ src = [
51
+ "src",
52
+ "tests",
53
+ ]
54
+
55
+ [tool.ruff.lint]
56
+ ignore = [
57
+ "DTZ001",
58
+ "DTZ005",
59
+ "DTZ006",
60
+ "DTZ011",
61
+ ]
@@ -0,0 +1,51 @@
1
+ [project]
2
+ name = "ecmind-blue-studio"
3
+ version = "1.0.0a1"
4
+ description = "ECMind blue Studio, admin interface for the ecmind-blue-client"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ authors = [{ name = "ECMind GmbH", email = "info@ecmind.ch" }]
10
+ dependencies = [
11
+ "fastapi",
12
+ "uvicorn",
13
+ "jinja2",
14
+ "pydantic-settings",
15
+ "itsdangerous",
16
+ "python-multipart",
17
+ "ecmind-blue-client==1.0.0",
18
+ ]
19
+
20
+ [dependency-groups]
21
+ dev = [
22
+ "pytest",
23
+ "pytest-asyncio",
24
+ "pytest-cov",
25
+ "httpx",
26
+ "ruff",
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://ecmind.ch/"
31
+ Repository = "https://gitlab.ecmind.ch/open/ecmind_blue_studio"
32
+
33
+ [project.scripts]
34
+ ecmind-blue-studio = "ecmind_blue_studio.__main__:main"
35
+
36
+ [build-system]
37
+ requires = ["uv_build>=0.11,<0.13"]
38
+ build-backend = "uv_build"
39
+
40
+ [tool.pytest.ini_options]
41
+ markers = ["live: needs a local DMS instance"]
42
+ addopts = "-m 'not live'"
43
+ asyncio_mode = "auto"
44
+
45
+ [tool.ruff]
46
+ line-length = 120
47
+ src = ["src", "tests"]
48
+
49
+ [tool.ruff.lint]
50
+ # DMS index data and query variables use naive server-local datetimes.
51
+ ignore = ["DTZ001", "DTZ005", "DTZ006", "DTZ011"]
@@ -0,0 +1,3 @@
1
+ """ECMind blue Studio, a web client for the DMS."""
2
+
3
+ __version__ = "1.0.0a1"
@@ -0,0 +1,18 @@
1
+ """Entry point: run the web client with uvicorn."""
2
+
3
+
4
+ def main() -> None:
5
+ import uvicorn
6
+
7
+ from ecmind_blue_studio.config import get_settings
8
+
9
+ settings = get_settings()
10
+ uvicorn.run(
11
+ "ecmind_blue_studio.main:app",
12
+ host=settings.host,
13
+ port=settings.port,
14
+ )
15
+
16
+
17
+ if __name__ == "__main__":
18
+ main()