From cc77097069dac6f91da95b5268a848bafc199d18 Mon Sep 17 00:00:00 2001 From: mkangia Date: Fri, 14 Dec 2018 00:52:45 +0530 Subject: [PATCH 01/24] add model --- .../0002_latestenabledbuildprofiles.py | 27 +++++++++++++++++++ corehq/apps/app_manager/models.py | 7 +++++ 2 files changed, 34 insertions(+) create mode 100644 corehq/apps/app_manager/migrations/0002_latestenabledbuildprofiles.py diff --git a/corehq/apps/app_manager/migrations/0002_latestenabledbuildprofiles.py b/corehq/apps/app_manager/migrations/0002_latestenabledbuildprofiles.py new file mode 100644 index 000000000000..cb4a76d2fc09 --- /dev/null +++ b/corehq/apps/app_manager/migrations/0002_latestenabledbuildprofiles.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.16 on 2018-12-11 22:05 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('app_manager', '0001_linked_app_domain'), + ] + + operations = [ + migrations.CreateModel( + name='LatestEnabledBuildProfiles', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('app_id', models.CharField(max_length=255)), + ('build_profile_id', models.CharField(max_length=255)), + ('version', models.IntegerField()), + ('build_id', models.CharField(max_length=255)), + ], + ), + ] diff --git a/corehq/apps/app_manager/models.py b/corehq/apps/app_manager/models.py index 5dd385b0d032..526c9f75a721 100644 --- a/corehq/apps/app_manager/models.py +++ b/corehq/apps/app_manager/models.py @@ -29,6 +29,7 @@ from django.core.cache import cache from django.utils.translation import override, ugettext as _, ugettext from django.utils.translation import ugettext_lazy +from django.db import models from couchdbkit.exceptions import BadValueError from corehq.apps.app_manager.app_schemas.case_properties import ( @@ -6834,6 +6835,12 @@ def save(self, *args, **kwargs): super(GlobalAppConfig, self).save(*args, **kwargs) +class LatestEnabledBuildProfiles(models.Model): + app_id = models.CharField(max_length=255) + build_profile_id = models.CharField(max_length=255) + version = models.IntegerField() + build_id = models.CharField(max_length=255) + # backwards compatibility with suite-1.0.xml FormBase.get_command_id = lambda self: id_strings.form_command(self) FormBase.get_locale_id = lambda self: id_strings.form_locale(self) From 47c59194e775ace8b4b13b27e9e63b675b3c9823 Mon Sep 17 00:00:00 2001 From: mkangia Date: Fri, 14 Dec 2018 00:54:26 +0530 Subject: [PATCH 02/24] add ability to view build profiles and toggle them --- .../templates/app_manager/download_index.html | 25 +++++++++++++++++++ .../templates/app_manager/source_files.html | 1 + corehq/apps/app_manager/urls.py | 4 ++- corehq/apps/app_manager/util.py | 5 ++++ corehq/apps/app_manager/views/__init__.py | 1 + corehq/apps/app_manager/views/download.py | 12 ++++++--- corehq/toggles.py | 8 ++++++ 7 files changed, 52 insertions(+), 4 deletions(-) diff --git a/corehq/apps/app_manager/templates/app_manager/download_index.html b/corehq/apps/app_manager/templates/app_manager/download_index.html index a06854f700dd..1e0753dc5c98 100644 --- a/corehq/apps/app_manager/templates/app_manager/download_index.html +++ b/corehq/apps/app_manager/templates/app_manager/download_index.html @@ -8,6 +8,31 @@ {{ app.name }}: Build #{{ app.version }}{% if app.build_comment %}: {{ app.build_comment }}{% endif %} {% endblock page_title %} +{% if request|toggle_enabled:"RELEASE_BUILDS_PER_PROFILE" %} + {% block app_profiles %} +

App Profiles

+ + + + + + + {% for build_profile_id, build_profile in app.build_profiles.items %} + + + + + + {% endfor %} +
NameLangsAction
{{ build_profile.name }}{{ build_profile.langs|join:", " }} + {% if build_profile_id in enabled_build_profiles %} + Disable + {% else %} + Enable + {% endif %} +
+ {% endblock %} +{% endif %} {% block downloads %}

Downloads

diff --git a/corehq/apps/app_manager/templates/app_manager/source_files.html b/corehq/apps/app_manager/templates/app_manager/source_files.html index b9bbc36190e9..20eb96299903 100644 --- a/corehq/apps/app_manager/templates/app_manager/source_files.html +++ b/corehq/apps/app_manager/templates/app_manager/source_files.html @@ -21,6 +21,7 @@ {% endif %}

+ {% block app_profiles %}{% endblock %} {% block downloads %}{% endblock %}

Resource Files

diff --git a/corehq/apps/app_manager/urls.py b/corehq/apps/app_manager/urls.py index 8cc993abdf0c..c4af88cf8f5c 100644 --- a/corehq/apps/app_manager/urls.py +++ b/corehq/apps/app_manager/urls.py @@ -27,7 +27,7 @@ edit_app_langs, edit_app_attr, edit_app_ui_translations, get_app_ui_translations, rearrange, odk_qr_code, odk_media_qr_code, odk_install, short_url, short_odk_url, save_copy, revert_to_copy, delete_copy, list_apps, direct_ccz, download_index, download_file, get_form_questions, pull_master_app, edit_add_ons, - update_linked_whitelist, overwrite_module_case_list, app_settings + update_linked_whitelist, overwrite_module_case_list, app_settings, toggle_build_profile, ) from corehq.apps.translations.views import ( download_bulk_ui_translations, download_bulk_app_translations, upload_bulk_ui_translations, @@ -180,6 +180,8 @@ url(r'^api/list_apps/$', list_apps, name='list_apps'), url(r'^api/download_ccz/$', direct_ccz, name='direct_ccz'), url(r'^download/(?P[\w-]+)/$', download_index, name='download_index'), + url(r'^build_profile/(?P[\w-]+)/toggle/(?P[\w-]+)$', toggle_build_profile, + name='toggle_build_profile'), # the order of these download urls is important url(r'^download/(?P[\w-]+)/CommCare.ccz$', DownloadCCZ.as_view(), name=DownloadCCZ.name), diff --git a/corehq/apps/app_manager/util.py b/corehq/apps/app_manager/util.py index c7019e1140d1..0896cd6056c7 100644 --- a/corehq/apps/app_manager/util.py +++ b/corehq/apps/app_manager/util.py @@ -27,6 +27,7 @@ get_apps_in_domain, get_app ) from corehq.apps.app_manager.exceptions import SuiteError, SuiteValidationError, PracticeUserException +from corehq.apps.app_manager.models import LatestEnabledBuildProfiles from corehq.apps.app_manager.xpath import DOT_INTERPOLATE_PATTERN, UserCaseXPath from corehq.apps.builds.models import CommCareBuildConfig from corehq.apps.app_manager.tasks import create_user_cases @@ -688,3 +689,7 @@ def get_form_source_download_url(xform): xform.build_id, app.get_form_filename(module=form.get_module(), form=form), ]) + +def get_enabled_build_profiles_for_version(app_id, version): + return list(LatestEnabledBuildProfiles.objects.filter( + app_id=app_id, version=version).values_list('build_profile_id', flat=True)) diff --git a/corehq/apps/app_manager/views/__init__.py b/corehq/apps/app_manager/views/__init__.py index 8412b611a9ea..380772012847 100644 --- a/corehq/apps/app_manager/views/__init__.py +++ b/corehq/apps/app_manager/views/__init__.py @@ -106,6 +106,7 @@ short_odk_url, short_url, update_build_comment, + toggle_build_profile, ) from corehq.apps.app_manager.views.schedules import ( edit_schedule_phases, diff --git a/corehq/apps/app_manager/views/download.py b/corehq/apps/app_manager/views/download.py index 3d523b94adba..71ddbbb9c9e5 100644 --- a/corehq/apps/app_manager/views/download.py +++ b/corehq/apps/app_manager/views/download.py @@ -12,12 +12,13 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ +from corehq import toggles from corehq.apps.app_manager.dbaccessors import get_all_built_app_ids_and_versions, get_app from corehq.apps.app_manager.decorators import safe_download, safe_cached_download from corehq.apps.app_manager.exceptions import ModuleNotFoundException, \ AppManagerException, FormNotFoundException -from corehq.apps.app_manager.models import Application -from corehq.apps.app_manager.util import add_odk_profile_after_build +from corehq.apps.app_manager.models import Application, LatestEnabledBuildProfiles +from corehq.apps.app_manager.util import add_odk_profile_after_build, get_enabled_build_profiles_for_version from corehq.apps.app_manager.views.utils import back_to_main, get_langs from corehq.apps.app_manager.tasks import make_async_build from corehq.apps.builds.jadjar import convert_XML_To_J2ME @@ -409,6 +410,10 @@ def download_index(request, domain, app_id): extra_tags='html' ) built_versions = get_all_built_app_ids_and_versions(domain, request.app.copy_of) + enabled_build_profiles = [] + if toggles.RELEASE_BUILDS_PER_PROFILE.enabled(domain): + enabled_build_profiles = get_enabled_build_profiles_for_version(request.app.copy_of, request.app.version) + return render(request, "app_manager/download_index.html", { 'app': request.app, 'files': OrderedDict(sorted(six.iteritems(files), key=lambda x: x[0])), @@ -418,7 +423,8 @@ def download_index(request, domain, app_id): 'build_id': build_id, 'version': version, 'comment': comment, - } for app_id, build_id, version, comment in built_versions] + } for app_id, build_id, version, comment in built_versions], + 'enabled_build_profiles': enabled_build_profiles }) diff --git a/corehq/toggles.py b/corehq/toggles.py index 1de2042e958a..e9a6072bf00f 100644 --- a/corehq/toggles.py +++ b/corehq/toggles.py @@ -1679,3 +1679,11 @@ def _commtrackify(domain_name, toggle_is_enabled): TAG_CUSTOM, namespaces=[NAMESPACE_DOMAIN], ) + + +RELEASE_BUILDS_PER_PROFILE = StaticToggle( + 'release_builds_per_profile', + 'Do not release builds for all app profiles by default. Then manage via Source files view', + TAG_CUSTOM, + namespaces=[NAMESPACE_DOMAIN], +) From f01fc37f3d3a3c3d21ba25615f462c2004015db0 Mon Sep 17 00:00:00 2001 From: mkangia Date: Fri, 14 Dec 2018 00:54:46 +0530 Subject: [PATCH 03/24] add view --- corehq/apps/app_manager/util.py | 10 +++++ corehq/apps/app_manager/views/releases.py | 48 ++++++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/corehq/apps/app_manager/util.py b/corehq/apps/app_manager/util.py index 0896cd6056c7..ebf507d01470 100644 --- a/corehq/apps/app_manager/util.py +++ b/corehq/apps/app_manager/util.py @@ -690,6 +690,16 @@ def get_form_source_download_url(xform): app.get_form_filename(module=form.get_module(), form=form), ]) + +def get_latest_enabled_build_for_profile(profile_id): + latest_enabled_build = (LatestEnabledBuildProfiles.objects. + filter(build_profile_id=profile_id) + .order_by('-version') + .first()) + if latest_enabled_build: + return latest_enabled_build.build_id + + def get_enabled_build_profiles_for_version(app_id, version): return list(LatestEnabledBuildProfiles.objects.filter( app_id=app_id, version=version).values_list('build_profile_id', flat=True)) diff --git a/corehq/apps/app_manager/views/releases.py b/corehq/apps/app_manager/views/releases.py index 04beaa2ca9a3..778faace63fe 100644 --- a/corehq/apps/app_manager/views/releases.py +++ b/corehq/apps/app_manager/views/releases.py @@ -19,7 +19,7 @@ from django.contrib import messages from django.shortcuts import render from django.template.loader import render_to_string -from django.utils.translation import ugettext_lazy +from django.utils.translation import ugettext_lazy, ugettext as _ from django.views.decorators.cache import cache_control import ghdiff @@ -44,7 +44,7 @@ from corehq.apps.app_manager.dbaccessors import get_app, get_latest_build_doc, get_latest_build_id, \ get_latest_released_app_version, get_built_app_ids_for_app_id -from corehq.apps.app_manager.models import BuildProfile +from corehq.apps.app_manager.models import BuildProfile, LatestEnabledBuildProfiles from corehq.apps.app_manager.const import DEFAULT_FETCH_LIMIT from corehq.apps.users.models import CommCareUser from corehq.util.datadog.gauges import datadog_bucket_timer @@ -554,3 +554,47 @@ def practice_user_id(): def get(self, request, *args, **kwargs): return HttpResponse() + + +def toggle_build_profile(request, domain, app_id, build_profile_id): + app = Application.get(app_id) + action = request.GET.get('action') + latest_enabled_build_profile = LatestEnabledBuildProfiles.objects.filter( + app_id=app.copy_of, + build_profile_id=build_profile_id + ).order_by('-version').first() + if latest_enabled_build_profile: + if latest_enabled_build_profile.version > app.version: + messages.error(request, _( + "Latest version available for this profile is {}, which is " + "higher than this version. Disable any higher versions first.".format( + latest_enabled_build_profile.version + ))) + return HttpResponseRedirect(reverse('download_index', args=[domain, app_id])) + if action == 'enable': + LatestEnabledBuildProfiles.objects.create( + app_id=app.copy_of, + version=app.version, + build_profile_id=build_profile_id, + build_id=app_id + ) + elif action == 'disable': + LatestEnabledBuildProfiles.objects.filter( + app_id=app.copy_of, + version=app.version, + build_profile_id=build_profile_id, + build_id=app_id + ).delete() + latest_enabled_build_profile = LatestEnabledBuildProfiles.objects.filter( + app_id=app.copy_of, + build_profile_id=build_profile_id + ).order_by('-version').first() + if latest_enabled_build_profile: + messages.success(request, _("Latest version for profile {} is now {}").format( + app.build_profiles[build_profile_id].name, latest_enabled_build_profile.version + )) + else: + messages.success(request, _("Latest release now available for profile {}").format( + app.build_profiles[build_profile_id].name + )) + return HttpResponseRedirect(reverse('download_index', args=[domain, app_id])) From 5adc7dcd5189c426d3a38edba9d5bebbe5efe606 Mon Sep 17 00:00:00 2001 From: mkangia Date: Fri, 14 Dec 2018 00:55:17 +0530 Subject: [PATCH 04/24] return latest enabled app for build profile when checked --- corehq/apps/app_manager/decorators.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/corehq/apps/app_manager/decorators.py b/corehq/apps/app_manager/decorators.py index 58c03810eb02..8fd90c0a3ba6 100644 --- a/corehq/apps/app_manager/decorators.py +++ b/corehq/apps/app_manager/decorators.py @@ -7,9 +7,11 @@ from couchdbkit.exceptions import ResourceConflict from django.views.decorators.http import require_POST from django.urls import reverse +from corehq import toggles from corehq.apps.app_manager.exceptions import CaseError from corehq.apps.app_manager.dbaccessors import get_app from corehq.apps.app_manager.models import AppEditingError +from corehq.apps.app_manager.util import get_latest_enabled_build_for_profile from corehq.apps.users.decorators import require_permission from corehq.apps.users.models import Permissions from corehq.apps.domain.decorators import login_and_domain_required @@ -68,7 +70,13 @@ def _safe_cached_download(request, *args, **kwargs): request.GET.pop('username') try: - request.app = get_app(domain, app_id, latest=latest, target=target) + latest_enabled_build = None + if request.GET.get('profile') and toggles.RELEASE_BUILDS_PER_PROFILE.enabled(domain): + latest_enabled_build = get_latest_enabled_build_for_profile(request.GET.get('profile')) + if latest_enabled_build: + request.app = get_app(domain, latest_enabled_build) + else: + request.app = get_app(domain, app_id, latest=latest, target=target) if not request.app.doc_type.endswith(DELETED_SUFFIX): response = f(request, *args, **kwargs) if request.app.copy_of is not None and request.app.is_released: From 1f860046c19d78a19c76a05d7478e7d84a47dddf Mon Sep 17 00:00:00 2001 From: mkangia Date: Fri, 14 Dec 2018 01:43:44 +0530 Subject: [PATCH 05/24] fix import issue --- corehq/apps/app_manager/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/corehq/apps/app_manager/util.py b/corehq/apps/app_manager/util.py index ebf507d01470..9a6bced83349 100644 --- a/corehq/apps/app_manager/util.py +++ b/corehq/apps/app_manager/util.py @@ -27,7 +27,6 @@ get_apps_in_domain, get_app ) from corehq.apps.app_manager.exceptions import SuiteError, SuiteValidationError, PracticeUserException -from corehq.apps.app_manager.models import LatestEnabledBuildProfiles from corehq.apps.app_manager.xpath import DOT_INTERPOLATE_PATTERN, UserCaseXPath from corehq.apps.builds.models import CommCareBuildConfig from corehq.apps.app_manager.tasks import create_user_cases @@ -692,6 +691,7 @@ def get_form_source_download_url(xform): def get_latest_enabled_build_for_profile(profile_id): + from corehq.apps.app_manager.models import LatestEnabledBuildProfiles latest_enabled_build = (LatestEnabledBuildProfiles.objects. filter(build_profile_id=profile_id) .order_by('-version') @@ -701,5 +701,6 @@ def get_latest_enabled_build_for_profile(profile_id): def get_enabled_build_profiles_for_version(app_id, version): + from corehq.apps.app_manager.models import LatestEnabledBuildProfiles return list(LatestEnabledBuildProfiles.objects.filter( app_id=app_id, version=version).values_list('build_profile_id', flat=True)) From fc042cf85dad34d0ce559bda027ba5ba5cd964ae Mon Sep 17 00:00:00 2001 From: mkangia Date: Fri, 14 Dec 2018 01:44:10 +0530 Subject: [PATCH 06/24] correct return and check for latest only when enabling --- corehq/apps/app_manager/views/releases.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/corehq/apps/app_manager/views/releases.py b/corehq/apps/app_manager/views/releases.py index 778faace63fe..d88145c10297 100644 --- a/corehq/apps/app_manager/views/releases.py +++ b/corehq/apps/app_manager/views/releases.py @@ -563,14 +563,14 @@ def toggle_build_profile(request, domain, app_id, build_profile_id): app_id=app.copy_of, build_profile_id=build_profile_id ).order_by('-version').first() - if latest_enabled_build_profile: + if action == 'enable' and latest_enabled_build_profile: if latest_enabled_build_profile.version > app.version: messages.error(request, _( "Latest version available for this profile is {}, which is " "higher than this version. Disable any higher versions first.".format( latest_enabled_build_profile.version ))) - return HttpResponseRedirect(reverse('download_index', args=[domain, app_id])) + return HttpResponseRedirect(reverse('download_index', args=[domain, app_id])) if action == 'enable': LatestEnabledBuildProfiles.objects.create( app_id=app.copy_of, From e9f0fca76c125b2ee0d6670aac9a10e41cd81847 Mon Sep 17 00:00:00 2001 From: mkangia Date: Fri, 14 Dec 2018 15:13:57 +0530 Subject: [PATCH 07/24] make if work by placing it correctly [skip ci] --- .../templates/app_manager/download_index.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/corehq/apps/app_manager/templates/app_manager/download_index.html b/corehq/apps/app_manager/templates/app_manager/download_index.html index 1e0753dc5c98..44e297535583 100644 --- a/corehq/apps/app_manager/templates/app_manager/download_index.html +++ b/corehq/apps/app_manager/templates/app_manager/download_index.html @@ -8,8 +8,8 @@ {{ app.name }}: Build #{{ app.version }}{% if app.build_comment %}: {{ app.build_comment }}{% endif %} {% endblock page_title %} -{% if request|toggle_enabled:"RELEASE_BUILDS_PER_PROFILE" %} - {% block app_profiles %} +{% block app_profiles %} + {% if request|toggle_enabled:"RELEASE_BUILDS_PER_PROFILE" %}

App Profiles

@@ -31,8 +31,9 @@

App Profiles

{% endfor %}
- {% endblock %} -{% endif %} + {% endif %} +{% endblock %} + {% block downloads %}

Downloads

From 2c633403f8827eea65cbdd8d1ab03d2ab30f5d46 Mon Sep 17 00:00:00 2001 From: mkangia Date: Fri, 14 Dec 2018 20:58:09 +0530 Subject: [PATCH 08/24] lint --- .../migrations/0002_latestenabledbuildprofiles.py | 1 + corehq/apps/app_manager/util.py | 2 +- corehq/apps/app_manager/views/download.py | 6 +++--- corehq/apps/app_manager/views/releases.py | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/corehq/apps/app_manager/migrations/0002_latestenabledbuildprofiles.py b/corehq/apps/app_manager/migrations/0002_latestenabledbuildprofiles.py index cb4a76d2fc09..f4fc1c92bcb3 100644 --- a/corehq/apps/app_manager/migrations/0002_latestenabledbuildprofiles.py +++ b/corehq/apps/app_manager/migrations/0002_latestenabledbuildprofiles.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-12-11 22:05 +from __future__ import absolute_import from __future__ import unicode_literals from django.db import migrations, models diff --git a/corehq/apps/app_manager/util.py b/corehq/apps/app_manager/util.py index 9a6bced83349..0c08127319a2 100644 --- a/corehq/apps/app_manager/util.py +++ b/corehq/apps/app_manager/util.py @@ -703,4 +703,4 @@ def get_latest_enabled_build_for_profile(profile_id): def get_enabled_build_profiles_for_version(app_id, version): from corehq.apps.app_manager.models import LatestEnabledBuildProfiles return list(LatestEnabledBuildProfiles.objects.filter( - app_id=app_id, version=version).values_list('build_profile_id', flat=True)) + app_id=app_id, version=version).values_list('build_profile_id', flat=True)) diff --git a/corehq/apps/app_manager/views/download.py b/corehq/apps/app_manager/views/download.py index 71ddbbb9c9e5..1ef269a64571 100644 --- a/corehq/apps/app_manager/views/download.py +++ b/corehq/apps/app_manager/views/download.py @@ -17,7 +17,7 @@ from corehq.apps.app_manager.decorators import safe_download, safe_cached_download from corehq.apps.app_manager.exceptions import ModuleNotFoundException, \ AppManagerException, FormNotFoundException -from corehq.apps.app_manager.models import Application, LatestEnabledBuildProfiles +from corehq.apps.app_manager.models import Application from corehq.apps.app_manager.util import add_odk_profile_after_build, get_enabled_build_profiles_for_version from corehq.apps.app_manager.views.utils import back_to_main, get_langs from corehq.apps.app_manager.tasks import make_async_build @@ -419,11 +419,11 @@ def download_index(request, domain, app_id): 'files': OrderedDict(sorted(six.iteritems(files), key=lambda x: x[0])), 'supports_j2me': request.app.build_spec.supports_j2me(), 'built_versions': [{ - 'app_id': app_id, + 'app_id': _app_id, 'build_id': build_id, 'version': version, 'comment': comment, - } for app_id, build_id, version, comment in built_versions], + } for _app_id, build_id, version, comment in built_versions], 'enabled_build_profiles': enabled_build_profiles }) diff --git a/corehq/apps/app_manager/views/releases.py b/corehq/apps/app_manager/views/releases.py index d88145c10297..2f7eecce7f19 100644 --- a/corehq/apps/app_manager/views/releases.py +++ b/corehq/apps/app_manager/views/releases.py @@ -569,7 +569,7 @@ def toggle_build_profile(request, domain, app_id, build_profile_id): "Latest version available for this profile is {}, which is " "higher than this version. Disable any higher versions first.".format( latest_enabled_build_profile.version - ))) + ))) return HttpResponseRedirect(reverse('download_index', args=[domain, app_id])) if action == 'enable': LatestEnabledBuildProfiles.objects.create( From b61feaf5647cb2f087319f4f916cfafd414113fc Mon Sep 17 00:00:00 2001 From: mkangia Date: Sat, 15 Dec 2018 00:16:26 +0530 Subject: [PATCH 09/24] app -> build and add authentication --- corehq/apps/app_manager/urls.py | 2 +- corehq/apps/app_manager/views/releases.py | 31 ++++++++++++----------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/corehq/apps/app_manager/urls.py b/corehq/apps/app_manager/urls.py index c4af88cf8f5c..52fba1898522 100644 --- a/corehq/apps/app_manager/urls.py +++ b/corehq/apps/app_manager/urls.py @@ -180,7 +180,7 @@ url(r'^api/list_apps/$', list_apps, name='list_apps'), url(r'^api/download_ccz/$', direct_ccz, name='direct_ccz'), url(r'^download/(?P[\w-]+)/$', download_index, name='download_index'), - url(r'^build_profile/(?P[\w-]+)/toggle/(?P[\w-]+)$', toggle_build_profile, + url(r'^build_profile/(?P[\w-]+)/toggle/(?P[\w-]+)$', toggle_build_profile, name='toggle_build_profile'), # the order of these download urls is important url(r'^download/(?P[\w-]+)/CommCare.ccz$', DownloadCCZ.as_view(), diff --git a/corehq/apps/app_manager/views/releases.py b/corehq/apps/app_manager/views/releases.py index 2f7eecce7f19..0f9ed097f884 100644 --- a/corehq/apps/app_manager/views/releases.py +++ b/corehq/apps/app_manager/views/releases.py @@ -556,45 +556,46 @@ def get(self, request, *args, **kwargs): return HttpResponse() -def toggle_build_profile(request, domain, app_id, build_profile_id): - app = Application.get(app_id) +@require_can_edit_apps +def toggle_build_profile(request, domain, build_id, build_profile_id): + build = Application.get(build_id) action = request.GET.get('action') latest_enabled_build_profile = LatestEnabledBuildProfiles.objects.filter( - app_id=app.copy_of, + app_id=build.copy_of, build_profile_id=build_profile_id ).order_by('-version').first() if action == 'enable' and latest_enabled_build_profile: - if latest_enabled_build_profile.version > app.version: + if latest_enabled_build_profile.version > build.version: messages.error(request, _( "Latest version available for this profile is {}, which is " "higher than this version. Disable any higher versions first.".format( latest_enabled_build_profile.version ))) - return HttpResponseRedirect(reverse('download_index', args=[domain, app_id])) + return HttpResponseRedirect(reverse('download_index', args=[domain, build_id])) if action == 'enable': LatestEnabledBuildProfiles.objects.create( - app_id=app.copy_of, - version=app.version, + app_id=build.copy_of, + version=build.version, build_profile_id=build_profile_id, - build_id=app_id + build_id=build_id ) elif action == 'disable': LatestEnabledBuildProfiles.objects.filter( - app_id=app.copy_of, - version=app.version, + app_id=build.copy_of, + version=build.version, build_profile_id=build_profile_id, - build_id=app_id + build_id=build_id ).delete() latest_enabled_build_profile = LatestEnabledBuildProfiles.objects.filter( - app_id=app.copy_of, + app_id=build.copy_of, build_profile_id=build_profile_id ).order_by('-version').first() if latest_enabled_build_profile: messages.success(request, _("Latest version for profile {} is now {}").format( - app.build_profiles[build_profile_id].name, latest_enabled_build_profile.version + build.build_profiles[build_profile_id].name, latest_enabled_build_profile.version )) else: messages.success(request, _("Latest release now available for profile {}").format( - app.build_profiles[build_profile_id].name + build.build_profiles[build_profile_id].name )) - return HttpResponseRedirect(reverse('download_index', args=[domain, app_id])) + return HttpResponseRedirect(reverse('download_index', args=[domain, build_id])) From 58f67dffb7dcd5b19d5def291ee89cf2f8d775ed Mon Sep 17 00:00:00 2001 From: mkangia Date: Sat, 15 Dec 2018 00:22:34 +0530 Subject: [PATCH 10/24] get non try-except logic out of that block. Use languages --- corehq/apps/app_manager/decorators.py | 6 +++--- .../app_manager/templates/app_manager/download_index.html | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/corehq/apps/app_manager/decorators.py b/corehq/apps/app_manager/decorators.py index 8fd90c0a3ba6..5d6809960abc 100644 --- a/corehq/apps/app_manager/decorators.py +++ b/corehq/apps/app_manager/decorators.py @@ -69,10 +69,10 @@ def _safe_cached_download(request, *args, **kwargs): request.GET = request.GET.copy() request.GET.pop('username') + latest_enabled_build = None + if request.GET.get('profile') and toggles.RELEASE_BUILDS_PER_PROFILE.enabled(domain): + latest_enabled_build = get_latest_enabled_build_for_profile(request.GET.get('profile')) try: - latest_enabled_build = None - if request.GET.get('profile') and toggles.RELEASE_BUILDS_PER_PROFILE.enabled(domain): - latest_enabled_build = get_latest_enabled_build_for_profile(request.GET.get('profile')) if latest_enabled_build: request.app = get_app(domain, latest_enabled_build) else: diff --git a/corehq/apps/app_manager/templates/app_manager/download_index.html b/corehq/apps/app_manager/templates/app_manager/download_index.html index 44e297535583..bb8bae864359 100644 --- a/corehq/apps/app_manager/templates/app_manager/download_index.html +++ b/corehq/apps/app_manager/templates/app_manager/download_index.html @@ -14,7 +14,7 @@

App Profiles

- + {% for build_profile_id, build_profile in app.build_profiles.items %} From d3b16a32c71d4f401075d95b23b22d6163f024bd Mon Sep 17 00:00:00 2001 From: mkangia Date: Mon, 17 Dec 2018 23:20:01 +0530 Subject: [PATCH 11/24] load build and cache it --- corehq/apps/app_manager/decorators.py | 4 ++-- corehq/apps/app_manager/util.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/corehq/apps/app_manager/decorators.py b/corehq/apps/app_manager/decorators.py index 5d6809960abc..a525ecf5d800 100644 --- a/corehq/apps/app_manager/decorators.py +++ b/corehq/apps/app_manager/decorators.py @@ -71,10 +71,10 @@ def _safe_cached_download(request, *args, **kwargs): latest_enabled_build = None if request.GET.get('profile') and toggles.RELEASE_BUILDS_PER_PROFILE.enabled(domain): - latest_enabled_build = get_latest_enabled_build_for_profile(request.GET.get('profile')) + latest_enabled_build = get_latest_enabled_build_for_profile(domain, request.GET.get('profile')) try: if latest_enabled_build: - request.app = get_app(domain, latest_enabled_build) + request.app = latest_enabled_build else: request.app = get_app(domain, app_id, latest=latest, target=target) if not request.app.doc_type.endswith(DELETED_SUFFIX): diff --git a/corehq/apps/app_manager/util.py b/corehq/apps/app_manager/util.py index 0c08127319a2..dd5bf0c3d66f 100644 --- a/corehq/apps/app_manager/util.py +++ b/corehq/apps/app_manager/util.py @@ -690,14 +690,15 @@ def get_form_source_download_url(xform): ]) -def get_latest_enabled_build_for_profile(profile_id): +@quickcache(['domain', 'profile_id'], timeout=24 * 60 * 60) +def get_latest_enabled_build_for_profile(domain, profile_id): from corehq.apps.app_manager.models import LatestEnabledBuildProfiles latest_enabled_build = (LatestEnabledBuildProfiles.objects. filter(build_profile_id=profile_id) .order_by('-version') .first()) if latest_enabled_build: - return latest_enabled_build.build_id + return get_app(domain, latest_enabled_build.build_id) def get_enabled_build_profiles_for_version(app_id, version): From 9f52f5157257177ad0fe0f55becbdef3be2429ee Mon Sep 17 00:00:00 2001 From: mkangia Date: Mon, 17 Dec 2018 23:21:10 +0530 Subject: [PATCH 12/24] use build id instead of app id --- corehq/apps/app_manager/util.py | 5 +++-- corehq/apps/app_manager/views/download.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/corehq/apps/app_manager/util.py b/corehq/apps/app_manager/util.py index dd5bf0c3d66f..95b1ed810493 100644 --- a/corehq/apps/app_manager/util.py +++ b/corehq/apps/app_manager/util.py @@ -701,7 +701,8 @@ def get_latest_enabled_build_for_profile(domain, profile_id): return get_app(domain, latest_enabled_build.build_id) -def get_enabled_build_profiles_for_version(app_id, version): +@quickcache(['build_id', 'version'], timeout=24 * 60 * 60) +def get_enabled_build_profiles_for_version(build_id, version): from corehq.apps.app_manager.models import LatestEnabledBuildProfiles return list(LatestEnabledBuildProfiles.objects.filter( - app_id=app_id, version=version).values_list('build_profile_id', flat=True)) + build_id=build_id, version=version).values_list('build_profile_id', flat=True)) diff --git a/corehq/apps/app_manager/views/download.py b/corehq/apps/app_manager/views/download.py index 1ef269a64571..46fca4da1d0a 100644 --- a/corehq/apps/app_manager/views/download.py +++ b/corehq/apps/app_manager/views/download.py @@ -412,7 +412,7 @@ def download_index(request, domain, app_id): built_versions = get_all_built_app_ids_and_versions(domain, request.app.copy_of) enabled_build_profiles = [] if toggles.RELEASE_BUILDS_PER_PROFILE.enabled(domain): - enabled_build_profiles = get_enabled_build_profiles_for_version(request.app.copy_of, request.app.version) + enabled_build_profiles = get_enabled_build_profiles_for_version(request.app.get_id, request.app.version) return render(request, "app_manager/download_index.html", { 'app': request.app, From b16bcde8422460a98ffa81a477e3eba469760c2e Mon Sep 17 00:00:00 2001 From: mkangia Date: Mon, 17 Dec 2018 23:22:26 +0530 Subject: [PATCH 13/24] expire caches on app save and profile updates --- corehq/apps/app_manager/models.py | 6 ++++++ corehq/apps/app_manager/signals.py | 10 ++++++++++ corehq/apps/app_manager/views/releases.py | 9 ++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/corehq/apps/app_manager/models.py b/corehq/apps/app_manager/models.py index 526c9f75a721..0a17632fbfa2 100644 --- a/corehq/apps/app_manager/models.py +++ b/corehq/apps/app_manager/models.py @@ -128,6 +128,8 @@ LatestAppInfo, update_report_module_ids, module_offers_search, + get_latest_enabled_build_for_profile, + get_enabled_build_profiles_for_version, ) from corehq.apps.app_manager.xform import XForm, parse_xml as _parse_xml, \ validate_xform @@ -6841,6 +6843,10 @@ class LatestEnabledBuildProfiles(models.Model): version = models.IntegerField() build_id = models.CharField(max_length=255) + def expire_cache(self, domain): + get_latest_enabled_build_for_profile.clear(domain, self.build_profile_id) + get_enabled_build_profiles_for_version.clear(self.build_id, self.version) + # backwards compatibility with suite-1.0.xml FormBase.get_command_id = lambda self: id_strings.form_command(self) FormBase.get_locale_id = lambda self: id_strings.form_locale(self) diff --git a/corehq/apps/app_manager/signals.py b/corehq/apps/app_manager/signals.py index 7ec566ed17e9..82a64ddf6752 100644 --- a/corehq/apps/app_manager/signals.py +++ b/corehq/apps/app_manager/signals.py @@ -34,9 +34,19 @@ def update_callcenter_config(sender, application, **kwargs): notify_exception(None, "Error updating CallCenter config for app build") +def expire_latest_enabled_build_profiles(sender, application, **kwargs): + from corehq.apps.app_manager.util import get_latest_enabled_build_for_profile + from corehq.apps.app_manager.util import get_enabled_build_profiles_for_version + if application.copy_of: + for build_profile_id in application.build_profiles: + get_latest_enabled_build_for_profile.clear(application.domain, build_profile_id) + get_enabled_build_profiles_for_version(application.get_id, application.version) + + app_post_save = Signal(providing_args=['application']) app_post_save.connect(create_app_structure_repeat_records) app_post_save.connect(update_callcenter_config) +app_post_save.connect(expire_latest_enabled_build_profiles) app_post_release = Signal(providing_args=['application']) diff --git a/corehq/apps/app_manager/views/releases.py b/corehq/apps/app_manager/views/releases.py index 0f9ed097f884..3cdbcc79e0e5 100644 --- a/corehq/apps/app_manager/views/releases.py +++ b/corehq/apps/app_manager/views/releases.py @@ -573,19 +573,22 @@ def toggle_build_profile(request, domain, build_id, build_profile_id): ))) return HttpResponseRedirect(reverse('download_index', args=[domain, build_id])) if action == 'enable': - LatestEnabledBuildProfiles.objects.create( + build_profile = LatestEnabledBuildProfiles.objects.create( app_id=build.copy_of, version=build.version, build_profile_id=build_profile_id, build_id=build_id ) + build_profile.expire_cache(domain) elif action == 'disable': - LatestEnabledBuildProfiles.objects.filter( + build_profile = LatestEnabledBuildProfiles.objects.filter( app_id=build.copy_of, version=build.version, build_profile_id=build_profile_id, build_id=build_id - ).delete() + ).first() + build_profile.delete() + build_profile.expire_cache(domain) latest_enabled_build_profile = LatestEnabledBuildProfiles.objects.filter( app_id=build.copy_of, build_profile_id=build_profile_id From 57cbd455ccdf20dfcad6d918f3118c77c0953724 Mon Sep 17 00:00:00 2001 From: mkangia Date: Mon, 17 Dec 2018 23:22:48 +0530 Subject: [PATCH 14/24] fix imports --- corehq/apps/app_manager/util.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/corehq/apps/app_manager/util.py b/corehq/apps/app_manager/util.py index 95b1ed810493..c2d1a5006d56 100644 --- a/corehq/apps/app_manager/util.py +++ b/corehq/apps/app_manager/util.py @@ -27,7 +27,7 @@ get_apps_in_domain, get_app ) from corehq.apps.app_manager.exceptions import SuiteError, SuiteValidationError, PracticeUserException -from corehq.apps.app_manager.xpath import DOT_INTERPOLATE_PATTERN, UserCaseXPath +from corehq.apps.app_manager.xpath import UserCaseXPath from corehq.apps.builds.models import CommCareBuildConfig from corehq.apps.app_manager.tasks import create_user_cases from corehq.util.soft_assert import soft_assert @@ -36,7 +36,8 @@ AUTO_SELECT_USERCASE, USERCASE_TYPE, USERCASE_ID, - USERCASE_PREFIX) + USERCASE_PREFIX, +) from corehq.apps.app_manager.xform import XForm, XFormException, parse_xml from corehq.apps.users.models import CommCareUser from corehq.util.quickcache import quickcache From ca57e29c15ad02dee3cdad0d2159cbe33c15d6e0 Mon Sep 17 00:00:00 2001 From: mkangia Date: Mon, 17 Dec 2018 23:40:44 +0530 Subject: [PATCH 15/24] fix expire cache --- corehq/apps/app_manager/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corehq/apps/app_manager/signals.py b/corehq/apps/app_manager/signals.py index 82a64ddf6752..83f71e22124c 100644 --- a/corehq/apps/app_manager/signals.py +++ b/corehq/apps/app_manager/signals.py @@ -40,7 +40,7 @@ def expire_latest_enabled_build_profiles(sender, application, **kwargs): if application.copy_of: for build_profile_id in application.build_profiles: get_latest_enabled_build_for_profile.clear(application.domain, build_profile_id) - get_enabled_build_profiles_for_version(application.get_id, application.version) + get_enabled_build_profiles_for_version.clear(application.get_id, application.version) app_post_save = Signal(providing_args=['application']) From 4c78cbb732a302e689b0f4b31a7f42ff0462384a Mon Sep 17 00:00:00 2001 From: mkangia Date: Mon, 17 Dec 2018 23:43:47 +0530 Subject: [PATCH 16/24] move imports --- corehq/apps/app_manager/signals.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/corehq/apps/app_manager/signals.py b/corehq/apps/app_manager/signals.py index 83f71e22124c..0e73b1ca2300 100644 --- a/corehq/apps/app_manager/signals.py +++ b/corehq/apps/app_manager/signals.py @@ -4,6 +4,8 @@ from corehq.apps.callcenter.app_parser import get_call_center_config_from_app from corehq.apps.domain.models import Domain +from corehq.apps.app_manager.util import get_latest_enabled_build_for_profile +from corehq.apps.app_manager.util import get_enabled_build_profiles_for_version from dimagi.utils.logging import notify_exception @@ -35,8 +37,6 @@ def update_callcenter_config(sender, application, **kwargs): def expire_latest_enabled_build_profiles(sender, application, **kwargs): - from corehq.apps.app_manager.util import get_latest_enabled_build_for_profile - from corehq.apps.app_manager.util import get_enabled_build_profiles_for_version if application.copy_of: for build_profile_id in application.build_profiles: get_latest_enabled_build_for_profile.clear(application.domain, build_profile_id) From 60a8ffd9ad4125e12e04c6078492993a47eba2a5 Mon Sep 17 00:00:00 2001 From: mkangia Date: Wed, 19 Dec 2018 14:21:57 +0530 Subject: [PATCH 17/24] show latest enabled version with app profiles --- .../js/releases/app_view_release_manager.js | 5 ++++- .../app_manager/js/releases/language_profiles.js | 8 +++++--- .../app_manager/app_view_release_manager.html | 1 + .../partials/releases/build_profiles.html | 16 +++++++++++++++- corehq/apps/app_manager/util.py | 11 +++++++++++ corehq/apps/app_manager/views/apps.py | 6 ++++++ corehq/apps/app_manager/views/download.py | 5 ++++- 7 files changed, 46 insertions(+), 6 deletions(-) diff --git a/corehq/apps/app_manager/static/app_manager/js/releases/app_view_release_manager.js b/corehq/apps/app_manager/static/app_manager/js/releases/app_view_release_manager.js index 910fe36b1828..d864ad91c0ae 100644 --- a/corehq/apps/app_manager/static/app_manager/js/releases/app_view_release_manager.js +++ b/corehq/apps/app_manager/static/app_manager/js/releases/app_view_release_manager.js @@ -30,13 +30,16 @@ hqDefine("app_manager/js/releases/app_view_release_manager", function () { var $profilesTab = $('#profiles-tab'); if ($profilesTab.length) { var profiles = hqImport('app_manager/js/releases/language_profiles'); + var latest_enabled_versions = hqImport("hqwebapp/js/initial_page_data").get( + 'latest_version_for_build_profiles'); profiles.setProfileUrl(initial_page_data('application_profile_url')); var profileManagerModel = profiles.profileManager; var app_langs = initial_page_data("langs"); var app_profiles = initial_page_data('build_profiles'); var enable_practice_users = initial_page_data('enable_practice_users'); var practice_users = initial_page_data('practice_users'); - var profileManager = profileManagerModel(app_profiles, app_langs, enable_practice_users, practice_users); + var profileManager = profileManagerModel(app_profiles, app_langs, enable_practice_users, practice_users, + latest_enabled_versions); $profilesTab.koApplyBindings(profileManager); } diff --git a/corehq/apps/app_manager/static/app_manager/js/releases/language_profiles.js b/corehq/apps/app_manager/static/app_manager/js/releases/language_profiles.js index 8ce5d508372b..43f43e69b060 100644 --- a/corehq/apps/app_manager/static/app_manager/js/releases/language_profiles.js +++ b/corehq/apps/app_manager/static/app_manager/js/releases/language_profiles.js @@ -3,13 +3,14 @@ hqDefine('app_manager/js/releases/language_profiles', function () { var _p = {}; _p.profileUrl = 'profiles/'; - var profileModel = function (profileLangs, name, id, practiceUser) { + var profileModel = function (profileLangs, name, id, practiceUser, latestEnabledVersions) { var self = {}; self.id = id; self.langs = ko.observableArray(profileLangs); self.name = ko.observable(name); self.defaultLang = ko.observable(profileLangs[0]); self.practiceUser = ko.observable(practiceUser); + self.latestEnabledVersion = ko.observable(latestEnabledVersions[self.id]); return self; }; @@ -17,8 +18,9 @@ hqDefine('app_manager/js/releases/language_profiles', function () { _p.profileUrl = url; } - var profileManager = function (appProfiles, appLangs, enablePracticeUsers, practiceUsers) { + var profileManager = function (appProfiles, appLangs, enablePracticeUsers, practiceUsers, latest_enabled_versions) { var self = {}; + self.latest_enabled_versions = latest_enabled_versions; self.app_profiles = ko.observableArray([]); self.app_langs = appLangs; self.enable_practice_users = enablePracticeUsers; @@ -58,7 +60,7 @@ hqDefine('app_manager/js/releases/language_profiles', function () { 'placeholder': gettext(practiceUsers.length > 0 ? 'Select a user' : 'No practice mode mobile workers available'), }; self.addProfile = function (langs, name, id, practiceUser) { - var profile = profileModel(langs, name, id, practiceUser); + var profile = profileModel(langs, name, id, practiceUser, self.latest_enabled_versions); profile.name.subscribe(changeSaveButton); profile.langs.subscribe(changeSaveButton); profile.defaultLang.subscribe(changeSaveButton); diff --git a/corehq/apps/app_manager/templates/app_manager/app_view_release_manager.html b/corehq/apps/app_manager/templates/app_manager/app_view_release_manager.html index a41faf289196..4fcf602f677f 100644 --- a/corehq/apps/app_manager/templates/app_manager/app_view_release_manager.html +++ b/corehq/apps/app_manager/templates/app_manager/app_view_release_manager.html @@ -29,6 +29,7 @@ {% initial_page_data 'app_version' app.version %} {% initial_page_data 'application_profile_url' application_profile_url %} {% initial_page_data 'build_profiles' app.build_profiles %} + {% initial_page_data 'latest_version_for_build_profiles' latest_version_for_build_profiles %} {% initial_page_data 'fetch_limit' fetchLimit %} {% initial_page_data 'latestReleasedVersion' latest_released_version %} {% initial_page_data 'practice_users' practice_users %} diff --git a/corehq/apps/app_manager/templates/app_manager/partials/releases/build_profiles.html b/corehq/apps/app_manager/templates/app_manager/partials/releases/build_profiles.html index 9c8bdafe7063..814a42a2791f 100644 --- a/corehq/apps/app_manager/templates/app_manager/partials/releases/build_profiles.html +++ b/corehq/apps/app_manager/templates/app_manager/partials/releases/build_profiles.html @@ -1,4 +1,6 @@ {% load i18n %} +{% load hq_shared_tags %} +
@@ -46,7 +48,19 @@
- + From 511b817fade1b20046150296c01465dd907c6e94 Mon Sep 17 00:00:00 2001 From: Manish Kangia Date: Thu, 20 Dec 2018 14:55:38 +0530 Subject: [PATCH 22/24] check for latest enabled build profile when needed --- corehq/apps/app_manager/decorators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corehq/apps/app_manager/decorators.py b/corehq/apps/app_manager/decorators.py index a525ecf5d800..0b63f9e4a218 100644 --- a/corehq/apps/app_manager/decorators.py +++ b/corehq/apps/app_manager/decorators.py @@ -70,7 +70,7 @@ def _safe_cached_download(request, *args, **kwargs): request.GET.pop('username') latest_enabled_build = None - if request.GET.get('profile') and toggles.RELEASE_BUILDS_PER_PROFILE.enabled(domain): + if latest and request.GET.get('profile') and toggles.RELEASE_BUILDS_PER_PROFILE.enabled(domain): latest_enabled_build = get_latest_enabled_build_for_profile(domain, request.GET.get('profile')) try: if latest_enabled_build: From 9d014b6a22a80e5e129228561473d68cfc4e46a5 Mon Sep 17 00:00:00 2001 From: mkangia Date: Sat, 22 Dec 2018 00:26:24 +0530 Subject: [PATCH 23/24] expire only when needed --- corehq/apps/app_manager/signals.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/corehq/apps/app_manager/signals.py b/corehq/apps/app_manager/signals.py index 0e73b1ca2300..2b9b956d1ffb 100644 --- a/corehq/apps/app_manager/signals.py +++ b/corehq/apps/app_manager/signals.py @@ -6,6 +6,7 @@ from corehq.apps.domain.models import Domain from corehq.apps.app_manager.util import get_latest_enabled_build_for_profile from corehq.apps.app_manager.util import get_enabled_build_profiles_for_version +from corehq import toggles from dimagi.utils.logging import notify_exception @@ -37,7 +38,7 @@ def update_callcenter_config(sender, application, **kwargs): def expire_latest_enabled_build_profiles(sender, application, **kwargs): - if application.copy_of: + if application.copy_of and toggles.RELEASE_BUILDS_PER_PROFILE.enabled(application.domain): for build_profile_id in application.build_profiles: get_latest_enabled_build_for_profile.clear(application.domain, build_profile_id) get_enabled_build_profiles_for_version.clear(application.get_id, application.version) From 99a14807d1d5342774fccb17c43ab9fd88f0d977 Mon Sep 17 00:00:00 2001 From: mkangia Date: Sat, 22 Dec 2018 00:30:16 +0530 Subject: [PATCH 24/24] lint --- .../apps/app_manager/static/app_manager/js/releases/releases.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corehq/apps/app_manager/static/app_manager/js/releases/releases.js b/corehq/apps/app_manager/static/app_manager/js/releases/releases.js index 338f929ba644..b0f255b9cb5d 100644 --- a/corehq/apps/app_manager/static/app_manager/js/releases/releases.js +++ b/corehq/apps/app_manager/static/app_manager/js/releases/releases.js @@ -352,7 +352,7 @@ hqDefine('app_manager/js/releases/releases', function () { } }, success: function (data) { - if(data.error){ + if (data.error) { alert(data.error); $(event.currentTarget).parent().prev('.js-release-waiting').addClass('hide'); savedApp.is_released(isReleased);
NameLangsLanguages Action
+ + + {% if request|toggle_enabled:"RELEASE_BUILDS_PER_PROFILE" %} +
+ + {% trans "Latest Enabled Version:" %} + + +
+ {% endif %} +
+
{{ build_profile.langs|join:", " }} {% if build_profile_id in enabled_build_profiles %} - Disable + + {% trans 'Revoke restriction' %} + {% else %} - Enable + + {% trans 'Restrict to this version' %} + {% endif %}