overhangio / tutor-indigo

An elegant, customizable theme for Open edX
GNU Affero General Public License v3.0
73 stars 275 forks source link

`Unterminated control keyword: 'if'` causes footer rendering to fail #57

Closed misilot closed 5 months ago

misilot commented 6 months ago

Unterminated control keyword: 'if' in file '/openedx/themes/indigo/lms/templates/footer.html' at line: 29 char: 1

Steps to reproduce: setup dev environment delete env/build/openedx/themes/indigo tutor config save which regenerates the theme in the env

try loading http://local.edly.io:8000/

Environment:

Request Method: GET
Request URL: http://local.edly.io:8000/

Django Version: 4.2.8
Python Version: 3.8.18
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.humanize',
 'django.contrib.messages',
 'django.contrib.redirects',
 'django.contrib.sessions',
 'django.contrib.sites',
 'openedx.core.djangoapps.staticfiles.apps.EdxPlatformStaticFilesConfig',
 'django_celery_results',
 'openedx.core.djangoapps.common_initialization.apps.CommonInitializationConfig',
 'lms.djangoapps.lms_initialization.apps.LMSInitializationConfig',
 'openedx.core.djangoapps.common_views',
 'simple_history',
 'config_models',
 'openedx.core.djangoapps.config_model_utils',
 'waffle',
 'openedx.core.djangoapps.service_status',
 'common.djangoapps.status',
 'common.djangoapps.edxmako.apps.EdxMakoConfig',
 'pipeline',
 'common.djangoapps.static_replace',
 'webpack_loader',
 'web_fragments',
 'openedx.core.djangoapps.plugin_api',
 'openedx.core.djangoapps.contentserver',
 'openedx.core.djangoapps.site_configuration',
 'openedx.core.djangoapps.video_config',
 'openedx.core.djangoapps.video_pipeline',
 'lms.djangoapps.courseware',
 'common.djangoapps.student.apps.StudentConfig',
 'common.djangoapps.split_modulestore_django.apps.SplitModulestoreDjangoBackendAppConfig',
 'lms.djangoapps.static_template_view',
 'lms.djangoapps.staticbook',
 'common.djangoapps.track',
 'eventtracking.django.apps.EventTrackingConfig',
 'common.djangoapps.util',
 'lms.djangoapps.certificates.apps.CertificatesConfig',
 'lms.djangoapps.instructor_task',
 'openedx.core.djangoapps.course_groups',
 'lms.djangoapps.bulk_email',
 'lms.djangoapps.branding',
 'lms.djangoapps.course_home_api',
 'lms.djangoapps.user_tours',
 'openedx.core.djangoapps.xblock.apps.LmsXBlockAppConfig',
 'lms.djangoapps.support',
 'oauth2_provider',
 'openedx.core.djangoapps.oauth_dispatch.apps.OAuthDispatchAppConfig',
 'common.djangoapps.third_party_auth',
 'openedx.core.djangoapps.system_wide_roles',
 'openedx.core.djangoapps.auth_exchange',
 'wiki',
 'django_notify',
 'lms.djangoapps.course_wiki',
 'mptt',
 'sekizai',
 'wiki.plugins.links',
 'lms.djangoapps.course_wiki.plugins.markdownedx',
 'django.contrib.admin',
 'lms.djangoapps.debug',
 'openedx.core.djangoapps.util.apps.UtilConfig',
 'openedx.core.djangoapps.django_comment_common',
 'lms.djangoapps.edxnotes',
 'splash',
 'rest_framework',
 'openedx.core.djangoapps.user_api',
 'common.djangoapps.course_modes.apps.CourseModesConfig',
 'openedx.core.djangoapps.enrollments.apps.EnrollmentsConfig',
 'common.djangoapps.entitlements.apps.EntitlementsConfig',
 'lms.djangoapps.bulk_enroll',
 'lms.djangoapps.verify_student.apps.VerifyStudentConfig',
 'openedx.core.djangoapps.dark_lang',
 'lms.djangoapps.rss_proxy',
 'openedx.core.djangoapps.embargo',
 'common.djangoapps.course_action_state',
 'django_countries',
 'lms.djangoapps.mobile_api.apps.MobileApiConfig',
 'social_django',
 'lms.djangoapps.survey.apps.SurveyConfig',
 'lms.djangoapps.lms_xblock.apps.LMSXBlockConfig',
 'submissions',
 'openassessment',
 'openassessment.assessment',
 'openassessment.fileupload',
 'openassessment.staffgrader',
 'openassessment.workflow',
 'openassessment.xblock',
 'edxval',
 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig',
 'openedx.core.djangoapps.content.block_structure.apps.BlockStructureConfig',
 'lms.djangoapps.course_blocks',
 'lms.djangoapps.mailing',
 'corsheaders',
 'openedx.core.djangoapps.cors_csrf',
 'lms.djangoapps.commerce.apps.CommerceConfig',
 'openedx.core.djangoapps.credit.apps.CreditConfig',
 'lms.djangoapps.teams',
 'common.djangoapps.xblock_django',
 'openedx.core.djangoapps.programs.apps.ProgramsConfig',
 'openedx.core.djangoapps.catalog',
 'sorl.thumbnail',
 'milestones',
 'lms.djangoapps.gating.apps.GatingConfig',
 'statici18n',
 'openedx.core.djangoapps.api_admin',
 'openedx.core.djangoapps.verified_track_content',
 'lms.djangoapps.learner_dashboard',
 'lms.djangoapps.badges.apps.BadgesConfig',
 'django_sites_extensions',
 'lms.djangoapps.email_marketing.apps.EmailMarketingConfig',
 'release_util',
 'rules.apps.AutodiscoverRulesConfig',
 'bridgekeeper',
 'celery_utils',
 'openedx.core.djangoapps.crawlers',
 'common.djangoapps.database_fixups',
 'openedx.core.djangoapps.waffle_utils',
 'lms.djangoapps.course_goals.apps.CourseGoalsConfig',
 'openedx_tagging.core.tagging.apps.TaggingConfig',
 'openedx.core.djangoapps.content_tagging',
 'openedx.features.calendar_sync',
 'openedx.features.course_bookmarks',
 'openedx.features.course_experience',
 'openedx.features.enterprise_support.apps.EnterpriseSupportConfig',
 'openedx.features.learner_profile',
 'openedx.features.course_duration_limits',
 'openedx.features.content_type_gating',
 'openedx.features.discounts',
 'openedx.features.effort_estimation',
 'openedx.features.name_affirmation_api.apps.NameAffirmationApiConfig',
 'lms.djangoapps.experiments',
 'django_filters',
 'drf_yasg',
 'csrf.apps.CsrfAppConfig',
 'xss_utils',
 'openedx.core.djangoapps.heartbeat',
 'openedx.core.djangoapps.course_date_signals',
 'openedx.core.djangoapps.external_user_ids',
 'openedx.core.djangoapps.demographics',
 'openedx.core.djangoapps.schedules',
 'rest_framework_jwt',
 'openedx.core.djangoapps.content.learning_sequences.apps.LearningSequencesConfig',
 'organizations',
 'lms.djangoapps.bulk_user_retirement',
 'openedx.core.djangoapps.agreements',
 'openedx.features.survey_report',
 'edx_django_utils.user',
 'pylti1p3.contrib.django.lti1p3_tool_config',
 'edx_ace',
 'blockstore.apps.bundles',
 'lms.djangoapps.mfe_config_api',
 'openedx.core.djangoapps.notifications',
 'edx_sga',
 'enterprise',
 'consent',
 'integrated_channels.integrated_channel',
 'integrated_channels.degreed',
 'integrated_channels.degreed2',
 'integrated_channels.sap_success_factors',
 'integrated_channels.cornerstone',
 'integrated_channels.xapi',
 'integrated_channels.blackboard',
 'integrated_channels.canvas',
 'integrated_channels.moodle',
 'django_object_actions',
 'openedx.core.djangoapps.ace_common.apps.AceCommonConfig',
 'openedx.features.announcements.apps.AnnouncementsConfig',
 'openedx.core.djangoapps.bookmarks.apps.BookmarksConfig',
 'openedx.core.djangoapps.content_libraries.apps.ContentLibrariesConfig',
 'openedx.core.djangoapps.course_apps.apps.CourseAppsConfig',
 'openedx.core.djangoapps.course_live.apps.CourseLiveConfig',
 'openedx.core.djangoapps.courseware_api.apps.CoursewareAPIConfig',
 'openedx.core.djangoapps.credentials.apps.CredentialsConfig',
 'lms.djangoapps.discussion.apps.DiscussionConfig',
 'openedx.core.djangoapps.discussions.apps.DiscussionsConfig',
 'lms.djangoapps.grades.apps.GradesConfig',
 'lms.djangoapps.instructor.apps.InstructorConfig',
 'openedx.core.djangoapps.password_policy.apps.PasswordPolicyConfig',
 'openedx.core.djangoapps.plugins.apps.PluginsConfig',
 'lms.djangoapps.program_enrollments.apps.ProgramEnrollmentsConfig',
 'openedx.core.djangoapps.theming.apps.ThemingConfig',
 'openedx.core.djangoapps.user_authn.apps.UserAuthnConfig',
 'openedx.core.djangoapps.zendesk_proxy.apps.ZendeskProxyConfig',
 'lti_consumer.apps.LTIConsumerApp',
 'super_csv.apps.SuperCSVConfig',
 'completion.apps.CompletionAppConfig',
 'bulk_grades.apps.BulkGradesConfig',
 'edx_proctoring.apps.EdxProctoringConfig',
 'edx_when.apps.EdxWhenConfig',
 'edx_toggles.apps.TogglesConfig',
 'edx_name_affirmation.apps.EdxNameAffirmationConfig',
 'debug_toolbar']
Installed Middleware:
['openedx.core.lib.x_forwarded_for.middleware.XForwardedForMiddleware',
 'edx_django_utils.security.csp.middleware.content_security_policy_middleware',
 'crum.CurrentRequestUserMiddleware',
 'edx_django_utils.cache.middleware.RequestCacheMiddleware',
 'edx_django_utils.monitoring.CachedCustomMonitoringMiddleware',
 'edx_django_utils.monitoring.CodeOwnerMonitoringMiddleware',
 'edx_django_utils.monitoring.CookieMonitoringMiddleware',
 'edx_django_utils.monitoring.DeploymentMonitoringMiddleware',
 'openedx.core.djangoapps.cookie_metadata.middleware.CookieNameChange',
 'openedx.core.lib.request_utils.IgnoredErrorMiddleware',
 'lms.djangoapps.mobile_api.middleware.AppVersionUpgrade',
 'openedx.core.djangoapps.header_control.middleware.HeaderControlMiddleware',
 'lms.djangoapps.discussion.django_comment_client.middleware.AjaxExceptionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.contrib.sites.middleware.CurrentSiteMiddleware',
 'edx_rest_framework_extensions.auth.jwt.middleware.JwtAuthCookieMiddleware',
 'django_sites_extensions.middleware.RedirectMiddleware',
 'openedx.core.djangoapps.safe_sessions.middleware.SafeSessionMiddleware',
 'openedx.core.djangoapps.cache_toolbox.middleware.CacheBackedAuthenticationMiddleware',
 'common.djangoapps.student.middleware.UserStandingMiddleware',
 'openedx.core.djangoapps.contentserver.middleware.StaticContentServer',
 'openedx.core.djangoapps.user_api.middleware.UserTagsEventContextMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'common.djangoapps.track.middleware.TrackMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'openedx.core.djangoapps.cors_csrf.middleware.CorsCSRFMiddleware',
 'openedx.core.djangoapps.cors_csrf.middleware.CsrfCrossDomainCookieMiddleware',
 'splash.middleware.SplashMiddleware',
 'openedx.core.djangoapps.geoinfo.middleware.CountryMiddleware',
 'openedx.core.djangoapps.embargo.middleware.EmbargoMiddleware',
 'enterprise.middleware.EnterpriseLanguagePreferenceMiddleware',
 'openedx.core.djangoapps.lang_pref.middleware.LanguagePreferenceMiddleware',
 'openedx.core.djangoapps.dark_lang.middleware.DarkLangMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'lms.djangoapps.discussion.django_comment_client.utils.ViewNameMiddleware',
 'codejail.django_integration.ConfigureCodeJailMiddleware',
 'openedx.core.djangoapps.session_inactivity_timeout.middleware.SessionInactivityTimeout',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'lms.djangoapps.courseware.middleware.CacheCourseIdMiddleware',
 'lms.djangoapps.courseware.middleware.RedirectMiddleware',
 'lms.djangoapps.course_wiki.middleware.WikiAccessMiddleware',
 'openedx.core.djangoapps.theming.middleware.CurrentSiteThemeMiddleware',
 'waffle.middleware.WaffleMiddleware',
 'edx_django_utils.cache.middleware.TieredCacheMiddleware',
 'edx_rest_framework_extensions.middleware.RequestCustomAttributesMiddleware',
 'edx_rest_framework_extensions.auth.jwt.middleware.EnsureJWTAuthSettingsMiddleware',
 'simple_history.middleware.HistoryRequestMiddleware',
 'openedx.core.djangoapps.site_configuration.middleware.SessionCookieDomainOverrideMiddleware',
 'lms.djangoapps.discussion.django_comment_client.utils.QueryCountDebugMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware',
 'common.djangoapps.third_party_auth.middleware.ExceptionMiddleware']

Traceback (most recent call last):
  File "/openedx/venv/lib/python3.8/site-packages/mako/lookup.py", line 241, in get_template
    return self._check(uri, self._collection[uri])

During handling of the above exception ('indigo/lms/templates/footer.html'), another exception occurred:
  File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 134, in _wrapper_view
    response = view_func(request, *args, **kwargs)
  File "/openedx/edx-platform/common/djangoapps/util/cache.py", line 83, in wrapper
    response = view_func(request, *args, **kwargs)
  File "/openedx/edx-platform/lms/djangoapps/branding/views.py", line 70, in index
    return student_views.index(request, user=request.user)
  File "/openedx/edx-platform/common/djangoapps/student/views/management.py", line 171, in index
    return render_to_response('index.html', context)
  File "/openedx/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 188, in render_to_response
    return HttpResponse(render_to_string(template_name, dictionary, namespace, request), **kwargs)
  File "/openedx/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/openedx/edx-platform/common/djangoapps/edxmako/template.py", line 82, in render
    return self.mako_template.render_unicode(**context_dictionary)
  File "/openedx/venv/lib/python3.8/site-packages/mako/template.py", line 444, in render_unicode
    return runtime._render(
  File "/openedx/venv/lib/python3.8/site-packages/mako/runtime.py", line 874, in _render
    _render_context(
  File "/openedx/venv/lib/python3.8/site-packages/mako/runtime.py", line 916, in _render_context
    _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)
  File "/openedx/venv/lib/python3.8/site-packages/mako/runtime.py", line 943, in _exec_template
    callable_(context, *args, **kwargs)
  File "/tmp/mako_lms/1ff981c2157d500713c1ce6bf7fdbce2/main.html.py", line 394, in render_body
    runtime._include_file(context, (static.get_template_path('footer.html')), _template_uri)
  File "/openedx/venv/lib/python3.8/site-packages/mako/runtime.py", line 780, in _include_file
    template = _lookup_template(context, uri, calling_uri)
  File "/openedx/venv/lib/python3.8/site-packages/mako/runtime.py", line 837, in _lookup_template
    return lookup.get_template(uri)
  File "/openedx/edx-platform/common/djangoapps/edxmako/paths.py", line 99, in get_template
    template = super().get_template(get_template_path_with_theme(uri))
  File "/openedx/venv/lib/python3.8/site-packages/mako/lookup.py", line 252, in get_template
    return self._load(srcfile, uri)
  File "/openedx/venv/lib/python3.8/site-packages/mako/lookup.py", line 313, in _load
    self._collection[uri] = template = Template(
  File "/openedx/venv/lib/python3.8/site-packages/mako/template.py", line 317, in __init__
    module = self._compile_from_file(path, filename)
  File "/openedx/venv/lib/python3.8/site-packages/mako/template.py", line 378, in _compile_from_file
    _compile_module_file(
  File "/openedx/venv/lib/python3.8/site-packages/mako/template.py", line 691, in _compile_module_file
    source, lexer = _compile(
  File "/openedx/venv/lib/python3.8/site-packages/mako/template.py", line 657, in _compile
    node = lexer.parse()
  File "/openedx/venv/lib/python3.8/site-packages/mako/lexer.py", line 264, in parse
    raise exceptions.SyntaxException(

Exception Type: SyntaxException at /
Exception Value: Unterminated control keyword: 'if' in file '/openedx/themes/indigo/lms/templates/footer.html' at line: 29 char: 1
misilot commented 6 months ago

Ok, so I think it might have been

INDIGO_FOOTER_LEGAL_LINKS: null
INDIGO_FOOTER_NAV_LINKS: null

no idea how they got set to that? but setting with tutor config save --set "INDIGO_FOOTER_NAV_LINKS=[]" --set "INDIGO_FOOTER_LEGAL_LINKS=[]" it doesn't yell about the if statements not being closed (and setting actual values which I had thought I copied from production) it doesn't yell either.

However,

I am not seeing a nicely rendered footer

image
misilot commented 6 months ago

Ok, so I think what is happening is the CSS isn't being regenerated with tutor config save? What needs to be run to generate the assets?

misilot commented 6 months ago

Just following up, that it might be generating some of it, but the bootstrap folder which exists in the original theme but not in a fork.

https://github.com/newliteraciesalliance/tutor-nla-theme/tree/nla-v17 here is my current code, which all I changed was the directory and plugin names.

regisb commented 6 months ago

@hinakhadim I think this can be considered as a bug. The footer does not render correctly when some of the variables are null.