Skip to content
5 changes: 5 additions & 0 deletions .changeset/long-lions-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'hive': patch
---

Add server-side sorting to app deployments table (Created, Activated, Last Used).
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ export default gql`
retired
}

"""
Fields available for sorting app deployments.
"""
enum AppDeploymentsSortField {
CREATED_AT
ACTIVATED_AT
LAST_USED
}

"""
Sort configuration for app deployments.
"""
input AppDeploymentsSortInput {
field: AppDeploymentsSortField!
direction: SortDirectionType!
}

type GraphQLDocumentConnection {
pageInfo: PageInfo!
edges: [GraphQLDocumentEdge!]!
Expand All @@ -63,6 +80,10 @@ export default gql`
type AppDeploymentConnection {
pageInfo: PageInfo! @tag(name: "public")
edges: [AppDeploymentEdge!]! @tag(name: "public")
"""
The total number of app deployments for this target.
"""
total: Int! @tag(name: "public")
}

type AppDeploymentEdge {
Expand Down Expand Up @@ -108,7 +129,11 @@ export default gql`
"""
The app deployments for this target.
"""
appDeployments(first: Int, after: String): AppDeploymentConnection
appDeployments(
first: Int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
first: Int
first: Int! = 20

Minor: I like to set the default in the SDL so that it's clearly visible to API consumer and so that although the argument doesnt need passed, youll always get a value in the resolver.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree but, there's already a code check for this that clamps and sets it to 20 when null. If there's any needed change, it has to also change all fields that utilize the (nullable, no default) first parameter pattern and not just appDeployments. For consistency, this should be a codebase-wide decision, not a one-off on this field.

This is based on the project patterns document: https://www.notion.so/theguildoss/Hive-Console-GraphQL-API-Design-Patterns-18ab6b71848a80678939c669699fe8e6#18ab6b71848a80d5a1b1d16abd881d32

after: String
sort: AppDeploymentsSortInput
): AppDeploymentConnection
appDeployment(appName: String!, appVersion: String!): AppDeployment
"""
Whether the viewer can access the app deployments within a target.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,38 @@ export class AppDeploymentsManager {

async getPaginatedAppDeploymentsForTarget(
target: Target,
args: { cursor: string | null; first: number | null },
args: {
cursor: string | null;
first: number | null;
sort: {
field: GraphQLSchema.AppDeploymentsSortField;
direction: GraphQLSchema.SortDirectionType;
} | null;
},
) {
return await this.appDeployments.getPaginatedAppDeployments({
targetId: target.id,
cursor: args.cursor,
first: args.first,
});
const { sort, cursor, first } = args;

const pagePromise =
sort?.field === 'LAST_USED'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have an exported enum from codegen we could use?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. codegen produces string union types, not typescript enums, so there's no enum member to reference

? this.appDeployments.getPaginatedAppDeploymentsSortedByLastUsed({
targetId: target.id,
cursor,
first,
direction: sort.direction,
})
: this.appDeployments.getPaginatedAppDeployments({
targetId: target.id,
cursor,
first,
sort: sort ? { field: sort.field, direction: sort.direction } : null,
});

const [page, total] = await Promise.all([
pagePromise,
this.appDeployments.countAppDeployments(target.id),
]);

return { ...page, total };
}

async getActiveAppDeploymentsForTarget(
Expand All @@ -243,12 +268,17 @@ export class AppDeploymentsManager {
};
},
) {
return await this.appDeployments.getActiveAppDeployments({
targetId: target.id,
cursor: args.cursor,
first: args.first,
filter: args.filter,
});
const [page, total] = await Promise.all([
this.appDeployments.getActiveAppDeployments({
targetId: target.id,
cursor: args.cursor,
first: args.first,
filter: args.filter,
}),
this.appDeployments.countAppDeployments(target.id),
]);

return { ...page, total };
}

getDocumentCountForAppDeployment = batch<AppDeploymentRecord, number>(async args => {
Expand Down
Loading
Loading