From 9ead7fb08302f8afb811735671d0c714d536b467 Mon Sep 17 00:00:00 2001 From: Julia Hoang Date: Thu, 14 May 2026 16:04:39 -0700 Subject: [PATCH 1/3] feat: integrate the legal pages with Wagtail --- core/views.py | 8 +- pages/migrations/0002_legalpage.py | 46 +++++++ pages/migrations/0003_create_legal_pages.py | 128 ++++++++++++++++++++ pages/models.py | 18 ++- static/css/v3/privacy-policy.css | 46 +++---- static/css/v3/terms-of-use.css | 20 +-- templates/v3/privacy_policy.html | 55 ++------- templates/v3/terms_of_use.html | 90 ++------------ 8 files changed, 235 insertions(+), 176 deletions(-) create mode 100644 pages/migrations/0002_legalpage.py create mode 100644 pages/migrations/0003_create_legal_pages.py diff --git a/core/views.py b/core/views.py index ef05864a3..bb76bf0be 100644 --- a/core/views.py +++ b/core/views.py @@ -486,7 +486,9 @@ class TermsOfUseView(V3Mixin, MarkdownTemplateView): v3_template_name = "v3/terms_of_use.html" def get_v3_context_data(self, **kwargs): - return {"last_updated": "2024-02-22"} + from pages.models import LegalPage + + return {"page": LegalPage.objects.live().filter(slug="terms-of-use").first()} class PrivacyPolicyView(V3Mixin, MarkdownTemplateView): @@ -495,7 +497,9 @@ class PrivacyPolicyView(V3Mixin, MarkdownTemplateView): v3_template_name = "v3/privacy_policy.html" def get_v3_context_data(self, **kwargs): - return {"last_updated": "2024-02-17"} + from pages.models import LegalPage + + return {"page": LegalPage.objects.live().filter(slug="privacy").first()} class LearnPageView(V3Mixin, TemplateView): diff --git a/pages/migrations/0002_legalpage.py b/pages/migrations/0002_legalpage.py new file mode 100644 index 000000000..c3d87d6c0 --- /dev/null +++ b/pages/migrations/0002_legalpage.py @@ -0,0 +1,46 @@ +import django.db.models.deletion +import modelcluster.contrib.taggit +import wagtail.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("wagtailcore", "0096_referenceindex_referenceindex_source_object_and_more"), + ("pages", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="LegalPage", + fields=[ + ( + "page_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="wagtailcore.page", + ), + ), + ("body", wagtail.fields.RichTextField(blank=True)), + ( + "tags", + modelcluster.contrib.taggit.ClusterTaggableManager( + blank=True, + help_text="A comma-separated list of tags.", + through="pages.TaggedContent", + to="pages.ContentTag", + verbose_name="Tags", + ), + ), + ], + options={ + "abstract": False, + }, + bases=("wagtailcore.page",), + ), + ] diff --git a/pages/migrations/0003_create_legal_pages.py b/pages/migrations/0003_create_legal_pages.py new file mode 100644 index 000000000..f8e1890a7 --- /dev/null +++ b/pages/migrations/0003_create_legal_pages.py @@ -0,0 +1,128 @@ +from django.db import migrations + + +PRIVACY_POLICY_BODY = """ +

This privacy notice for The C Plus Plus Alliance, Inc. describes how and why we might collect, store, use, and/or share your information when you use our services ("Services").

+

The C Plus Plus Alliance is committed to protecting the privacy and accuracy of confidential information to the extent possible, subject to provisions of state and federal law. Other than as required by laws that guarantee public access to certain types of information, or in response to subpoenas or other legal instruments that authorize access, personal information is not actively shared.

+

In particular, we do not re-distribute or sell personal information collected on our web servers.

+

Information collected

+

The website collects the following analytics:

+ +

We also collect any personal information that you voluntarily provide to us either while registering for an account or while using the site. This includes information such as your name, email address, and profile photo among other things.

+

We do not collect any sensitive information.

+

Cookies

+

The website may use cookies in order to deliver web content specific to individual users' interests or as functional cookies for the authentication purposes of the site. Sensitive personal information is not stored within cookies.

+

Log and Usage Data

+

We collect and store log and usage data for diagnostic and performance purposes. This may include the same analytics information above along with additional information related to your usage of the site.

+

Privacy Statement Revisions

+

We may update this privacy notice from time to time. The updated version will be indicated by an updated "Revised" date and the updated version will be effective as soon as it is accessible. If we make material changes to this privacy notice, we may notify you either by prominently posting a notice of such changes or by directly sending you a notification. We encourage you to review this privacy notice frequently to be informed of how we are protecting your information.

+

Questions

+

Questions or concerns? Reading this privacy notice will help you understand your privacy rights and choices. If you do not agree with our policies and practices, please do not use our Services. If you still have any questions or concerns, please contact us at info@cppalliance.org.

+""".strip() + + +TERMS_OF_USE_BODY = """ +

We are The C Plus Plus Alliance, Inc., a company registered in California, United States at 5716 Corsa Ave suite 110, Westlake Village, CA 91362, USA.

+

We operate this website, as well as any other related products and services that refer or link to these legal terms ("the Services").

+

These Legal Terms constitute a legally binding agreement made between you and The C Plus Plus Alliance, Inc., concerning your access to and use of the Services. You agree that by accessing the Services, you have read, understood, and agreed to be bound by all of these Legal Terms.

+

IF YOU DO NOT AGREE WITH ALL OF THESE LEGAL TERMS, THEN YOU ARE EXPRESSLY PROHIBITED FROM USING THE SERVICES AND YOU MUST DISCONTINUE USE IMMEDIATELY.

+

We reserve the right, in our sole discretion, to make changes or modifications to these Legal Terms from time to time. We will alert you about any changes by updating the "Last updated" date of these Legal Terms, and you waive any right to receive specific notice of each such change. It is your responsibility to periodically review these Legal Terms to stay informed of updates. You will be subject to, and will be deemed to have been made aware of and to have accepted, the changes in any revised Legal Terms by your continued use of the Services after the date such revised Legal Terms are posted.

+

We will make our best effort to notify registered users who have provided us with a valid email address of any changes to our Terms of Use via email. While we aim to ensure timely and accurate notifications, we do not guarantee that all changes will be communicated.

+

Intellectual Property

+

Boost libraries, documentation, source code, and this website are provided under the terms of the Boost Software License.

+

You grant The C Plus Plus Alliance, Inc. a royalty-free and non-exclusive license to display, use, copy, transmit, and broadcast the content you upload and publish. For issues regarding intellectual property claims, you should contact The C Plus Plus Alliance, Inc.

+

User Accounts

+

As a user of this website you have the option, but not the requirement, to register with us and provide additional information. You are responsible for ensuring the accuracy of this information, and you are responsible for maintaining the safety and security of your identifying information.

+

You are also responsible for all activities that occur under your account or password.

+

If you think there are any possible issues regarding the security of your account on the website, inform us immediately so we may address them accordingly.

+

We reserve all rights to terminate accounts, edit or remove content and cancel orders at our sole discretion.

+

Prohibited Activities

+

As a user of the Services, you agree not to:

+ +

In addition your contributions must meet these requirements:

+ +

Third-Party Websites and Content

+

The Services may contain links to other websites ("Third-Party Websites") as well as articles, photographs, text, graphics, pictures, designs, music, sound, video, information, applications, software, and other content or items belonging to or originating from third parties ("Third-Party Content"). Such Third-Party Websites and Third-Party Content are not investigated, monitored, or checked for accuracy, appropriateness, or completeness by us, and we are not responsible for any Third-Party Websites accessed through the Services or any Third-Party Content posted on, available through, or installed from the Services, including the content, accuracy, offensiveness, opinions, reliability, privacy practices, or other policies of or contained in the Third-Party Websites or the Third-Party Content.

+

Modifications and Interruptions

+

We reserve the right to change, modify, or remove the contents of the Services at any time or for any reason at our sole discretion without notice.

+

We cannot guarantee the Services will be available at all times. We may experience hardware, software, or other problems or need to perform maintenance related to the Services, resulting in interruptions, delays, or errors. We reserve the right to change, revise, update, suspend, discontinue, or otherwise modify the Services at any time or for any reason without notice to you.

+

Governing Law

+

These Legal Terms and your use of the Services are governed by and construed in accordance with the laws of the State of California applicable to agreements made and to be entirely performed within the State of California, without regard to its conflict of law principles.

+

Disclaimer

+

THE SERVICES ARE PROVIDED ON AN AS-IS AND AS-AVAILABLE BASIS. YOU AGREE THAT YOUR USE OF THE SERVICES WILL BE AT YOUR SOLE RISK. TO THE FULLEST EXTENT PERMITTED BY LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, IN CONNECTION WITH THE SERVICES AND YOUR USE THEREOF, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. WE MAKE NO WARRANTIES OR REPRESENTATIONS ABOUT THE ACCURACY OR COMPLETENESS OF THE SERVICES' CONTENT OR THE CONTENT OF ANY WEBSITES OR MOBILE APPLICATIONS LINKED TO THE SERVICES AND WE WILL ASSUME NO LIABILITY OR RESPONSIBILITY FOR ANY (1) ERRORS, MISTAKES, OR INACCURACIES OF CONTENT AND MATERIALS, (2) PERSONAL INJURY OR PROPERTY DAMAGE, OF ANY NATURE WHATSOEVER, RESULTING FROM YOUR ACCESS TO AND USE OF THE SERVICES, (3) ANY UNAUTHORIZED ACCESS TO OR USE OF OUR SECURE SERVERS AND/OR ANY AND ALL PERSONAL INFORMATION AND/OR FINANCIAL INFORMATION STORED THEREIN, (4) ANY INTERRUPTION OR CESSATION OF TRANSMISSION TO OR FROM THE SERVICES, (5) ANY BUGS, VIRUSES, TROJAN HORSES, OR THE LIKE WHICH MAY BE TRANSMITTED TO OR THROUGH THE SERVICES BY ANY THIRD PARTY, AND/OR (6) ANY ERRORS OR OMISSIONS IN ANY CONTENT AND MATERIALS OR FOR ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF ANY CONTENT POSTED, TRANSMITTED, OR OTHERWISE MADE AVAILABLE VIA THE SERVICES. WE DO NOT WARRANT, ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR ANY PRODUCT OR SERVICE ADVERTISED OR OFFERED BY A THIRD PARTY THROUGH THE SERVICES, ANY HYPERLINKED WEBSITE, OR ANY WEBSITE OR MOBILE APPLICATION FEATURED IN ANY BANNER OR OTHER ADVERTISING, AND WE WILL NOT BE A PARTY TO OR IN ANY WAY BE RESPONSIBLE FOR MONITORING ANY TRANSACTION BETWEEN YOU AND ANY THIRD-PARTY PROVIDERS OF PRODUCTS OR SERVICES. AS WITH THE PURCHASE OF A PRODUCT OR SERVICE THROUGH ANY MEDIUM OR IN ANY ENVIRONMENT, YOU SHOULD USE YOUR BEST JUDGMENT AND EXERCISE CAUTION WHERE APPROPRIATE.

+

Contact us

+

In order to resolve a complaint regarding the Services or to receive further information regarding use of the Services, please contact us at:

+

The C Plus Plus Alliance, Inc.
5716 Corsa Ave suite 110
Westlake Village, CA 91362
United States

+

Phone: (+1) 305 216 5538
info@cppalliance.org

+""".strip() + + +LEGAL_PAGES = [ + {"title": "Privacy Policy", "slug": "privacy", "body": PRIVACY_POLICY_BODY}, + {"title": "Terms of Use", "slug": "terms-of-use", "body": TERMS_OF_USE_BODY}, +] + + +def create_legal_pages(apps, schema_editor): + # Use real models so treebeard's add_child() and Wagtail's + # save_revision()/publish() work; historical models drop these methods. + from django.utils import timezone + + from pages.models import LegalPage, RoutableHomePage + + home = RoutableHomePage.objects.first() + if home is None: + return + + now = timezone.now() + for page_data in LEGAL_PAGES: + if LegalPage.objects.filter(slug=page_data["slug"]).exists(): + continue + page = home.add_child( + instance=LegalPage( + title=page_data["title"], + slug=page_data["slug"], + body=page_data["body"], + live=True, + first_published_at=now, + last_published_at=now, + ) + ) + page.save_revision().publish() + + +def delete_legal_pages(apps, schema_editor): + from pages.models import LegalPage + + LegalPage.objects.filter(slug__in=[p["slug"] for p in LEGAL_PAGES]).delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ("pages", "0002_legalpage"), + ("contenttypes", "0002_remove_content_type_name"), + ] + + operations = [ + migrations.RunPython(create_legal_pages, delete_legal_pages), + ] diff --git a/pages/models.py b/pages/models.py index 68cef23a3..a5e77dd18 100644 --- a/pages/models.py +++ b/pages/models.py @@ -1,7 +1,8 @@ from typing import NamedTuple from structlog import get_logger -from wagtail.fields import StreamField +from wagtail.fields import RichTextField, StreamField +from django.conf import settings from django.db import models from django.utils.functional import cached_property from django.utils.text import slugify @@ -228,3 +229,18 @@ def filter_name(self): "image", "summary", ] + + +class LegalPage(BasePage): + """Simple policy/legal page: title + rich text body. + + "Last Updated" in the template uses the built-in `last_published_at`, + so republishing in Wagtail auto-updates the visible date. + """ + + parent_page_types = ["pages.RoutableHomePage"] + subpage_types = [] + + body = RichTextField(features=settings.RICH_TEXT_FEATURES, blank=True) + + content_panels = BasePage.content_panels + ["body"] diff --git a/static/css/v3/privacy-policy.css b/static/css/v3/privacy-policy.css index 1826487e5..1c01cba2f 100644 --- a/static/css/v3/privacy-policy.css +++ b/static/css/v3/privacy-policy.css @@ -55,7 +55,7 @@ letter-spacing: var(--letter-spacing-tight); } -.privacy-policy__intro { +.privacy-policy__body { color: var(--color-text-secondary); font-family: var(--font-sans); font-size: var(--font-size-base); @@ -63,18 +63,11 @@ line-height: var(--line-height-loose); letter-spacing: var(--letter-spacing-tight); width: 100%; + padding: 0; } -.privacy-policy__section { - display: flex; - flex-direction: column; - gap: var(--space-card); - align-items: flex-start; - width: 100%; -} - -.privacy-policy__section-title { - margin: 0; +.privacy-policy__body h2 { + margin: var(--space-xl) 0 var(--space-card); color: var(--color-text-primary); font-family: var(--font-sans); font-size: var(--font-size-large); @@ -83,34 +76,29 @@ letter-spacing: var(--letter-spacing-tight); } -.privacy-policy__section-body { - color: var(--color-text-secondary); - font-family: var(--font-sans); - font-size: var(--font-size-base); - font-weight: var(--font-weight-regular); - line-height: var(--line-height-loose); - letter-spacing: var(--letter-spacing-tight); - width: 100%; +.privacy-policy__body > :first-child { + margin-top: 0; } -.privacy-policy__section-body ul { - list-style-type: disc; - padding-left: 1em; +.privacy-policy__body p { margin: 0 0 1em 0; + padding: 0; } -.privacy-policy__section-body li { - margin-bottom: var(--space-s); +.privacy-policy__body p:last-child { + margin-bottom: 0; } -.privacy-policy__section-body p { +.privacy-policy__body ul { + list-style-type: disc; + padding-left: 1em; margin: 0 0 1em 0; } -.privacy-policy__section-body p:last-child { - margin-bottom: 0; +.privacy-policy__body li { + margin-bottom: var(--space-s); } -.privacy-policy__section-body a { - color: var(--color-text-link-accent, var(--color-text-primary)); +.privacy-policy__body a { + color: var(--color-text-link-accent); } diff --git a/static/css/v3/terms-of-use.css b/static/css/v3/terms-of-use.css index 3c3db5f1c..41a33aaba 100644 --- a/static/css/v3/terms-of-use.css +++ b/static/css/v3/terms-of-use.css @@ -48,22 +48,18 @@ padding: 0; } -.terms-page__section { - display: flex; - flex-direction: column; - gap: var(--space-large); - align-items: flex-start; - width: 100%; -} - -.terms-page__section-heading { +.terms-page__body h2 { font-family: var(--font-sans); font-weight: var(--font-weight-medium); font-size: var(--font-size-large); line-height: 1; letter-spacing: -0.24px; color: var(--color-text-primary); - margin: 0; + margin: var(--space-xl) 0 var(--space-large); +} + +.terms-page__body > :first-child { + margin-top: 0; } .terms-page__body p { @@ -94,10 +90,6 @@ text-decoration: underline; } -.terms-page__body a.terms-page__link-plain { - text-decoration: none; -} - .terms-page__wrapper { max-width: 800px; margin: 0 auto; diff --git a/templates/v3/privacy_policy.html b/templates/v3/privacy_policy.html index d4f602d9f..76b63f0a5 100644 --- a/templates/v3/privacy_policy.html +++ b/templates/v3/privacy_policy.html @@ -1,59 +1,20 @@ {% extends "base.html" %} -{% load static %} +{% load static wagtailcore_tags %} -{% block title %}Privacy Policy{% endblock %} +{% block title %}{{ page.title|default:"Privacy Policy" }}{% endblock %} {% block content %}
-

Privacy Policy

-

Last Updated: {{ last_updated }}

+

{{ page.title|default:"Privacy Policy" }}

+ {% if page.last_published_at %} +

Last Updated: {{ page.last_published_at|date:"F j, Y" }}

+ {% endif %}
-
-

This privacy notice for The C Plus Plus Alliance, Inc. describes how and why we might collect, store, use, and/or share your information when you use our services ("Services").

-

The C Plus Plus Alliance is committed to protecting the privacy and accuracy of confidential information to the extent possible, subject to provisions of state and federal law. Other than as required by laws that guarantee public access to certain types of information, or in response to subpoenas or other legal instruments that authorize access, personal information is not actively shared.

-

In particular, we do not re-distribute or sell personal information collected on our web servers.

+
+ {{ page.body|richtext }}
-
-

Information collected

-
-

The website collects the following analytics:

-
    -
  • Internet Protocol (IP) address of computer being used
  • -
  • web pages requested
  • -
  • referring web page
  • -
  • browser used
  • -
  • date and time
  • -
-

We also collect any personal information that you voluntarily provide to us either while registering for an account or while using the site. This includes information such as your name, email address, and profile photo among other things.

-

We do not collect any sensitive information.

-
-
-
-

Cookies

-
-

The website may use cookies in order to deliver web content specific to individual users' interests or as functional cookies for the authentication purposes of the site. Sensitive personal information is not stored within cookies.

-
-
-
-

Log and Usage Data

-
-

We collect and store log and usage data for diagnostic and performance purposes. This may include the same analytics information above along with additional information related to your usage of the site.

-
-
-
-

Privacy Statement Revisions

-
-

We may update this privacy notice from time to time. The updated version will be indicated by an updated "Revised" date and the updated version will be effective as soon as it is accessible. If we make material changes to this privacy notice, we may notify you either by prominently posting a notice of such changes or by directly sending you a notification. We encourage you to review this privacy notice frequently to be informed of how we are protecting your information.

-
-
-
-

Questions

-
-

Questions or concerns? Reading this privacy notice will help you understand your privacy rights and choices. If you do not agree with our policies and practices, please do not use our Services. If you still have any questions or concerns, please contact us at info@cppalliance.org.

-
-
{% endblock %} diff --git a/templates/v3/terms_of_use.html b/templates/v3/terms_of_use.html index 8e402fdbb..205198d9f 100644 --- a/templates/v3/terms_of_use.html +++ b/templates/v3/terms_of_use.html @@ -1,98 +1,22 @@ {% extends "base.html" %} -{% load i18n %} +{% load i18n wagtailcore_tags %} -{% block title %}Terms of Use{% endblock %} +{% block title %}{{ page.title|default:"Terms of Use" }}{% endblock %} {% block description %}Terms of Use for The C Plus Plus Alliance, Inc. Services.{% endblock %} {% block content %}
-

Terms of Use

-

Last Updated: {{ last_updated|default:"2024-02-22" }}

+

{{ page.title|default:"Terms of Use" }}

+ {% if page.last_published_at %} +

Last Updated: {{ page.last_published_at|date:"F j, Y" }}

+ {% endif %}
-

We are The C Plus Plus Alliance, Inc., a company registered in California, United States at 5716 Corsa Ave suite 110, Westlake Village, CA 91362, USA.

-

We operate this website, as well as any other related products and services that refer or link to these legal terms ("the Services").

-

These Legal Terms constitute a legally binding agreement made between you and The C Plus Plus Alliance, Inc., concerning your access to and use of the Services. You agree that by accessing the Services, you have read, understood, and agreed to be bound by all of these Legal Terms.

-

IF YOU DO NOT AGREE WITH ALL OF THESE LEGAL TERMS, THEN YOU ARE EXPRESSLY PROHIBITED FROM USING THE SERVICES AND YOU MUST DISCONTINUE USE IMMEDIATELY.

-

We reserve the right, in our sole discretion, to make changes or modifications to these Legal Termhs from time to time. We will alert you about any changes by updating the "Last updated" date of these Legal Terms, and you waive any right to receive specific notice of each such change. It is your responsibility to periodically review these Legal Terms to stay informed of updates. You will be subject to, and will be deemed to have been made aware of and to have accepted, the changes in any revised Legal Terms by your continued use of the Services after the date such revised Legal Terms are posted.

-

We will make our best effort to notify registered users who have provided us with a valid email address of any changes to our Terms of Use via email. While we aim to ensure timely and accurate notifications, we do not guarantee that all changes will be communicated.

+ {{ page.body|richtext }}
- -
-

Intellectual Property

-
-

Boost libraries, documentation, source code, and this website are provided under the terms of the Boost Software License.

-

You grant The C Plus Plus Alliance, Inc. a royalty-free and non-exclusive license to display, use, copy, transmit, and broadcast the content you upload and publish. For issues regarding intellectual property claims, you should contact The C Plus Plus Alliance, Inc.

-
-
- -
-

User Accounts

-
-

As a user of this website you have the option, but not the requirement, to register with us and provide additional information. You are responsible for ensuring the accuracy of this information, and you are responsible for maintaining the safety and security of your identifying information.

-

You are also responsible for all activities that occur under your account or password.

-

If you think there are any possible issues regarding the security of your account on the website, inform us immediately so we may address them accordingly.

-

We reserve all rights to terminate accounts, edit or remove content and cancel orders at our sole discretion.

-
-
- -
-

Prohibited Activities

-
-

As a user of the Services, you agree not to:

-
    -
  • Use any information obtained from the Services in order to harass, abuse, or harm another person.
  • -
  • Use the Services in a manner inconsistent with any applicable laws or regulations.
  • -
  • Attempt to impersonate another user or person or use the username of another user.
  • -
  • Interfere with, disrupt, or create an undue burden on the Services or the networks or services connected to the Services.
  • -
  • Harass, annoy, intimidate, or threaten any of our users, employees or agents engaged in providing any portion of the Services to you.
  • -
  • Attempt to bypass any measures of the Services designed to prevent or restrict access to the Services, or any portion of the Services.
  • -
  • Register another account after you have been terminated or suspended from the Services.
  • -
-

In addition your contributions must meet these requirements:

-
    -
  • They are not obscene, lewd, lascivious, filthy, violent, harassing, libelous, slanderous, or otherwise objectionable (as determined by us).
  • -
  • They do not violate any applicable law, regulation, or rule.
  • -
  • They do not include any offensive comments including but not limited to race, national origin, gender, sexual preference, or physical handicap.
  • -
  • Your contributions must adhere to all relevant laws regarding child pornography and any which can or does result in the harming of a minor is strictly prohibited.
  • -
-
-
- -
-

Third-Party Websites and Content

-

The Services may contain links to other websites ("Third-Party Websites") as well as articles, photographs, text, graphics, pictures, designs, music, sound, video, information, applications, software, and other content or items belonging to or originating from third parties ("Third-Party Content"). Such Third-Party Websites and Third-Party Content are not investigated, monitored, or checked for accuracy, appropriateness, or completeness by us, and we are not responsible for any Third-Party Websites accessed through the Services or any Third-Party Content posted on, available through, or installed from the Services, including the content, accuracy, offensiveness, opinions, reliability, privacy practices, or other policies of or contained in the Third-Party Websites or the Third-Party Content.

-
- -
-

Modifications and Interruptions

-
-

We reserve the right to change, modify, or remove the contents of the Services at any time or for any reason at our sole discretion without notice.

-

We cannot guarantee the Services will be available at all times. We may experience hardware, software, or other problems or need to perform maintenance related to the Services, resulting in interruptions, delays, or errors. We reserve the right to change, revise, update, suspend, discontinue, or otherwise modify the Services at any time or for any reason without notice to you.

-
-
- -
-

Governing Law

-

These Legal Terms and your use of the Services are governed by and construed in accordance with the laws of the State of California applicable to agreements made and to be entirely performed within the State of California, without regard to its conflict of law principles.

-
- -
-

Disclaimer

-

THE SERVICES ARE PROVIDED ON AN AS-IS AND AS-AVAILABLE BASIS. YOU AGREE THAT YOUR USE OF THE SERVICES WILL BE AT YOUR SOLE RISK. TO THE FULLEST EXTENT PERMITTED BY LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, IN CONNECTION WITH THE SERVICES AND YOUR USE THEREOF, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. WE MAKE NO WARRANTIES OR REPRESENTATIONS ABOUT THE ACCURACY OR COMPLETENESS OF THE SERVICES' CONTENT OR THE CONTENT OF ANY WEBSITES OR MOBILE APPLICATIONS LINKED TO THE SERVICES AND WE WILL ASSUME NO LIABILITY OR RESPONSIBILITY FOR ANY (1) ERRORS, MISTAKES, OR INACCURACIES OF CONTENT AND MATERIALS, (2) PERSONAL INJURY OR PROPERTY DAMAGE, OF ANY NATURE WHATSOEVER, RESULTING FROM YOUR ACCESS TO AND USE OF THE SERVICES, (3) ANY UNAUTHORIZED ACCESS TO OR USE OF OUR SECURE SERVERS AND/OR ANY AND ALL PERSONAL INFORMATION AND/OR FINANCIAL INFORMATION STORED THEREIN, (4) ANY INTERRUPTION OR CESSATION OF TRANSMISSION TO OR FROM THE SERVICES, (5) ANY BUGS, VIRUSES, TROJAN HORSES, OR THE LIKE WHICH MAY BE TRANSMITTED TO OR THROUGH THE SERVICES BY ANY THIRD PARTY, AND/OR (6) ANY ERRORS OR OMISSIONS IN ANY CONTENT AND MATERIALS OR FOR ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF ANY CONTENT POSTED, TRANSMITTED, OR OTHERWISE MADE AVAILABLE VIA THE SERVICES. WE DO NOT WARRANT, ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR ANY PRODUCT OR SERVICE ADVERTISED OR OFFERED BY A THIRD PARTY THROUGH THE SERVICES, ANY HYPERLINKED WEBSITE, OR ANY WEBSITE OR MOBILE APPLICATION FEATURED IN ANY BANNER OR OTHER ADVERTISING, AND WE WILL NOT BE A PARTY TO OR IN ANY WAY BE RESPONSIBLE FOR MONITORING ANY TRANSACTION BETWEEN YOU AND ANY THIRD-PARTY PROVIDERS OF PRODUCTS OR SERVICES. AS WITH THE PURCHASE OF A PRODUCT OR SERVICE THROUGH ANY MEDIUM OR IN ANY ENVIRONMENT, YOU SHOULD USE YOUR BEST JUDGMENT AND EXERCISE CAUTION WHERE APPROPRIATE.

-
- -
-

Contact us

-
-

In order to resolve a complaint regarding the Services or to receive further information regarding use of the Services, please contact us at:

-

The C Plus Plus Alliance, Inc.
5716 Corsa Ave suite 110
Westlake Village, CA 91362
United States

-

Phone: (+1) 305 216 5538
info@cppalliance.org

-
-
{% endblock %} From c4fb6bf182e0e4e0fd447db437c89e8d33c36924 Mon Sep 17 00:00:00 2001 From: Julia Hoang Date: Thu, 14 May 2026 16:51:48 -0700 Subject: [PATCH 2/3] refactor: consolidate Privacy and Terms of Use into 1 Legal template --- core/views.py | 4 +- static/css/v3/components.css | 2 - static/css/v3/header.css | 6 +- .../v3/{privacy-policy.css => legal-page.css} | 81 ++++++++++----- static/css/v3/terms-of-use.css | 98 ------------------- templates/v3/legal_page.html | 26 +++++ templates/v3/privacy_policy.html | 20 ---- templates/v3/terms_of_use.html | 22 ----- 8 files changed, 92 insertions(+), 167 deletions(-) rename static/css/v3/{privacy-policy.css => legal-page.css} (59%) delete mode 100644 static/css/v3/terms-of-use.css create mode 100644 templates/v3/legal_page.html delete mode 100644 templates/v3/privacy_policy.html delete mode 100644 templates/v3/terms_of_use.html diff --git a/core/views.py b/core/views.py index bb76bf0be..523a059f8 100644 --- a/core/views.py +++ b/core/views.py @@ -483,7 +483,7 @@ def get(self, request, *args, **kwargs): class TermsOfUseView(V3Mixin, MarkdownTemplateView): """Renders the v3 Terms of Use page when the v3 flag is active, else markdown template.""" - v3_template_name = "v3/terms_of_use.html" + v3_template_name = "v3/legal_page.html" def get_v3_context_data(self, **kwargs): from pages.models import LegalPage @@ -494,7 +494,7 @@ def get_v3_context_data(self, **kwargs): class PrivacyPolicyView(V3Mixin, MarkdownTemplateView): """Renders the v3 Privacy Policy page when the v3 flag is active, else markdown template.""" - v3_template_name = "v3/privacy_policy.html" + v3_template_name = "v3/legal_page.html" def get_v3_context_data(self, **kwargs): from pages.models import LegalPage diff --git a/static/css/v3/components.css b/static/css/v3/components.css index 4a7bb53c1..dee1f4483 100644 --- a/static/css/v3/components.css +++ b/static/css/v3/components.css @@ -23,10 +23,8 @@ @import "./search-card.css"; @import "./create-account-card.css"; @import "./badges-card.css"; -@import "./privacy-policy.css"; @import "./library-intro-card.css"; @import "./learn-cards.css"; -@import "./terms-of-use.css"; @import "./tab.css"; @import "./install-card.css"; @import "./banner.css"; diff --git a/static/css/v3/header.css b/static/css/v3/header.css index 3452294df..a77ddc135 100644 --- a/static/css/v3/header.css +++ b/static/css/v3/header.css @@ -12,7 +12,7 @@ --header-radius: var(--border-radius-xl); --header-bg: var(--color-surface-weak); position: relative; - padding: var(--space-medium); + padding: var(--space-default) var(--space-large); font-family: var(--font-sans); font-size: var(--font-size-small); font-weight: var(--font-weight-regular); @@ -516,6 +516,10 @@ html.dark .header__icon--theme-moon { padding: 0; } + .header { + padding: var(--space-medium); + } + .header__logo { justify-content: center; height: 100%; diff --git a/static/css/v3/privacy-policy.css b/static/css/v3/legal-page.css similarity index 59% rename from static/css/v3/privacy-policy.css rename to static/css/v3/legal-page.css index 1c01cba2f..0c64d6dcb 100644 --- a/static/css/v3/privacy-policy.css +++ b/static/css/v3/legal-page.css @@ -1,4 +1,20 @@ -.privacy-policy { +/* + * Styles for v3/legal_page.html — the shared template behind /privacy/ and /terms-of-use/. + */ + +body:has(.legal-page) .v3-container { + display: flex; + flex-direction: column; + min-height: 100vh; + padding: 0; +} + +body:has(.legal-page) .v3-container > .min-vh-110 { + flex: 1; + min-height: 0; +} + +.legal-page { box-sizing: border-box; display: flex; flex-direction: column; @@ -7,13 +23,10 @@ position: relative; gap: calc(2 * var(--space-xl)); width: 100%; - padding-left: var(--space-large); - padding-right: var(--space-large); - padding-top: var(--space-xxl); - padding-bottom: var(--space-xxl); + padding: 80px var(--space-medium) 43px var(--space-medium); } -.privacy-policy__inner { +.legal-page__inner { display: flex; flex-direction: column; gap: var(--space-xl); @@ -21,20 +34,20 @@ justify-content: flex-start; width: 100%; min-width: 0; - max-width: 50rem; + max-width: 696px; margin-left: auto; margin-right: auto; } -.privacy-policy__header { +.legal-page__header { display: flex; flex-direction: column; - gap: var(--space-card); + gap: var(--space-large); align-items: flex-start; width: 100%; } -.privacy-policy__title { +.legal-page__title { margin: 0; color: var(--color-text-primary); font-family: var(--font-sans); @@ -44,7 +57,7 @@ letter-spacing: var(--letter-spacing-tight); } -.privacy-policy__last-updated { +.legal-page__last-updated { margin: 0; padding: 0; color: var(--color-text-secondary); @@ -55,19 +68,18 @@ letter-spacing: var(--letter-spacing-tight); } -.privacy-policy__body { +.legal-page__body { + width: 100%; color: var(--color-text-secondary); font-family: var(--font-sans); font-size: var(--font-size-base); font-weight: var(--font-weight-regular); line-height: var(--line-height-loose); letter-spacing: var(--letter-spacing-tight); - width: 100%; - padding: 0; } -.privacy-policy__body h2 { - margin: var(--space-xl) 0 var(--space-card); +.legal-page__body h2 { + margin: var(--space-xl) 0 var(--space-large); color: var(--color-text-primary); font-family: var(--font-sans); font-size: var(--font-size-large); @@ -76,29 +88,54 @@ letter-spacing: var(--letter-spacing-tight); } -.privacy-policy__body > :first-child { +.legal-page__body > :first-child { margin-top: 0; } -.privacy-policy__body p { +.legal-page__body p { + color: var(--color-text-secondary); margin: 0 0 1em 0; padding: 0; } -.privacy-policy__body p:last-child { +.legal-page__body p:last-child { margin-bottom: 0; } -.privacy-policy__body ul { +.legal-page__body ul { list-style-type: disc; padding-left: 1em; margin: 0 0 1em 0; } -.privacy-policy__body li { +.legal-page__body li { margin-bottom: var(--space-s); } -.privacy-policy__body a { +.legal-page__body li::marker { + font-size: var(--font-size-xs); +} + +.legal-page__body a { color: var(--color-text-link-accent); + font-weight: var(--font-weight-medium); + text-decoration: underline; +} + +/* Responsive Adjustments */ +@media (max-width: 1024px) { + .legal-page { + padding-top: 40px; + padding-bottom: 64px; + } + + .legal-page__inner { + max-width: 656px; + } +} + +@media (max-width: 767px) { + .legal-page { + padding-top: 32px; + } } diff --git a/static/css/v3/terms-of-use.css b/static/css/v3/terms-of-use.css deleted file mode 100644 index 41a33aaba..000000000 --- a/static/css/v3/terms-of-use.css +++ /dev/null @@ -1,98 +0,0 @@ -.terms-page { - display: flex; - flex-direction: column; - align-items: flex-end; - gap: var(--space-xl); - width: 100%; - font-family: var(--font-sans); -} - -.terms-page__title-block { - display: flex; - flex-direction: column; - gap: var(--space-large); - align-items: flex-start; - width: 100%; -} - -.terms-page__title { - font-family: var(--font-sans); - font-weight: var(--font-weight-medium); - font-size: var(--font-size-2xl); - line-height: 1; - letter-spacing: -0.4px; - color: var(--color-text-primary); - margin: 0; - padding: 0; -} - -.terms-page__last-updated { - font-family: var(--font-sans); - font-weight: var(--font-weight-regular); - font-size: var(--font-size-xs); - line-height: 1.2; - letter-spacing: -0.12px; - color: var(--color-text-secondary); - margin: 0; - padding: 0; -} - -.terms-page__body { - font-family: var(--font-sans); - font-weight: var(--font-weight-regular); - font-size: var(--font-size-base); - line-height: var(--line-height-loose); - letter-spacing: -0.16px; - color: var(--color-text-secondary); - width: 100%; - padding: 0; -} - -.terms-page__body h2 { - font-family: var(--font-sans); - font-weight: var(--font-weight-medium); - font-size: var(--font-size-large); - line-height: 1; - letter-spacing: -0.24px; - color: var(--color-text-primary); - margin: var(--space-xl) 0 var(--space-large); -} - -.terms-page__body > :first-child { - margin-top: 0; -} - -.terms-page__body p { - margin: 0 0 0.5em 0; - padding: 0; -} - -.terms-page__body p:last-child { - margin: 0; -} - -.terms-page__body ul { - list-style: disc; - padding-left: 24px; - margin: 0 0 0.5em 0; -} - -.terms-page__body ul li { - margin-bottom: var(--space-default); -} - -.terms-page__body ul li:last-child { - margin-bottom: 0; -} - -.terms-page__body a { - color: var(--color-text-secondary); - text-decoration: underline; -} - -.terms-page__wrapper { - max-width: 800px; - margin: 0 auto; - padding: 88px var(--space-medium) var(--space-xlarge); - box-sizing: border-box; -} diff --git a/templates/v3/legal_page.html b/templates/v3/legal_page.html new file mode 100644 index 000000000..7d3df06ba --- /dev/null +++ b/templates/v3/legal_page.html @@ -0,0 +1,26 @@ +{% extends "base.html" %} +{% load static wagtailcore_tags %} + +{% block title %}{{ page.title }}{% endblock %} +{% block description %}{{ page.search_description }}{% endblock %} + +{% block css %} + {{ block.super }} + +{% endblock %} + +{% block content %} + +{% endblock %} diff --git a/templates/v3/privacy_policy.html b/templates/v3/privacy_policy.html deleted file mode 100644 index 76b63f0a5..000000000 --- a/templates/v3/privacy_policy.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "base.html" %} -{% load static wagtailcore_tags %} - -{% block title %}{{ page.title|default:"Privacy Policy" }}{% endblock %} - -{% block content %} -
-
-
-

{{ page.title|default:"Privacy Policy" }}

- {% if page.last_published_at %} -

Last Updated: {{ page.last_published_at|date:"F j, Y" }}

- {% endif %} -
-
- {{ page.body|richtext }} -
-
-
-{% endblock %} diff --git a/templates/v3/terms_of_use.html b/templates/v3/terms_of_use.html deleted file mode 100644 index 205198d9f..000000000 --- a/templates/v3/terms_of_use.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "base.html" %} -{% load i18n wagtailcore_tags %} - -{% block title %}{{ page.title|default:"Terms of Use" }}{% endblock %} -{% block description %}Terms of Use for The C Plus Plus Alliance, Inc. Services.{% endblock %} - -{% block content %} -
-
-
-

{{ page.title|default:"Terms of Use" }}

- {% if page.last_published_at %} -

Last Updated: {{ page.last_published_at|date:"F j, Y" }}

- {% endif %} -
- -
- {{ page.body|richtext }} -
-
-
-{% endblock %} From 5dc5260a2c6632e0dae0bcf86c2fe87c9fd3655d Mon Sep 17 00:00:00 2001 From: Julia Hoang Date: Wed, 20 May 2026 13:58:36 -0700 Subject: [PATCH 3/3] chore: fix some copies in the legal page migration content seed to match prod --- pages/migrations/0003_create_legal_pages.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pages/migrations/0003_create_legal_pages.py b/pages/migrations/0003_create_legal_pages.py index f8e1890a7..fe684a3d2 100644 --- a/pages/migrations/0003_create_legal_pages.py +++ b/pages/migrations/0003_create_legal_pages.py @@ -22,8 +22,8 @@

We collect and store log and usage data for diagnostic and performance purposes. This may include the same analytics information above along with additional information related to your usage of the site.

Privacy Statement Revisions

We may update this privacy notice from time to time. The updated version will be indicated by an updated "Revised" date and the updated version will be effective as soon as it is accessible. If we make material changes to this privacy notice, we may notify you either by prominently posting a notice of such changes or by directly sending you a notification. We encourage you to review this privacy notice frequently to be informed of how we are protecting your information.

-

Questions

-

Questions or concerns? Reading this privacy notice will help you understand your privacy rights and choices. If you do not agree with our policies and practices, please do not use our Services. If you still have any questions or concerns, please contact us at info@cppalliance.org.

+

Questions?

+

Questions or concerns? Reading this privacy notice will help you understand your privacy rights and choices. If you do not agree with our policies and practices, please do not use our Services. If you still have any questions or concerns, please contact us at info@cppalliance.org.

""".strip() @@ -36,7 +36,7 @@

We will make our best effort to notify registered users who have provided us with a valid email address of any changes to our Terms of Use via email. While we aim to ensure timely and accurate notifications, we do not guarantee that all changes will be communicated.

Intellectual Property

Boost libraries, documentation, source code, and this website are provided under the terms of the Boost Software License.

-

You grant The C Plus Plus Alliance, Inc. a royalty-free and non-exclusive license to display, use, copy, transmit, and broadcast the content you upload and publish. For issues regarding intellectual property claims, you should contact The C Plus Plus Alliance, Inc.

+

You grant The C Plus Plus Alliance, Inc. a royalty-free and non-exclusive license to display, use, copy, transmit, and broadcast the content you upload and publish. For issues regarding intellectual property claims, you should contact the The C Plus Plus Alliance, Inc.

User Accounts

As a user of this website you have the option, but not the requirement, to register with us and provide additional information. You are responsible for ensuring the accuracy of this information, and you are responsible for maintaining the safety and security of your identifying information.

You are also responsible for all activities that occur under your account or password.

@@ -69,10 +69,10 @@

These Legal Terms and your use of the Services are governed by and construed in accordance with the laws of the State of California applicable to agreements made and to be entirely performed within the State of California, without regard to its conflict of law principles.

Disclaimer

THE SERVICES ARE PROVIDED ON AN AS-IS AND AS-AVAILABLE BASIS. YOU AGREE THAT YOUR USE OF THE SERVICES WILL BE AT YOUR SOLE RISK. TO THE FULLEST EXTENT PERMITTED BY LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, IN CONNECTION WITH THE SERVICES AND YOUR USE THEREOF, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. WE MAKE NO WARRANTIES OR REPRESENTATIONS ABOUT THE ACCURACY OR COMPLETENESS OF THE SERVICES' CONTENT OR THE CONTENT OF ANY WEBSITES OR MOBILE APPLICATIONS LINKED TO THE SERVICES AND WE WILL ASSUME NO LIABILITY OR RESPONSIBILITY FOR ANY (1) ERRORS, MISTAKES, OR INACCURACIES OF CONTENT AND MATERIALS, (2) PERSONAL INJURY OR PROPERTY DAMAGE, OF ANY NATURE WHATSOEVER, RESULTING FROM YOUR ACCESS TO AND USE OF THE SERVICES, (3) ANY UNAUTHORIZED ACCESS TO OR USE OF OUR SECURE SERVERS AND/OR ANY AND ALL PERSONAL INFORMATION AND/OR FINANCIAL INFORMATION STORED THEREIN, (4) ANY INTERRUPTION OR CESSATION OF TRANSMISSION TO OR FROM THE SERVICES, (5) ANY BUGS, VIRUSES, TROJAN HORSES, OR THE LIKE WHICH MAY BE TRANSMITTED TO OR THROUGH THE SERVICES BY ANY THIRD PARTY, AND/OR (6) ANY ERRORS OR OMISSIONS IN ANY CONTENT AND MATERIALS OR FOR ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF ANY CONTENT POSTED, TRANSMITTED, OR OTHERWISE MADE AVAILABLE VIA THE SERVICES. WE DO NOT WARRANT, ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR ANY PRODUCT OR SERVICE ADVERTISED OR OFFERED BY A THIRD PARTY THROUGH THE SERVICES, ANY HYPERLINKED WEBSITE, OR ANY WEBSITE OR MOBILE APPLICATION FEATURED IN ANY BANNER OR OTHER ADVERTISING, AND WE WILL NOT BE A PARTY TO OR IN ANY WAY BE RESPONSIBLE FOR MONITORING ANY TRANSACTION BETWEEN YOU AND ANY THIRD-PARTY PROVIDERS OF PRODUCTS OR SERVICES. AS WITH THE PURCHASE OF A PRODUCT OR SERVICE THROUGH ANY MEDIUM OR IN ANY ENVIRONMENT, YOU SHOULD USE YOUR BEST JUDGMENT AND EXERCISE CAUTION WHERE APPROPRIATE.

-

Contact us

+

CONTACT US

In order to resolve a complaint regarding the Services or to receive further information regarding use of the Services, please contact us at:

-

The C Plus Plus Alliance, Inc.
5716 Corsa Ave suite 110
Westlake Village, CA 91362
United States

-

Phone: (+1) 305 216 5538
info@cppalliance.org

+

The C Plus Plus Alliance, Inc. 5716 Corsa Ave suite 110 Westlake Village, CA 91362 United States

+

Phone: (+1)3052165538 info@cppalliance.org

""".strip()