From d0e2f423e6c04179819e0a8fe692d288174b6282 Mon Sep 17 00:00:00 2001 From: DCCONSTRUCTIONS Date: Tue, 12 May 2026 18:28:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=A3=D0=9D=D0=9A=D0=A6=D0=98=D0=98=20-?= =?UTF-8?q?=20=D0=9C=D0=95=D0=96=D0=9F=D0=A0=D0=9E=D0=95=D0=9A=D0=A2=D0=9D?= =?UTF-8?q?=D0=90=D0=AF=20=D0=9A=D0=9E=D0=9C=D0=9C=D0=A3=D0=9D=D0=98=D0=9A?= =?UTF-8?q?=D0=90=D0=A6=D0=98=D0=AF:=20=D0=BC=D0=B0=D0=BF=D0=BF=D0=B8?= =?UTF-8?q?=D0=BD=D0=B3=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=84=D0=B8=D0=BB=D1=8F=20Tasker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apps/api/plane/app/views/user/base.py | 7 +++++ .../authentication/nodedc_profile_sync.py | 28 +++++++++++++------ .../views/nodedc_workspace_adapter.py | 25 +++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/plane-src/apps/api/plane/app/views/user/base.py b/plane-src/apps/api/plane/app/views/user/base.py index a874e2b..4bb7b23 100644 --- a/plane-src/apps/api/plane/app/views/user/base.py +++ b/plane-src/apps/api/plane/app/views/user/base.py @@ -104,6 +104,13 @@ class UserEndpoint(BaseViewSet): field for field in NODEDC_PROFILE_SYNC_FIELDS if previous_profile.get(field) != getattr(user, field, None) ] + if {"first_name", "last_name"} & set(changed_fields) and "display_name" not in changed_fields: + display_name = " ".join([user.first_name, user.last_name]).strip() + if display_name and user.display_name != display_name: + user.display_name = display_name + user.save(update_fields=["display_name", "updated_at"]) + changed_fields.append("display_name") + if changed_fields: publish_nodedc_user_profile_event_on_commit(user, changed_fields=changed_fields) push_nodedc_user_profile_update_on_commit(user, changed_fields=changed_fields) diff --git a/plane-src/apps/api/plane/authentication/nodedc_profile_sync.py b/plane-src/apps/api/plane/authentication/nodedc_profile_sync.py index 4792cf4..364d9c0 100644 --- a/plane-src/apps/api/plane/authentication/nodedc_profile_sync.py +++ b/plane-src/apps/api/plane/authentication/nodedc_profile_sync.py @@ -61,15 +61,24 @@ def normalize_tasker_avatar_url(value): return avatar_url -def get_user_display_name(user): +def get_user_full_name(user): + return " ".join( + value for value in [getattr(user, "first_name", ""), getattr(user, "last_name", "")] if value + ).strip() + + +def get_user_display_name(user, changed_fields=None): + changed_fields = set(changed_fields or []) + full_name = get_user_full_name(user) display_name = getattr(user, "display_name", "") + + if {"first_name", "last_name"} & changed_fields and "display_name" not in changed_fields and full_name: + return full_name + if display_name: return display_name - name = " ".join( - value for value in [getattr(user, "first_name", ""), getattr(user, "last_name", "")] if value - ).strip() - return name or user.email + return full_name or user.email def get_nodedc_subject(user): @@ -78,17 +87,20 @@ def get_nodedc_subject(user): def build_nodedc_profile_payload(user, changed_fields=None): + changed_fields = sorted(set(changed_fields or [])) + display_name = get_user_display_name(user, changed_fields=changed_fields) + return { "source": "tasker", "planeUserId": str(user.id), "subject": get_nodedc_subject(user), "email": user.email, - "name": get_user_display_name(user), - "displayName": user.display_name or get_user_display_name(user), + "name": display_name, + "displayName": display_name, "firstName": user.first_name, "lastName": user.last_name, "avatarUrl": normalize_tasker_avatar_url(user.avatar_url), - "changedFields": sorted(set(changed_fields or [])), + "changedFields": changed_fields, } diff --git a/plane-src/apps/api/plane/authentication/views/nodedc_workspace_adapter.py b/plane-src/apps/api/plane/authentication/views/nodedc_workspace_adapter.py index e87d7e8..25f6889 100644 --- a/plane-src/apps/api/plane/authentication/views/nodedc_workspace_adapter.py +++ b/plane-src/apps/api/plane/authentication/views/nodedc_workspace_adapter.py @@ -141,6 +141,18 @@ def first_payload_string(payload, *keys): return "" +def split_display_name(value): + if not isinstance(value, str): + return "", "" + + parts = value.strip().split(None, 1) + if not parts: + return "", "" + if len(parts) == 1: + return parts[0], "" + return parts[0], parts[1] + + def normalize_nodedc_avatar_url(value): if not isinstance(value, str): return "" @@ -183,13 +195,26 @@ def resolve_nodedc_launcher_origin(): def sync_user_profile_from_payload(user, payload): updated_fields = [] display_name = first_payload_string(payload, "displayName", "display_name", "name") + first_name = first_payload_string(payload, "firstName", "first_name") + last_name = first_payload_string(payload, "lastName", "last_name") has_avatar = any(key in payload for key in ["avatarUrl", "avatar_url", "avatar"]) avatar_url = normalize_nodedc_avatar_url(first_payload_string(payload, "avatarUrl", "avatar_url", "avatar")) + if display_name and not first_name and not last_name: + first_name, last_name = split_display_name(display_name) + if display_name and user.display_name != display_name: user.display_name = display_name updated_fields.append("display_name") + if first_name and user.first_name != first_name: + user.first_name = first_name + updated_fields.append("first_name") + + if (last_name or first_name) and user.last_name != last_name: + user.last_name = last_name + updated_fields.append("last_name") + if has_avatar and (user.avatar != avatar_url or user.avatar_asset_id is not None): user.avatar = avatar_url user.avatar_asset_id = None