diff --git a/network-api/networkapi/tests.py b/network-api/networkapi/tests.py index baed40ae92b..c1eb81cd8fa 100644 --- a/network-api/networkapi/tests.py +++ b/network-api/networkapi/tests.py @@ -265,7 +265,6 @@ def setUp(self): company='Percy Corp', blurb='This is a general product specifically created for visual regression testing', product_url='http://example.com/general-percy', - price=999, worst_case='Visual regression fails', # general product fields camera_app='Yes', @@ -303,7 +302,6 @@ def setUp(self): company='Percy Corp', blurb='This is a general product specifically created for visual regression testing', product_url='http://example.com/general-percy', - price=999, worst_case='Visual regression fails', # software product fields ) @@ -326,7 +324,6 @@ def test_product_page_import_mappings(self): self.assertEqual(mappings["Company"], "company") self.assertEqual(mappings["Blurb"], "blurb") self.assertEqual(mappings["Product link"], "product_url") - self.assertEqual(mappings["Price"], "price") self.assertEqual(mappings["Worst case"], "worst_case") self.assertEqual(mappings["Signup requires email"], "signup_requires_email") self.assertEqual(mappings["Signup requires phone number"], "signup_requires_phone") @@ -401,7 +398,6 @@ def test_product_page_export_fields(self): self.assertIn("Company", export_fields) self.assertIn("Blurb", export_fields) self.assertIn("Product link", export_fields) - self.assertIn("Price", export_fields) self.assertIn("Worst case", export_fields) self.assertIn("Signup requires email", export_fields) self.assertIn("Signup requires phone number", export_fields) diff --git a/network-api/networkapi/wagtailpages/factory/buyersguide.py b/network-api/networkapi/wagtailpages/factory/buyersguide.py index 7db7467d5c0..ffbd8267bec 100644 --- a/network-api/networkapi/wagtailpages/factory/buyersguide.py +++ b/network-api/networkapi/wagtailpages/factory/buyersguide.py @@ -6,7 +6,6 @@ from factory import ( Faker, post_generation, - LazyAttribute, LazyFunction, ) from factory.django import DjangoModelFactory @@ -96,7 +95,6 @@ class Meta: company = Faker('company') blurb = Faker('sentence') product_url = Faker('url') - price = LazyAttribute(lambda _: randint(49, 1500)) worst_case = Faker('sentence') first_published_at = Faker('past_datetime', start_date='-2d', tzinfo=timezone.utc) last_published_at = Faker('past_datetime', start_date='-1d', tzinfo=timezone.utc) @@ -168,8 +166,6 @@ class SoftwareProductPageFactory(ProductPageFactory): class Meta: model = SoftwareProductPage - price = 0 - handles_recordings_how = Faker('sentence') recording_alert = LazyFunction(get_extended_yes_no_value) recording_alert_helptext = Faker('sentence') @@ -206,7 +202,6 @@ def create_general_product_visual_regression_product(seed, pni_homepage): company='Percy Corp', blurb='This is a general product specifically created for visual regression testing', product_url='http://example.com/general-percy', - price=999, worst_case='Visual regression fails', # general product fields camera_app='Yes', @@ -248,7 +243,6 @@ def create_software_product_visual_regression_product(seed, pni_homepage): company='Percy Corp', blurb='This is a general product specifically created for visual regression testing', product_url='http://example.com/general-percy', - price=999, worst_case='Visual regression fails', # software product fields ) diff --git a/network-api/networkapi/wagtailpages/migrations/0050_auto_20211104_2126.py b/network-api/networkapi/wagtailpages/migrations/0050_auto_20211104_2126.py new file mode 100644 index 00000000000..dde3a2a85a0 --- /dev/null +++ b/network-api/networkapi/wagtailpages/migrations/0050_auto_20211104_2126.py @@ -0,0 +1,326 @@ +# Generated by Django 3.1.11 on 2021-11-04 21:26 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import networkapi.wagtailpages.fields +import wagtail.core.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailimages', '0023_add_choose_permissions'), + ('wagtailpages', '0049_auto_20211101_1811'), + ] + + operations = [ + migrations.RemoveField( + model_name='generalproductpage', + name='ai_is_untrustworthy_helptext', + ), + migrations.RemoveField( + model_name='productpage', + name='price', + ), + migrations.AlterField( + model_name='generalproductpage', + name='ai_can_user_control', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='does the user have control over the AI features?'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='ai_can_user_control_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='control of AI description'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='ai_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='general AI description'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='ai_is_transparent', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='is the company transparent about how the AI works?'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='ai_is_transparent_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='aI transparency description'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='ai_is_untrustworthy', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='is this AI untrustworthy?'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='ai_is_untrustworthy_ding', + field=models.BooleanField(default=False, verbose_name='mini-ding for bad AI'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='ai_what_can_it_do', + field=wagtail.core.fields.RichTextField(blank=True, verbose_name='what kind of decisions does the AI make about you or for you?'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='biometric_data_collected', + field=models.TextField(blank=True, max_length=5000, verbose_name='body Related'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='camera_app', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='camera: App'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='camera_device', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='camera: Device'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='company_track_record', + field=models.CharField(choices=[('Great', 'Great'), ('Average', 'Average'), ('Needs Improvement', 'Needs Improvement'), ('Bad', 'Bad')], default='Average', max_length=20, verbose_name="company's known track record?"), + ), + migrations.AlterField( + model_name='generalproductpage', + name='data_control_policy_is_bad', + field=models.BooleanField(default=False, verbose_name='mini-ding for bad data control?'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='how_can_you_control_your_data', + field=models.TextField(blank=True, max_length=5000, verbose_name='how can you control your data?'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='location_app', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='tracks location: App'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='location_device', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='tracks location: Device'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='microphone_app', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='microphone: App'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='microphone_device', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='microphone: Device'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='offline_capable', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='can this product be used offline?'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='offline_use_description', + field=models.TextField(blank=True, max_length=5000, verbose_name='offline description'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='personal_data_collected', + field=models.TextField(blank=True, max_length=5000, verbose_name='personal'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='social_data_collected', + field=models.TextField(blank=True, max_length=5000, verbose_name='social'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='track_record_details', + field=models.TextField(blank=True, max_length=5000, verbose_name='known track record description'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='track_record_is_bad', + field=models.BooleanField(default=False, verbose_name='mini-ding for bad track record'), + ), + migrations.AlterField( + model_name='generalproductpage', + name='uses_ai', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='does the product use AI?'), + ), + migrations.AlterField( + model_name='productpage', + name='adult_content', + field=models.BooleanField(default=False, verbose_name='adult Content'), + ), + migrations.AlterField( + model_name='productpage', + name='blurb', + field=wagtail.core.fields.RichTextField(blank=True, verbose_name='intro Blurb'), + ), + migrations.AlterField( + model_name='productpage', + name='company', + field=models.CharField(blank=True, max_length=100, verbose_name='company Name'), + ), + migrations.AlterField( + model_name='productpage', + name='data_collection_policy_is_bad', + field=models.BooleanField(default=False, verbose_name='mini-ding for bad data use?'), + ), + migrations.AlterField( + model_name='productpage', + name='how_does_it_use_data_collected', + field=models.TextField(blank=True, max_length=5000, verbose_name='how does the company use this data?'), + ), + migrations.AlterField( + model_name='productpage', + name='image', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image'), + ), + migrations.AlterField( + model_name='productpage', + name='manage_vulnerabilities', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='manages security vulnerabilities'), + ), + migrations.AlterField( + model_name='productpage', + name='manage_vulnerabilities_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='description'), + ), + migrations.AlterField( + model_name='productpage', + name='meets_minimum_security_standards', + field=models.BooleanField(blank=True, null=True, verbose_name='does this product meet our Minimum Security Standards?'), + ), + migrations.AlterField( + model_name='productpage', + name='mozilla_says', + field=models.BooleanField(blank=True, help_text="Use 'Yes' for Thumbs Up, 'No' for Thumbs Down, and 'Unknown' for Thumb Sideways", null=True, verbose_name='mozilla Says'), + ), + migrations.AlterField( + model_name='productpage', + name='privacy_ding', + field=models.BooleanField(default=False, verbose_name='*privacy not included ding'), + ), + migrations.AlterField( + model_name='productpage', + name='privacy_policy', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(), + ), + migrations.AlterField( + model_name='productpage', + name='privacy_policy_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='description'), + ), + migrations.AlterField( + model_name='productpage', + name='product_url', + field=models.URLField(blank=True, max_length=2048, verbose_name='product URL'), + ), + migrations.AlterField( + model_name='productpage', + name='review_date', + field=models.DateField(default=django.utils.timezone.now, verbose_name='review Date'), + ), + migrations.AlterField( + model_name='productpage', + name='security_updates', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(), + ), + migrations.AlterField( + model_name='productpage', + name='security_updates_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='description'), + ), + migrations.AlterField( + model_name='productpage', + name='show_ding_for_minimum_security_standards', + field=models.BooleanField(default=False, verbose_name='mini-ding for doesnt meet Minimum Security Standards'), + ), + migrations.AlterField( + model_name='productpage', + name='signup_requirement_explanation', + field=models.TextField(blank=True, max_length=5000, verbose_name='signup requirement description'), + ), + migrations.AlterField( + model_name='productpage', + name='signup_requires_email', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='email'), + ), + migrations.AlterField( + model_name='productpage', + name='signup_requires_phone', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='phone'), + ), + migrations.AlterField( + model_name='productpage', + name='signup_requires_third_party_account', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='third-party account'), + ), + migrations.AlterField( + model_name='productpage', + name='strong_password_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='description'), + ), + migrations.AlterField( + model_name='productpage', + name='time_researched', + field=models.PositiveIntegerField(default=0, verbose_name='time spent on research'), + ), + migrations.AlterField( + model_name='productpage', + name='user_friendly_privacy_policy', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='user-friendly privacy information?'), + ), + migrations.AlterField( + model_name='productpage', + name='user_friendly_privacy_policy_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='user-friendly privacy description'), + ), + migrations.AlterField( + model_name='productpage', + name='uses_bluetooth', + field=models.BooleanField(default=False, verbose_name='uses Bluetooth'), + ), + migrations.AlterField( + model_name='productpage', + name='uses_encryption', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(verbose_name='encryption'), + ), + migrations.AlterField( + model_name='productpage', + name='uses_encryption_helptext', + field=models.TextField(blank=True, max_length=5000, verbose_name='description'), + ), + migrations.AlterField( + model_name='productpage', + name='uses_wifi', + field=models.BooleanField(default=False, verbose_name='uses WiFi'), + ), + migrations.AlterField( + model_name='productpage', + name='worst_case', + field=wagtail.core.fields.RichTextField(blank=True, verbose_name='what could happen if something goes wrong?'), + ), + migrations.AlterField( + model_name='softwareproductpage', + name='easy_to_learn_and_use', + field=networkapi.wagtailpages.fields.ExtendedBoolean(), + ), + migrations.AlterField( + model_name='softwareproductpage', + name='handles_recordings_how', + field=models.TextField(blank=True, max_length=5000), + ), + migrations.AlterField( + model_name='softwareproductpage', + name='medical_privacy_compliant', + field=networkapi.wagtailpages.fields.ExtendedBoolean(), + ), + migrations.AlterField( + model_name='softwareproductpage', + name='recording_alert', + field=networkapi.wagtailpages.fields.ExtendedYesNoField(null=True), + ), + ] diff --git a/network-api/networkapi/wagtailpages/pagemodels/products.py b/network-api/networkapi/wagtailpages/pagemodels/products.py index 227d537d49c..9d1bb2d2f97 100644 --- a/network-api/networkapi/wagtailpages/pagemodels/products.py +++ b/network-api/networkapi/wagtailpages/pagemodels/products.py @@ -442,44 +442,38 @@ class ProductPage(AirtableMixin, FoundationMetadataPageMixin, Page): template = 'buyersguide/product_page.html' privacy_ding = models.BooleanField( - help_text='Tick this box if privacy is not included for this product', + verbose_name='*privacy not included ding', default=False, ) adult_content = models.BooleanField( - help_text='When checked, product thumbnail will appear blurred as well as have an 18+ badge on it', + verbose_name='adult Content', default=False, ) uses_wifi = models.BooleanField( - help_text='Does this product rely on WiFi connectivity?', + verbose_name='uses WiFi', default=False, ) uses_bluetooth = models.BooleanField( - help_text='Does this product rely on Bluetooth connectivity?', + verbose_name='uses Bluetooth', default=False, ) review_date = models.DateField( - help_text='Review date of this product', + verbose_name='review Date', default=timezone.now, ) company = models.CharField( + verbose_name='company Name', max_length=100, - help_text='Name of Company', blank=True, ) blurb = RichTextField( - max_length=5000, + verbose_name='intro Blurb', features=['bold', 'italic', 'link'], - help_text='Description of the product', blank=True ) product_url = models.URLField( + verbose_name='product URL', max_length=2048, - help_text='Link to this product page', - blank=True, - ) - price = models.CharField( - max_length=100, - help_text='Price', blank=True, ) image = models.ForeignKey( @@ -488,12 +482,10 @@ class ProductPage(AirtableMixin, FoundationMetadataPageMixin, Page): blank=True, on_delete=models.SET_NULL, related_name='+', - help_text='Image representing this product', ) worst_case = RichTextField( - max_length=5000, + verbose_name='what could happen if something goes wrong?', features=['bold', 'italic', 'link'], - help_text="What's the worst thing that could happen by using this product?", blank=True, ) tips_to_protect_yourself = RichTextField( @@ -501,13 +493,13 @@ class ProductPage(AirtableMixin, FoundationMetadataPageMixin, Page): blank=True ) mozilla_says = models.BooleanField( + verbose_name='mozilla Says', null=True, blank=True, - help_text='Whether or not Mozilla would recommend this product. ' - 'Will appear as a thumbs up/down/middle.', + help_text="Use 'Yes' for Thumbs Up, 'No' for Thumbs Down, and 'Unknown' for Thumb Sideways", ) time_researched = models.PositiveIntegerField( - help_text="How many hours were spent researching this product?", + verbose_name='time spent on research', default=0 ) @@ -519,37 +511,38 @@ class ProductPage(AirtableMixin, FoundationMetadataPageMixin, Page): # What is required to sign up? signup_requires_email = ExtendedYesNoField( - help_text='Does this product requires providing an email address in order to sign up?' + verbose_name='email' ) signup_requires_phone = ExtendedYesNoField( - help_text='Does this product requires providing a phone number in order to sign up?' + verbose_name='phone' ) signup_requires_third_party_account = ExtendedYesNoField( - help_text='Does this product require a third party account in order to sign up?' + verbose_name='third-party account' ) signup_requirement_explanation = models.TextField( + verbose_name='signup requirement description', max_length=5000, blank=True, - help_text='Describe the particulars around sign-up requirements here.' ) # How does it use this data? how_does_it_use_data_collected = models.TextField( + verbose_name='how does the company use this data?', max_length=5000, blank=True, - help_text='How does this product use the data collected?' ) data_collection_policy_is_bad = models.BooleanField( default=False, - verbose_name='Privacy ding' + verbose_name='mini-ding for bad data use?' ) # Privacy policy user_friendly_privacy_policy = ExtendedYesNoField( - help_text='Does this product have a user-friendly privacy policy?' + verbose_name='user-friendly privacy information?', ) user_friendly_privacy_policy_helptext = models.TextField( + verbose_name='user-friendly privacy description', max_length=5000, blank=True ) @@ -557,43 +550,46 @@ class ProductPage(AirtableMixin, FoundationMetadataPageMixin, Page): # Minimum security standards show_ding_for_minimum_security_standards = models.BooleanField( default=False, - verbose_name="Privacy ding" + verbose_name='mini-ding for doesnt meet Minimum Security Standards' ) meets_minimum_security_standards = models.BooleanField( + verbose_name='does this product meet our Minimum Security Standards?', null=True, blank=True, - help_text='Does this product meet our minimum security standards?', ) uses_encryption = ExtendedYesNoField( - help_text='Does the product use encryption?', + verbose_name='encryption', ) uses_encryption_helptext = models.TextField( + verbose_name='description', max_length=5000, blank=True ) security_updates = ExtendedYesNoField( - help_text='Security updates?', ) security_updates_helptext = models.TextField( + verbose_name='description', max_length=5000, blank=True ) strong_password = ExtendedYesNoField() strong_password_helptext = models.TextField( + verbose_name='description', max_length=5000, blank=True ) manage_vulnerabilities = ExtendedYesNoField( - help_text='Manages security vulnerabilities?', + verbose_name='manages security vulnerabilities', ) manage_vulnerabilities_helptext = models.TextField( + verbose_name='description', max_length=5000, blank=True ) privacy_policy = ExtendedYesNoField( - help_text='Does this product have a privacy policy?' ) privacy_policy_helptext = models.TextField( # REPURPOSED: WILL REQUIRE A 'clear' MIGRATION + verbose_name='description', max_length=5000, blank=True ) @@ -626,7 +622,6 @@ def map_import_fields(cls): "Company": "company", "Blurb": "blurb", "Product link": "product_url", - "Price": "price", "Worst case": "worst_case", "Signup requires email": "signup_requires_email", "Signup requires phone number": "signup_requires_phone", @@ -672,7 +667,6 @@ def get_export_fields(self): "Company": self.company, "Blurb": self.blurb, "Product link": self.product_url if self.product_url else '', - "Price": self.price, "Worst case": self.worst_case, "Signup requires email": self.signup_requires_email, "Signup requires phone number": self.signup_requires_phone, @@ -755,33 +749,32 @@ def get_voting_json(self): return json.dumps(data) content_panels = Page.content_panels + [ + FieldPanel('company'), + MultiFieldPanel( + [ + InlinePanel('product_categories', label='Category'), + ], + heading='Product Category', + classname='collapsible', + ), MultiFieldPanel( [ - FieldPanel('review_date'), FieldPanel('privacy_ding'), + FieldPanel('review_date'), FieldPanel('adult_content'), - FieldPanel('company'), + ImageChooserPanel('image'), FieldPanel('product_url'), - FieldPanel('price'), + FieldPanel('time_researched'), + FieldPanel('mozilla_says'), FieldPanel('uses_wifi'), FieldPanel('uses_bluetooth'), FieldPanel('blurb'), - ImageChooserPanel('image'), FieldPanel('worst_case'), FieldPanel('tips_to_protect_yourself'), - FieldPanel('mozilla_says'), - FieldPanel('time_researched') ], heading='General Product Details', classname='collapsible' ), - MultiFieldPanel( - [ - InlinePanel('product_categories', label='Category'), - ], - heading='Product Categories', - classname='collapsible', - ), MultiFieldPanel( [ FieldPanel('signup_requires_email'), @@ -789,24 +782,7 @@ def get_voting_json(self): FieldPanel('signup_requires_third_party_account'), FieldPanel('signup_requirement_explanation'), ], - heading='What is required to sign up', - classname='collapsible' - ), - MultiFieldPanel( - [ - - FieldPanel('how_does_it_use_data_collected'), - FieldPanel('data_collection_policy_is_bad'), - ], - heading='How does it use this data', - classname='collapsible', - ), - MultiFieldPanel( - [ - FieldPanel('user_friendly_privacy_policy'), - FieldPanel('user_friendly_privacy_policy_helptext'), - ], - heading='Privacy policy', + heading='What can be used to sign up?', classname='collapsible' ), MultiFieldPanel( @@ -823,14 +799,14 @@ def get_voting_json(self): ), MultiFieldPanel( [ - FieldPanel('show_ding_for_minimum_security_standards'), FieldPanel('meets_minimum_security_standards'), + FieldPanel('show_ding_for_minimum_security_standards'), FieldPanel('uses_encryption'), FieldPanel('uses_encryption_helptext'), - FieldPanel('security_updates'), - FieldPanel('security_updates_helptext'), FieldPanel('strong_password'), FieldPanel('strong_password_helptext'), + FieldPanel('security_updates'), + FieldPanel('security_updates_helptext'), FieldPanel('manage_vulnerabilities'), FieldPanel('manage_vulnerabilities_helptext'), FieldPanel('privacy_policy'), @@ -843,7 +819,7 @@ def get_voting_json(self): [ InlinePanel('updates', label='Update') ], - heading='Product Updates', + heading='News Links', ), MultiFieldPanel( [ @@ -870,7 +846,6 @@ def get_voting_json(self): SynchronizedField('company'), TranslatableField('blurb'), SynchronizedField('product_url'), - TranslatableField('price'), SynchronizedField('image'), TranslatableField('worst_case'), SynchronizedField('product_categories'), @@ -999,12 +974,10 @@ class SoftwareProductPage(ProductPage): handles_recordings_how = models.TextField( max_length=5000, blank=True, - help_text='How does this software handle your recordings' ) recording_alert = ExtendedYesNoField( null=True, - help_text='Alerts when calls are being recorded?', ) recording_alert_helptext = models.TextField( @@ -1013,7 +986,6 @@ class SoftwareProductPage(ProductPage): ) medical_privacy_compliant = ExtendedBoolean( - help_text='Compliant with US medical privacy laws?' ) medical_privacy_compliant_helptext = models.TextField( @@ -1029,7 +1001,6 @@ class SoftwareProductPage(ProductPage): ) easy_to_learn_and_use = ExtendedBoolean( - help_text='Is it easy to learn & use the features?', ) easy_to_learn_and_use_helptext = models.TextField( @@ -1076,7 +1047,7 @@ def get_export_fields(self): content_panels = ProductPage.content_panels.copy() content_panels = insert_panels_after( content_panels, - 'Product Categories', + 'Security', [ MultiFieldPanel( [ @@ -1125,135 +1096,130 @@ class GeneralProductPage(ProductPage): template = 'buyersguide/product_page.html' camera_device = ExtendedYesNoField( - help_text='Does this device have or access a camera?', + verbose_name='camera: Device', ) camera_app = ExtendedYesNoField( - help_text='Does the app have or access a camera?', + verbose_name='camera: App', ) microphone_device = ExtendedYesNoField( - help_text='Does this Device have or access a microphone?', + verbose_name='microphone: Device', ) microphone_app = ExtendedYesNoField( - help_text='Does this app have or access a microphone?', + verbose_name='microphone: App', ) location_device = ExtendedYesNoField( - help_text='Does this product access your location?', + verbose_name='tracks location: Device', ) location_app = ExtendedYesNoField( - help_text='Does this app access your location?', + verbose_name='tracks location: App', ) # What data does it collect? personal_data_collected = models.TextField( + verbose_name='personal', max_length=5000, blank=True, - help_text='What kind of personal data does this product collect?' ) biometric_data_collected = models.TextField( + verbose_name='body Related', max_length=5000, blank=True, - help_text='What kind of biometric data does this product collect?' ) social_data_collected = models.TextField( + verbose_name='social', max_length=5000, blank=True, - help_text='What kind of social data does this product collect?' ) # How can you control your data how_can_you_control_your_data = models.TextField( + verbose_name='how can you control your data?', max_length=5000, blank=True, - help_text='How does this product let you control your data?' ) data_control_policy_is_bad = models.BooleanField( default=False, - verbose_name='Privacy ding' + verbose_name='mini-ding for bad data control?' ) # Company track record company_track_record = models.CharField( + verbose_name="company's known track record?", choices=TRACK_RECORD_CHOICES, default='Average', - help_text='This company has a ... track record', max_length=20 ) track_record_is_bad = models.BooleanField( default=False, - verbose_name='Privacy ding' + verbose_name='mini-ding for bad track record' ) track_record_details = models.TextField( + verbose_name='known track record description', max_length=5000, blank=True, - help_text='Describe the track record of this company here.' ) # Offline use offline_capable = ExtendedYesNoField( - help_text='Can this product be used offline?', + verbose_name='can this product be used offline?', ) offline_use_description = models.TextField( + verbose_name='offline description', max_length=5000, blank=True, - help_text='Describe how this product can be used offline.' ) # Artificial Intelligence uses_ai = ExtendedYesNoField( - help_text='Does the product use AI?' + verbose_name='does the product use AI?', ) ai_helptext = models.TextField( + verbose_name='general AI description', max_length=5000, blank=True, - help_text='Helpful text around AI to show on the product page', ) ai_is_untrustworthy = ExtendedYesNoField( - help_text='Is the AI untrustworthy?' - ) - ai_is_untrustworthy_helptext = models.TextField( - max_length=5000, - blank=True, - help_text='Helptext that will appear in the AI is untrustworthy section.', + verbose_name='is this AI untrustworthy?', ) ai_is_untrustworthy_ding = models.BooleanField( - help_text='Tick this box if the AI invades privacy or behaves unethically.', + verbose_name='mini-ding for bad AI', default=False, ) ai_what_can_it_do = RichTextField( + verbose_name='what kind of decisions does the AI make about you or for you?', blank=True, - help_text='What kind of decisions does this AI make about you or for you?' ) ai_is_transparent = ExtendedYesNoField( - help_text='Does the company allow users to see how the AI works?' + verbose_name='is the company transparent about how the AI works?', ) ai_is_transparent_helptext = models.TextField( + verbose_name='aI transparency description', max_length=5000, blank=True, - help_text='Helptext that will appear in the AI is transparent section.', ) ai_can_user_control = ExtendedYesNoField( - help_text='Does the user have control over the AI features?' + verbose_name='does the user have control over the AI features?', ) ai_can_user_control_helptext = models.TextField( + verbose_name='control of AI description', max_length=5000, blank=True, - help_text='Helptext that will appear in the can user control section.', ) @classmethod @@ -1279,7 +1245,6 @@ def map_import_fields(cls): "AI is transparent": "ai_is_transparent", "AI is transparent help text": "ai_is_transparent_helptext", "AI is untrustworthy": "ai_is_untrustworthy", - "AI is untrustworthy help text": "ai_is_untrustworthy_helptext", "AI is untrustworthy ding": "ai_is_untrustworthy_ding", "AI What can it do": "ai_what_can_it_do", "AI can user control": "ai_can_user_control", @@ -1314,7 +1279,6 @@ def get_export_fields(self): "AI is transparent help text": self.ai_is_transparent_helptext, "AI help text": self.ai_helptext, "AI is untrustworthy": self.ai_is_untrustworthy, - "AI is untrustworthy help text": self.ai_is_untrustworthy_helptext, "AI is untrustworthy ding": self.ai_is_untrustworthy_ding, "AI What can it do": self.ai_what_can_it_do, "AI can user control": self.ai_can_user_control, @@ -1328,7 +1292,7 @@ def get_export_fields(self): content_panels = ProductPage.content_panels.copy() content_panels = insert_panels_after( content_panels, - 'Product Categories', + 'General Product Details', [ MultiFieldPanel( [ @@ -1339,7 +1303,7 @@ def get_export_fields(self): FieldPanel('location_device'), FieldPanel('location_app'), ], - heading='Can it snoop?', + heading='Can it snoop on me?', classname='collapsible' ), ], @@ -1347,50 +1311,29 @@ def get_export_fields(self): content_panels = insert_panels_after( content_panels, - 'What is required to sign up', + 'What can be used to sign up?', [ MultiFieldPanel( [ FieldPanel('personal_data_collected'), FieldPanel('biometric_data_collected'), FieldPanel('social_data_collected'), - ], - heading='What data does it collect', - classname='collapsible', - ), - ] - ) - - content_panels = insert_panels_after( - content_panels, - 'How does it use this data', - [ - MultiFieldPanel( - [ + FieldPanel('how_does_it_use_data_collected'), + FieldPanel('data_collection_policy_is_bad'), FieldPanel('how_can_you_control_your_data'), FieldPanel('data_control_policy_is_bad'), - ], - heading='How can you control your data', - classname='collapsible', - ), - MultiFieldPanel( - [ FieldPanel('company_track_record'), - FieldPanel('track_record_is_bad'), FieldPanel('track_record_details'), - ], - heading='Company track record', - classname='collapsible' - ), - MultiFieldPanel( - [ + FieldPanel('track_record_is_bad'), FieldPanel('offline_capable'), FieldPanel('offline_use_description'), + FieldPanel('user_friendly_privacy_policy'), + FieldPanel('user_friendly_privacy_policy_helptext'), ], - heading='Offline use', - classname='collapsible' + heading='What data does the company collect?', + classname='collapsible', ), - ], + ] ) content_panels = insert_panels_after( @@ -1402,7 +1345,6 @@ def get_export_fields(self): FieldPanel('uses_ai'), FieldPanel('ai_helptext'), FieldPanel('ai_is_untrustworthy'), - FieldPanel('ai_is_untrustworthy_helptext'), FieldPanel('ai_is_untrustworthy_ding'), FieldPanel('ai_what_can_it_do'), FieldPanel('ai_is_transparent'), @@ -1432,7 +1374,6 @@ def get_export_fields(self): TranslatableField('ai_is_transparent_helptext'), TranslatableField('ai_helptext'), SynchronizedField('ai_is_untrustworthy'), - TranslatableField('ai_is_untrustworthy_helptext'), SynchronizedField('ai_is_untrustworthy_ding'), TranslatableField('ai_what_can_it_do'), SynchronizedField('ai_can_user_control'), diff --git a/network-api/networkapi/wagtailpages/pagemodels/serializers.py b/network-api/networkapi/wagtailpages/pagemodels/serializers.py index 13ce4f8f243..57fa8347e86 100644 --- a/network-api/networkapi/wagtailpages/pagemodels/serializers.py +++ b/network-api/networkapi/wagtailpages/pagemodels/serializers.py @@ -60,7 +60,6 @@ class ProductSerializer(AirtableSerializer): company = serializers.CharField(required=False, max_length=100) blurb = serializers.CharField(required=False, max_length=5000) product_url = serializers.URLField(required=False, max_length=2048) - price = serializers.CharField(required=False, max_length=100) worst_case = serializers.CharField(required=False, max_length=5000) signup_requires_email = ExtendedYesNoSerializer(default='CD') signup_requires_phone = ExtendedYesNoSerializer(default='CD') diff --git a/network-api/networkapi/wagtailpages/translation.py b/network-api/networkapi/wagtailpages/translation.py index 18da7ef3168..a6743cb651f 100644 --- a/network-api/networkapi/wagtailpages/translation.py +++ b/network-api/networkapi/wagtailpages/translation.py @@ -277,7 +277,6 @@ class YoutubeRegretsReporterPageTR(TranslationOptions): @register(ProductPage) class ProductPageTR(TranslationOptions): fields = ( - 'price', 'blurb', 'worst_case', 'signup_requirement_explanation',