@powerhousedao/vetra-builder-package 0.0.24 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,7 @@ interface MembersSectionProps {
4
4
  members: BuilderTeamDocument["state"]["global"]["members"];
5
5
  onAddMember: (profileData: MemberProfileData) => boolean;
6
6
  onRemoveMember: (id: string) => void;
7
+ onUpdateMember: (id: string, profileData: Partial<MemberProfileData>) => void;
7
8
  }
8
- export declare function MembersSection({ members, onAddMember, onRemoveMember, }: MembersSectionProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function MembersSection({ members, onAddMember, onRemoveMember, onUpdateMember, }: MembersSectionProps): import("react/jsx-runtime").JSX.Element;
9
10
  export {};
@@ -4,7 +4,7 @@ import { useState } from "react";
4
4
  import { config } from "../config.js";
5
5
  import { getProfile, searchProfileOptions, getProfileOption, } from "../services/renown-api.js";
6
6
  import { truncateAddress } from "../utils/format.js";
7
- export function MembersSection({ members, onAddMember, onRemoveMember, }) {
7
+ export function MembersSection({ members, onAddMember, onRemoveMember, onUpdateMember, }) {
8
8
  const [selectedProfile, setSelectedProfile] = useState(null);
9
9
  const handleAddMember = () => {
10
10
  if (selectedProfile) {
@@ -25,9 +25,8 @@ export function MembersSection({ members, onAddMember, onRemoveMember, }) {
25
25
  : null;
26
26
  const handleUpdateMember = () => {
27
27
  if (selectedProfile && existingMember) {
28
- // Remove the old member and add the updated one
29
- onRemoveMember(existingMember.id);
30
- onAddMember({
28
+ // Update the member with new profile data
29
+ onUpdateMember(existingMember.id, {
31
30
  phid: selectedProfile.documentId,
32
31
  ethAddress: selectedProfile.ethAddress,
33
32
  name: selectedProfile.username,
@@ -75,5 +75,5 @@ export function Editor(props) {
75
75
  vetraDriveUrl: packageInfo.vetraDriveUrl,
76
76
  }));
77
77
  packageHandlers.handleCancelPackageEdit();
78
- }, onCancelPackageEdit: packageHandlers.handleCancelPackageEdit, onReorderSpaces: handleReorderSpaces, onReorderPackages: handleReorderPackages }), isAddingPackage && (_jsx(PackageForm, { spaceId: selectedSpaceForPackage, onSave: handleSavePackage, onCancel: handleCancelAddPackage }))] }), _jsxs("div", { className: "space-y-6", children: [_jsx(MembersSection, { members: members, onAddMember: memberHandlers.handleAddMember, onRemoveMember: memberHandlers.handleRemoveMember }), _jsx(QuickStats, { spaces: spaces, members: members })] })] }) })] }));
78
+ }, onCancelPackageEdit: packageHandlers.handleCancelPackageEdit, onReorderSpaces: handleReorderSpaces, onReorderPackages: handleReorderPackages }), isAddingPackage && (_jsx(PackageForm, { spaceId: selectedSpaceForPackage, onSave: handleSavePackage, onCancel: handleCancelAddPackage }))] }), _jsxs("div", { className: "space-y-6", children: [_jsx(MembersSection, { members: members, onAddMember: memberHandlers.handleAddMember, onRemoveMember: memberHandlers.handleRemoveMember, onUpdateMember: memberHandlers.handleUpdateMember }), _jsx(QuickStats, { spaces: spaces, members: members })] })] }) })] }));
79
79
  }
@@ -9,4 +9,5 @@ export interface MemberProfileData {
9
9
  export declare function useMemberHandlers(dispatch: DocumentDispatch<Action>): {
10
10
  handleAddMember: (profileData: MemberProfileData) => boolean;
11
11
  handleRemoveMember: (id: string) => void;
12
+ handleUpdateMember: (id: string, profileData: Partial<MemberProfileData>) => void;
12
13
  };
@@ -20,8 +20,18 @@ export function useMemberHandlers(dispatch) {
20
20
  const handleRemoveMember = useCallback((id) => {
21
21
  dispatch(actions.removeMember({ id }));
22
22
  }, [dispatch]);
23
+ const handleUpdateMember = useCallback((id, profileData) => {
24
+ dispatch(actions.updateMemberInfo({
25
+ id,
26
+ ...(profileData.phid !== undefined && { phid: profileData.phid }),
27
+ ...(profileData.ethAddress !== undefined && { ethAddress: profileData.ethAddress.trim() }),
28
+ ...(profileData.name !== undefined && { name: profileData.name }),
29
+ ...(profileData.profileImage !== undefined && { profileImage: profileData.profileImage }),
30
+ }));
31
+ }, [dispatch]);
23
32
  return {
24
33
  handleAddMember,
25
34
  handleRemoveMember,
35
+ handleUpdateMember,
26
36
  };
27
37
  }
@@ -1,6 +1,6 @@
1
- import type { DB } from "./schema.js";
2
1
  import type { IRelationalDb } from "document-drive";
3
- import { type BuilderTeamState, type BuilderTeamAction } from "document-models/builder-team/index.js";
2
+ import { type BuilderTeamAction, type BuilderTeamState } from "document-models/builder-team/index.js";
3
+ import type { DB } from "./schema.js";
4
4
  export declare class BuilderTeamHandlers {
5
5
  private db;
6
6
  private dbHelpers;
@@ -13,6 +13,7 @@ export declare class BuilderTeamHandlers {
13
13
  private handleUpdateSocials;
14
14
  private handleAddMember;
15
15
  private handleRemoveMember;
16
+ private handleUpdateMemberInfo;
16
17
  private handleAddSpace;
17
18
  private handleDeleteSpace;
18
19
  private handleUpdateSpaceInfo;
@@ -31,6 +31,9 @@ export class BuilderTeamHandlers {
31
31
  case "REMOVE_MEMBER":
32
32
  await this.handleRemoveMember(documentId, action, state);
33
33
  break;
34
+ case "UPDATE_MEMBER_INFO":
35
+ await this.handleUpdateMemberInfo(documentId, action, state);
36
+ break;
34
37
  // Spaces operations
35
38
  case "ADD_SPACE":
36
39
  await this.handleAddSpace(documentId, action, state);
@@ -97,6 +100,13 @@ export class BuilderTeamHandlers {
97
100
  await this.dbHelpers.ensureBuilderAccountExistsAndIsNotdeleted(documentId);
98
101
  if (!action.input.id)
99
102
  return;
103
+ // Find member in state to get full details
104
+ const member = state.members.find((m) => m.id === action.input.id);
105
+ // If member not found in state, skip
106
+ if (!member) {
107
+ console.warn(`Member ${action.input.id} not found in state`);
108
+ return;
109
+ }
100
110
  const memberExists = await this.dbHelpers.memberExists(documentId, action.input.id);
101
111
  if (!memberExists) {
102
112
  await this.db
@@ -104,11 +114,28 @@ export class BuilderTeamHandlers {
104
114
  .values({
105
115
  id: action.input.id,
106
116
  builder_team_id: documentId,
107
- eth_address: "",
117
+ eth_address: member.ethAddress || "",
118
+ phid: member.phid || null,
119
+ name: member.name || null,
120
+ profile_image: member.profileImage || null,
108
121
  created_at: new Date(),
109
122
  })
110
123
  .execute();
111
124
  }
125
+ else {
126
+ // Update existing member with new information
127
+ await this.db
128
+ .updateTable("builder_team_members")
129
+ .set({
130
+ eth_address: member.ethAddress || "",
131
+ phid: member.phid || null,
132
+ name: member.name || null,
133
+ profile_image: member.profileImage || null,
134
+ })
135
+ .where("id", "=", action.input.id)
136
+ .where("builder_team_id", "=", documentId)
137
+ .execute();
138
+ }
112
139
  }
113
140
  async handleRemoveMember(documentId, action, state) {
114
141
  if (!action.input.id)
@@ -116,9 +143,43 @@ export class BuilderTeamHandlers {
116
143
  await this.db
117
144
  .deleteFrom("builder_team_members")
118
145
  .where("builder_team_id", "=", documentId)
119
- .where("eth_address", "=", action.input.id)
146
+ .where("id", "=", action.input.id)
120
147
  .execute();
121
148
  }
149
+ async handleUpdateMemberInfo(documentId, action, state) {
150
+ if (!action.input.id)
151
+ return;
152
+ // Find member in state to get full details
153
+ const member = state.members.find((m) => m.id === action.input.id);
154
+ // If member not found in state, skip
155
+ if (!member) {
156
+ console.warn(`Member ${action.input.id} not found in state for update`);
157
+ return;
158
+ }
159
+ const updates = {};
160
+ // Update fields from state
161
+ if (member.ethAddress !== undefined) {
162
+ updates.eth_address = member.ethAddress || "";
163
+ }
164
+ if (member.phid !== undefined) {
165
+ updates.phid = member.phid;
166
+ }
167
+ if (member.name !== undefined) {
168
+ updates.name = member.name;
169
+ }
170
+ if (member.profileImage !== undefined) {
171
+ updates.profile_image = member.profileImage;
172
+ }
173
+ // Only update if there are actual changes
174
+ if (Object.keys(updates).length > 0) {
175
+ await this.db
176
+ .updateTable("builder_team_members")
177
+ .set(updates)
178
+ .where("id", "=", action.input.id)
179
+ .where("builder_team_id", "=", documentId)
180
+ .execute();
181
+ }
182
+ }
122
183
  // Spaces operations
123
184
  async handleAddSpace(documentId, action, state) {
124
185
  await this.dbHelpers.ensureBuilderAccountExistsAndIsNotdeleted(documentId);
@@ -152,7 +213,8 @@ export class BuilderTeamHandlers {
152
213
  if (action.input.title !== undefined && action.input.title !== null) {
153
214
  updates.title = action.input.title;
154
215
  }
155
- if (action.input.description !== undefined && action.input.description !== null) {
216
+ if (action.input.description !== undefined &&
217
+ action.input.description !== null) {
156
218
  updates.description = action.input.description;
157
219
  }
158
220
  // Only update if there are actual changes
@@ -229,7 +291,8 @@ export class BuilderTeamHandlers {
229
291
  if (action.input.title !== undefined && action.input.title !== null) {
230
292
  updates.title = action.input.title;
231
293
  }
232
- if (action.input.description !== undefined && action.input.description !== null) {
294
+ if (action.input.description !== undefined &&
295
+ action.input.description !== null) {
233
296
  updates.description = action.input.description;
234
297
  }
235
298
  if (action.input.github !== undefined && action.input.github !== null) {
@@ -238,7 +301,8 @@ export class BuilderTeamHandlers {
238
301
  if (action.input.npm !== undefined && action.input.npm !== null) {
239
302
  updates.npm_url = action.input.npm;
240
303
  }
241
- if (action.input.vetraDriveUrl !== undefined && action.input.vetraDriveUrl !== null) {
304
+ if (action.input.vetraDriveUrl !== undefined &&
305
+ action.input.vetraDriveUrl !== null) {
242
306
  updates.vetra_drive_url = action.input.vetraDriveUrl;
243
307
  }
244
308
  if (action.input.spaceId !== undefined && action.input.spaceId !== null) {
@@ -23,6 +23,9 @@ export async function up(db) {
23
23
  .addColumn("id", "varchar(255)", (col) => col.primaryKey())
24
24
  .addColumn("builder_team_id", "varchar(255)", (col) => col.notNull())
25
25
  .addColumn("eth_address", "varchar(42)", (col) => col.notNull()) // Ethereum addresses are 42 chars
26
+ .addColumn("phid", "varchar(255)") // Powerhouse ID for Renown integration
27
+ .addColumn("name", "varchar(255)") // Member name
28
+ .addColumn("profile_image", "text") // Profile image URL
26
29
  .addColumn("created_at", "timestamp", (col) => col.defaultTo("now()").notNull())
27
30
  .addForeignKeyConstraint("builder_team_members_account_fk", ["builder_team_id"], "builder_teams", ["id"], (cb) => cb.onDelete("cascade"))
28
31
  .ifNotExists()
@@ -98,6 +101,12 @@ export async function up(db) {
98
101
  .column("eth_address")
99
102
  .ifNotExists()
100
103
  .execute();
104
+ await db.schema
105
+ .createIndex("idx_builder_team_members_phid")
106
+ .on("builder_team_members")
107
+ .column("phid")
108
+ .ifNotExists()
109
+ .execute();
101
110
  await db.schema
102
111
  .createIndex("idx_builder_team_spaces_account")
103
112
  .on("builder_team_spaces")
@@ -6,6 +6,9 @@ export interface BuilderTeamMembers {
6
6
  created_at: Generated<Timestamp>;
7
7
  eth_address: string;
8
8
  id: string;
9
+ name: string | null;
10
+ phid: string | null;
11
+ profile_image: string | null;
9
12
  }
10
13
  export interface BuilderTeamPackageKeywords {
11
14
  created_at: Generated<Timestamp>;
@@ -43,6 +43,9 @@ export const getResolvers = (subgraph) => {
43
43
  .select([
44
44
  "builder_team_members.id",
45
45
  "builder_team_members.builder_team_id",
46
+ "builder_team_members.phid",
47
+ "builder_team_members.name",
48
+ "builder_team_members.profile_image",
46
49
  "builder_team_members.eth_address",
47
50
  "builder_team_members.created_at",
48
51
  ])
@@ -55,6 +58,9 @@ export const getResolvers = (subgraph) => {
55
58
  return members.map((member) => ({
56
59
  id: member.id,
57
60
  builderAccountId: member.builder_team_id,
61
+ phid: member.phid,
62
+ name: member.name,
63
+ profileImage: member.profile_image,
58
64
  ethAddress: member.eth_address,
59
65
  createdAt: member.created_at.toISOString(),
60
66
  }));
@@ -45,6 +45,9 @@ export const schema = gql `
45
45
  type BuilderTeamMember {
46
46
  id: String!
47
47
  builderAccountId: String!
48
+ phid: String
49
+ name: String
50
+ profileImage: String
48
51
  ethAddress: String!
49
52
  createdAt: String!
50
53
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@powerhousedao/vetra-builder-package",
3
3
  "description": "",
4
- "version": "0.0.24",
4
+ "version": "0.0.26",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
7
7
  "files": [