Compare commits

..

21 Commits

Author SHA1 Message Date
Dean Wenstrand
9250e4c639 Add username + profileImageUri to PlayerClusterGQL
All checks were successful
Tests / Tests (pull_request) Successful in 9s
The labeling UI was falling back to "user N" for any assigned cluster
whose user wasn't the video owner — e.g. an admin re-labels a video
they don't own. With the resolver now resolving usernames for every
confirmed cluster, the FE can render real names regardless of who's
viewing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:25:34 -07:00
Dean Wenstrand
5cf2dbaf01 Add averageDifficulty to PlayerSummaryFields
All checks were successful
Tests / Tests (pull_request) Successful in 9s
Regenerated via `just gql` after BE added average_difficulty to
PlayerSummaryGQL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:34:25 -07:00
239a143554 Merge pull request 'Regenerate schema + add longestRun to PlayerSummaryFields' (#244) from dean/player-summaries-longest-run-types into master
Reviewed-on: #244
2026-05-11 20:29:39 +00:00
Dean Wenstrand
296522afb8 Regenerate schema + add longestRun to PlayerSummaryFields
All checks were successful
Tests / Tests (pull_request) Successful in 10s
Generated by `just gql` after BE added longest_run to PlayerSummaryGQL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:21:47 -07:00
f42579076e Merge pull request 'Add score to PlayerSummaryFields + PlayerClusterFields fragments' (#243) from dean/video-match-score-types into master
Reviewed-on: #243
2026-05-11 17:43:43 +00:00
Dean Wenstrand
0c9eb4945a Add score to PlayerSummaryFields + PlayerClusterFields fragments
All checks were successful
Tests / Tests (pull_request) Successful in 9s
Picks up the BE additions in railbird PR dean/video-match-score:
new `score` field on PlayerClusterGQL and PlayerSummaryGQL, and
a new `score` input field on ClusterAssignmentInput.

Generated by `just gql`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:22:58 -07:00
1182c15004 Merge pull request 'Add playerSummaries to schema + Video fragments' (#242) from dean/player-summaries-types into master
Reviewed-on: #242
2026-05-09 19:34:40 +00:00
Dean Wenstrand
755336b16a Add playerSummaries to schema + Video fragments
All checks were successful
Tests / Tests (pull_request) Successful in 10s
Backs the multi-player vs UI: feed cards and the detail page both
read `video.playerSummaries`, a per-cluster rollup with username,
profile image, representative full-frame URL, makes/total/percentage.

  - PlayerSummaryFields fragment in shooter.gql
  - VideoCardFields (feed) and GetVideoDetails (detail) include
    playerSummaries via the new fragment
  - VideoCardFields tag selection extended to include tagClasses,
    needed for the FE's player_count detection

Generated by `just gql` from the BE additions in railbird PR
dean/video-player-summaries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:02:57 -07:00
c1efe9f5f2 Merge pull request 'Add VideoPlayerClusters query + FinalizePlayerAssignments mutation' (#241) from dean/player-labeling-ops into master
Reviewed-on: #241
2026-05-09 04:46:10 +00:00
Dean Wenstrand
a3460842ac Add VideoPlayerClusters query + FinalizePlayerAssignments mutation
All checks were successful
Tests / Tests (pull_request) Successful in 10s
Operation file for the per-video player-labeling UI that consumes the
schema types added in #240.

  - VideoPlayerClusters($videoId): read clusters + crops
  - FinalizePlayerAssignments($input): apply user assignments and
    shot moves in one transaction

Generated by `just gql`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 21:44:42 -07:00
84d3a0252d Merge pull request 'Add player cluster + labeling mutation types' (#240) from dean/labeling-api-types into master
Reviewed-on: #240
2026-05-09 00:38:29 +00:00
Dean Wenstrand
1de4a97cb6 Add player cluster + labeling mutation types
All checks were successful
Tests / Tests (pull_request) Successful in 10s
Schema additions for the per-video player labeling UI:
  * `PlayerClusterGQL` / `PlayerClusterShotGQL` — read shape.
  * `FinalizePlayerAssignmentsInput` + `ClusterAssignmentInput` +
    `ShotMoveInput` — write shape.
  * Query: `videoPlayerClusters(videoId)`.
  * Mutation: `finalizePlayerAssignments(input)`.

Generated by `just gql` from the backend type definitions in
`railbird/datatypes/gql/shooter.py` and resolvers in
`railbird/server/resolvers/shooter.py`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:04:41 -07:00
130314546c Merge pull request 'Add trial days to GetAvailableSubscriptions' (#239) from loewy/add-trial-period-days into master
Reviewed-on: #239
2026-05-04 21:46:45 +00:00
b88f172355 add trial days to return
All checks were successful
Tests / Tests (pull_request) Successful in 10s
2026-05-04 14:07:16 -07:00
639fc88b0b Merge pull request 'Add createCustomerPortalSession' (#238) from loewy/create-customer-portal-session into master
Reviewed-on: #238
2026-05-01 22:45:40 +00:00
20f50368c9 remove return url
All checks were successful
Tests / Tests (pull_request) Successful in 10s
2026-05-01 13:15:18 -07:00
8367c2d0cd add createCustomerPortalSession
All checks were successful
Tests / Tests (pull_request) Successful in 10s
2026-04-30 11:44:34 -07:00
b0c62f6e80 Merge pull request 'Trim getFeed query fragment' (#237) from loewy/trim-get-feed-query-fragment into master
Reviewed-on: #237
2026-04-29 20:26:40 +00:00
bc1ff66467 trim uncessary requested fields
All checks were successful
Tests / Tests (pull_request) Successful in 38s
2026-04-28 12:53:25 -07:00
ae37a3d9d9 Merge pull request 'Default getLongestRunsLeaderboard limit to 50' (#236) from dean/leaderboard-default-top-50 into master
Reviewed-on: #236
2026-04-24 00:01:23 +00:00
Dean Wenstrand
114b21400e Default getLongestRunsLeaderboard limit to 50
All checks were successful
Tests / Tests (pull_request) Successful in 10s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 16:56:56 -07:00
6 changed files with 630 additions and 90 deletions

View File

@@ -205,6 +205,12 @@ export enum ClientUploadStatusEnum {
UploadEnabled = "UPLOAD_ENABLED", UploadEnabled = "UPLOAD_ENABLED",
} }
export type ClusterAssignmentInput = {
clusterId: Scalars["Int"]["input"];
score?: InputMaybe<Scalars["Int"]["input"]>;
userId?: InputMaybe<Scalars["Int"]["input"]>;
};
export type CommentGql = { export type CommentGql = {
__typename?: "CommentGQL"; __typename?: "CommentGQL";
id: Scalars["Int"]["output"]; id: Scalars["Int"]["output"];
@@ -224,6 +230,11 @@ export type CreateBucketSetInput = {
keyName: Scalars["String"]["input"]; keyName: Scalars["String"]["input"];
}; };
export type CreateCustomerPortalSessionResultGql = {
__typename?: "CreateCustomerPortalSessionResultGQL";
portalUrl: Scalars["String"]["output"];
};
export type CreateSubscriptionResultGql = { export type CreateSubscriptionResultGql = {
__typename?: "CreateSubscriptionResultGQL"; __typename?: "CreateSubscriptionResultGQL";
checkoutUrl: Scalars["String"]["output"]; checkoutUrl: Scalars["String"]["output"];
@@ -2177,6 +2188,12 @@ export type FilterInput =
videoId: Array<Scalars["Int"]["input"]>; videoId: Array<Scalars["Int"]["input"]>;
}; };
export type FinalizePlayerAssignmentsInput = {
clusterAssignments?: Array<ClusterAssignmentInput>;
shotMoves?: Array<ShotMoveInput>;
videoId: Scalars["Int"]["input"];
};
export type FloatOrdering = { export type FloatOrdering = {
descending?: Scalars["Boolean"]["input"]; descending?: Scalars["Boolean"]["input"];
startingAt?: InputMaybe<Scalars["Float"]["input"]>; startingAt?: InputMaybe<Scalars["Float"]["input"]>;
@@ -2373,6 +2390,7 @@ export type Mutation = {
commentOnVideo: Scalars["Boolean"]["output"]; commentOnVideo: Scalars["Boolean"]["output"];
createBucketSet: BucketSetGql; createBucketSet: BucketSetGql;
createChallenge: Challenge; createChallenge: Challenge;
createCustomerPortalSession: CreateCustomerPortalSessionResultGql;
createRuleSet: RuleSet; createRuleSet: RuleSet;
createSubscription: CreateSubscriptionResultGql; createSubscription: CreateSubscriptionResultGql;
createUploadStream: CreateUploadStreamReturn; createUploadStream: CreateUploadStreamReturn;
@@ -2388,6 +2406,7 @@ export type Mutation = {
editUploadStream: Scalars["Boolean"]["output"]; editUploadStream: Scalars["Boolean"]["output"];
editUser: UserGql; editUser: UserGql;
ensureStripeCustomerExists: UserGql; ensureStripeCustomerExists: UserGql;
finalizePlayerAssignments: Array<PlayerClusterGql>;
findPrerecordTableLayout?: Maybe<HomographyInfoGql>; findPrerecordTableLayout?: Maybe<HomographyInfoGql>;
followUser: UserGql; followUser: UserGql;
getHlsInitUploadLink: GetUploadLinkReturn; getHlsInitUploadLink: GetUploadLinkReturn;
@@ -2462,7 +2481,6 @@ export type MutationCreateSubscriptionArgs = {
export type MutationCreateUploadStreamArgs = { export type MutationCreateUploadStreamArgs = {
expectedDurationSeconds?: InputMaybe<Scalars["Float"]["input"]>; expectedDurationSeconds?: InputMaybe<Scalars["Float"]["input"]>;
uploadKind?: InputMaybe<UploadKindEnum>;
videoMetadata: VideoMetadataInput; videoMetadata: VideoMetadataInput;
}; };
@@ -2512,6 +2530,10 @@ export type MutationEditUserArgs = {
input: EditUserInputGql; input: EditUserInputGql;
}; };
export type MutationFinalizePlayerAssignmentsArgs = {
input: FinalizePlayerAssignmentsInput;
};
export type MutationFindPrerecordTableLayoutArgs = { export type MutationFindPrerecordTableLayoutArgs = {
b64Image: Scalars["String"]["input"]; b64Image: Scalars["String"]["input"];
videoId: Scalars["Int"]["input"]; videoId: Scalars["Int"]["input"];
@@ -2674,6 +2696,48 @@ export type PageInfoGql = {
hasNextPage: Scalars["Boolean"]["output"]; hasNextPage: Scalars["Boolean"]["output"];
}; };
export type PlayerClusterGql = {
__typename?: "PlayerClusterGQL";
clusterId: Scalars["Int"]["output"];
confirmed: Scalars["Boolean"]["output"];
nShots: Scalars["Int"]["output"];
profileImageUri?: Maybe<Scalars["String"]["output"]>;
score?: Maybe<Scalars["Int"]["output"]>;
shots: Array<PlayerClusterShotGql>;
userId?: Maybe<Scalars["Int"]["output"]>;
username?: Maybe<Scalars["String"]["output"]>;
videoId: Scalars["Int"]["output"];
};
export type PlayerClusterShotGql = {
__typename?: "PlayerClusterShotGQL";
bboxX1: Scalars["Int"]["output"];
bboxX2: Scalars["Int"]["output"];
bboxY1: Scalars["Int"]["output"];
bboxY2: Scalars["Int"]["output"];
confidence: Scalars["Float"]["output"];
cropUrl?: Maybe<Scalars["String"]["output"]>;
fullFrameUrl?: Maybe<Scalars["String"]["output"]>;
isConfirmed: Scalars["Boolean"]["output"];
shotId: Scalars["Int"]["output"];
};
export type PlayerSummaryGql = {
__typename?: "PlayerSummaryGQL";
averageDifficulty?: Maybe<Scalars["Float"]["output"]>;
averageTimeBetweenShots?: Maybe<Scalars["Float"]["output"]>;
clusterId: Scalars["Int"]["output"];
longestRun: Scalars["Int"]["output"];
makePercentage: Scalars["Float"]["output"];
profileImageUri?: Maybe<Scalars["String"]["output"]>;
representativeFullFrameUrl?: Maybe<Scalars["String"]["output"]>;
score?: Maybe<Scalars["Int"]["output"]>;
totalShots: Scalars["Int"]["output"];
totalShotsMade: Scalars["Int"]["output"];
userId?: Maybe<Scalars["Int"]["output"]>;
username?: Maybe<Scalars["String"]["output"]>;
};
export enum PocketEnum { export enum PocketEnum {
Corner = "CORNER", Corner = "CORNER",
Side = "SIDE", Side = "SIDE",
@@ -2784,6 +2848,7 @@ export type Query = {
notifications: NotificationConnection; notifications: NotificationConnection;
ruleSets: Array<RuleSet>; ruleSets: Array<RuleSet>;
unreadNotificationCount: Scalars["Int"]["output"]; unreadNotificationCount: Scalars["Int"]["output"];
videoPlayerClusters: Array<PlayerClusterGql>;
waitFor: Scalars["Float"]["output"]; waitFor: Scalars["Float"]["output"];
}; };
@@ -2950,6 +3015,10 @@ export type QueryNotificationsArgs = {
offset?: Scalars["Int"]["input"]; offset?: Scalars["Int"]["input"];
}; };
export type QueryVideoPlayerClustersArgs = {
videoId: Scalars["Int"]["input"];
};
export type QueryWaitForArgs = { export type QueryWaitForArgs = {
duration: Scalars["Float"]["input"]; duration: Scalars["Float"]["input"];
}; };
@@ -2960,11 +3029,9 @@ export type QuotaStatusGql = {
durationLimitSeconds?: Maybe<Scalars["Int"]["output"]>; durationLimitSeconds?: Maybe<Scalars["Int"]["output"]>;
durationRemainingSeconds?: Maybe<Scalars["Float"]["output"]>; durationRemainingSeconds?: Maybe<Scalars["Float"]["output"]>;
durationUsedSeconds: Scalars["Float"]["output"]; durationUsedSeconds: Scalars["Float"]["output"];
importUploadPermission: UploadPermissionGql;
maxVideoDurationSeconds?: Maybe<Scalars["Int"]["output"]>; maxVideoDurationSeconds?: Maybe<Scalars["Int"]["output"]>;
periodEnd: Scalars["DateTime"]["output"]; periodEnd: Scalars["DateTime"]["output"];
periodStart: Scalars["DateTime"]["output"]; periodStart: Scalars["DateTime"]["output"];
recordingPermission: UploadPermissionGql;
tierName: Scalars["String"]["output"]; tierName: Scalars["String"]["output"];
}; };
@@ -3169,6 +3236,11 @@ export type ShotGql = {
videoId: Scalars["Int"]["output"]; videoId: Scalars["Int"]["output"];
}; };
export type ShotMoveInput = {
newClusterId: Scalars["Int"]["input"];
shotId: Scalars["Int"]["input"];
};
export type ShotsOrderingComponent = export type ShotsOrderingComponent =
| { | {
difficulty: FloatOrdering; difficulty: FloatOrdering;
@@ -3267,6 +3339,7 @@ export type StripeProductGql = {
export type StripeSubscriptionOptionsGql = { export type StripeSubscriptionOptionsGql = {
__typename?: "StripeSubscriptionOptionsGQL"; __typename?: "StripeSubscriptionOptionsGQL";
products: Array<StripeProductGql>; products: Array<StripeProductGql>;
trialPeriodDays?: Maybe<Scalars["Int"]["output"]>;
}; };
export enum StripeSubscriptionStatusEnum { export enum StripeSubscriptionStatusEnum {
@@ -3350,11 +3423,6 @@ export type UpdateShotAnnotationReturn = {
shot?: Maybe<ShotGql>; shot?: Maybe<ShotGql>;
}; };
export enum UploadKindEnum {
Import = "IMPORT",
Recording = "RECORDING",
}
export type UploadLink = { export type UploadLink = {
__typename?: "UploadLink"; __typename?: "UploadLink";
headers: Array<Maybe<Header>>; headers: Array<Maybe<Header>>;
@@ -3367,12 +3435,6 @@ export type UploadLinkGetProfileUploadLinkErrors =
export type UploadLinkGetUploadLinkErrors = GetUploadLinkErrors | UploadLink; export type UploadLinkGetUploadLinkErrors = GetUploadLinkErrors | UploadLink;
export type UploadPermissionGql = {
__typename?: "UploadPermissionGQL";
allowed: Scalars["Boolean"]["output"];
reason?: Maybe<Scalars["String"]["output"]>;
};
export type UploadSegmentGql = { export type UploadSegmentGql = {
__typename?: "UploadSegmentGQL"; __typename?: "UploadSegmentGQL";
durationInSeconds?: Maybe<Scalars["Float"]["output"]>; durationInSeconds?: Maybe<Scalars["Float"]["output"]>;
@@ -3515,6 +3577,7 @@ export type VideoGql = {
medianRun?: Maybe<Scalars["Float"]["output"]>; medianRun?: Maybe<Scalars["Float"]["output"]>;
name?: Maybe<Scalars["String"]["output"]>; name?: Maybe<Scalars["String"]["output"]>;
owner?: Maybe<UserGql>; owner?: Maybe<UserGql>;
playerSummaries: Array<PlayerSummaryGql>;
playlist?: Maybe<HlsPlaylistGql>; playlist?: Maybe<HlsPlaylistGql>;
pocketSize?: Maybe<Scalars["Float"]["output"]>; pocketSize?: Maybe<Scalars["Float"]["output"]>;
private: Scalars["Boolean"]["output"]; private: Scalars["Boolean"]["output"];
@@ -4111,15 +4174,11 @@ export type GetFeedQuery = {
id: number; id: number;
name?: string | null; name?: string | null;
screenshotUri?: string | null; screenshotUri?: string | null;
totalShotsMade: number;
totalShots: number; totalShots: number;
makePercentage: number; makePercentage: number;
averageTimeBetweenShots?: number | null; averageTimeBetweenShots?: number | null;
averageDifficulty?: number | null; averageDifficulty?: number | null;
createdAt?: any | null;
updatedAt?: any | null;
startTime?: any | null; startTime?: any | null;
endTime?: any | null;
private: boolean; private: boolean;
elapsedTime?: number | null; elapsedTime?: number | null;
tableSize: number; tableSize: number;
@@ -4134,7 +4193,6 @@ export type GetFeedQuery = {
__typename?: "UploadStreamGQL"; __typename?: "UploadStreamGQL";
id: string; id: string;
lastIntendedSegmentBound?: number | null; lastIntendedSegmentBound?: number | null;
isCompleted: boolean;
streamSegmentType: StreamSegmentTypeEnum; streamSegmentType: StreamSegmentTypeEnum;
} | null; } | null;
tags: Array<{ tags: Array<{
@@ -4142,18 +4200,25 @@ export type GetFeedQuery = {
name: string; name: string;
tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>; tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>;
}>; }>;
playerSummaries: Array<{
__typename?: "PlayerSummaryGQL";
clusterId: number;
userId?: number | null;
username?: string | null;
profileImageUri?: string | null;
representativeFullFrameUrl?: string | null;
totalShots: number;
totalShotsMade: number;
makePercentage: number;
score?: number | null;
longestRun: number;
averageDifficulty?: number | null;
averageTimeBetweenShots?: number | null;
}>;
currentProcessing?: { currentProcessing?: {
__typename?: "VideoProcessingGQL"; __typename?: "VideoProcessingGQL";
id: number; id: number;
status: ProcessingStatusEnum; status: ProcessingStatusEnum;
errors: Array<{
__typename?: "VideoProcessingErrorGQL";
message: string;
}>;
statuses: Array<{
__typename?: "VideoProcessingStatusGQL";
status: ProcessingStatusEnum;
}>;
} | null; } | null;
reactions: Array<{ reactions: Array<{
__typename?: "ReactionGQL"; __typename?: "ReactionGQL";
@@ -4213,15 +4278,11 @@ export type VideoCardFieldsFragment = {
id: number; id: number;
name?: string | null; name?: string | null;
screenshotUri?: string | null; screenshotUri?: string | null;
totalShotsMade: number;
totalShots: number; totalShots: number;
makePercentage: number; makePercentage: number;
averageTimeBetweenShots?: number | null; averageTimeBetweenShots?: number | null;
averageDifficulty?: number | null; averageDifficulty?: number | null;
createdAt?: any | null;
updatedAt?: any | null;
startTime?: any | null; startTime?: any | null;
endTime?: any | null;
private: boolean; private: boolean;
elapsedTime?: number | null; elapsedTime?: number | null;
tableSize: number; tableSize: number;
@@ -4236,7 +4297,6 @@ export type VideoCardFieldsFragment = {
__typename?: "UploadStreamGQL"; __typename?: "UploadStreamGQL";
id: string; id: string;
lastIntendedSegmentBound?: number | null; lastIntendedSegmentBound?: number | null;
isCompleted: boolean;
streamSegmentType: StreamSegmentTypeEnum; streamSegmentType: StreamSegmentTypeEnum;
} | null; } | null;
tags: Array<{ tags: Array<{
@@ -4244,15 +4304,25 @@ export type VideoCardFieldsFragment = {
name: string; name: string;
tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>; tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>;
}>; }>;
playerSummaries: Array<{
__typename?: "PlayerSummaryGQL";
clusterId: number;
userId?: number | null;
username?: string | null;
profileImageUri?: string | null;
representativeFullFrameUrl?: string | null;
totalShots: number;
totalShotsMade: number;
makePercentage: number;
score?: number | null;
longestRun: number;
averageDifficulty?: number | null;
averageTimeBetweenShots?: number | null;
}>;
currentProcessing?: { currentProcessing?: {
__typename?: "VideoProcessingGQL"; __typename?: "VideoProcessingGQL";
id: number; id: number;
status: ProcessingStatusEnum; status: ProcessingStatusEnum;
errors: Array<{ __typename?: "VideoProcessingErrorGQL"; message: string }>;
statuses: Array<{
__typename?: "VideoProcessingStatusGQL";
status: ProcessingStatusEnum;
}>;
} | null; } | null;
reactions: Array<{ reactions: Array<{
__typename?: "ReactionGQL"; __typename?: "ReactionGQL";
@@ -4326,15 +4396,11 @@ export type GetVideoFeedQuery = {
id: number; id: number;
name?: string | null; name?: string | null;
screenshotUri?: string | null; screenshotUri?: string | null;
totalShotsMade: number;
totalShots: number; totalShots: number;
makePercentage: number; makePercentage: number;
averageTimeBetweenShots?: number | null; averageTimeBetweenShots?: number | null;
averageDifficulty?: number | null; averageDifficulty?: number | null;
createdAt?: any | null;
updatedAt?: any | null;
startTime?: any | null; startTime?: any | null;
endTime?: any | null;
private: boolean; private: boolean;
elapsedTime?: number | null; elapsedTime?: number | null;
tableSize: number; tableSize: number;
@@ -4349,7 +4415,6 @@ export type GetVideoFeedQuery = {
__typename?: "UploadStreamGQL"; __typename?: "UploadStreamGQL";
id: string; id: string;
lastIntendedSegmentBound?: number | null; lastIntendedSegmentBound?: number | null;
isCompleted: boolean;
streamSegmentType: StreamSegmentTypeEnum; streamSegmentType: StreamSegmentTypeEnum;
} | null; } | null;
tags: Array<{ tags: Array<{
@@ -4357,18 +4422,25 @@ export type GetVideoFeedQuery = {
name: string; name: string;
tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>; tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>;
}>; }>;
playerSummaries: Array<{
__typename?: "PlayerSummaryGQL";
clusterId: number;
userId?: number | null;
username?: string | null;
profileImageUri?: string | null;
representativeFullFrameUrl?: string | null;
totalShots: number;
totalShotsMade: number;
makePercentage: number;
score?: number | null;
longestRun: number;
averageDifficulty?: number | null;
averageTimeBetweenShots?: number | null;
}>;
currentProcessing?: { currentProcessing?: {
__typename?: "VideoProcessingGQL"; __typename?: "VideoProcessingGQL";
id: number; id: number;
status: ProcessingStatusEnum; status: ProcessingStatusEnum;
errors: Array<{
__typename?: "VideoProcessingErrorGQL";
message: string;
}>;
statuses: Array<{
__typename?: "VideoProcessingStatusGQL";
status: ProcessingStatusEnum;
}>;
} | null; } | null;
reactions: Array<{ reactions: Array<{
__typename?: "ReactionGQL"; __typename?: "ReactionGQL";
@@ -4763,6 +4835,18 @@ export type CreateSubscriptionMutation = {
}; };
}; };
export type CreateCustomerPortalSessionMutationVariables = Exact<{
[key: string]: never;
}>;
export type CreateCustomerPortalSessionMutation = {
__typename?: "Mutation";
createCustomerPortalSession: {
__typename?: "CreateCustomerPortalSessionResultGQL";
portalUrl: string;
};
};
export type GetAvailableSubscriptionOptionsQueryVariables = Exact<{ export type GetAvailableSubscriptionOptionsQueryVariables = Exact<{
[key: string]: never; [key: string]: never;
}>; }>;
@@ -4771,6 +4855,7 @@ export type GetAvailableSubscriptionOptionsQuery = {
__typename?: "Query"; __typename?: "Query";
getAvailableSubscriptionOptions: { getAvailableSubscriptionOptions: {
__typename?: "StripeSubscriptionOptionsGQL"; __typename?: "StripeSubscriptionOptionsGQL";
trialPeriodDays?: number | null;
products: Array<{ products: Array<{
__typename?: "StripeProductGQL"; __typename?: "StripeProductGQL";
id: string; id: string;
@@ -4922,6 +5007,121 @@ export type GetRunsWithTimestampsQuery = {
}; };
}; };
export type PlayerSummaryFieldsFragment = {
__typename?: "PlayerSummaryGQL";
clusterId: number;
userId?: number | null;
username?: string | null;
profileImageUri?: string | null;
representativeFullFrameUrl?: string | null;
totalShots: number;
totalShotsMade: number;
makePercentage: number;
score?: number | null;
longestRun: number;
averageDifficulty?: number | null;
averageTimeBetweenShots?: number | null;
};
export type PlayerClusterShotFieldsFragment = {
__typename?: "PlayerClusterShotGQL";
shotId: number;
bboxX1: number;
bboxY1: number;
bboxX2: number;
bboxY2: number;
confidence: number;
isConfirmed: boolean;
cropUrl?: string | null;
fullFrameUrl?: string | null;
};
export type PlayerClusterFieldsFragment = {
__typename?: "PlayerClusterGQL";
videoId: number;
clusterId: number;
nShots: number;
userId?: number | null;
username?: string | null;
profileImageUri?: string | null;
confirmed: boolean;
score?: number | null;
shots: Array<{
__typename?: "PlayerClusterShotGQL";
shotId: number;
bboxX1: number;
bboxY1: number;
bboxX2: number;
bboxY2: number;
confidence: number;
isConfirmed: boolean;
cropUrl?: string | null;
fullFrameUrl?: string | null;
}>;
};
export type VideoPlayerClustersQueryVariables = Exact<{
videoId: Scalars["Int"]["input"];
}>;
export type VideoPlayerClustersQuery = {
__typename?: "Query";
videoPlayerClusters: Array<{
__typename?: "PlayerClusterGQL";
videoId: number;
clusterId: number;
nShots: number;
userId?: number | null;
username?: string | null;
profileImageUri?: string | null;
confirmed: boolean;
score?: number | null;
shots: Array<{
__typename?: "PlayerClusterShotGQL";
shotId: number;
bboxX1: number;
bboxY1: number;
bboxX2: number;
bboxY2: number;
confidence: number;
isConfirmed: boolean;
cropUrl?: string | null;
fullFrameUrl?: string | null;
}>;
}>;
};
export type FinalizePlayerAssignmentsMutationVariables = Exact<{
input: FinalizePlayerAssignmentsInput;
}>;
export type FinalizePlayerAssignmentsMutation = {
__typename?: "Mutation";
finalizePlayerAssignments: Array<{
__typename?: "PlayerClusterGQL";
videoId: number;
clusterId: number;
nShots: number;
userId?: number | null;
username?: string | null;
profileImageUri?: string | null;
confirmed: boolean;
score?: number | null;
shots: Array<{
__typename?: "PlayerClusterShotGQL";
shotId: number;
bboxX1: number;
bboxY1: number;
bboxX2: number;
bboxY2: number;
confidence: number;
isConfirmed: boolean;
cropUrl?: string | null;
fullFrameUrl?: string | null;
}>;
}>;
};
export type GetSerializedShotPathsQueryVariables = Exact<{ export type GetSerializedShotPathsQueryVariables = Exact<{
filterInput: FilterInput; filterInput: FilterInput;
}>; }>;
@@ -5858,6 +6058,21 @@ export type GetVideoDetailsQuery = {
name: string; name: string;
tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>; tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>;
}>; }>;
playerSummaries: Array<{
__typename?: "PlayerSummaryGQL";
clusterId: number;
userId?: number | null;
username?: string | null;
profileImageUri?: string | null;
representativeFullFrameUrl?: string | null;
totalShots: number;
totalShotsMade: number;
makePercentage: number;
score?: number | null;
longestRun: number;
averageDifficulty?: number | null;
averageTimeBetweenShots?: number | null;
}>;
}; };
}; };
@@ -6515,6 +6730,22 @@ export type GetUploadStreamsWithDetailsQuery = {
}; };
}; };
export const PlayerSummaryFieldsFragmentDoc = gql`
fragment PlayerSummaryFields on PlayerSummaryGQL {
clusterId
userId
username
profileImageUri
representativeFullFrameUrl
totalShots
totalShotsMade
makePercentage
score
longestRun
averageDifficulty
averageTimeBetweenShots
}
`;
export const UserSocialsFieldsFragmentDoc = gql` export const UserSocialsFieldsFragmentDoc = gql`
fragment UserSocialsFields on UserGQL { fragment UserSocialsFields on UserGQL {
id id
@@ -6533,41 +6764,32 @@ export const VideoCardFieldsFragmentDoc = gql`
} }
name name
screenshotUri screenshotUri
totalShotsMade
totalShots totalShots
makePercentage makePercentage
averageTimeBetweenShots averageTimeBetweenShots
averageDifficulty averageDifficulty
createdAt
updatedAt
startTime startTime
endTime
private private
elapsedTime elapsedTime
screenshotUri
stream { stream {
id id
lastIntendedSegmentBound lastIntendedSegmentBound
isCompleted
streamSegmentType streamSegmentType
} }
tableSize tableSize
pocketSize pocketSize
tags { tags {
name
tagClasses { tagClasses {
name name
} }
name }
playerSummaries {
...PlayerSummaryFields
} }
currentProcessing { currentProcessing {
id id
errors {
message
}
status status
statuses {
status
}
} }
reactions { reactions {
videoId videoId
@@ -6591,6 +6813,7 @@ export const VideoCardFieldsFragmentDoc = gql`
} }
} }
} }
${PlayerSummaryFieldsFragmentDoc}
${UserSocialsFieldsFragmentDoc} ${UserSocialsFieldsFragmentDoc}
`; `;
export const MedalFieldsFragmentDoc = gql` export const MedalFieldsFragmentDoc = gql`
@@ -6640,6 +6863,35 @@ export const PocketingIntentionFragmentFragmentDoc = gql`
difficulty difficulty
} }
`; `;
export const PlayerClusterShotFieldsFragmentDoc = gql`
fragment PlayerClusterShotFields on PlayerClusterShotGQL {
shotId
bboxX1
bboxY1
bboxX2
bboxY2
confidence
isConfirmed
cropUrl
fullFrameUrl
}
`;
export const PlayerClusterFieldsFragmentDoc = gql`
fragment PlayerClusterFields on PlayerClusterGQL {
videoId
clusterId
nShots
userId
username
profileImageUri
confirmed
score
shots {
...PlayerClusterShotFields
}
}
${PlayerClusterShotFieldsFragmentDoc}
`;
export const ShotWithAllFeaturesFragmentDoc = gql` export const ShotWithAllFeaturesFragmentDoc = gql`
fragment ShotWithAllFeatures on ShotGQL { fragment ShotWithAllFeatures on ShotGQL {
id id
@@ -9666,9 +9918,60 @@ export type CreateSubscriptionMutationOptions = Apollo.BaseMutationOptions<
CreateSubscriptionMutation, CreateSubscriptionMutation,
CreateSubscriptionMutationVariables CreateSubscriptionMutationVariables
>; >;
export const CreateCustomerPortalSessionDocument = gql`
mutation CreateCustomerPortalSession {
createCustomerPortalSession {
portalUrl
}
}
`;
export type CreateCustomerPortalSessionMutationFn = Apollo.MutationFunction<
CreateCustomerPortalSessionMutation,
CreateCustomerPortalSessionMutationVariables
>;
/**
* __useCreateCustomerPortalSessionMutation__
*
* To run a mutation, you first call `useCreateCustomerPortalSessionMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useCreateCustomerPortalSessionMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [createCustomerPortalSessionMutation, { data, loading, error }] = useCreateCustomerPortalSessionMutation({
* variables: {
* },
* });
*/
export function useCreateCustomerPortalSessionMutation(
baseOptions?: Apollo.MutationHookOptions<
CreateCustomerPortalSessionMutation,
CreateCustomerPortalSessionMutationVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useMutation<
CreateCustomerPortalSessionMutation,
CreateCustomerPortalSessionMutationVariables
>(CreateCustomerPortalSessionDocument, options);
}
export type CreateCustomerPortalSessionMutationHookResult = ReturnType<
typeof useCreateCustomerPortalSessionMutation
>;
export type CreateCustomerPortalSessionMutationResult =
Apollo.MutationResult<CreateCustomerPortalSessionMutation>;
export type CreateCustomerPortalSessionMutationOptions =
Apollo.BaseMutationOptions<
CreateCustomerPortalSessionMutation,
CreateCustomerPortalSessionMutationVariables
>;
export const GetAvailableSubscriptionOptionsDocument = gql` export const GetAvailableSubscriptionOptionsDocument = gql`
query GetAvailableSubscriptionOptions { query GetAvailableSubscriptionOptions {
getAvailableSubscriptionOptions { getAvailableSubscriptionOptions {
trialPeriodDays
products { products {
id id
name name
@@ -10192,6 +10495,132 @@ export type GetRunsWithTimestampsQueryResult = Apollo.QueryResult<
GetRunsWithTimestampsQuery, GetRunsWithTimestampsQuery,
GetRunsWithTimestampsQueryVariables GetRunsWithTimestampsQueryVariables
>; >;
export const VideoPlayerClustersDocument = gql`
query VideoPlayerClusters($videoId: Int!) {
videoPlayerClusters(videoId: $videoId) {
...PlayerClusterFields
}
}
${PlayerClusterFieldsFragmentDoc}
`;
/**
* __useVideoPlayerClustersQuery__
*
* To run a query within a React component, call `useVideoPlayerClustersQuery` and pass it any options that fit your needs.
* When your component renders, `useVideoPlayerClustersQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useVideoPlayerClustersQuery({
* variables: {
* videoId: // value for 'videoId'
* },
* });
*/
export function useVideoPlayerClustersQuery(
baseOptions: Apollo.QueryHookOptions<
VideoPlayerClustersQuery,
VideoPlayerClustersQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<
VideoPlayerClustersQuery,
VideoPlayerClustersQueryVariables
>(VideoPlayerClustersDocument, options);
}
export function useVideoPlayerClustersLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
VideoPlayerClustersQuery,
VideoPlayerClustersQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
VideoPlayerClustersQuery,
VideoPlayerClustersQueryVariables
>(VideoPlayerClustersDocument, options);
}
export function useVideoPlayerClustersSuspenseQuery(
baseOptions?: Apollo.SuspenseQueryHookOptions<
VideoPlayerClustersQuery,
VideoPlayerClustersQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSuspenseQuery<
VideoPlayerClustersQuery,
VideoPlayerClustersQueryVariables
>(VideoPlayerClustersDocument, options);
}
export type VideoPlayerClustersQueryHookResult = ReturnType<
typeof useVideoPlayerClustersQuery
>;
export type VideoPlayerClustersLazyQueryHookResult = ReturnType<
typeof useVideoPlayerClustersLazyQuery
>;
export type VideoPlayerClustersSuspenseQueryHookResult = ReturnType<
typeof useVideoPlayerClustersSuspenseQuery
>;
export type VideoPlayerClustersQueryResult = Apollo.QueryResult<
VideoPlayerClustersQuery,
VideoPlayerClustersQueryVariables
>;
export const FinalizePlayerAssignmentsDocument = gql`
mutation FinalizePlayerAssignments($input: FinalizePlayerAssignmentsInput!) {
finalizePlayerAssignments(input: $input) {
...PlayerClusterFields
}
}
${PlayerClusterFieldsFragmentDoc}
`;
export type FinalizePlayerAssignmentsMutationFn = Apollo.MutationFunction<
FinalizePlayerAssignmentsMutation,
FinalizePlayerAssignmentsMutationVariables
>;
/**
* __useFinalizePlayerAssignmentsMutation__
*
* To run a mutation, you first call `useFinalizePlayerAssignmentsMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useFinalizePlayerAssignmentsMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [finalizePlayerAssignmentsMutation, { data, loading, error }] = useFinalizePlayerAssignmentsMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useFinalizePlayerAssignmentsMutation(
baseOptions?: Apollo.MutationHookOptions<
FinalizePlayerAssignmentsMutation,
FinalizePlayerAssignmentsMutationVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useMutation<
FinalizePlayerAssignmentsMutation,
FinalizePlayerAssignmentsMutationVariables
>(FinalizePlayerAssignmentsDocument, options);
}
export type FinalizePlayerAssignmentsMutationHookResult = ReturnType<
typeof useFinalizePlayerAssignmentsMutation
>;
export type FinalizePlayerAssignmentsMutationResult =
Apollo.MutationResult<FinalizePlayerAssignmentsMutation>;
export type FinalizePlayerAssignmentsMutationOptions =
Apollo.BaseMutationOptions<
FinalizePlayerAssignmentsMutation,
FinalizePlayerAssignmentsMutationVariables
>;
export const GetSerializedShotPathsDocument = gql` export const GetSerializedShotPathsDocument = gql`
query GetSerializedShotPaths($filterInput: FilterInput!) { query GetSerializedShotPaths($filterInput: FilterInput!) {
getShots(filterInput: $filterInput) { getShots(filterInput: $filterInput) {
@@ -12381,8 +12810,12 @@ export const GetVideoDetailsDocument = gql`
} }
name name
} }
playerSummaries {
...PlayerSummaryFields
}
} }
} }
${PlayerSummaryFieldsFragmentDoc}
`; `;
/** /**

View File

@@ -31,41 +31,32 @@ fragment VideoCardFields on VideoGQL {
} }
name name
screenshotUri screenshotUri
totalShotsMade
totalShots totalShots
makePercentage makePercentage
averageTimeBetweenShots averageTimeBetweenShots
averageDifficulty averageDifficulty
createdAt
updatedAt
startTime startTime
endTime
private private
elapsedTime elapsedTime
screenshotUri
stream { stream {
id id
lastIntendedSegmentBound lastIntendedSegmentBound
isCompleted
streamSegmentType streamSegmentType
} }
tableSize tableSize
pocketSize pocketSize
tags { tags {
name
tagClasses { tagClasses {
name name
} }
name }
playerSummaries {
...PlayerSummaryFields
} }
currentProcessing { currentProcessing {
id id
errors {
message
}
status status
statuses {
status
}
} }
reactions { reactions {
videoId videoId

View File

@@ -20,8 +20,15 @@ mutation CreateSubscription($priceId: String!) {
} }
} }
mutation CreateCustomerPortalSession {
createCustomerPortalSession {
portalUrl
}
}
query GetAvailableSubscriptionOptions { query GetAvailableSubscriptionOptions {
getAvailableSubscriptionOptions { getAvailableSubscriptionOptions {
trialPeriodDays
products { products {
id id
name name

View File

@@ -0,0 +1,52 @@
fragment PlayerSummaryFields on PlayerSummaryGQL {
clusterId
userId
username
profileImageUri
representativeFullFrameUrl
totalShots
totalShotsMade
makePercentage
score
longestRun
averageDifficulty
averageTimeBetweenShots
}
fragment PlayerClusterShotFields on PlayerClusterShotGQL {
shotId
bboxX1
bboxY1
bboxX2
bboxY2
confidence
isConfirmed
cropUrl
fullFrameUrl
}
fragment PlayerClusterFields on PlayerClusterGQL {
videoId
clusterId
nShots
userId
username
profileImageUri
confirmed
score
shots {
...PlayerClusterShotFields
}
}
query VideoPlayerClusters($videoId: Int!) {
videoPlayerClusters(videoId: $videoId) {
...PlayerClusterFields
}
}
mutation FinalizePlayerAssignments($input: FinalizePlayerAssignmentsInput!) {
finalizePlayerAssignments(input: $input) {
...PlayerClusterFields
}
}

View File

@@ -83,6 +83,9 @@ query GetVideoDetails($videoId: Int!) {
} }
name name
} }
playerSummaries {
...PlayerSummaryFields
}
} }
} }

View File

@@ -28,7 +28,7 @@ type Query {
getLongestRunsLeaderboard( getLongestRunsLeaderboard(
interval: TimeInterval = null interval: TimeInterval = null
when: DateTime = null when: DateTime = null
limit: Int! = 100 limit: Int! = 50
requiredTags: [String!] = null requiredTags: [String!] = null
): RunLeaderboardGQL! ): RunLeaderboardGQL!
getMakesLeaderboard( getMakesLeaderboard(
@@ -49,6 +49,7 @@ type Query {
limit: Int! = 500 limit: Int! = 500
countRespectsLimit: Boolean! = false countRespectsLimit: Boolean! = false
): GetRunsResult! ): GetRunsResult!
videoPlayerClusters(videoId: Int!): [PlayerClusterGQL!]!
getShotAnnotationTypes(errorTypes: Boolean = false): [ShotAnnotationTypeGQL!]! getShotAnnotationTypes(errorTypes: Boolean = false): [ShotAnnotationTypeGQL!]!
getTableState( getTableState(
b64Image: String! b64Image: String!
@@ -405,6 +406,7 @@ type VideoGQL {
currentProcessing: VideoProcessingGQL currentProcessing: VideoProcessingGQL
reactions: [ReactionGQL!]! reactions: [ReactionGQL!]!
comments: [CommentGQL!]! comments: [CommentGQL!]!
playerSummaries: [PlayerSummaryGQL!]!
} }
type ShotGQL { type ShotGQL {
@@ -664,6 +666,21 @@ type CommentGQL {
replies: [CommentGQL!]! replies: [CommentGQL!]!
} }
type PlayerSummaryGQL {
clusterId: Int!
userId: Int
username: String
profileImageUri: String
representativeFullFrameUrl: String
totalShots: Int!
totalShotsMade: Int!
makePercentage: Float!
score: Int
longestRun: Int!
averageDifficulty: Float
averageTimeBetweenShots: Float
}
type DeployedConfigGQL { type DeployedConfigGQL {
allowNewUsers: Boolean! allowNewUsers: Boolean!
firebase: Boolean! firebase: Boolean!
@@ -860,6 +877,30 @@ input DatetimeOrdering {
startingAt: DateTime = null startingAt: DateTime = null
} }
type PlayerClusterGQL {
videoId: Int!
clusterId: Int!
nShots: Int!
userId: Int
username: String
profileImageUri: String
confirmed: Boolean!
score: Int
shots: [PlayerClusterShotGQL!]!
}
type PlayerClusterShotGQL {
shotId: Int!
bboxX1: Int!
bboxY1: Int!
bboxX2: Int!
bboxY2: Int!
confidence: Float!
isConfirmed: Boolean!
cropUrl: String
fullFrameUrl: String
}
type TableStateGQL { type TableStateGQL {
identifierToPosition: [[Float!]!]! identifierToPosition: [[Float!]!]!
homography: HomographyInfoGQL homography: HomographyInfoGQL
@@ -940,6 +981,7 @@ type UserRelationship {
type StripeSubscriptionOptionsGQL { type StripeSubscriptionOptionsGQL {
products: [StripeProductGQL!]! products: [StripeProductGQL!]!
trialPeriodDays: Int
} }
type StripeProductGQL { type StripeProductGQL {
@@ -998,17 +1040,10 @@ type QuotaStatusGQL {
durationUsedSeconds: Float! durationUsedSeconds: Float!
durationLimitSeconds: Int durationLimitSeconds: Int
maxVideoDurationSeconds: Int maxVideoDurationSeconds: Int
recordingPermission: UploadPermissionGQL!
importUploadPermission: UploadPermissionGQL!
durationRemainingSeconds: Float durationRemainingSeconds: Float
canUpload: Boolean! canUpload: Boolean!
} }
type UploadPermissionGQL {
allowed: Boolean!
reason: String
}
type UserPlayTimeGQL { type UserPlayTimeGQL {
totalSeconds: Float! totalSeconds: Float!
} }
@@ -1100,6 +1135,9 @@ type Mutation {
markAllNotificationsAsRead: Boolean! markAllNotificationsAsRead: Boolean!
markNotificationsAsRead(notificationIds: [Int!]!): Boolean! markNotificationsAsRead(notificationIds: [Int!]!): Boolean!
deleteNotification(notificationId: Int!): Boolean! deleteNotification(notificationId: Int!): Boolean!
finalizePlayerAssignments(
input: FinalizePlayerAssignmentsInput!
): [PlayerClusterGQL!]!
addAnnotationToShot( addAnnotationToShot(
shotId: Int! shotId: Int!
annotationName: String! annotationName: String!
@@ -1124,6 +1162,7 @@ type Mutation {
ensureStripeCustomerExists: UserGQL! ensureStripeCustomerExists: UserGQL!
deleteUser: Boolean! deleteUser: Boolean!
createSubscription(priceId: String!): CreateSubscriptionResultGQL! createSubscription(priceId: String!): CreateSubscriptionResultGQL!
createCustomerPortalSession: CreateCustomerPortalSessionResultGQL!
cancelSubscription: UserSubscriptionStatusGQL! cancelSubscription: UserSubscriptionStatusGQL!
grantManualEntitlement( grantManualEntitlement(
userId: Int! userId: Int!
@@ -1141,7 +1180,6 @@ type Mutation {
findPrerecordTableLayout(b64Image: String!, videoId: Int!): HomographyInfoGQL findPrerecordTableLayout(b64Image: String!, videoId: Int!): HomographyInfoGQL
createUploadStream( createUploadStream(
videoMetadata: VideoMetadataInput! videoMetadata: VideoMetadataInput!
uploadKind: UploadKindEnum = null
expectedDurationSeconds: Float = null expectedDurationSeconds: Float = null
): CreateUploadStreamReturn! ): CreateUploadStreamReturn!
getUploadLink(videoId: Int!, segmentIndex: Int!): GetUploadLinkReturn! getUploadLink(videoId: Int!, segmentIndex: Int!): GetUploadLinkReturn!
@@ -1171,6 +1209,23 @@ enum ReportReasonEnum {
OTHER OTHER
} }
input FinalizePlayerAssignmentsInput {
videoId: Int!
clusterAssignments: [ClusterAssignmentInput!]! = []
shotMoves: [ShotMoveInput!]! = []
}
input ClusterAssignmentInput {
clusterId: Int!
userId: Int = null
score: Int = null
}
input ShotMoveInput {
shotId: Int!
newClusterId: Int!
}
type AddShotAnnotationReturn { type AddShotAnnotationReturn {
value: SuccessfulAddAddShotAnnotationErrors! value: SuccessfulAddAddShotAnnotationErrors!
} }
@@ -1264,6 +1319,10 @@ type CreateSubscriptionResultGQL {
sessionId: String! sessionId: String!
} }
type CreateCustomerPortalSessionResultGQL {
portalUrl: String!
}
enum CancellationReasonEnum { enum CancellationReasonEnum {
DONT_PLAY_ENOUGH DONT_PLAY_ENOUGH
TOO_EXPENSIVE TOO_EXPENSIVE
@@ -1310,11 +1369,6 @@ input VideoResolution {
height: Int! height: Int!
} }
enum UploadKindEnum {
RECORDING
IMPORT
}
type GetUploadLinkReturn { type GetUploadLinkReturn {
value: UploadLinkGetUploadLinkErrors! value: UploadLinkGetUploadLinkErrors!
stream: UploadStreamGQL stream: UploadStreamGQL