From 793a2b3ca1dc5c46558a438978b8a4fb9af2bda9 Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Mon, 9 Oct 2023 09:10:48 +0000 Subject: [PATCH 01/11] model tweaks for media publicity --- src/api/handlers/media_library.py | 10 +- src/api/store/media_library.py | 21 ++- .../0140_usermediaupload_publicity.py | 18 +++ src/database/models.py | 129 +++++++++++------- .../model_constants/user_media_uploads.py | 7 + 5 files changed, 126 insertions(+), 59 deletions(-) create mode 100644 src/database/migrations/0140_usermediaupload_publicity.py create mode 100644 src/database/utils/settings/model_constants/user_media_uploads.py diff --git a/src/api/handlers/media_library.py b/src/api/handlers/media_library.py index 9f3aa16a5..79f0a858c 100644 --- a/src/api/handlers/media_library.py +++ b/src/api/handlers/media_library.py @@ -37,7 +37,7 @@ def fetch_content(self, request): return error return MassenergizeResponse(data=images) - @admins_only + @admins_only def search(self, request): """Filters images and only retrieves content related to a scope(events, testimonials,actions etc). More search types to be added later when requested...""" context: Context = request.context @@ -80,7 +80,9 @@ def addToGallery(self, request): args: dict = context.args self.validator.expect("user_id", str, is_required=True).expect( "community_ids", list - ).expect("title", str).expect("file", "file", is_required=True).expect( + ).expect("publicity", str).expect("title", str).expect( + "file", "file", is_required=True + ).expect( "is_universal", bool ).expect( "tags", "str_list" @@ -137,7 +139,7 @@ def find_images(self, request): return error return MassenergizeResponse(data=response) - @admins_only + @admins_only def edit_details(self, request): """Saves changes to updated image details""" context: Context = request.context @@ -152,7 +154,7 @@ def edit_details(self, request): "media_id", int, is_required=True ).expect( "user_upload_id", int, is_required=True - ) + ).expect("publicity", str) args, err = self.validator.verify(args, strict=True) if err: return err diff --git a/src/api/store/media_library.py b/src/api/store/media_library.py index f03115ccd..134c37559 100644 --- a/src/api/store/media_library.py +++ b/src/api/store/media_library.py @@ -1,5 +1,6 @@ from functools import reduce from django.core.exceptions import ValidationError +from database.utils.settings.model_constants.user_media_uploads import UserMediaConstants from sentry_sdk import capture_message from _main_.utils.context import Context from _main_.utils.footage.FootageConstants import FootageConstants @@ -44,6 +45,7 @@ def edit_details(self, args, context: Context): copyright_att = args.get("copyright_att") tags = args.get("tags") communities = args.get("community_ids", []) + publicity = args.get("publicity", None) info = { **(user_media_upload.info or {}), "has_children": under_age, @@ -60,6 +62,8 @@ def edit_details(self, args, context: Context): user_media_upload.communities.clear() user_media_upload.communities.set(communities) + if publicity: + user_media_upload.publicity = publicity user_media_upload.save() if tags: @@ -222,8 +226,8 @@ def search(self, args, context: Context): if most_recent: if context.user_is_super_admin: return self.get_most_recent(args, context) - else : - communities,_ = get_admin_communities(context) + else: + communities, _ = get_admin_communities(context) args["target_communities"] = [c.id for c in communities] return self.get_most_recent(args, context) @@ -283,8 +287,6 @@ def get_uploads_by_user(self, args): return images, None - - def remove(self, args, context): media_id = args.get("media_id") media = Media.objects.get(pk=media_id) @@ -325,6 +327,7 @@ def addToGallery(self, args, context): is_universal = args.get("is_universal", None) communities = user = None description = args.get("description", None) + publicity = args.get("publicity", None) # --------------------------------------------- copyright_permission = args.get("copyright", "") under_age = args.get("underAge", "") @@ -361,6 +364,7 @@ def addToGallery(self, args, context): is_universal=is_universal, tags=tags, info=info, + publicity=publicity, ) # ---------------------------------------------------------------- Spy.create_media_footage( @@ -379,6 +383,9 @@ def makeMediaAndSave(self, **kwargs): user = kwargs.get("user") tags = kwargs.get("tags") info = kwargs.get("info") + publicity = kwargs.get("publicity", None) + if not publicity: + publicity = UserMediaConstants.open_to() communities = kwargs.get("communities") is_universal = kwargs.get("is_universal") is_universal = True if is_universal else False @@ -391,7 +398,11 @@ def makeMediaAndSave(self, **kwargs): file=file, ) user_media = UserMediaUpload( - user=user, media=media, is_universal=is_universal, info=info + user=user, + media=media, + is_universal=is_universal, + info=info, + publicity=publicity, ) user_media.save() if media: diff --git a/src/database/migrations/0140_usermediaupload_publicity.py b/src/database/migrations/0140_usermediaupload_publicity.py new file mode 100644 index 000000000..a6dda6776 --- /dev/null +++ b/src/database/migrations/0140_usermediaupload_publicity.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.14 on 2023-10-09 06:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('database', '0139_merge_20230921_1405'), + ] + + operations = [ + migrations.AddField( + model_name='usermediaupload', + name='publicity', + field=models.CharField(default='OPEN_TO', max_length=100), + ), + ] diff --git a/src/database/models.py b/src/database/models.py index 96c189d5e..cb555168f 100644 --- a/src/database/models.py +++ b/src/database/models.py @@ -10,6 +10,9 @@ from _main_.utils.footage.FootageConstants import FootageConstants from database.utils.constants import * from database.utils.settings.admin_settings import AdminPortalSettings +from database.utils.settings.model_constants.user_media_uploads import ( + UserMediaConstants, +) from database.utils.settings.user_settings import UserPortalSettings from django.utils import timezone from django.core.files.storage import default_storage @@ -31,6 +34,7 @@ # ------------------------------------------------------------------------- + def get_enabled_flags( _self, users=False ): # _self : CommunityObject or UserProfileObject @@ -75,16 +79,21 @@ def user_is_due_for_mou(user): ).latest("signed_at") except PolicyAcceptanceRecords.DoesNotExist: return True, None - + # ok if user signed MOU after the date one year ago - if last_record.signed_at and last_record.signed_at > a_year_ago: + if last_record.signed_at and last_record.signed_at > a_year_ago: return False, last_record.simple_json() - + return True, last_record.simple_json() - -def fetch_few_visits(user): - footages = Footage.objects.filter(actor__id = user.id, activity_type=FootageConstants.sign_in(), portal = FootageConstants.on_user_portal()).values_list("created_at", flat=True)[:5] - if len(footages): + + +def fetch_few_visits(user): + footages = Footage.objects.filter( + actor__id=user.id, + activity_type=FootageConstants.sign_in(), + portal=FootageConstants.on_user_portal(), + ).values_list("created_at", flat=True)[:5] + if len(footages): return list(footages) visits = user.visit_log or [] @@ -265,16 +274,16 @@ def __str__(self): return str(self.id) + "-" + self.name + "(" + self.file.name + ")" def simple_json(self): - obj= { + obj = { "id": self.id, "name": self.name, "url": self.file.url, } - if hasattr(self, "user_upload"): + if hasattr(self, "user_upload"): obj["created_at"] = self.user_upload.created_at - return obj + return obj def full_json(self): return { @@ -285,8 +294,8 @@ def full_json(self): "media_type": self.media_type, "tags": [tag.simple_json() for tag in self.tags.all()], } - - def delete(self, *args, **kwargs): + + def delete(self, *args, **kwargs): # Overriding the default delete fxn to delete actual file from storage as well if self.file: file_path = self.file.name @@ -468,8 +477,12 @@ class Community(models.Model): subdomain = models.SlugField(max_length=SHORT_STR_LEN, unique=True, db_index=True) owner_name = models.CharField(max_length=SHORT_STR_LEN, default="Unknown") owner_email = models.EmailField(blank=False) - contact_sender_alias = models.CharField(blank=True, null=True, max_length=SHORT_STR_LEN) - owner_phone_number = models.CharField(blank=True, null=True, max_length=SHORT_STR_LEN) + contact_sender_alias = models.CharField( + blank=True, null=True, max_length=SHORT_STR_LEN + ) + owner_phone_number = models.CharField( + blank=True, null=True, max_length=SHORT_STR_LEN + ) about_community = models.TextField(max_length=LONG_STR_LEN, blank=True) logo = models.ForeignKey( Media, @@ -602,43 +615,47 @@ def full_json(self): carbon_footprint_reduction = 0 for actionRel in done_actions: if actionRel.action and actionRel.action.calculator_action: - carbon_footprint_reduction += AverageImpact(actionRel.action.calculator_action, actionRel.date_completed) + carbon_footprint_reduction += AverageImpact( + actionRel.action.calculator_action, actionRel.date_completed + ) goal["organic_attained_carbon_footprint_reduction"] = carbon_footprint_reduction # calculate values for community impact to be displayed on front-end sites - impact_page_settings: ImpactPageSettings = ImpactPageSettings.objects.filter(community__id=self.pk).first() + impact_page_settings: ImpactPageSettings = ImpactPageSettings.objects.filter( + community__id=self.pk + ).first() if impact_page_settings: display_prefs = impact_page_settings.more_info or {} else: - #capture_message("Impact Page Settings not found", level="error") - display_prefs = {} # not usual - show nothing - + # capture_message("Impact Page Settings not found", level="error") + display_prefs = {} # not usual - show nothing + value = 0 if display_prefs.get("manual_households"): - value += goal.get("initial_number_of_households",0) + value += goal.get("initial_number_of_households", 0) if display_prefs.get("state_households"): - value += goal.get("attained_number_of_households",0) + value += goal.get("attained_number_of_households", 0) if display_prefs.get("platform_households"): - value += goal.get("organic_attained_number_of_households",0) + value += goal.get("organic_attained_number_of_households", 0) goal["displayed_number_of_households"] = value value = 0 if display_prefs.get("manual_actions"): - value += goal.get("initial_number_of_actions",0) + value += goal.get("initial_number_of_actions", 0) if display_prefs.get("state_actions"): - value += goal.get("attained_number_of_actions",0) + value += goal.get("attained_number_of_actions", 0) if display_prefs.get("platform_actions"): - value += goal.get("organic_attained_number_of_actions",0) + value += goal.get("organic_attained_number_of_actions", 0) goal["displayed_number_of_actions"] = value value = 0 if display_prefs.get("manual_carbon"): - value += goal.get("initial_carbon_footprint_reduction",0) + value += goal.get("initial_carbon_footprint_reduction", 0) if display_prefs.get("state_carbon"): - value += goal.get("attained_carbon_footprint_reduction",0) + value += goal.get("attained_carbon_footprint_reduction", 0) if display_prefs.get("platform_carbon"): - value += goal.get("organic_attained_carbon_footprint_reduction",0) + value += goal.get("organic_attained_carbon_footprint_reduction", 0) goal["displayed_carbon_footprint_reduction"] = value locations = "" @@ -702,7 +719,7 @@ def full_json(self): "locations": locations, "feature_flags": get_enabled_flags(self), "is_demo": self.is_demo, - "contact_sender_alias": self.contact_sender_alias + "contact_sender_alias": self.contact_sender_alias, } class Meta: @@ -1092,10 +1109,10 @@ def full_json(self): "admin_portal_settings": admin_portal_settings, } data["feature_flags"] = get_enabled_flags(self, True) - if self.is_community_admin: + if self.is_community_admin: mou_details = user_is_due_for_mou(self) data["needs_to_accept_mou"] = mou_details[0] - data["mou_details"] = mou_details[1] + data["mou_details"] = mou_details[1] return data @@ -1135,15 +1152,13 @@ class PolicyAcceptanceRecords(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - def simple_json(self): - res = model_to_dict( - self, [ "signed_at", "id"] - ) - if self.policy: + def simple_json(self): + res = model_to_dict(self, ["signed_at", "id"]) + if self.policy: res["policy"] = self.policy.simple_json() return res - def full_json(self): + def full_json(self): return self.simple_json() def __str__(self) -> str: @@ -1182,6 +1197,12 @@ class UserMediaUpload(models.Model): info = models.JSONField(null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + publicity = models.CharField( + max_length=SHORT_STR_LEN, + default=UserMediaConstants.open_to(), + null=True, + blank=True, + ) def __str__(self): return f"{str(self.id)} - {self.media.name} from {self.user.preferred_name or self.user.full_name} " @@ -1925,8 +1946,10 @@ def simple_json(self): # Adding this so that vendors will be preselected when creating/updating action. # List of vendors will typically not be that long, so this doesnt pose any problems data["vendors"] = [v.info() for v in self.vendors.all()] - data["action_users"] =len( UserActionRel.objects.filter(action=self, is_deleted=False)) or 0 - + data["action_users"] = ( + len(UserActionRel.objects.filter(action=self, is_deleted=False)) or 0 + ) + if self.user: data["user_email"] = self.user.email return data @@ -1945,13 +1968,16 @@ def full_json(self): "email": u.user.email, "full_name": u.user.full_name, "real_estate_unit": { - "zipcode":u.real_estate_unit.address.zipcode if u.real_estate_unit and u.real_estate_unit.address else None, + "zipcode": u.real_estate_unit.address.zipcode + if u.real_estate_unit and u.real_estate_unit.address + else None, "name": u.real_estate_unit.name if u.real_estate_unit else None, }, "date_completed": u.date_completed, - "carbon_impact": u.action.calculator_action.average_points if u.action.calculator_action else None, + "carbon_impact": u.action.calculator_action.average_points + if u.action.calculator_action + else None, "recorded_at": u.updated_at, - } for u in UserActionRel.objects.filter(action=self, is_deleted=False) ] or [] @@ -3706,19 +3732,23 @@ def full_json(self): def enabled(self): current_date_and_time = datetime.datetime.now(timezone.utc) - if self.expires_on and self.expires_on str: class Meta: db_table = "footages" ordering = ("-id",) - diff --git a/src/database/utils/settings/model_constants/user_media_uploads.py b/src/database/utils/settings/model_constants/user_media_uploads.py new file mode 100644 index 000000000..c081f4bd2 --- /dev/null +++ b/src/database/utils/settings/model_constants/user_media_uploads.py @@ -0,0 +1,7 @@ + + +from database.utils.settings.model_constants.events import EventConstants + + +class UserMediaConstants(EventConstants): + pass From 4764cc4ab34564a7a4fca1f8e2c92244b9ba86b7 Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Tue, 10 Oct 2023 11:25:26 +0000 Subject: [PATCH 02/11] extracted to "expect_media_fields" --- src/api/handlers/media_library.py | 21 ++------- src/api/store/common.py | 71 ++++++++++++++++++++----------- src/api/store/media_library.py | 10 ++++- src/database/models.py | 2 +- 4 files changed, 59 insertions(+), 45 deletions(-) diff --git a/src/api/handlers/media_library.py b/src/api/handlers/media_library.py index 79f0a858c..d36627e53 100644 --- a/src/api/handlers/media_library.py +++ b/src/api/handlers/media_library.py @@ -3,6 +3,7 @@ from api.decorators import admins_only from api.services.media_library import MediaLibraryService from _main_.utils.massenergize_response import MassenergizeResponse +from api.store.common import expect_media_fields class MediaLibraryHandler(RouteHandler): @@ -86,21 +87,8 @@ def addToGallery(self, request): "is_universal", bool ).expect( "tags", "str_list" - ).expect( - "size", str - ).expect( - "size_text", str - ).expect( - "description" - ).expect( - "underAge", bool - ).expect( - "copyright", bool - ).expect( - "copyright_att", str - ).expect( - "guardian_info", str ) + self = expect_media_fields(self) args, err = self.validator.verify(args, strict=True) if err: return err @@ -144,9 +132,7 @@ def edit_details(self, request): """Saves changes to updated image details""" context: Context = request.context args: dict = context.args - self.validator.expect("description").expect("underAge", bool).expect( - "copyright", bool - ).expect("copyright_att", str).expect("guardian_info", str).expect( + self.validator.expect( "tags", "str_list" ).expect( "community_ids", list @@ -155,6 +141,7 @@ def edit_details(self, request): ).expect( "user_upload_id", int, is_required=True ).expect("publicity", str) + self = expect_media_fields(self) args, err = self.validator.verify(args, strict=True) if err: return err diff --git a/src/api/store/common.py b/src/api/store/common.py index 0b0b48ba0..eee4f9d08 100644 --- a/src/api/store/common.py +++ b/src/api/store/common.py @@ -5,9 +5,9 @@ import pytz from _main_.utils.utils import Console from api.store.utils import getCarbonScoreFromActionRel -from database.models import UserActionRel +from database.models import UserActionRel from django.db.models import Q -from django.utils import timezone +from django.utils import timezone LAST_VISIT = "last-visit" @@ -15,12 +15,14 @@ LAST_MONTH = "last-month" LAST_YEAR = "last-year" -def js_datetime_to_python(datetext): + +def js_datetime_to_python(datetext): _format = "%Y-%m-%dT%H:%M:%SZ" _date = datetime.datetime.strptime(datetext, _format) return pytz.utc.localize(_date) -def make_time_range_from_text(time_range): + +def make_time_range_from_text(time_range): today = datetime.datetime.utcnow() if time_range == LAST_WEEK: start_time = today - datetime.timedelta(days=7) @@ -31,32 +33,36 @@ def make_time_range_from_text(time_range): end_time = today elif time_range == LAST_YEAR: start_time = today - datetime.timedelta(days=365) - end_time = today + end_time = today return [pytz.utc.localize(start_time), pytz.utc.localize(end_time)] + def count_action_completed_and_todos(**kwargs): """ ### args: communities(list), actions(list), time_range(str), start_date(str), end_date(str) This function counts how many times an action has been completed, or added to todolist Returns an array of dictionaries with the following: (name,id,done_count, todo_count, carbon_score, category) - * Given a list of communities, todo/done will be counted within only those communities. - * When given a list of actions, counts will only be done for only the actions given + * Given a list of communities, todo/done will be counted within only those communities. + * When given a list of actions, counts will only be done for only the actions given * When given both (actions & communities) an AND query will be built before counting * And when a time range is specified, all the query combinations listed above will run within the given time range """ - + communities = kwargs.get("communities", []) actions = kwargs.get("actions", []) action_count_objects = {} query = None - time_range = kwargs.get("time_range") + time_range = kwargs.get("time_range") # ---------------------------------------------------------------------------- - if time_range == "custom": - start_date = kwargs.get('start_date',"") - end_date = kwargs.get("end_date","") - time_range = [js_datetime_to_python(start_date), js_datetime_to_python(end_date)] - else: + if time_range == "custom": + start_date = kwargs.get("start_date", "") + end_date = kwargs.get("end_date", "") + time_range = [ + js_datetime_to_python(start_date), + js_datetime_to_python(end_date), + ] + else: time_range = make_time_range_from_text(time_range) if time_range else [] # ---------------------------------------------------------------------------- @@ -70,13 +76,13 @@ def count_action_completed_and_todos(**kwargs): action__in=actions, is_deleted=False, ) - # ---------------------------------------------------------------------------- + # ---------------------------------------------------------------------------- if not query: return [] # add time range specification to the query if available - if time_range: + if time_range: query &= Q(updated_at__range=time_range) completed_actions = UserActionRel.objects.filter(query).select_related( @@ -112,10 +118,6 @@ def count_action_completed_and_todos(**kwargs): return list(action_count_objects.values()) - - - - def create_pdf_from_rich_text(rich_text, filename): # Convert rich text to PDF pdf_buffer = io.BytesIO() @@ -125,17 +127,36 @@ def create_pdf_from_rich_text(rich_text, filename): # Close the buffer and return the response pdf_buffer.seek(0) - response = FileResponse(pdf_buffer, content_type='application/pdf') - response['Content-Disposition'] = f'attachment; filename={filename}.pdf' + response = FileResponse(pdf_buffer, content_type="application/pdf") + response["Content-Disposition"] = f"attachment; filename={filename}.pdf" return pdf_buffer.getvalue(), response -def sign_mou(mou_rich_text, user=None, date=None): - return f""" +def sign_mou(mou_rich_text, user=None, date=None): + return ( + f""" {mou_rich_text}

Signed By

Name: {user.full_name}

Date: {date}

- """ if (user and date) else mou_rich_text \ No newline at end of file + """ + if (user and date) + else mou_rich_text + ) + + +def expect_media_fields(self): + self.validator.expect("size", str).expect("size_text", str).expect( + "description" + ).expect("underAge", bool).expect("copyright", bool).expect( + "copyright_att", str + ).expect( + "guardian_info", str + ).expect( + "permission_key", str + ).expect( + "permission_notes", str + ) + return self diff --git a/src/api/store/media_library.py b/src/api/store/media_library.py index 134c37559..609f5a407 100644 --- a/src/api/store/media_library.py +++ b/src/api/store/media_library.py @@ -1,6 +1,8 @@ from functools import reduce from django.core.exceptions import ValidationError -from database.utils.settings.model_constants.user_media_uploads import UserMediaConstants +from database.utils.settings.model_constants.user_media_uploads import ( + UserMediaConstants, +) from sentry_sdk import capture_message from _main_.utils.context import Context from _main_.utils.footage.FootageConstants import FootageConstants @@ -52,6 +54,8 @@ def edit_details(self, args, context: Context): "has_copyright_permission": copyright_permission, "guardian_info": guardian_info, "copyright_att": copyright_att, + "permission_key": args.get("permission_key", None), + "permission_notes": args.get("permission_notes", None), } user_media_upload.info = info # user_media_upload.save() @@ -62,7 +66,7 @@ def edit_details(self, args, context: Context): user_media_upload.communities.clear() user_media_upload.communities.set(communities) - if publicity: + if publicity: user_media_upload.publicity = publicity user_media_upload.save() @@ -344,6 +348,8 @@ def addToGallery(self, args, context): "has_copyright_permission": copyright_permission, "guardian_info": guardian_info, "copyright_att": copyright_att, + "permission_key": args.get("permission_key", None), + "permission_notes": args.get("permission_notes", None), } try: diff --git a/src/database/models.py b/src/database/models.py index cb555168f..d89951054 100644 --- a/src/database/models.py +++ b/src/database/models.py @@ -1209,7 +1209,7 @@ def __str__(self): def simple_json(self): res = model_to_dict( - self, ["settings", "media", "created_at", "id", "is_universal", "info"] + self, ["settings", "media", "created_at", "id", "is_universal", "info", "publicity"] ) res["user"] = get_summary_info(self.user) res["image"] = get_json_if_not_none(self.media) From a0b7e3da931debd43315942f644fb5d49045758d Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Wed, 11 Oct 2023 09:38:48 +0000 Subject: [PATCH 03/11] new tot count, new public fetch query, count fix --- src/api/handlers/media_library.py | 2 +- src/api/services/media_library.py | 36 ++++++++++++++++------------- src/api/store/media_library.py | 38 +++++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/api/handlers/media_library.py b/src/api/handlers/media_library.py index d36627e53..677e7e9ae 100644 --- a/src/api/handlers/media_library.py +++ b/src/api/handlers/media_library.py @@ -49,7 +49,7 @@ def search(self, request): "user_ids", "str_list" ).expect( "keywords", "str_list" - ) + ).expect("public", str) args, err = self.validator.verify(args, strict=True) if err: return err diff --git a/src/api/services/media_library.py b/src/api/services/media_library.py index 5d8fd0f3c..42831e767 100644 --- a/src/api/services/media_library.py +++ b/src/api/services/media_library.py @@ -14,10 +14,12 @@ def fetch_content(self, args): return self.organiseData(data=serialize_all(images, True), args=args), None def search(self, args, context): - images, error = self.store.search(args,context) + images, meta, error = self.store.search(args, context) if error: return None, error - return self.organiseData(data=serialize_all(images), args=args), None + organised = self.organiseData(data=serialize_all(images), args=args) + organised["meta"] = meta + return organised, None def organiseData(self, **kwargs): data = kwargs.get("data") or [] @@ -40,28 +42,30 @@ def organiseData(self, **kwargs): "images": data, } - def remove(self, args,context): - response, error = self.store.remove(args,context) + def remove(self, args, context): + response, error = self.store.remove(args, context) if error: return None, error return response, None - def addToGallery(self, args,context): - image, error = self.store.addToGallery(args,context) + def addToGallery(self, args, context): + image, error = self.store.addToGallery(args, context) if error: return None, error return image.simple_json(), None - - def edit_details(self, args,context): - media, error = self.store.edit_details(args,context) + + def edit_details(self, args, context): + media, error = self.store.edit_details(args, context) if error: return None, error - if media: - return self.getImageInfo({"media_id": media.id}) # Refer back to the getinfo routine so that data can be returned in the same structture + if media: + return self.getImageInfo( + {"media_id": media.id} + ) # Refer back to the getinfo routine so that data can be returned in the same structture return {}, None - - def find_images(self, args,context): - images, error = self.store.find_images(args,context) + + def find_images(self, args, context): + images, error = self.store.find_images(args, context) if error: return None, error images = serialize_all(images) @@ -79,7 +83,7 @@ def getImageInfo(self, args): events = serialize_all(media.events.all()) actions = serialize_all(media.actions.all()) testimonials = serialize_all(media.testimonials.all()) - vendors = serialize_all(media.vender_logo.all()) # yhup, thats right. lmfao! + vendors = serialize_all(media.vender_logo.all()) # yhup, thats right. lmfao! media_json = get_json_if_not_none(media, True) return { **media_json, @@ -88,6 +92,6 @@ def getImageInfo(self, args): "event": events, "action": actions, "testimonial": testimonials, - "vendor": vendors + "vendor": vendors, }, }, None diff --git a/src/api/store/media_library.py b/src/api/store/media_library.py index 609f5a407..78678e563 100644 --- a/src/api/store/media_library.py +++ b/src/api/store/media_library.py @@ -204,7 +204,9 @@ def get_most_recent(self, args, context: Context): else: query |= qObj + count = 0 if not upper_limit and not lower_limit: + count = Media.objects.filter(query).distinct().count() images = Media.objects.filter(query).distinct().order_by("-id")[:limit] else: images = ( @@ -213,7 +215,27 @@ def get_most_recent(self, args, context: Context): .exclude(id__gte=lower_limit, id__lte=upper_limit) .order_by("-id")[:limit] ) - return images, None + return images, {"total": count}, None + + def get_public_images(self, args): + upper_limit = args.get("upper_limit") + lower_limit = args.get("lower_limit") + count = 0 + if not upper_limit and not lower_limit: + count = Media.objects.filter( + user_upload__publicity=UserMediaConstants.open() + ).count() + images = Media.objects.filter( + user_upload__publicity=UserMediaConstants.open() + ).order_by("-id")[:limit] + else: + images = ( + Media.objects.filter(user_upload__publicity=UserMediaConstants.open()) + .exclude(id__gte=lower_limit, id__lte=upper_limit) + .order_by("-id")[:limit] + ) + + return images, {"total": count}, None def search(self, args, context: Context): community_ids = args.get("target_communities", []) @@ -223,7 +245,11 @@ def search(self, args, context: Context): other_admins = not mine and other_admins search_by_community = not most_recent and community_ids keywords = args.get("keywords", []) + public = args.get("public", False) + + if public: + return self.get_public_images(args) if keywords: return self.get_by_keywords(args) @@ -245,7 +271,7 @@ def search(self, args, context: Context): if other_admins: return self.get_uploads_by_user(args) - return [], None + return [], {}, None def get_by_keywords(self, args): words = args.get("keywords", []) @@ -263,7 +289,9 @@ def get_by_keywords(self, args): else: query |= queryObj + count = 0 if not upper_limit and not lower_limit: + count = Media.objects.filter(query).distinct().count() images = Media.objects.filter(query).distinct().order_by("-id")[:limit] else: images = ( @@ -273,13 +301,14 @@ def get_by_keywords(self, args): .order_by("-id")[:limit] ) - return images, None + return images, {"total": count}, None def get_uploads_by_user(self, args): user_ids = args.get("user_ids", []) upper_limit = args.get("upper_limit") lower_limit = args.get("lower_limit") query = Q(user_upload__user__id__in=user_ids) + count = 0 if upper_limit and lower_limit: images = ( Media.objects.filter(query) @@ -287,9 +316,10 @@ def get_uploads_by_user(self, args): .order_by("-id")[:limit] ) else: + count = Media.objects.filter(query).count() images = Media.objects.filter(query).order_by("-id")[:limit] - return images, None + return images, {"total": count}, None def remove(self, args, context): media_id = args.get("media_id") From c0a7686f32ec8e354fddd380f84547f5125a4ab6 Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Thu, 12 Oct 2023 07:15:30 +0000 Subject: [PATCH 04/11] more on count & documentation --- src/api/store/media_library.py | 14 +++++--------- src/database/models.py | 27 ++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/api/store/media_library.py b/src/api/store/media_library.py index 78678e563..3f768b928 100644 --- a/src/api/store/media_library.py +++ b/src/api/store/media_library.py @@ -204,9 +204,8 @@ def get_most_recent(self, args, context: Context): else: query |= qObj - count = 0 + count = Media.objects.filter(query).distinct().count() if not upper_limit and not lower_limit: - count = Media.objects.filter(query).distinct().count() images = Media.objects.filter(query).distinct().order_by("-id")[:limit] else: images = ( @@ -220,11 +219,10 @@ def get_most_recent(self, args, context: Context): def get_public_images(self, args): upper_limit = args.get("upper_limit") lower_limit = args.get("lower_limit") - count = 0 - if not upper_limit and not lower_limit: - count = Media.objects.filter( + count = Media.objects.filter( user_upload__publicity=UserMediaConstants.open() ).count() + if not upper_limit and not lower_limit: images = Media.objects.filter( user_upload__publicity=UserMediaConstants.open() ).order_by("-id")[:limit] @@ -289,9 +287,8 @@ def get_by_keywords(self, args): else: query |= queryObj - count = 0 + count = Media.objects.filter(query).distinct().count() if not upper_limit and not lower_limit: - count = Media.objects.filter(query).distinct().count() images = Media.objects.filter(query).distinct().order_by("-id")[:limit] else: images = ( @@ -308,7 +305,7 @@ def get_uploads_by_user(self, args): upper_limit = args.get("upper_limit") lower_limit = args.get("lower_limit") query = Q(user_upload__user__id__in=user_ids) - count = 0 + count = Media.objects.filter(query).count() if upper_limit and lower_limit: images = ( Media.objects.filter(query) @@ -316,7 +313,6 @@ def get_uploads_by_user(self, args): .order_by("-id")[:limit] ) else: - count = Media.objects.filter(query).count() images = Media.objects.filter(query).order_by("-id")[:limit] return images, {"total": count}, None diff --git a/src/database/models.py b/src/database/models.py index d89951054..9cb0cf98b 100644 --- a/src/database/models.py +++ b/src/database/models.py @@ -1171,7 +1171,32 @@ class Meta: class UserMediaUpload(models.Model): - """A class that creates a relationship between a user(all user kinds) on the platform and media they have uploaded""" + """A class that creates a relationship between a user(all user kinds) on the platform and media they have uploaded + + Attributes + ---------- + user : UserProfile + A user profile object of the currently signed in user who uploaded the media + + communities: Community + All communities that have access to the attached media object + + media : Media + A reference to the actual media object + + is_universal: bool + True/False value that indicates whether or not an image is open to everyone. + PS: Its no longer being used (as at 12/10/23). We want more than two states, so we now use "publicity" + + publicity: str + This value is used to determine whether or not an upload is OPEN_TO specific communities, CLOSED_TO, or wide open to any communities check UserMediaConstants for all the available options + + info: JSON + Json field that stores very important information about the attached media. Example: has_copyright_permission,copyright_att,guardian_info,size etc. + + settings: JSON + Just another field to store more information about the media (I dont think we use this...) + """ id = models.AutoField(primary_key=True) user = models.ForeignKey( From d5b06cbfca7833433a60fae101ce781b93ac5766 Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Tue, 26 Sep 2023 11:59:13 +0400 Subject: [PATCH 05/11] F.E & B.E work well with action.add now --- src/.gitignore | 3 ++- src/api/handlers/action.py | 13 +++++++++++++ src/api/store/action.py | 8 +++++++- src/api/store/common.py | 17 +++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/.gitignore b/src/.gitignore index b1630e79a..bb94c74ab 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -12,4 +12,5 @@ deployment/aws/ *.sqlite3* test_data/ celerybeat-schedule.db -*.rdb* \ No newline at end of file +*.rdb* +venv \ No newline at end of file diff --git a/src/api/handlers/action.py b/src/api/handlers/action.py index a5a9b85fe..fe4c78261 100644 --- a/src/api/handlers/action.py +++ b/src/api/handlers/action.py @@ -90,6 +90,19 @@ def submit(self, request): .expect("image", "file", is_required=False, options={"is_logo": True}) .expect("vendors", list, is_required=False) .expect("action_id", str, is_required=False) + .expect( + "underAge", bool, + ).expect( + "copyright", bool, + ).expect( + "copyright_att", str, + ).expect( + "guardian_info", str, + ).expect( + "size", str + ).expect( + "size_text", str + ) ) args, err = self.validator.verify(args) diff --git a/src/api/store/action.py b/src/api/store/action.py index 90ce20fdd..448f7c9a5 100644 --- a/src/api/store/action.py +++ b/src/api/store/action.py @@ -1,6 +1,8 @@ from _main_.utils.footage.FootageConstants import FootageConstants from _main_.utils.footage.spy import Spy -from api.tests.common import RESET +from _main_.utils.utils import Console +from api.store.common import make_media_info +from api.tests.common import RESET, makeUserUpload from api.utils.api_utils import is_admin_of_community from api.utils.filter_functions import get_actions_filter_params from database.models import Action, UserProfile, Community, Media @@ -72,6 +74,7 @@ def create_action(self, context: Context, args, user_submitted) -> Tuple[dict, M calculator_action = args.pop('calculator_action', None) title = args.get('title', None) user_email = args.pop('user_email', context.user_email) + image_info = make_media_info(args) # check if there is an existing action with this name and community actions = Action.objects.filter(title=title, community__id=community_id, is_deleted=False) @@ -90,6 +93,9 @@ def create_action(self, context: Context, args, user_submitted) -> Tuple[dict, M if user_submitted: name = f'ImageFor {new_action.title} Action' media = Media.objects.create(name=name, file=images) + # create user media upload here + makeUserUpload(media = media,info=image_info) + else: media = Media.objects.filter(pk = images[0]).first() new_action.image = media diff --git a/src/api/store/common.py b/src/api/store/common.py index eee4f9d08..8f0e4522f 100644 --- a/src/api/store/common.py +++ b/src/api/store/common.py @@ -147,6 +147,7 @@ def sign_mou(mou_rich_text, user=None, date=None): ) + def expect_media_fields(self): self.validator.expect("size", str).expect("size_text", str).expect( "description" @@ -160,3 +161,19 @@ def expect_media_fields(self): "permission_notes", str ) return self + + + +def make_media_info(args): + copyright_permission = args.pop("copyright", "") + under_age = args.pop("underAge", "") + guardian_info = args.pop("guardian_info","") + copyright_att = args.pop("copyright_att","") + return { + "size": args.pop("size"), + "size_text": args.pop("size_text"), + "has_children": under_age, + "has_copyright_permission": copyright_permission, + "guardian_info": guardian_info, + "copyright_att": copyright_att, + } From e7e7997bdf47c5f1ea20811145866e426240cc2c Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Wed, 27 Sep 2023 11:45:47 +0400 Subject: [PATCH 06/11] events, vendors, testimonials save copyright info now --- src/api/handlers/event.py | 7 +++++++ src/api/handlers/testimonial.py | 7 +++++++ src/api/handlers/vendor.py | 9 ++++++++- src/api/store/action.py | 7 ++++++- src/api/store/common.py | 4 ++-- src/api/store/event.py | 16 ++++++++++++++-- src/api/store/testimonial.py | 9 +++++++-- src/api/store/vendor.py | 11 ++++++++++- src/database/models.py | 13 ++++++++----- 9 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/api/handlers/event.py b/src/api/handlers/event.py index a60b4aa99..52cf0dac6 100644 --- a/src/api/handlers/event.py +++ b/src/api/handlers/event.py @@ -221,6 +221,13 @@ def submit(self, request): self.validator.expect('rsvp_enabled', bool) self.validator.expect('rsvp_email', bool) self.validator.expect('event_id', str) + self.validator.expect("size", str) + self.validator.expect("size_text", str) + self.validator.expect("description") + self.validator.expect("underAge", bool) + self.validator.expect("copyright", bool) + self.validator.expect("copyright_att", str) + self.validator.expect("guardian_info", str) args, err = self.validator.verify(args) if err: diff --git a/src/api/handlers/testimonial.py b/src/api/handlers/testimonial.py index 12aa98180..6a417942b 100644 --- a/src/api/handlers/testimonial.py +++ b/src/api/handlers/testimonial.py @@ -94,6 +94,13 @@ def submit(self, request): self.validator.rename('preferredName', 'preferred_name') self.validator.expect('testimonial_id', str) self.validator.expect("image", "file", is_required=False) + self.validator.expect("size", str) + self.validator.expect("size_text", str) + self.validator.expect("description") + self.validator.expect("underAge", bool) + self.validator.expect("copyright", bool) + self.validator.expect("copyright_att", str) + self.validator.expect("guardian_info", str) args, err = self.validator.verify(args) if err: diff --git a/src/api/handlers/vendor.py b/src/api/handlers/vendor.py index fa2e9837f..ddcda623c 100644 --- a/src/api/handlers/vendor.py +++ b/src/api/handlers/vendor.py @@ -107,7 +107,14 @@ def submit(self, request): .expect("location", str, is_required=False) .expect("vendor_id", str) - ) + ) + self.validator.expect("size", str) + self.validator.expect("size_text", str) + self.validator.expect("description") + self.validator.expect("underAge", bool) + self.validator.expect("copyright", bool) + self.validator.expect("copyright_att", str) + self.validator.expect("guardian_info", str) args, err = self.validator.verify(args) if err: diff --git a/src/api/store/action.py b/src/api/store/action.py index 448f7c9a5..c2639f6b2 100644 --- a/src/api/store/action.py +++ b/src/api/store/action.py @@ -94,7 +94,7 @@ def create_action(self, context: Context, args, user_submitted) -> Tuple[dict, M name = f'ImageFor {new_action.title} Action' media = Media.objects.create(name=name, file=images) # create user media upload here - makeUserUpload(media = media,info=image_info) + user_media_upload = makeUserUpload(media = media,info=image_info) else: media = Media.objects.filter(pk = images[0]).first() @@ -110,6 +110,9 @@ def create_action(self, context: Context, args, user_submitted) -> Tuple[dict, M user = UserProfile.objects.filter(email=user_email).first() if user: new_action.user = user + if user_media_upload: + user_media_upload.user = user + user_media_upload.save() #save so you set an id new_action.save() @@ -198,6 +201,7 @@ def copy_action(self, context: Context, args) -> Tuple[Action, MassEnergizeAPIEr def update_action(self, context: Context, args, user_submitted) -> Tuple[dict, MassEnergizeAPIError]: try: + image_info = make_media_info(args) action_id = args.pop('action_id', None) actions = Action.objects.filter(id=action_id) if not actions: @@ -246,6 +250,7 @@ def update_action(self, context: Context, args, user_submitted) -> Tuple[dict, M else: image= Media.objects.create(file=image, name=f'ImageFor {action.title} Action') action.image = image + makeUserUpload(media = media,info=image_info, user = action.user) else: if image[0] == RESET: #if image is reset, delete the existing image action.image = None diff --git a/src/api/store/common.py b/src/api/store/common.py index 8f0e4522f..c1c5b40ba 100644 --- a/src/api/store/common.py +++ b/src/api/store/common.py @@ -170,8 +170,8 @@ def make_media_info(args): guardian_info = args.pop("guardian_info","") copyright_att = args.pop("copyright_att","") return { - "size": args.pop("size"), - "size_text": args.pop("size_text"), + "size": args.pop("size",""), + "size_text": args.pop("size_text",""), "has_children": under_age, "has_copyright_permission": copyright_permission, "guardian_info": guardian_info, diff --git a/src/api/store/event.py b/src/api/store/event.py index ea5c7d153..2ba007350 100644 --- a/src/api/store/event.py +++ b/src/api/store/event.py @@ -1,7 +1,8 @@ from _main_.utils.footage.FootageConstants import FootageConstants from _main_.utils.footage.spy import Spy -from _main_.utils.utils import is_url_valid -from api.tests.common import RESET +from _main_.utils.utils import Console, is_url_valid +from api.store.common import make_media_info +from api.tests.common import RESET, makeUserUpload from api.utils.api_utils import is_admin_of_community from api.utils.filter_functions import get_events_filter_params from database.models import Event, RecurringEventException, UserProfile, EventAttendee, Media, Community @@ -242,6 +243,7 @@ def create_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma tags = args.pop('tags', []) community = args.pop("community_id", None) user_email = args.pop('user_email', context.user_email) + image_info = make_media_info(args) start_date_and_time = args.get('start_date_and_time', None) end_date_and_time = args.get('end_date_and_time', None) @@ -306,12 +308,14 @@ def create_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma if user_submitted: name= f'ImageFor {new_event.name} Event' media = Media.objects.create(name=name, file=image) + user_media_upload = makeUserUpload(media = media,info=image_info) else: media = Media.objects.filter(pk = image[0]).first() new_event.image = media if tags: new_event.tags.set(tags) + user = None if user_email: @@ -323,6 +327,9 @@ def create_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma user = UserProfile.objects.filter(email=user_email).first() if user: new_event.user = user + if user_media_upload: + user_media_upload.user = user + user_media_upload.save() if publicity_selections: new_event.communities_under_publicity.set(publicity_selections) @@ -359,6 +366,10 @@ def update_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma try: event_id = args.pop('event_id', None) events = Event.objects.filter(id=event_id) + image_info = make_media_info(args) + # image_info = None + # Console.log("LE ARGS", args) + Console.log("SEE IMAGE_INFO",image_info) publicity_selections = args.pop("publicity_selections", []) shared_to = args.pop("shared_to", []) @@ -484,6 +495,7 @@ def update_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma else: image= Media.objects.create(file=image, name=f'ImageFor {event.name} Event') event.image = image + makeUserUpload(media = media,info=image_info, user = event.user) else: if image[0] == RESET: #if image is reset, delete the existing image event.image = None diff --git a/src/api/store/testimonial.py b/src/api/store/testimonial.py index 4c09c4e13..962b5d77f 100644 --- a/src/api/store/testimonial.py +++ b/src/api/store/testimonial.py @@ -1,6 +1,8 @@ from _main_.utils.footage.FootageConstants import FootageConstants from _main_.utils.footage.spy import Spy -from api.tests.common import RESET +from _main_.utils.utils import Console +from api.store.common import make_media_info +from api.tests.common import RESET, makeUserUpload from api.utils.api_utils import is_admin_of_community from api.utils.filter_functions import get_testimonials_filter_params from database.models import Testimonial, UserProfile, Media, Vendor, Action, Community, CommunityAdminGroup, Tag @@ -69,6 +71,7 @@ def list_testimonials(self, context: Context, args) -> Tuple[list, MassEnergizeA def create_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergizeAPIError]: try: + image_info = make_media_info(args) images = args.pop("image", None) tags = args.pop('tags', []) action = args.pop('action', None) @@ -101,9 +104,9 @@ def create_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize else: # from community portal, image upload images.name = unique_media_filename(images) - image = Media.objects.create(file=images, name=f"ImageFor {args.get('title', '')} Testimonial") new_testimonial.image = image + makeUserUpload(media = image,info=image_info, user = user) if action: @@ -142,6 +145,7 @@ def create_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize def update_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergizeAPIError]: try: + image_info = make_media_info(args) id = args.pop("id", None) testimonials = Testimonial.objects.filter(id=id) if not testimonials: @@ -191,6 +195,7 @@ def update_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize else: image = Media.objects.create(file=images, name=f"ImageFor {testimonial.title} Testimonial") testimonial.image = image + makeUserUpload(media = image,info=image_info, user = testimonial.user) if action: testimonial_action = Action.objects.filter(id=action).first() diff --git a/src/api/store/vendor.py b/src/api/store/vendor.py index 3dff5da7f..b63c7b649 100644 --- a/src/api/store/vendor.py +++ b/src/api/store/vendor.py @@ -1,6 +1,7 @@ from _main_.utils.footage.FootageConstants import FootageConstants from _main_.utils.footage.spy import Spy -from api.tests.common import RESET +from api.store.common import make_media_info +from api.tests.common import RESET, makeUserUpload from api.utils.filter_functions import get_vendor_filter_params from database.models import Vendor, UserProfile, Media, Community from _main_.utils.massenergize_errors import MassEnergizeAPIError, NotAuthorizedError, InvalidResourceError, CustomMassenergizeError @@ -63,6 +64,7 @@ def list_vendors(self, context: Context, args) -> Tuple[list, MassEnergizeAPIErr def create_vendor(self, context: Context, args, user_submitted) -> Tuple[Vendor, MassEnergizeAPIError]: try: + image_info = make_media_info(args) tags = args.pop('tags', []) communities = args.pop('communities', []) images = args.pop('image', None) @@ -85,6 +87,8 @@ def create_vendor(self, context: Context, args, user_submitted) -> Tuple[Vendor, if user_submitted: name=f"ImageFor {new_vendor.name} Vendor" logo = Media.objects.create(name=name, file=images) + user_media_upload = makeUserUpload(media = logo,info=image_info) + else: logo = Media.objects.filter(pk = images[0]).first() new_vendor.logo = logo @@ -104,6 +108,9 @@ def create_vendor(self, context: Context, args, user_submitted) -> Tuple[Vendor, user = UserProfile.objects.filter(email=user_email).first() if user: new_vendor.user = user + if user_media_upload: + user_media_upload.user = user + user_media_upload.save() if website: new_vendor.more_info = {'website': website} @@ -128,6 +135,7 @@ def create_vendor(self, context: Context, args, user_submitted) -> Tuple[Vendor, def update_vendor(self, context: Context, args, user_submitted) -> Tuple[dict, MassEnergizeAPIError]: try: + image_info = make_media_info(args) vendor_id = args.pop('vendor_id', None) vendors = Vendor.objects.filter(id=vendor_id) if not vendors: @@ -176,6 +184,7 @@ def update_vendor(self, context: Context, args, user_submitted) -> Tuple[dict, M else: image= Media.objects.create(file=images, name=f'ImageFor {vendor.name} Vendor') vendor.logo = image + makeUserUpload(media = image,info=image_info, user=vendor.user) else: if images[0] == RESET: #if image is reset, delete the existing image vendor.logo = None diff --git a/src/database/models.py b/src/database/models.py index 9cb0cf98b..d40fe4a06 100644 --- a/src/database/models.py +++ b/src/database/models.py @@ -277,11 +277,11 @@ def simple_json(self): obj = { "id": self.id, "name": self.name, - "url": self.file.url, + "url": self.file.url, } - - if hasattr(self, "user_upload"): + if hasattr(self, "user_upload"): obj["created_at"] = self.user_upload.created_at + obj["info"] = self.user_upload.info return obj @@ -1230,8 +1230,11 @@ class UserMediaUpload(models.Model): ) def __str__(self): - return f"{str(self.id)} - {self.media.name} from {self.user.preferred_name or self.user.full_name} " - + if self.user: + return f"{str(self.id)} - {self.media.name} from {self.user.preferred_name or self.user.full_name} " + + return f"{str(self.id)} - {self.media.name} from ..." + def simple_json(self): res = model_to_dict( self, ["settings", "media", "created_at", "id", "is_universal", "info", "publicity"] From f847995f6f6ae793f5f2490a90d3588ac37a7842 Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Thu, 28 Sep 2023 05:18:52 +0400 Subject: [PATCH 07/11] events update with copyright info works --- src/api/store/common.py | 29 +++++++++++++++++------------ src/api/store/event.py | 14 ++++++++++---- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/api/store/common.py b/src/api/store/common.py index c1c5b40ba..a0db8ed7c 100644 --- a/src/api/store/common.py +++ b/src/api/store/common.py @@ -165,15 +165,20 @@ def expect_media_fields(self): def make_media_info(args): - copyright_permission = args.pop("copyright", "") - under_age = args.pop("underAge", "") - guardian_info = args.pop("guardian_info","") - copyright_att = args.pop("copyright_att","") - return { - "size": args.pop("size",""), - "size_text": args.pop("size_text",""), - "has_children": under_age, - "has_copyright_permission": copyright_permission, - "guardian_info": guardian_info, - "copyright_att": copyright_att, - } + fields = ["copyright","copyright_att", "underAge","size", "size_text", "guardian_info"] + name_to_obj_name = {"underAge":"has_children", "copyright": "has_copyright_permission"} + obj = {} + for name in fields: + value = args.pop(name, None) + name = name_to_obj_name.get(name,name) + if value: + obj[name] = value + return obj + +def get_media_info(media): + if not media: + return {}, False + if hasattr(media,"user_upload"): + if hasattr(media.user_upload, "info"): + return media.user_upload.info or {}, True + return {}, False diff --git a/src/api/store/event.py b/src/api/store/event.py index 2ba007350..bcff99041 100644 --- a/src/api/store/event.py +++ b/src/api/store/event.py @@ -1,7 +1,7 @@ from _main_.utils.footage.FootageConstants import FootageConstants from _main_.utils.footage.spy import Spy from _main_.utils.utils import Console, is_url_valid -from api.store.common import make_media_info +from api.store.common import get_media_info, make_media_info from api.tests.common import RESET, makeUserUpload from api.utils.api_utils import is_admin_of_community from api.utils.filter_functions import get_events_filter_params @@ -245,6 +245,7 @@ def create_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma user_email = args.pop('user_email', context.user_email) image_info = make_media_info(args) + start_date_and_time = args.get('start_date_and_time', None) end_date_and_time = args.get('end_date_and_time', None) is_recurring = args.pop('is_recurring', False) @@ -367,9 +368,6 @@ def update_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma event_id = args.pop('event_id', None) events = Event.objects.filter(id=event_id) image_info = make_media_info(args) - # image_info = None - # Console.log("LE ARGS", args) - Console.log("SEE IMAGE_INFO",image_info) publicity_selections = args.pop("publicity_selections", []) shared_to = args.pop("shared_to", []) @@ -502,6 +500,14 @@ def update_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma else: media = Media.objects.filter(id = image[0]).first() event.image = media + + if event.image: + old_image_info, can_save_info = get_media_info(event.image) + # There are media objects that do not have user upload references. (because we didnt have that model at the time of upload) thats why we need to check first + if can_save_info: + event.image.user_upload.info.update({**old_image_info,**image_info}) + event.image.user_upload.save() + if community_id: community = Community.objects.filter(pk=community_id).first() From cdfd7ad629818e107327156b20a94c7f6c066c6b Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Thu, 28 Sep 2023 08:57:40 +0400 Subject: [PATCH 08/11] copyright edit setup for actions and testimonials now working tooo --- src/api/store/action.py | 8 +++++++- src/api/store/testimonial.py | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/api/store/action.py b/src/api/store/action.py index c2639f6b2..9a8757f89 100644 --- a/src/api/store/action.py +++ b/src/api/store/action.py @@ -1,7 +1,7 @@ from _main_.utils.footage.FootageConstants import FootageConstants from _main_.utils.footage.spy import Spy from _main_.utils.utils import Console -from api.store.common import make_media_info +from api.store.common import get_media_info, make_media_info from api.tests.common import RESET, makeUserUpload from api.utils.api_utils import is_admin_of_community from api.utils.filter_functions import get_actions_filter_params @@ -258,6 +258,12 @@ def update_action(self, context: Context, args, user_submitted) -> Tuple[dict, M media = Media.objects.filter(id = image[0]).first() action.image = media + if action.image: + old_image_info, can_save_info = get_media_info(action.image) + if can_save_info: + action.image.user_upload.info.update({**old_image_info,**image_info}) + action.image.user_upload.save() + action.steps_to_take = steps_to_take action.deep_dive = deep_dive diff --git a/src/api/store/testimonial.py b/src/api/store/testimonial.py index 962b5d77f..8f7ea7248 100644 --- a/src/api/store/testimonial.py +++ b/src/api/store/testimonial.py @@ -1,7 +1,7 @@ from _main_.utils.footage.FootageConstants import FootageConstants from _main_.utils.footage.spy import Spy from _main_.utils.utils import Console -from api.store.common import make_media_info +from api.store.common import get_media_info, make_media_info from api.tests.common import RESET, makeUserUpload from api.utils.api_utils import is_admin_of_community from api.utils.filter_functions import get_testimonials_filter_params @@ -197,6 +197,12 @@ def update_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize testimonial.image = image makeUserUpload(media = image,info=image_info, user = testimonial.user) + if testimonial.image: + old_image_info, can_save_info = get_media_info(testimonial.image) + if can_save_info: + testimonial.image.user_upload.info.update({**old_image_info,**image_info}) + testimonial.image.user_upload.save() + if action: testimonial_action = Action.objects.filter(id=action).first() testimonial.action = testimonial_action From f8ad1ee92143c85cc6aa7fdb00c056ed611aaeb6 Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Thu, 28 Sep 2023 23:37:24 +0400 Subject: [PATCH 09/11] vendor will now save copyright dets updates --- src/api/store/vendor.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/store/vendor.py b/src/api/store/vendor.py index b63c7b649..7eb009e6a 100644 --- a/src/api/store/vendor.py +++ b/src/api/store/vendor.py @@ -1,6 +1,6 @@ from _main_.utils.footage.FootageConstants import FootageConstants from _main_.utils.footage.spy import Spy -from api.store.common import make_media_info +from api.store.common import get_media_info, make_media_info from api.tests.common import RESET, makeUserUpload from api.utils.filter_functions import get_vendor_filter_params from database.models import Vendor, UserProfile, Media, Community @@ -191,6 +191,12 @@ def update_vendor(self, context: Context, args, user_submitted) -> Tuple[dict, M else: media = Media.objects.filter(id = image[0]).first() vendor.logo = media + + if vendor.image: + old_image_info, can_save_info = get_media_info(vendor.logo) + if can_save_info: + vendor.image.user_upload.info.update({**old_image_info,**image_info}) + vendor.image.user_upload.save() if onboarding_contact_email: From 723fc5be94e24bfb08d3851ba8c813858b0181e8 Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Fri, 13 Oct 2023 10:42:16 +0000 Subject: [PATCH 10/11] expect media field replaces bulky setup --- src/api/handlers/action.py | 17 +++---------- src/api/handlers/event.py | 9 ++----- src/api/handlers/testimonial.py | 9 ++----- src/api/handlers/vendor.py | 17 +++++++------ src/api/store/common.py | 43 +++++++++++++++++++++------------ 5 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/api/handlers/action.py b/src/api/handlers/action.py index fe4c78261..7c5a0e196 100644 --- a/src/api/handlers/action.py +++ b/src/api/handlers/action.py @@ -6,6 +6,7 @@ #from types import FunctionType as function from _main_.utils.context import Context from api.decorators import admins_only, super_admins_only, login_required +from api.store.common import expect_media_fields class ActionHandler(RouteHandler): @@ -90,20 +91,8 @@ def submit(self, request): .expect("image", "file", is_required=False, options={"is_logo": True}) .expect("vendors", list, is_required=False) .expect("action_id", str, is_required=False) - .expect( - "underAge", bool, - ).expect( - "copyright", bool, - ).expect( - "copyright_att", str, - ).expect( - "guardian_info", str, - ).expect( - "size", str - ).expect( - "size_text", str - ) ) + self = expect_media_fields(self) args, err = self.validator.verify(args) if err: @@ -164,6 +153,8 @@ def update(self, request): .expect("vendors", list, is_required=False) ) + self = expect_media_fields(self) + args, err = self.validator.verify(args) if err: return err diff --git a/src/api/handlers/event.py b/src/api/handlers/event.py index 52cf0dac6..4a94543ea 100644 --- a/src/api/handlers/event.py +++ b/src/api/handlers/event.py @@ -7,6 +7,7 @@ from types import FunctionType as function from _main_.utils.context import Context from api.decorators import admins_only, super_admins_only, login_required +from api.store.common import expect_media_fields class EventHandler(RouteHandler): @@ -221,13 +222,7 @@ def submit(self, request): self.validator.expect('rsvp_enabled', bool) self.validator.expect('rsvp_email', bool) self.validator.expect('event_id', str) - self.validator.expect("size", str) - self.validator.expect("size_text", str) - self.validator.expect("description") - self.validator.expect("underAge", bool) - self.validator.expect("copyright", bool) - self.validator.expect("copyright_att", str) - self.validator.expect("guardian_info", str) + self = expect_media_fields(self) args, err = self.validator.verify(args) if err: diff --git a/src/api/handlers/testimonial.py b/src/api/handlers/testimonial.py index 6a417942b..ed768bb77 100644 --- a/src/api/handlers/testimonial.py +++ b/src/api/handlers/testimonial.py @@ -8,6 +8,7 @@ from _main_.utils.context import Context from _main_.utils.validator import Validator from api.decorators import admins_only, super_admins_only, login_required +from api.store.common import expect_media_fields class TestimonialHandler(RouteHandler): @@ -94,13 +95,7 @@ def submit(self, request): self.validator.rename('preferredName', 'preferred_name') self.validator.expect('testimonial_id', str) self.validator.expect("image", "file", is_required=False) - self.validator.expect("size", str) - self.validator.expect("size_text", str) - self.validator.expect("description") - self.validator.expect("underAge", bool) - self.validator.expect("copyright", bool) - self.validator.expect("copyright_att", str) - self.validator.expect("guardian_info", str) + self = expect_media_fields(self) args, err = self.validator.verify(args) if err: diff --git a/src/api/handlers/vendor.py b/src/api/handlers/vendor.py index ddcda623c..8a0cebb09 100644 --- a/src/api/handlers/vendor.py +++ b/src/api/handlers/vendor.py @@ -10,6 +10,7 @@ from _main_.utils.context import Context from _main_.utils.validator import Validator from api.decorators import admins_only, super_admins_only, login_required +from api.store.common import expect_media_fields @@ -108,13 +109,15 @@ def submit(self, request): .expect("vendor_id", str) ) - self.validator.expect("size", str) - self.validator.expect("size_text", str) - self.validator.expect("description") - self.validator.expect("underAge", bool) - self.validator.expect("copyright", bool) - self.validator.expect("copyright_att", str) - self.validator.expect("guardian_info", str) + # self.validator.expect("size", str) + # self.validator.expect("size_text", str) + # self.validator.expect("description") + # self.validator.expect("underAge", bool) + # self.validator.expect("copyright", bool) + # self.validator.expect("copyright_att", str) + # self.validator.expect("guardian_info", str) + + self = expect_media_fields(self) args, err = self.validator.verify(args) if err: diff --git a/src/api/store/common.py b/src/api/store/common.py index a0db8ed7c..5cd4abd71 100644 --- a/src/api/store/common.py +++ b/src/api/store/common.py @@ -147,7 +147,6 @@ def sign_mou(mou_rich_text, user=None, date=None): ) - def expect_media_fields(self): self.validator.expect("size", str).expect("size_text", str).expect( "description" @@ -161,24 +160,38 @@ def expect_media_fields(self): "permission_notes", str ) return self - -def make_media_info(args): - fields = ["copyright","copyright_att", "underAge","size", "size_text", "guardian_info"] - name_to_obj_name = {"underAge":"has_children", "copyright": "has_copyright_permission"} - obj = {} - for name in fields: +def make_media_info(args): + """Request arg names are different from how they are stored on the media object, so this function corrects the naming and makes sure it matches the structure that is actually saved on the media object""" + fields = [ + "copyright", + "copyright_att", + "underAge", + "size", + "size_text", + "guardian_info", + "permission_key", + "permission_notes" + ] + name_to_obj_name = { + "underAge": "has_children", + "copyright": "has_copyright_permission", + } + obj = {} + for name in fields: value = args.pop(name, None) - name = name_to_obj_name.get(name,name) - if value: - obj[name] = value - return obj + name = name_to_obj_name.get(name, name) + if value: + obj[name] = value + return obj + -def get_media_info(media): - if not media: +def get_media_info(media): + """Retrieves media info from media object""" + if not media: return {}, False - if hasattr(media,"user_upload"): - if hasattr(media.user_upload, "info"): + if hasattr(media, "user_upload"): + if hasattr(media.user_upload, "info"): return media.user_upload.info or {}, True return {}, False From adb3d175085f6f3554d55c68e7648149f8b944c5 Mon Sep 17 00:00:00 2001 From: frimpongopoku Date: Fri, 13 Oct 2023 11:45:52 +0000 Subject: [PATCH 11/11] permission key and more media tweaks for portal specific uploads. --- src/api/handlers/event.py | 2 ++ src/api/handlers/testimonial.py | 2 ++ src/api/handlers/vendor.py | 1 + src/api/store/action.py | 19 +++++++++------ src/api/store/event.py | 18 ++++++++------ src/api/store/testimonial.py | 43 +++++++++++++++++++-------------- src/api/store/vendor.py | 12 ++++++--- 7 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/api/handlers/event.py b/src/api/handlers/event.py index 4a94543ea..d55ce6904 100644 --- a/src/api/handlers/event.py +++ b/src/api/handlers/event.py @@ -312,6 +312,8 @@ def update(self, request): self.validator.expect("event_type",str) self.validator.expect("publicity_selections","str_list") self.validator.expect("shared_to","str_list") + + self = expect_media_fields(self) args, err = self.validator.verify(args) if err: diff --git a/src/api/handlers/testimonial.py b/src/api/handlers/testimonial.py index ed768bb77..98a895816 100644 --- a/src/api/handlers/testimonial.py +++ b/src/api/handlers/testimonial.py @@ -146,6 +146,8 @@ def update(self, request): self.validator.rename('action_id', 'action') self.validator.rename('vendor_id', 'vendor') self.validator.expect("image", "str_list") + + self = expect_media_fields(self) args, err = self.validator.verify(args) if err: diff --git a/src/api/handlers/vendor.py b/src/api/handlers/vendor.py index 8a0cebb09..62946ff80 100644 --- a/src/api/handlers/vendor.py +++ b/src/api/handlers/vendor.py @@ -170,6 +170,7 @@ def update(self, request): .expect("location", "location", is_required=False) ) + self = expect_media_fields(self) args, err = self.validator.verify(args) if err: return err diff --git a/src/api/store/action.py b/src/api/store/action.py index 9a8757f89..671fd0eb7 100644 --- a/src/api/store/action.py +++ b/src/api/store/action.py @@ -94,7 +94,7 @@ def create_action(self, context: Context, args, user_submitted) -> Tuple[dict, M name = f'ImageFor {new_action.title} Action' media = Media.objects.create(name=name, file=images) # create user media upload here - user_media_upload = makeUserUpload(media = media,info=image_info) + user_media_upload = makeUserUpload(media = media,info=image_info, communities=[community]) else: media = Media.objects.filter(pk = images[0]).first() @@ -243,6 +243,14 @@ def update_action(self, context: Context, args, user_submitted) -> Tuple[dict, M actions.update(**args) action = actions.first() # refresh after update + + if community_id and not args.get('is_global', False): + community = Community.objects.filter(id=community_id).first() + if community: + action.community = community + else: + action.community = None + if image: #now, images will always come as an array of ids, or "reset" string if user_submitted: if "ImgToDel" in image: @@ -250,7 +258,7 @@ def update_action(self, context: Context, args, user_submitted) -> Tuple[dict, M else: image= Media.objects.create(file=image, name=f'ImageFor {action.title} Action') action.image = image - makeUserUpload(media = media,info=image_info, user = action.user) + makeUserUpload(media = image,info=image_info, user = action.user, communities=[community]) else: if image[0] == RESET: #if image is reset, delete the existing image action.image = None @@ -273,12 +281,7 @@ def update_action(self, context: Context, args, user_submitted) -> Tuple[dict, M if vendors: action.vendors.set(vendors) - if community_id and not args.get('is_global', False): - community = Community.objects.filter(id=community_id).first() - if community: - action.community = community - else: - action.community = None + if calculator_action: ccAction = CCAction.objects.filter(pk=calculator_action).first() diff --git a/src/api/store/event.py b/src/api/store/event.py index bcff99041..87d51fb1c 100644 --- a/src/api/store/event.py +++ b/src/api/store/event.py @@ -309,7 +309,7 @@ def create_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma if user_submitted: name= f'ImageFor {new_event.name} Event' media = Media.objects.create(name=name, file=image) - user_media_upload = makeUserUpload(media = media,info=image_info) + user_media_upload = makeUserUpload(media = media,info=image_info,communities=[community]) else: media = Media.objects.filter(pk = image[0]).first() new_event.image = media @@ -486,6 +486,13 @@ def update_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma events.update(**args) event: Event = events.first() + if community_id: + community = Community.objects.filter(pk=community_id).first() + if community: + event.community = community + else: + event.community = None + if image: #now, images will always come as an array of ids, or "reset" string if user_submitted: if "ImgToDel" in image: @@ -493,7 +500,7 @@ def update_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma else: image= Media.objects.create(file=image, name=f'ImageFor {event.name} Event') event.image = image - makeUserUpload(media = media,info=image_info, user = event.user) + makeUserUpload(media = image,info=image_info, user = event.user , communities=[community]) else: if image[0] == RESET: #if image is reset, delete the existing image event.image = None @@ -509,12 +516,7 @@ def update_event(self, context: Context, args, user_submitted) -> Tuple[dict, Ma event.image.user_upload.save() - if community_id: - community = Community.objects.filter(pk=community_id).first() - if community: - event.community = community - else: - event.community = None + if tags: event.tags.set(tags) diff --git a/src/api/store/testimonial.py b/src/api/store/testimonial.py index 8f7ea7248..3fdc18024 100644 --- a/src/api/store/testimonial.py +++ b/src/api/store/testimonial.py @@ -96,17 +96,7 @@ def create_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize new_testimonial.user = user - if images: - if type(images) == list: - # from admin portal, using media library - image = Media.objects.filter(id = images[0]).first(); - new_testimonial.image = image - else: - # from community portal, image upload - images.name = unique_media_filename(images) - image = Media.objects.create(file=images, name=f"ImageFor {args.get('title', '')} Testimonial") - new_testimonial.image = image - makeUserUpload(media = image,info=image_info, user = user) + if action: @@ -123,6 +113,21 @@ def create_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize else: testimonial_community = None + if images: + if type(images) == list: + # from admin portal, using media library + image = Media.objects.filter(id = images[0]).first(); + new_testimonial.image = image + else: + # from community portal, image upload + images.name = unique_media_filename(images) + image = Media.objects.create(file=images, name=f"ImageFor {args.get('title', '')} Testimonial") + new_testimonial.image = image + + user_media_upload = makeUserUpload(media = image,info=image_info, user = user,communities=[testimonial_community]) + user_media_upload.user = user + user_media_upload.save() + tags_to_set = [] for t in tags: tag = Tag.objects.filter(pk=t).first() @@ -182,6 +187,13 @@ def update_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize testimonials.update(**args) testimonial = testimonials.first() # refresh after update + if community: + testimonial_community = Community.objects.filter(id=community).first() + if testimonial_community: + testimonial.community = testimonial_community + else: + testimonial.community = None + if images: if type(images) == list: if images[0] == RESET: @@ -195,7 +207,7 @@ def update_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize else: image = Media.objects.create(file=images, name=f"ImageFor {testimonial.title} Testimonial") testimonial.image = image - makeUserUpload(media = image,info=image_info, user = testimonial.user) + makeUserUpload(media = image,info=image_info, user = testimonial.user,communities=[testimonial_community]) if testimonial.image: old_image_info, can_save_info = get_media_info(testimonial.image) @@ -215,12 +227,7 @@ def update_testimonial(self, context: Context, args) -> Tuple[dict, MassEnergize else: testimonial.vendor = None - if community: - testimonial_community = Community.objects.filter(id=community).first() - if testimonial_community: - testimonial.community = testimonial_community - else: - testimonial.community = None + if rank: testimonial.rank = rank diff --git a/src/api/store/vendor.py b/src/api/store/vendor.py index 7eb009e6a..a387ac521 100644 --- a/src/api/store/vendor.py +++ b/src/api/store/vendor.py @@ -83,11 +83,15 @@ def create_vendor(self, context: Context, args, user_submitted) -> Tuple[Vendor, args['location'] = None new_vendor = Vendor.objects.create(**args) + + if communities: + new_vendor.communities.set(communities) + if images: if user_submitted: name=f"ImageFor {new_vendor.name} Vendor" logo = Media.objects.create(name=name, file=images) - user_media_upload = makeUserUpload(media = logo,info=image_info) + user_media_upload = makeUserUpload(media = logo,info=image_info,communities=new_vendor.communities) else: logo = Media.objects.filter(pk = images[0]).first() @@ -117,8 +121,7 @@ def create_vendor(self, context: Context, args, user_submitted) -> Tuple[Vendor, new_vendor.save() - if communities: - new_vendor.communities.set(communities) + if tags: new_vendor.tags.set(tags) @@ -184,7 +187,8 @@ def update_vendor(self, context: Context, args, user_submitted) -> Tuple[dict, M else: image= Media.objects.create(file=images, name=f'ImageFor {vendor.name} Vendor') vendor.logo = image - makeUserUpload(media = image,info=image_info, user=vendor.user) + makeUserUpload(media = image,info=image_info, user=vendor.user,communities=vendor.communities) + else: if images[0] == RESET: #if image is reset, delete the existing image vendor.logo = None