diff --git a/frontends/api/src/generated/v0/api.ts b/frontends/api/src/generated/v0/api.ts index a8ecc603ce..694b9b5086 100644 --- a/frontends/api/src/generated/v0/api.ts +++ b/frontends/api/src/generated/v0/api.ts @@ -1597,12 +1597,6 @@ export interface PatchedChannelWriteRequest { * @interface PatchedProfileRequest */ export interface PatchedProfileRequest { - /** - * - * @type {string} - * @memberof PatchedProfileRequest - */ - name?: string | null /** * * @type {string} @@ -1928,11 +1922,11 @@ export interface PreferencesSearch { */ export interface Profile { /** - * + * Get the user\'s name * @type {string} * @memberof Profile */ - name?: string | null + name: string /** * * @type {string} @@ -2054,12 +2048,6 @@ export interface Profile { * @interface ProfileRequest */ export interface ProfileRequest { - /** - * - * @type {string} - * @memberof ProfileRequest - */ - name?: string | null /** * * @type {string} diff --git a/frontends/mit-learn/src/page-components/Header/Header.test.tsx b/frontends/mit-learn/src/page-components/Header/Header.test.tsx index 39c6962901..f6427bbdd5 100644 --- a/frontends/mit-learn/src/page-components/Header/Header.test.tsx +++ b/frontends/mit-learn/src/page-components/Header/Header.test.tsx @@ -31,10 +31,7 @@ describe("UserMenu", () => { return screen.findByRole("menu") } - test.each([ - { first_name: "", last_name: "" }, - { first_name: null, last_name: null }, - ])( + test.each([{}, { profile: null }, { profile: {} }])( "Trigger button shows UserIcon for authenticated users w/o initials", async (userSettings) => { setMockResponse.get(urls.userMe.get(), userSettings) @@ -46,29 +43,13 @@ describe("UserMenu", () => { }, ) - test.each([ - { - userSettings: { first_name: "Alice", last_name: "Bee" }, - expectedName: "Alice Bee", - }, - { - userSettings: { first_name: "Alice", last_name: "" }, - expectedName: "Alice", - }, - { - userSettings: { first_name: "", last_name: "Bee" }, - expectedName: "Bee", - }, - ])( - "Trigger button shows name if available", - async ({ userSettings, expectedName }) => { - setMockResponse.get(urls.userMe.get(), userSettings) + test("Trigger button shows name if available", async () => { + setMockResponse.get(urls.userMe.get(), { profile: { name: "Alice Bee" } }) - renderWithProviders(
) - const trigger = await screen.findByRole("button", { name: "User Menu" }) - expect(trigger.textContent).toBe(expectedName) - }, - ) + renderWithProviders(
) + const trigger = await screen.findByRole("button", { name: "User Menu" }) + expect(trigger.textContent).toBe("Alice Bee") + }) test("Unauthenticated users see the Sign Up / Login link", async () => { const isAuthenticated = false diff --git a/frontends/mit-learn/src/page-components/Header/UserMenu.tsx b/frontends/mit-learn/src/page-components/Header/UserMenu.tsx index 22c6304fc3..a90add21c0 100644 --- a/frontends/mit-learn/src/page-components/Header/UserMenu.tsx +++ b/frontends/mit-learn/src/page-components/Header/UserMenu.tsx @@ -70,15 +70,7 @@ const UserNameContainer = styled.span(({ theme }) => ({ })) const UserName: React.FC<{ user: User | undefined }> = ({ user }) => { - const first = user?.first_name ?? "" - const last = user?.last_name ?? "" - return ( - - {first} - {first && last ? " " : ""} - {last} - - ) + return {user?.profile?.name ?? ""} } const UserMenuChevron: React.FC<{ open: boolean }> = ({ open }) => { diff --git a/frontends/mit-learn/src/pages/DashboardPage/Dashboard.test.tsx b/frontends/mit-learn/src/pages/DashboardPage/Dashboard.test.tsx index d1c1efdbe6..2833ec9e0e 100644 --- a/frontends/mit-learn/src/pages/DashboardPage/Dashboard.test.tsx +++ b/frontends/mit-learn/src/pages/DashboardPage/Dashboard.test.tsx @@ -210,17 +210,20 @@ describe("DashboardPage", () => { setupAPIs() setMockResponse.get(urls.userMe.get(), { [Permissions.Authenticated]: true, - first_name: "User", - last_name: "Info", + first_name: "Joe", + last_name: "Smith", + profile: { + name: "Jane Smith", + }, }) renderWithProviders() await waitFor(() => { /** - * There should be two instances of "User Info" text, + * There should be two instances of "Jane Smith" text, * one in the header and one in the main content */ - const userInfoText = screen.getByText("User Info") + const userInfoText = screen.getByText("Jane Smith") expect(userInfoText).toBeInTheDocument() }) }) diff --git a/frontends/mit-learn/src/pages/DashboardPage/DashboardPage.tsx b/frontends/mit-learn/src/pages/DashboardPage/DashboardPage.tsx index 7b0073d72a..96310366cc 100644 --- a/frontends/mit-learn/src/pages/DashboardPage/DashboardPage.tsx +++ b/frontends/mit-learn/src/pages/DashboardPage/DashboardPage.tsx @@ -330,7 +330,7 @@ const DashboardPage: React.FC = () => { {isLoadingUser ? ( ) : ( - {`${user?.first_name} ${user?.last_name}`} + {`${user?.profile?.name}`} )} diff --git a/frontends/mit-learn/src/pages/DashboardPage/ProfileEditForm.tsx b/frontends/mit-learn/src/pages/DashboardPage/ProfileEditForm.tsx index eefdbe2f66..b7e89a58d9 100644 --- a/frontends/mit-learn/src/pages/DashboardPage/ProfileEditForm.tsx +++ b/frontends/mit-learn/src/pages/DashboardPage/ProfileEditForm.tsx @@ -103,17 +103,10 @@ const ProfileEditForm: React.FC = ({ profile }) => { - diff --git a/openapi/specs/v0.yaml b/openapi/specs/v0.yaml index 5bde16164e..98ff99fe1f 100644 --- a/openapi/specs/v0.yaml +++ b/openapi/specs/v0.yaml @@ -1893,9 +1893,6 @@ components: type: object description: Serializer for Profile properties: - name: - type: string - nullable: true image: type: string nullable: true @@ -2096,7 +2093,8 @@ components: properties: name: type: string - nullable: true + description: Get the user's name + readOnly: true image: type: string nullable: true @@ -2179,6 +2177,7 @@ components: - image_file - image_medium_file - image_small_file + - name - placename - preference_search_filters - profile_image_medium @@ -2188,9 +2187,6 @@ components: type: object description: Serializer for Profile properties: - name: - type: string - nullable: true image: type: string nullable: true diff --git a/profiles/serializers.py b/profiles/serializers.py index 27315bd0a6..2e0e1b7672 100644 --- a/profiles/serializers.py +++ b/profiles/serializers.py @@ -81,6 +81,7 @@ class PreferencesSearchSerializer(serializers.Serializer): class ProfileSerializer(serializers.ModelSerializer): """Serializer for Profile""" + name = serializers.SerializerMethodField(read_only=True) email_optin = serializers.BooleanField(write_only=True, required=False) toc_optin = serializers.BooleanField(write_only=True, required=False) username = serializers.SerializerMethodField(read_only=True) @@ -90,6 +91,12 @@ class ProfileSerializer(serializers.ModelSerializer): topic_interests = TopicInterestsField(default=list) preference_search_filters = serializers.SerializerMethodField(read_only=True) + def get_name(self, obj) -> str: + """Get the user's name""" + return obj.name or " ".join( + filter(lambda name: name, [obj.user.first_name, obj.user.last_name]) + ) + def get_username(self, obj) -> str: """Custom getter for the username""" # noqa: D401 return str(obj.user.username) diff --git a/profiles/serializers_test.py b/profiles/serializers_test.py index bcd433640d..1393b1b2fa 100644 --- a/profiles/serializers_test.py +++ b/profiles/serializers_test.py @@ -50,7 +50,6 @@ def test_serialize_create_user(db, mocker): Test creating a user """ profile = { - "name": "name", "email_optin": True, "toc_optin": True, "bio": "bio", @@ -67,6 +66,7 @@ def test_serialize_create_user(db, mocker): profile.update( { + "name": "", "image": None, "image_small": None, "image_medium": None, @@ -100,7 +100,6 @@ def test_serialize_create_user(db, mocker): @pytest.mark.parametrize( ("key", "value"), [ - ("name", "name_value"), ("email_optin", True), ("email_optin", False), ("bio", "bio_value"), @@ -191,7 +190,6 @@ def test_location_validation(user, data, is_valid): @pytest.mark.parametrize( ("key", "value"), [ - ("name", "name_value"), ("bio", "bio_value"), ("headline", "headline_value"), ("location", {"value": "Hobbiton, The Shire, Middle-Earth"}),