diff options
-rw-r--r-- | src/hydrilla/proxy/state.py | 32 | ||||
-rw-r--r-- | src/hydrilla/proxy/state_impl/_operations/load_packages.py | 52 | ||||
-rw-r--r-- | src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py | 66 | ||||
-rw-r--r-- | src/hydrilla/proxy/state_impl/mappings.py | 155 | ||||
-rw-r--r-- | src/hydrilla/proxy/state_impl/repos.py | 30 | ||||
-rw-r--r-- | src/hydrilla/proxy/tables.sql | 71 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/packages.py | 34 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/root.py | 6 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja | 12 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja | 36 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja | 12 |
11 files changed, 288 insertions, 218 deletions
diff --git a/src/hydrilla/proxy/state.py b/src/hydrilla/proxy/state.py index 0e45725..e5c7bd7 100644 --- a/src/hydrilla/proxy/state.py +++ b/src/hydrilla/proxy/state.py @@ -56,14 +56,10 @@ class EnabledStatus(Enum): DISABLED - User wished to never apply given mapping. - AUTO_ENABLED - User has not configured given mapping but it will still be - used when automatic application of mappings is turned on. - NO_MARK - User has not configured given mapping and it won't be used. """ ENABLED = 'E' DISABLED = 'D' - AUTO_ENABLED = 'A' NO_MARK = 'N' @@ -84,6 +80,20 @@ class InstalledStatus(Enum): FAILED_TO_INSTALL = 'F' +class ActiveStatus(Enum): + """ + REQUIRED - Mapping version got active to fulfill a requirement of some (this + or another) explicitly enabled mapping. + + AUTO - Mapping version was activated automatically. + + NOT_ACTIVE - Mapping version is not currently being used. + """ + REQUIRED = 'R' + AUTO = 'A' + NOT_ACTIVE = 'N' + + @dc.dataclass(frozen=True, unsafe_hash=True) class Ref: """....""" @@ -188,18 +198,17 @@ class RepoIterationRef(Ref): @dc.dataclass(frozen=True) class MappingDisplayInfo: - ref: 'MappingRef' - identifier: str - enabled: EnabledStatus - active_version_ref: t.Optional['MappingVersionRef'] - active_version_info: t.Optional[item_infos.MappingInfo] + ref: 'MappingRef' + identifier: str + enabled: EnabledStatus + active_version: t.Optional['MappingVersionDisplayInfo'] @dc.dataclass(frozen=True) class MappingVersionDisplayInfo: ref: 'MappingVersionRef' info: item_infos.MappingInfo installed: InstalledStatus - is_active: bool + active: ActiveStatus is_orphan: bool is_local: bool mapping_enabled: EnabledStatus @@ -231,7 +240,8 @@ class MappingVersionRef(Ref): ... @abstractmethod - def get_display_info(self) -> MappingVersionDisplayInfo: + def get_all_version_display_infos(self) \ + -> t.Sequence[MappingVersionDisplayInfo]: ... class MappingVersionStore(Store[MappingVersionRef]): diff --git a/src/hydrilla/proxy/state_impl/_operations/load_packages.py b/src/hydrilla/proxy/state_impl/_operations/load_packages.py index 6b9047a..0660ce2 100644 --- a/src/hydrilla/proxy/state_impl/_operations/load_packages.py +++ b/src/hydrilla/proxy/state_impl/_operations/load_packages.py @@ -64,18 +64,6 @@ def make_repo_iteration(cursor: sqlite3.Cursor, repo_id: int) -> int: cursor.execute( ''' - UPDATE - repos - SET - next_iteration = ? - WHERE - repo_id = ?; - ''', - (next_iteration + 1, repo_id) - ) - - cursor.execute( - ''' INSERT INTO repo_iterations(repo_id, iteration) VALUES(?, ?); ''', @@ -96,6 +84,30 @@ def make_repo_iteration(cursor: sqlite3.Cursor, repo_id: int) -> int: (repo_iteration_id,), = cursor.fetchall() + cursor.execute( + ''' + UPDATE + repos + SET + next_iteration = ?, + active_iteration_id = ( + CASE + WHEN repo_id = 1 THEN NULL + ELSE ? + END + ), + last_refreshed = ( + CASE + WHEN repo_id = 1 THEN NULL + ELSE STRFTIME('%s', 'NOW') + END + ) + WHERE + repo_id = ?; + ''', + (next_iteration + 1, repo_iteration_id, repo_id) + ) + return repo_iteration_id def get_or_make_item(cursor: sqlite3.Cursor, type: str, identifier: str) -> int: @@ -162,12 +174,9 @@ def update_or_make_item_version( item_versions SET installed = ( - CASE WHEN - installed = 'I' OR ? = 'I' - THEN - 'I' - ELSE - 'N' + CASE + WHEN installed = 'I' OR ? = 'I' THEN 'I' + ELSE 'N' END ), repo_iteration_id = ? @@ -213,10 +222,7 @@ def update_or_make_item_version( def make_mapping_status(cursor: sqlite3.Cursor, item_id: int) -> None: cursor.execute( - ''' - INSERT OR IGNORE INTO mapping_statuses(item_id, enabled, required) - VALUES(?, 'N', FALSE); - ''', + 'INSERT OR IGNORE INTO mapping_statuses(item_id) VALUES(?);', (item_id,) ) @@ -395,6 +401,8 @@ def _load_packages_no_state_update( repo_id = repo_id ) + prune_packages(cursor) + _recompute_dependencies_no_state_update( cursor = cursor, semirepo_file_resolver = MalcontentFileResolver(malcontent_path) diff --git a/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py b/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py index 494d130..4b48ce8 100644 --- a/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py +++ b/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py @@ -51,12 +51,13 @@ def _get_infos_of_type(cursor: sqlite3.Cursor, info_type: t.Type[AnyInfoVar],) \ cursor.execute( ''' SELECT - i.item_id, iv.definition, r.name, ri.iteration + ive.item_version_id, + ive.definition, + ive.repo, + ive.repo_iteration FROM - item_versions AS iv - JOIN items AS i USING (item_id) - JOIN repo_iterations AS ri USING (repo_iteration_id) - JOIN repos AS r USING (repo_id) + item_versions_extra AS ive + JOIN items AS i USING (item_id) WHERE i.type = ?; ''', @@ -65,9 +66,10 @@ def _get_infos_of_type(cursor: sqlite3.Cursor, info_type: t.Type[AnyInfoVar],) \ result: dict[int, AnyInfoVar] = {} - for item_id, definition, repo_name, repo_iteration in cursor.fetchall(): + for item_version_id, definition, repo_name, repo_iteration \ + in cursor.fetchall(): info = info_type.load(definition, repo_name, repo_iteration) - result[item_id] = info + result[item_version_id] = info return result @@ -93,11 +95,8 @@ def _recompute_dependencies_no_state_update_no_pull_files( ids_to_resources = _get_infos_of_type(cursor, item_infos.ResourceInfo) ids_to_mappings = _get_infos_of_type(cursor, item_infos.MappingInfo) - resources = ids_to_resources.items() - resources_to_ids = dict((info.identifier, id) for id, info in resources) - - mappings = ids_to_mappings.items() - mappings_to_ids = dict((info.identifier, id) for id, info in mappings) + resources_to_ids = dict((info, id) for id, info in ids_to_resources.items()) + mappings_to_ids = dict((info, id) for id, info in ids_to_mappings.items()) requirements = [*extra_requirements] @@ -150,17 +149,18 @@ def _recompute_dependencies_no_state_update_no_pull_files( UPDATE mapping_statuses SET - required = FALSE, active_version_id = NULL WHERE enabled != 'E'; ''' ) + cursor.execute("UPDATE item_versions SET active = 'N';") + cursor.execute('DELETE FROM payloads;') for choice in mapping_choices.values(): - mapping_ver_id = mappings_to_ids[choice.info.identifier] + mapping_ver_id = mappings_to_ids[choice.info] if choice.required: _mark_version_installed(cursor, mapping_ver_id) @@ -184,12 +184,23 @@ def _recompute_dependencies_no_state_update_no_pull_files( UPDATE mapping_statuses SET - required = ?, active_version_id = ? WHERE item_id = ?; ''', - (choice.required, mapping_ver_id, mapping_item_id) + (mapping_ver_id, mapping_item_id) + ) + + cursor.execute( + ''' + UPDATE + item_versions + SET + active = ? + WHERE + item_version_id = ?; + ''', + (mapping_ver_id, 'R' if choice.required else 'A') ) for num, (pattern, payload) in enumerate(choice.payloads.items()): @@ -226,7 +237,7 @@ def _recompute_dependencies_no_state_update_no_pull_files( (payload_id,), = cursor.fetchall() for res_num, resource_info in enumerate(payload.resources): - resource_ver_id = resources_to_ids[resource_info.identifier] + resource_ver_id = resources_to_ids[resource_info] if choice.required: _mark_version_installed(cursor, resource_ver_id) @@ -243,6 +254,27 @@ def _recompute_dependencies_no_state_update_no_pull_files( (payload_id, resource_ver_id, res_num) ) + new_status = 'R' if choice.required else 'A' + + cursor.execute( + ''' + UPDATE + item_versions + SET + active = ( + CASE + WHEN active = 'R' OR ? = 'R' THEN 'R' + WHEN active = 'A' OR ? = 'A' THEN 'A' + ELSE 'N' + END + ) + WHERE + item_version_id = ?; + ''', + (new_status, new_status, resource_ver_id) + ) + + def _recompute_dependencies_no_state_update( cursor: sqlite3.Cursor, extra_requirements: t.Iterable[sds.MappingRequirement] = (), diff --git a/src/hydrilla/proxy/state_impl/mappings.py b/src/hydrilla/proxy/state_impl/mappings.py index 946df14..7d08e58 100644 --- a/src/hydrilla/proxy/state_impl/mappings.py +++ b/src/hydrilla/proxy/state_impl/mappings.py @@ -51,19 +51,20 @@ class ConcreteMappingRef(st.MappingRef): cursor.execute( ''' SELECT - item_version_id, - definition, - repo, - repo_iteration, - installed, - is_active, - is_orphan, - is_local, - enabled + ive.item_version_id, + ive.definition, + ive.repo, + ive.repo_iteration, + ive.installed, + ive.active, + ive.is_orphan, + ive.is_local, + ms.enabled FROM - mapping_display_infos + item_versions_extra AS ive + JOIN mapping_statuses AS ms USING (item_id) WHERE - item_id = ?; + ive.item_id = ?; ''', (self.id,) ) @@ -75,8 +76,9 @@ class ConcreteMappingRef(st.MappingRef): result = [] - for (item_version_id, definition, repo, repo_iteration, installed, - is_active, is_orphan, is_local, status_letter) in rows: + for (item_version_id, definition, repo, repo_iteration, + installed_status, active_status, is_orphan, is_local, + enabled_status) in rows: ref = ConcreteMappingVersionRef(str(item_version_id), self.state) item_info = item_infos.MappingInfo.load( @@ -88,11 +90,11 @@ class ConcreteMappingRef(st.MappingRef): display_info = st.MappingVersionDisplayInfo( ref = ref, info = item_info, - installed = st.InstalledStatus(installed), - is_active = is_active, + installed = st.InstalledStatus(installed_status), + active = st.ActiveStatus(active_status), is_orphan = is_orphan, is_local = is_local, - mapping_enabled = st.EnabledStatus(status_letter) + mapping_enabled = st.EnabledStatus(enabled_status) ) result.append(display_info) @@ -104,22 +106,31 @@ class ConcreteMappingStore(st.MappingStore): state: base.HaketiloStateWithFields def get(self, id: str) -> st.MappingRef: - return ConcreteMappingRef(id, self.state) + return ConcreteMappingRef(str(int(id)), self.state) def get_display_infos(self) -> t.Sequence[st.MappingDisplayInfo]: with self.state.cursor() as cursor: cursor.execute( ''' - SELECT DISTINCT - item_id, - identifier, - CASE WHEN is_active THEN item_version_id ELSE NULL END, - CASE WHEN is_active THEN definition ELSE NULL END, - CASE WHEN is_active THEN repo ELSE NULL END, - CASE WHEN is_active THEN repo_iteration ELSE NULL END, - enabled + SELECT + i.item_id, + i.identifier, + ive.item_version_id, + ive.definition, + ive.repo, + ive.repo_iteration, + ive.installed, + ive.active, + ive.is_orphan, + ive.is_local, + ms.enabled FROM - mapping_display_infos; + items AS i + JOIN mapping_statuses AS ms + USING (item_id) + LEFT JOIN item_versions_extra AS ive + ON ms.active_version_id = ive.item_version_id AND + ive.active IN ('R', 'A'); ''' ) @@ -128,34 +139,45 @@ class ConcreteMappingStore(st.MappingStore): result = [] for (item_id, identifier, item_version_id, definition, repo, - repo_iteration, status_letter) in rows: + repo_iteration, installed_status, active_status, is_orphan, + is_local, enabled_status) in rows: ref = ConcreteMappingRef(str(item_id), self.state) - active_version_ref: t.Optional[st.MappingVersionRef] = None - item_info: t.Optional[item_infos.MappingInfo] = None + active_version: t.Optional[st.MappingVersionDisplayInfo] = None if item_version_id is not None: active_version_ref = ConcreteMappingVersionRef( id = str(item_version_id), state = self.state ) - item_info = item_infos.MappingInfo.load( + + active_version_info = item_infos.MappingInfo.load( definition, repo, repo_iteration ) + active_version = st.MappingVersionDisplayInfo( + ref = active_version_ref, + info = active_version_info, + installed = st.InstalledStatus(installed_status), + active = st.ActiveStatus(active_status), + is_orphan = is_orphan, + is_local = is_local, + mapping_enabled = st.EnabledStatus(enabled_status) + ) + + display_info = st.MappingDisplayInfo( - ref = ref, - identifier = identifier, - enabled = st.EnabledStatus(status_letter), - active_version_ref = active_version_ref, - active_version_info = item_info + ref = ref, + identifier = identifier, + enabled = st.EnabledStatus(enabled_status), + active_version = active_version ) result.append(display_info) - return result + return sorted(result, key=(lambda di: di.identifier)) @dc.dataclass(frozen=True, unsafe_hash=True) @@ -181,9 +203,26 @@ class ConcreteMappingVersionRef(st.MappingVersionRef): def install(self) -> None: with self.state.cursor(transaction=True) as cursor: - info = self.get_display_info() + cursor.execute( + ''' + SELECT + installed + FROM + item_versions + WHERE + item_version_id = ?; + ''', + (self.id,) + ) + + rows = cursor.fetchall() + + if rows == []: + raise st.MissingItemError() + + (installed_status,), = rows - if info.installed == st.InstalledStatus.INSTALLED: + if installed_status == 'I': return self._set_installed_status(cursor, st.InstalledStatus.INSTALLED) @@ -204,21 +243,15 @@ class ConcreteMappingVersionRef(st.MappingVersionRef): # # .... - def get_display_info(self) -> st.MappingVersionDisplayInfo: + def get_all_version_display_infos(self) \ + -> t.Sequence[st.MappingVersionDisplayInfo]: with self.state.cursor() as cursor: cursor.execute( ''' SELECT - definition, - repo, - repo_iteration, - installed, - is_orphan, - is_active, - is_local, - enabled + item_id FROM - mapping_display_infos + item_versions WHERE item_version_id = ?; ''', @@ -226,28 +259,14 @@ class ConcreteMappingVersionRef(st.MappingVersionRef): ) rows = cursor.fetchall() + if rows == []: + raise st.MissingItemError() - if rows == []: - raise st.MissingItemError() - - (definition, repo, repo_iteration, installed, is_orphan, is_active, - is_local, status_letter), = rows + (mapping_id,), = rows - item_info = item_infos.MappingInfo.load( - definition, - repo, - repo_iteration - ) + mapping_ref = ConcreteMappingRef(str(mapping_id), self.state) - return st.MappingVersionDisplayInfo( - ref = self, - info = item_info, - installed = st.InstalledStatus(installed), - is_active = is_active, - is_orphan = is_orphan, - is_local = is_local, - mapping_enabled = st.EnabledStatus(status_letter) - ) + return mapping_ref.get_version_display_infos() @dc.dataclass(frozen=True) @@ -255,4 +274,4 @@ class ConcreteMappingVersionStore(st.MappingVersionStore): state: base.HaketiloStateWithFields def get(self, id: str) -> st.MappingVersionRef: - return ConcreteMappingVersionRef(id, self.state) + return ConcreteMappingVersionRef(str(int(id)), self.state) diff --git a/src/hydrilla/proxy/state_impl/repos.py b/src/hydrilla/proxy/state_impl/repos.py index d4fbbce..346e113 100644 --- a/src/hydrilla/proxy/state_impl/repos.py +++ b/src/hydrilla/proxy/state_impl/repos.py @@ -202,17 +202,11 @@ class ConcreteRepoRef(st.RepoRef): cursor.execute( ''' SELECT - iv.definition, r.name, ri.iteration + definition, repo, repo_iteration FROM - mapping_statuses AS ms - JOIN item_versions AS iv - ON ms.active_version_id = iv.item_version_id - JOIN repo_iterations AS ri - USING (repo_iteration_id) - JOIN repos AS r - USING (repo_id) + item_versions_extra WHERE - ms.required + active = 'R'; ''' ) @@ -288,18 +282,6 @@ class ConcreteRepoRef(st.RepoRef): self.state.rebuild_structures() - cursor.execute( - ''' - UPDATE - repos - SET - last_refreshed = STRFTIME('%s', 'NOW') - WHERE - repo_id = ?; - ''', - (self.id,) - ) - return ConcreteRepoIterationRef(str(new_iteration_id), self.state) def get_display_info(self) -> st.RepoDisplayInfo: @@ -332,7 +314,7 @@ class ConcreteRepoStore(st.RepoStore): state: base.HaketiloStateWithFields def get(self, id: str) -> st.RepoRef: - return ConcreteRepoRef(id, self.state) + return ConcreteRepoRef(str(int(id)), self.state) def add(self, name: str, url: str) -> st.RepoRef: name = name.strip() @@ -360,8 +342,8 @@ class ConcreteRepoStore(st.RepoStore): cursor.execute( ''' - INSERT INTO repos(name, url, deleted, next_iteration) - VALUES (?, ?, FALSE, 1) + INSERT INTO repos(name, url) + VALUES (?, ?) ON CONFLICT (name) DO UPDATE SET name = excluded.name, diff --git a/src/hydrilla/proxy/tables.sql b/src/hydrilla/proxy/tables.sql index 863c989..918c1f1 100644 --- a/src/hydrilla/proxy/tables.sql +++ b/src/hydrilla/proxy/tables.sql @@ -68,8 +68,8 @@ CREATE TABLE repos( name VARCHAR NOT NULL, url VARCHAR NOT NULL, - deleted BOOLEAN NOT NULL, - next_iteration INTEGER NOT NULL, + deleted BOOLEAN NOT NULL DEFAULT FALSE, + next_iteration INTEGER NOT NULL DEFAULT 1, active_iteration_id INTEGER NULL, last_refreshed INTEGER NULL, @@ -93,8 +93,8 @@ CREATE TABLE repos( ON DELETE SET NULL ); -INSERT INTO repos(repo_id, name, url, deleted, next_iteration) -VALUES(1, '', '', TRUE, 1); +INSERT INTO repos(repo_id, name, url, deleted) +VALUES(1, '', '', TRUE); CREATE TABLE repo_iterations( repo_iteration_id INTEGER PRIMARY KEY, @@ -139,30 +139,22 @@ CREATE TABLE mapping_statuses( -- "enabled" determines whether mapping's status is ENABLED, -- DISABLED or NO_MARK. - enabled CHAR(1) NOT NULL, + enabled CHAR(1) NOT NULL DEFAULT 'N', -- "frozen" determines whether an enabled mapping is to be kept in its -- EXACT_VERSION, is to be updated only with versions from the same -- REPOSITORY or is NOT_FROZEN at all. frozen CHAR(1) NULL, - -- The last 2 fields defined below shall be updated when dependency tree - -- is recomputed. - -- When "required" is TRUE, the mapping is assumed to either be enabled - -- or be (directly or indirectly) required by another mapping which is - -- enabled (i.e. has "enabled" set to 'E'). - required BOOLEAN NOT NULL, -- Only one version of a mapping is allowed to be active at any time. -- "active_version_id" indicates which version it is. Only a mapping -- version referenced by "active_version_id" is allowed to have rows -- in the "payloads" table reference it. + -- "active_version_id" shall be updated every time dependency tree is + -- recomputed. active_version_id INTEGER NULL, CHECK (enabled IN ('E', 'D', 'N')), CHECK ((frozen IS NULL) = (enabled != 'E')), CHECK (frozen IS NULL OR frozen in ('E', 'R', 'N')), - CHECK (enabled != 'E' OR required), - CHECK (enabled != 'D' OR NOT required), - CHECK (not required OR active_version_id IS NOT NULL), - CHECK (enabled != 'D' OR active_version_id IS NULL), FOREIGN KEY (item_id) REFERENCES items (item_id) @@ -189,11 +181,18 @@ CREATE TABLE item_versions( repo_iteration_id INTEGER NOT NULL, definition BLOB NOT NULL, definition_sha256 CHAR(64) NOT NULL, + -- "active" determines whether a version of this mapping is active + -- because it is REQUIRED, has been AUTO activated or is NOT_ACTIVE. + -- "active" shall be updated every time dependency tree is recomputed. + -- It shall be set to NOT_ACTIVE if and only if given row does not + -- correspond to "active_version_id" of any row in "mapping_statuses". + active CHAR(1) NOT NULL DEFAULT 'N', UNIQUE (item_id, version, repo_iteration_id), -- Constraint below needed to allow foreign key from "mapping_statuses". UNIQUE (item_version_id, item_id), CHECK (installed in ('I', 'N', 'F')), + CHECK (active in ('R', 'A', 'N')), FOREIGN KEY (item_id) REFERENCES items (item_id), @@ -236,35 +235,25 @@ CREATE TABLE payloads( ON DELETE CASCADE ); -CREATE VIEW mapping_display_infos +CREATE VIEW item_versions_extra AS SELECT - i.item_id, i.identifier, - CASE WHEN - ms.enabled = 'N' AND - COALESCE(ms.active_version_id, -1) = iv.item_version_id - THEN - 'A' -- AUTO_ENABLED mapping - ELSE - ms.enabled - END AS enabled, - iv.item_version_id, iv.definition, iv.installed, - r.name AS repo, - ri.iteration AS repo_iteration, - COALESCE(r.active_iteration_id, -1) != ri.repo_iteration_id AND - r.repo_id != 1 AS is_orphan, - r.repo_id = 1 AS is_local, - COALESCE(ms.active_version_id, -1) = iv.item_version_id AS is_active + iv.item_version_id, + iv.item_id, + iv.version, + iv.installed, + iv.repo_iteration_id, + iv.definition, + iv.active, + r.name AS repo, + ri.iteration AS repo_iteration, + COALESCE(r.active_iteration_id, -1) != ri.repo_iteration_id AND r.repo_id != 1 + AS is_orphan, + r.repo_id = 1 AS is_local FROM - items AS i - JOIN mapping_statuses AS ms - USING (item_id) - JOIN item_versions AS iv - USING (item_id) - JOIN repo_iterations AS ri - USING (repo_iteration_id) - JOIN repos AS r - USING (repo_id); + item_versions AS iv + JOIN repo_iterations AS ri USING (repo_iteration_id) + JOIN repos AS r USING (repo_id); CREATE TABLE resolved_depended_resources( payload_id INTEGER, diff --git a/src/hydrilla/proxy/web_ui/packages.py b/src/hydrilla/proxy/web_ui/packages.py index ac8b480..e14c1fd 100644 --- a/src/hydrilla/proxy/web_ui/packages.py +++ b/src/hydrilla/proxy/web_ui/packages.py @@ -42,6 +42,7 @@ import werkzeug from ...exceptions import HaketiloException from ...translations import smart_gettext as _ +from ... import item_infos from .. import state as st from . import _app @@ -109,17 +110,17 @@ def show_package(mapping_id: str) -> werkzeug.Response: mapping_ref = store.get(str(mapping_id)) version_display_infos = mapping_ref.get_version_display_infos() - active_list = [info for info in version_display_infos if info.is_active] + active_version: t.Optional[st.MappingVersionDisplayInfo] = None - active_version_ref = None if active_list == [] else active_list[0].ref - active_version_info = None if active_list == [] else active_list[0].info + for info in version_display_infos: + if info.active != st.ActiveStatus.NOT_ACTIVE: + active_version = info display_info = st.MappingDisplayInfo( - ref = mapping_ref, - identifier = version_display_infos[0].info.identifier, - enabled = version_display_infos[0].mapping_enabled, - active_version_ref = active_version_ref, - active_version_info = active_version_info + ref = mapping_ref, + identifier = version_display_infos[0].info.identifier, + enabled = version_display_infos[0].mapping_enabled, + active_version = active_version ) html = flask.render_template( @@ -138,11 +139,24 @@ def show_package_version( ) -> werkzeug.Response: try: store = _app.get_haketilo_state().mapping_version_store() - display_info = store.get(mapping_version_id).get_display_info() + version_ref = store.get(mapping_version_id) + display_infos = version_ref.get_all_version_display_infos() + + other_infos: list[st.MappingVersionDisplayInfo] = [] + this_info: t.Optional[st.MappingVersionDisplayInfo] = None + + for info in display_infos: + if info.ref == version_ref: + this_info = info + else: + other_infos.append(info) + + assert this_info is not None html = flask.render_template( 'packages/show_single_version.html.jinja', - display_info = display_info, + display_info = this_info, + version_display_infos = other_infos, **errors ) return flask.make_response(html, 200) diff --git a/src/hydrilla/proxy/web_ui/root.py b/src/hydrilla/proxy/web_ui/root.py index c3e0c80..a6e3151 100644 --- a/src/hydrilla/proxy/web_ui/root.py +++ b/src/hydrilla/proxy/web_ui/root.py @@ -76,14 +76,16 @@ class WebUIAppImpl(_app.WebUIApp): 'autoescape': jinja2.select_autoescape(['html.jinja']), 'extensions': [ *self.jinja_options.get('extensions', []), - 'jinja2.ext.i18n' + 'jinja2.ext.i18n', + 'jinja2.ext.do' ] } self.jinja_env.globals['versions'] = versions self.jinja_env.globals['get_current_endpoint'] = get_current_endpoint - self.jinja_env.globals['InstalledStatus'] = st.InstalledStatus self.jinja_env.globals['EnabledStatus'] = st.EnabledStatus + self.jinja_env.globals['InstalledStatus'] = st.InstalledStatus + self.jinja_env.globals['ActiveStatus'] = st.ActiveStatus self.before_request(authenticate_by_referrer) diff --git a/src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja b/src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja index bac774e..cbdd3d9 100644 --- a/src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/packages/index.html.jinja @@ -35,11 +35,15 @@ in a proprietary work, I am not going to enforce this in court. <div> {{ info.identifier }} </div> - {% if info.active_version_ref is not none %} + {%- + if info.active_version is not none and + info.active_version.active == ActiveStatus.REQUIRED + %} + {%- set ver = info.active_version.info.version %} + {%- set ver_str = versions.version_string(ver) %} + {%- set ver_desc = ver_str + '@' + info.active_version.info.repo %} <div class="small-print"> - {{ versions.version_string(info.active_version_info.version) }} - @ - {{ info.active_version_info.repo }} + {{ _('web_ui.packages.enabled_version_{}').format(ver_desc) }} </div> {% endif %} </a> diff --git a/src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja b/src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja index 17f958c..e362fa9 100644 --- a/src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/packages/show_single.html.jinja @@ -27,22 +27,32 @@ in a proprietary work, I am not going to enforce this in court. {% include 'include/item_list_style.css.jinja' %} {% endblock %} {% block main %} - <h3> - {{ - _('web_ui.packages.single.heading.name_{}') - .format(display_info.identifier) - }} - </h3> - TODO: add more info... - <h4>{{ _('web_ui.packages.single.version_list_heading') }}</h4> + {% block main_info %} + <h3> + {{ + _('web_ui.packages.single.heading.name_{}') + .format(display_info.identifier) + }} + </h3> + TODO: add more info... + {% endblock %} + <h4> + {% if version_display_infos|length > 0 %} + {% block version_list_heading %} + {{ _('web_ui.packages.single.version_list_heading') }} + {% endblock %} + {% endif %} + </h4> <ul id="item_list"> {%- for info in version_display_infos %} - {% if info.info.repo == '<local>' -%} - {%- set entry_classes = 'version-entry-local' -%} - {%- else -%} - {%- set entry_classes = '' -%} + {%- set entry_classes = [] %} + {% if info.is_local %} + {%- do entry_classes.append('version-entry-local') %} {%- endif %} - <li class="{{ entry_classes }}"> + {%- if info.is_orphan %} + {%- do entry_classes.append('version-entry-orphan') %} + {%- endif %} + <li class="{{ entry_classes|join(' ') }}"> {%- set href = url_for( '.show_package_version', diff --git a/src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja b/src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja index 1b46da7..9943521 100644 --- a/src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/packages/show_single_version.html.jinja @@ -19,12 +19,9 @@ I, Wojtek Kosior, thereby promise not to sue for violation of this file's licenses. Although I request that you do not make use this code in a proprietary work, I am not going to enforce this in court. #} -{% extends "base.html.jinja" %} +{% extends "packages/show_single.html.jinja" %} {% block title %} {{ _('web_ui.packages.single_version.title') }} {% endblock %} -{% block style %} - {{ super() }} -{% endblock %} -{% block main %} +{% block main_info %} {%- if uninstall_disallowed is defined %} <aside class="error-note"> {{ _('web_ui.err.uninstall_disallowed') }} @@ -86,4 +83,7 @@ in a proprietary work, I am not going to enforce this in court. </form> </div> {%- endif %} -{%- endblock %} +{%- endblock main_info %} +{% block version_list_heading %} + {{ _('web_ui.packages.single_version.version_list_heading') }} +{% endblock %} |