Skip to content

Commit

Permalink
merge v1.0.4 release
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie authored Jan 3, 2025
2 parents e9a61f2 + 6549f45 commit baa9fc4
Show file tree
Hide file tree
Showing 18 changed files with 328 additions and 180 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/release_cleanup.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TBA
- [ ] Review and update doc entries if needed
- [ ] Ensure all relevant updates are in `CHANGELOG` and major changes doc
- [ ] Ensure REST API versions are up to date and documented
- [ ] Upgrade version number of pypi package references in `README` and docs
- [ ] Upgrade version number of pypi package references in `README`
- [ ] Upgrade docs config version number (usually at `x.y.z-WIP` when developing)
- [ ] Update latest version info in `codemeta.json`
- [ ] Update version number and date in `CHANGELOG`
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ Changelog for the **SODAR Core** Django app package. Loosely follows the
`Keep a Changelog <http://keepachangelog.com/en/1.0.0/>`_ guidelines.


v1.0.4 (2025-01-03)
===================

Added
-----

- **Projectroles**
- Check mode in ``cleanappsettings`` command (#1520)
- Support for all scopes in ``cleanappsettings`` undefined setting cleanup (#1526)
- **Timeline**
- ``get_event_name()`` template tag (#1524)

Changed
-------

- **Projectroles**
- Optimize ``cleanappsettings`` database queries (#1527)
- **Timeline**
- Capitalize event description in UI (#1522)
- Display event name in UI friendly format (#1524)
- Display search results with new layout (#1521)
- Enable search for display formatting of event name (#1525)


v1.0.3 (2024-12-12)
===================

Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ and breaking changes are possible.

.. code-block:: console
pip install django-sodar-core==1.0.3
pip install django-sodar-core==1.0.4
For installing a development version you can point your dependency to a specific
commit ID in GitHub. Note that these versions may not be stable.
Expand Down
6 changes: 3 additions & 3 deletions codemeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
],
"identifier": "https://doi.org/10.5281/zenodo.4269346",
"codeRepository": "https://github.com/bihealth/sodar-core",
"datePublished": "2024-12-12",
"dateModified": "2024-12-12",
"datePublished": "2025-01-03",
"dateModified": "2025-01-03",
"dateCreated": "2019-06-26",
"description": "SODAR Core: A Django-based framework for scientific data management and analysis web apps",
"keywords": "Python, Django, scientific data managmenent, software library",
"license": "MIT",
"title": "SODAR Core",
"version": "v1.0.3"
"version": "v1.0.4"
}
Binary file modified docs/source/_static/app_timeline/sodar_timeline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/source/app_timeline_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ All Timeline Events

.. figure:: _static/app_timeline/sodar_timeline.png
:align: center
:scale: 65%
:scale: 60%

Timeline project event list view

Expand Down
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
# -- Project information -----------------------------------------------------

project = 'SODAR Core'
copyright = '2018-2024, Berlin Institute of Health'
copyright = '2018-2025, Berlin Institute of Health'
author = 'BIH Core Unit Bioinformatics'

# The short X.Y version
version = '1.0'
# The full version, including alpha/beta/rc tags
release = '1.0.3'
release = '1.0.4'


# -- General configuration ---------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions docs/source/dev_resource.rst
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,12 @@ the Django database:
$ ./manage.py cleanappsettings
.. hint::

If you want to ensure desired effects for cleanup when developing, run the
command with the ``-c`` or ``--check`` argument. This will log changes to be
made without actually altering the database.


Project Modifying API
=====================
Expand Down
12 changes: 12 additions & 0 deletions docs/source/major_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ older SODAR Core version. For a complete list of changes in current and previous
releases, see the :ref:`full changelog<changelog>`.


v1.0.4 (2025-01-03)
*******************

Release Highlights
==================

- Add timeline search for display formatting of event name
- Add check mode to cleanappsettings management command
- Add support for all scopes in cleanappsettings undefined setting cleanup
- Update timeline event displaying in UI


v1.0.3 (2024-12-12)
*******************

Expand Down
129 changes: 71 additions & 58 deletions projectroles/management/commands/cleanappsettings.py
Original file line number Diff line number Diff line change
@@ -1,94 +1,107 @@
"""
Cleanappsettings management command for cleaning up unused or invalid app
settings
Cleanappsettings management command for cleaning up undefined or orphaned app
settings.
"""

from django.core.management.base import BaseCommand

from projectroles.app_settings import AppSettingAPI
from projectroles.management.logging import ManagementCommandLogger
from projectroles.models import AppSetting
from projectroles.models import AppSetting, SODAR_CONSTANTS


app_settings = AppSettingAPI()
logger = ManagementCommandLogger(__name__)

# SODAR constants
PROJECT_TYPE_PROJECT = SODAR_CONSTANTS['PROJECT_TYPE_PROJECT']
APP_SETTING_SCOPE_USER = SODAR_CONSTANTS['APP_SETTING_SCOPE_USER']

# Local constants
START_MSG = 'Checking database for undefined app settings..'
START_MSG = 'Querying database for undefined app settings..'
CHECK_MODE_MSG = 'Check mode enabled, database will not be altered'
END_MSG = 'OK'
DEFINITION_NOT_FOUND_MSG = 'definition not found'
DEF_NOT_FOUND_MSG = 'definition not found'
ALLOWED_TYPES_MSG = 'does not match allowed types'
DELETE_PREFIX_MSG = 'Deleting "{}" from project "{}": '
LOG_NONE_LABEL = 'None'
PREFIX_MSG = '"{s_name}" (project={project}; user={user}): '
CHECK_PREFIX_MSG = 'Found ' + PREFIX_MSG
DELETE_PREFIX_MSG = 'Deleting ' + PREFIX_MSG
DELETE_PROJECT_TYPE_MSG = 'project type "{}" {}: {}'
DELETE_SCOPE_MSG = 'user {} has no role in project'
DELETE_SCOPE_MSG = 'user has no role in project'


def get_setting_str(db_setting):
return '.'.join(
[
'settings',
(
'projectroles'
if db_setting.app_plugin is None
else db_setting.app_plugin.name
),
db_setting.name,
]
)
class Command(BaseCommand):
"""Command for cleaning up undefined or orphaned app settings"""

help = (
'Cleans up undefined or otherwise orphaned app settings from the '
'database.'
)

class Command(BaseCommand):
help = 'Cleans up undefined app settings from the database.'
@classmethod
def _get_log_msg(cls, s, msg, check):
"""Return delete/check message for logging"""
prefix_msg = CHECK_PREFIX_MSG if check else DELETE_PREFIX_MSG
s_name = '.'.join(
[
'settings',
'projectroles' if s.app_plugin is None else s.app_plugin.name,
s.name,
]
)
p_str = f'"{s.project.title}"' if s.project else LOG_NONE_LABEL
u_str = f'"{s.user.username}"' if s.user else LOG_NONE_LABEL
return prefix_msg.format(s_name=s_name, project=p_str, user=u_str) + msg

def add_arguments(self, parser):
pass
parser.add_argument(
'-c',
'--check',
dest='check',
required=False,
default=False,
action='store_true',
help='Log settings to be cleaned up without altering the database',
)

def handle(self, *args, **options):
check = options.get('check', False)
if check:
logger.info(CHECK_MODE_MSG)
logger.info(START_MSG)
db_settings = AppSetting.objects.filter(user=None)
s_def = None
p_types = []
db_settings = AppSetting.objects.all()
for s in db_settings:
# Undefined settings
def_kwargs = {'name': s.name}
if s.app_plugin:
def_kwargs['plugin'] = s.app_plugin.get_plugin()
else:
def_kwargs['plugin_name'] = 'projectroles'
try:
definition = app_settings.get_definition(**def_kwargs)
s_def = app_settings.get_definition(**def_kwargs)
# Get allowed project types (if unset, default is PROJECT only)
if s_def['scope'] != APP_SETTING_SCOPE_USER:
p_types = s_def.get('project_types', [PROJECT_TYPE_PROJECT])
except ValueError:
logger.info(
DELETE_PREFIX_MSG.format(
get_setting_str(s), s.project.title
)
+ DEFINITION_NOT_FOUND_MSG
)
s.delete()
continue
if s.project and s.project.type not in definition.get(
'project_types', ['PROJECT']
):
logger.info(
DELETE_PREFIX_MSG.format(
get_setting_str(s), s.project.title
)
+ DELETE_PROJECT_TYPE_MSG.format(
s.project.type,
ALLOWED_TYPES_MSG,
definition.get('project_types', ['PROJECT']),
)
)
s.delete()

db_settings = AppSetting.objects.filter(
project__isnull=False, user__isnull=False
)
for s in db_settings:
if not s.project.get_role(s.user):
logger.info(
DELETE_PREFIX_MSG.format(
get_setting_str(s), s.project.title
)
+ DELETE_SCOPE_MSG.format(s.user.username)
logger.info(self._get_log_msg(s, DEF_NOT_FOUND_MSG, check))
if not check:
s.delete()
continue
# Invalid scope
if s_def and s.project and s.project.type not in p_types:
msg = DELETE_PROJECT_TYPE_MSG.format(
s.project.type, ALLOWED_TYPES_MSG, ', '.join(p_types)
)
s.delete()
logger.info(self._get_log_msg(s, msg, check))
if not check:
s.delete()
continue
# No user role for PROJECT_USER scope setting
if s.project and s.user and not s.project.get_role(s.user):
logger.info(self._get_log_msg(s, DELETE_SCOPE_MSG, check))
if not check:
s.delete()
logger.info(END_MSG)
Loading

0 comments on commit baa9fc4

Please sign in to comment.