Skip to content

Commit

Permalink
Add i18n-demo plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasr8 committed Apr 30, 2024
1 parent 7fba489 commit 5772823
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 0 deletions.
6 changes: 6 additions & 0 deletions i18n-demo/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
graft indico_i18n_demo/client
graft indico_i18n_demo/static
graft indico_i18n_demo/templates
graft indico_i18n_demo/translations

global-exclude *.pyc __pycache__ .keep
8 changes: 8 additions & 0 deletions i18n-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# indico-plugin-i18n-demo

This is a plugin intended for the [i18n demo instance](https://localization-demo.getindico.io). It does two things:

- All emails are redirected to the user who sent them (avoids spamming random people and lets you check email translations)
- Adds a new **Clone** button to the example events. When clicked, the corresponding event is cloned into your own personal subcategory and you get management rights to it. This way, you can see the management area without accidentally modifying the example events.

![](example.png)
Empty file.
15 changes: 15 additions & 0 deletions i18n-demo/indico_i18n_demo/blueprint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This file is part of the Indico plugins.

Check failure on line 1 in i18n-demo/indico_i18n_demo/blueprint.py

View workflow job for this annotation

GitHub Actions / lint

Incorrect header
# Copyright (C) 2002 - 2023 CERN
#
# The Indico plugins are free software; you can redistribute
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.

from indico.core.plugins import IndicoPluginBlueprint

from indico_i18n_demo.controllers import RHCloneEvent


blueprint = IndicoPluginBlueprint('i18n_demo', __name__, url_prefix='/i18n-demo')

blueprint.add_url_rule('/event/<int:event_id>/clone', 'clone_event', RHCloneEvent, methods=('POST',))
59 changes: 59 additions & 0 deletions i18n-demo/indico_i18n_demo/controllers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# This file is part of the Indico plugins.

Check failure on line 1 in i18n-demo/indico_i18n_demo/controllers.py

View workflow job for this annotation

GitHub Actions / lint

Incorrect header
# Copyright (C) 2002 - 2023 CERN
#
# The Indico plugins are free software; you can redistribute
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.

from flask import flash, redirect
from flask_pluginengine import current_plugin

from werkzeug.exceptions import BadRequest
from indico.modules.events.controllers.base import RHEventBase
from indico.modules.events.operations import clone_event
from indico.modules.categories.operations import create_category as _create_category
from indico.modules.categories.models.categories import Category
from indico.modules.events.cloning import get_event_cloners
from indico.web.flask.util import url_for
from flask import session
from indico.core.db.sqlalchemy.protection import ProtectionMode


class RHCloneEvent(RHEventBase):
"""Clone an event to a user's personal category.
If the category does not exist, it will be created.
The user has full management rights within the category.
"""
ALLOW_LOCKED = True

def _process(self):
if not (category_id := current_plugin.settings.get('test_category_id')):
raise BadRequest('No test category ID configured')

test_category = Category.get(int(category_id))
user_category = get_user_category(test_category, session.user)

cloners = {c for c in get_event_cloners().values() if not c.is_internal}
new_event = clone_event(self.event, n_occurrence=0, start_dt=self.event.start_dt, cloners=cloners,
category=user_category, refresh_users=False)

flash('Event successfully cloned!', 'success')
return redirect(url_for('event_management.settings', new_event))


def get_user_category(parent, user):
category = Category.query.filter(Category.title == get_category_title(user)).first()
return category if category else create_category(parent, user)

Check failure on line 47 in i18n-demo/indico_i18n_demo/controllers.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (FURB110)

i18n-demo/indico_i18n_demo/controllers.py:47:12: FURB110 Replace ternary `if` expression with `or` operator


def create_category(parent, user):
description = 'This is your own category where you have full management rights. Have fun!'
category = _create_category(parent, {'title': get_category_title(user), 'description': description})
category.protection_mode = ProtectionMode.protected
category.update_principal(user, full_access=True)
return category


def get_category_title(user):
return f"{user.full_name}'s category ({user.id})"
66 changes: 66 additions & 0 deletions i18n-demo/indico_i18n_demo/plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from flask_pluginengine.plugin import render_plugin_template

Check failure on line 1 in i18n-demo/indico_i18n_demo/plugin.py

View workflow job for this annotation

GitHub Actions / lint

Missing header

from indico.core.plugins import IndicoPlugin
from indico.core import signals

from indico.web.forms.base import IndicoForm
from wtforms.fields import IntegerField
from wtforms.validators import NumberRange, Optional
from indico.modules.categories.models.categories import Category
from indico_i18n_demo.blueprint import blueprint
from indico.util.signals import interceptable_sender
from indico.core.notifications import make_email
from flask import session
from indico.core.config import config


class PluginSettingsForm(IndicoForm):
test_category_id = IntegerField('Test category ID', [Optional(), NumberRange(min=1)],
description='The ID of the category to clone events to')


class I18nDemoPlugin(IndicoPlugin):
"""I18n Demo
Provides utilities for the i18n-demo instance.
"""

configurable = True
settings_form = PluginSettingsForm
default_settings = {
'test_category_id': ''
}

def init(self):
super().init()
self.template_hook('event-status-labels', self._inject_clone_button)
self.connect(signals.plugin.interceptable_function, self._intercept_make_email,
sender=interceptable_sender(make_email))

def get_blueprints(self):
return blueprint

def _inject_clone_button(self, event, **kwargs):
if not (test_category_id := self.settings.get('test_category_id')):
return

if not (test_category := Category.get(int(test_category_id))):
return

if event.category != test_category and not event.category.is_descendant_of(test_category):
return render_plugin_template('clone_button.html', event=event)

def _intercept_make_email(self, sender, func, args, **kwargs):
ret = func(**args.arguments)

return {
'to': {session.user.email},
'cc': set(),
'bcc': set(),
'from': config.NO_REPLY_EMAIL,
'reply_to': set(),
'attachments': ret['attachments'],
'subject': ret['subject'],
'body': ret['body'],
'html': ret['html'],
}
9 changes: 9 additions & 0 deletions i18n-demo/indico_i18n_demo/templates/clone_button.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<button type="button"
class="ui tiny compact button ui-qtip"
style="margin-left: 2em;"
title="Clone event into your personal category with full management rights"
data-href="{{ url_for('plugin_i18n_demo.clone_event', event) }}"
data-method="POST">
<i aria-hidden="true" class="icon clone alternate"></i>
Clone
</button>
28 changes: 28 additions & 0 deletions i18n-demo/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[metadata]
name = indico-plugin-i18n-demo
version = 3.3-dev
description = Indico plugin to sanitize a database for testing
url = https://github.com/indico/indico-plugins-cern/i18n-demo
license = MIT
author = Indico Team
author_email = indico-team@cern.ch
classifiers =
Environment :: Plugins
Environment :: Web Environment
License :: OSI Approved :: MIT License
Programming Language :: Python :: 3.12

[options]
packages = find:
zip_safe = false
include_package_data = true
python_requires = >=3.12, <3.13
install_requires =
indico>=3.3.2-dev0

[options.entry_points]
indico.plugins =
i18n_demo = indico_i18n_demo.plugin:I18nDemoPlugin

[pydocstyle]
ignore = D100,D101,D102,D103,D104,D105,D107,D203,D213
4 changes: 4 additions & 0 deletions i18n-demo/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from setuptools import setup

Check failure on line 1 in i18n-demo/setup.py

View workflow job for this annotation

GitHub Actions / lint

Missing header


setup()

0 comments on commit 5772823

Please sign in to comment.